2 Help functions to access UDP service, it is used by both the DHCP and MTFTP.
4 Copyright (c) 2005 - 2009, Intel Corporation.<BR>
5 All rights reserved. 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.
137 UDP_RX_TOKEN
*RxToken
;
139 RxToken
= (UDP_RX_TOKEN
*) Context
;
141 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
142 gBS
->SignalEvent (RxToken
->Token
.Udp4
.Packet
.RxData
->RecycleSignal
);
143 } else if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
) {
144 gBS
->SignalEvent (RxToken
->Token
.Udp6
.Packet
.RxData
->RecycleSignal
);
149 UdpIoFreeRxToken (RxToken
);
153 The event handle for UDP receive request.
155 It will build a NET_BUF from the recieved UDP data, then deliver it
158 @param[in] Context The UDP RX token.
163 UdpIoOnDgramRcvdDpc (
171 UDP_RX_TOKEN
*RxToken
;
172 UDP_END_POINT EndPoint
;
175 RxToken
= (UDP_RX_TOKEN
*) Context
;
177 ZeroMem (&EndPoint
, sizeof(UDP_END_POINT
));
179 ASSERT ((RxToken
->Signature
== UDP_IO_RX_SIGNATURE
) &&
180 (RxToken
== RxToken
->UdpIo
->RecvRequest
));
182 ASSERT ((RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
183 (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
186 // Clear the receive request first in case that the caller
187 // wants to restart the receive in the callback.
189 RxToken
->UdpIo
->RecvRequest
= NULL
;
191 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
192 Token
= &RxToken
->Token
.Udp4
;
193 RxData
= ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Packet
.RxData
;
194 Status
= ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Status
;
196 Token
= &RxToken
->Token
.Udp6
;
197 RxData
= ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Packet
.RxData
;
198 Status
= ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Status
;
201 if (EFI_ERROR (Status
) || RxData
== NULL
) {
202 if (Status
!= EFI_ABORTED
) {
204 // Invoke the CallBack only if the reception is not actively aborted.
206 RxToken
->CallBack (NULL
, NULL
, Status
, RxToken
->Context
);
209 UdpIoFreeRxToken (RxToken
);
214 // Build a NET_BUF from the UDP receive data, then deliver it up.
216 if (RxToken
->UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
218 Netbuf
= NetbufFromExt (
219 (NET_FRAGMENT
*)((EFI_UDP4_RECEIVE_DATA
*) RxData
)->FragmentTable
,
220 ((EFI_UDP4_RECEIVE_DATA
*) RxData
)->FragmentCount
,
222 (UINT32
) RxToken
->HeadLen
,
227 if (Netbuf
== NULL
) {
228 gBS
->SignalEvent (((EFI_UDP4_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
229 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
231 UdpIoFreeRxToken (RxToken
);
235 Session
= &((EFI_UDP4_RECEIVE_DATA
*) RxData
)->UdpSession
;
236 EndPoint
.LocalPort
= ((EFI_UDP4_SESSION_DATA
*) Session
)->DestinationPort
;
237 EndPoint
.RemotePort
= ((EFI_UDP4_SESSION_DATA
*) Session
)->SourcePort
;
241 &((EFI_UDP4_SESSION_DATA
*) Session
)->DestinationAddress
,
242 sizeof (EFI_IPv4_ADDRESS
)
246 &EndPoint
.RemoteAddr
,
247 &((EFI_UDP4_SESSION_DATA
*) Session
)->SourceAddress
,
248 sizeof (EFI_IPv4_ADDRESS
)
251 EndPoint
.LocalAddr
.Addr
[0] = NTOHL (EndPoint
.LocalAddr
.Addr
[0]);
252 EndPoint
.RemoteAddr
.Addr
[0] = NTOHL (EndPoint
.RemoteAddr
.Addr
[0]);
255 Netbuf
= NetbufFromExt (
256 (NET_FRAGMENT
*)((EFI_UDP6_RECEIVE_DATA
*) RxData
)->FragmentTable
,
257 ((EFI_UDP6_RECEIVE_DATA
*) RxData
)->FragmentCount
,
259 (UINT32
) RxToken
->HeadLen
,
264 if (Netbuf
== NULL
) {
265 gBS
->SignalEvent (((EFI_UDP6_RECEIVE_DATA
*) RxData
)->RecycleSignal
);
266 RxToken
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, RxToken
->Context
);
268 UdpIoFreeRxToken (RxToken
);
272 Session
= &((EFI_UDP6_RECEIVE_DATA
*) RxData
)->UdpSession
;
273 EndPoint
.LocalPort
= ((EFI_UDP6_SESSION_DATA
*) Session
)->DestinationPort
;
274 EndPoint
.RemotePort
= ((EFI_UDP6_SESSION_DATA
*) Session
)->SourcePort
;
278 &((EFI_UDP6_SESSION_DATA
*) Session
)->DestinationAddress
,
279 sizeof (EFI_IPv6_ADDRESS
)
283 &EndPoint
.RemoteAddr
,
284 &((EFI_UDP6_SESSION_DATA
*) Session
)->SourceAddress
,
285 sizeof (EFI_IPv6_ADDRESS
)
288 Ip6Swap128 (&EndPoint
.LocalAddr
.v6
);
289 Ip6Swap128 (&EndPoint
.RemoteAddr
.v6
);
292 RxToken
->CallBack (Netbuf
, &EndPoint
, EFI_SUCCESS
, RxToken
->Context
);
296 Request UdpIoOnDgramRcvdDpc() as a DPC at TPL_CALLBACK.
298 @param[in] Event The UDP receive request event.
299 @param[in] Context The UDP RX token.
310 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK
312 QueueDpc (TPL_CALLBACK
, UdpIoOnDgramRcvdDpc
, Context
);
316 Create a UDP_RX_TOKEN to wrap the request.
318 @param[in] UdpIo The UdpIo to receive packets from.
319 @param[in] CallBack The function to call when receive finished.
320 @param[in] Context The opaque parameter to the CallBack.
321 @param[in] HeadLen The head length to reserver for the packet.
323 @return The Wrapped request or NULL if failed to allocate resources or some errors happened.
329 IN UDP_IO_CALLBACK CallBack
,
337 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
338 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
340 Token
= AllocatePool (sizeof (UDP_RX_TOKEN
));
346 Token
->Signature
= UDP_IO_RX_SIGNATURE
;
347 Token
->UdpIo
= UdpIo
;
348 Token
->CallBack
= CallBack
;
349 Token
->Context
= Context
;
350 Token
->HeadLen
= HeadLen
;
352 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
354 Token
->Token
.Udp4
.Status
= EFI_NOT_READY
;
355 Token
->Token
.Udp4
.Packet
.RxData
= NULL
;
357 Status
= gBS
->CreateEvent (
362 &Token
->Token
.Udp4
.Event
366 Token
->Token
.Udp6
.Status
= EFI_NOT_READY
;
367 Token
->Token
.Udp6
.Packet
.RxData
= NULL
;
369 Status
= gBS
->CreateEvent (
374 &Token
->Token
.Udp6
.Event
379 if (EFI_ERROR (Status
)) {
388 Wrap a transmit request into a new created UDP_TX_TOKEN.
390 @param[in] UdpIo The UdpIo to send packet to.
391 @param[in] Packet The user's packet.
392 @param[in] EndPoint The local and remote access point.
393 @param[in] Gateway The overrided next hop.
394 @param[in] CallBack The function to call when transmission completed.
395 @param[in] Context The opaque parameter to the call back.
397 @return The wrapped transmission request or NULL if failed to allocate resources
405 IN UDP_END_POINT
*EndPoint OPTIONAL
,
406 IN EFI_IP_ADDRESS
*Gateway OPTIONAL
,
407 IN UDP_IO_CALLBACK CallBack
,
411 UDP_TX_TOKEN
*TxToken
;
419 ASSERT (Packet
!= NULL
);
420 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
421 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
423 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
424 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP4_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
426 Size
= sizeof (UDP_TX_TOKEN
) + sizeof (EFI_UDP6_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1);
429 TxToken
= AllocatePool (Size
);
431 if (TxToken
== NULL
) {
435 TxToken
->Signature
= UDP_IO_TX_SIGNATURE
;
436 InitializeListHead (&TxToken
->Link
);
438 TxToken
->UdpIo
= UdpIo
;
439 TxToken
->CallBack
= CallBack
;
440 TxToken
->Packet
= Packet
;
441 TxToken
->Context
= Context
;
443 Token
= &(TxToken
->Token
);
444 Count
= Packet
->BlockOpNum
;
446 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
448 ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Status
= EFI_NOT_READY
;
450 Status
= gBS
->CreateEvent (
455 &((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Event
458 if (EFI_ERROR (Status
)) {
463 Data
= &(TxToken
->Data
.Udp4
);
464 ((EFI_UDP4_COMPLETION_TOKEN
*) Token
)->Packet
.TxData
= Data
;
466 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->UdpSessionData
= NULL
;
467 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->GatewayAddress
= NULL
;
468 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
472 (NET_FRAGMENT
*)((EFI_UDP4_TRANSMIT_DATA
*) Data
)->FragmentTable
,
476 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->FragmentCount
= Count
;
478 if (EndPoint
!= NULL
) {
479 Ip
= HTONL (EndPoint
->LocalAddr
.Addr
[0]);
481 &TxToken
->Session
.Udp4
.SourceAddress
,
483 sizeof (EFI_IPv4_ADDRESS
)
486 Ip
= HTONL (EndPoint
->RemoteAddr
.Addr
[0]);
488 &TxToken
->Session
.Udp4
.DestinationAddress
,
490 sizeof (EFI_IPv4_ADDRESS
)
493 TxToken
->Session
.Udp4
.SourcePort
= EndPoint
->LocalPort
;
494 TxToken
->Session
.Udp4
.DestinationPort
= EndPoint
->RemotePort
;
495 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->UdpSessionData
= &(TxToken
->Session
.Udp4
);
498 if (Gateway
!= NULL
&& (Gateway
->Addr
[0] != 0)) {
499 Ip
= HTONL (Gateway
->Addr
[0]);
500 CopyMem (&TxToken
->Gateway
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
501 ((EFI_UDP4_TRANSMIT_DATA
*) Data
)->GatewayAddress
= &TxToken
->Gateway
;
506 ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Status
= EFI_NOT_READY
;
508 Status
= gBS
->CreateEvent (
513 &((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Event
516 if (EFI_ERROR (Status
)) {
521 Data
= &(TxToken
->Data
.Udp6
);
522 ((EFI_UDP6_COMPLETION_TOKEN
*) Token
)->Packet
.TxData
= Data
;
523 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->UdpSessionData
= NULL
;
524 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->DataLength
= Packet
->TotalSize
;
528 (NET_FRAGMENT
*)((EFI_UDP6_TRANSMIT_DATA
*) Data
)->FragmentTable
,
532 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->FragmentCount
= Count
;
534 if (EndPoint
!= NULL
) {
536 &TxToken
->Session
.Udp6
.SourceAddress
,
537 &EndPoint
->LocalAddr
.v6
,
538 sizeof(EFI_IPv6_ADDRESS
)
542 &TxToken
->Session
.Udp6
.DestinationAddress
,
543 &EndPoint
->RemoteAddr
.v6
,
544 sizeof(EFI_IPv6_ADDRESS
)
547 TxToken
->Session
.Udp6
.SourcePort
= EndPoint
->LocalPort
;
548 TxToken
->Session
.Udp6
.DestinationPort
= EndPoint
->RemotePort
;
549 ((EFI_UDP6_TRANSMIT_DATA
*) Data
)->UdpSessionData
= &(TxToken
->Session
.Udp6
);
557 Creates a UDP_IO to access the UDP service. It creates and configures
561 # locates the UDP service binding prototype on the Controller parameter
562 # uses the UDP service binding prototype to create a UDP child (also known as a UDP instance)
563 # configures the UDP child by calling Configure function prototype.
564 Any failures in creating or configuring the UDP child return NULL for failure.
566 @param[in] Controller The controller that has the UDP service binding.
568 @param[in] ImageHandle The image handle for the driver.
569 @param[in] Configure The function to configure the created UDP child.
570 @param[in] UdpVersion The UDP protocol version, UDP4 or UDP6.
571 @param[in] Context The opaque parameter for the Configure funtion.
573 @return Newly-created UDP_IO or NULL if failed.
579 IN EFI_HANDLE Controller
,
580 IN EFI_HANDLE ImageHandle
,
581 IN UDP_IO_CONFIG Configure
,
589 ASSERT (Configure
!= NULL
);
590 ASSERT ((UdpVersion
== UDP_IO_UDP4_VERSION
) || (UdpVersion
== UDP_IO_UDP6_VERSION
));
592 UdpIo
= AllocatePool (sizeof (UDP_IO
));
598 UdpIo
->UdpVersion
= UdpVersion
;
599 UdpIo
->Signature
= UDP_IO_SIGNATURE
;
600 InitializeListHead (&UdpIo
->Link
);
603 UdpIo
->Controller
= Controller
;
604 UdpIo
->Image
= ImageHandle
;
606 InitializeListHead (&UdpIo
->SentDatagram
);
607 UdpIo
->RecvRequest
= NULL
;
608 UdpIo
->UdpHandle
= NULL
;
610 if (UdpVersion
== UDP_IO_UDP4_VERSION
) {
612 // Create a UDP child then open and configure it
614 Status
= NetLibCreateServiceChild (
617 &gEfiUdp4ServiceBindingProtocolGuid
,
621 if (EFI_ERROR (Status
)) {
625 Status
= gBS
->OpenProtocol (
627 &gEfiUdp4ProtocolGuid
,
628 (VOID
**) &UdpIo
->Protocol
.Udp4
,
631 EFI_OPEN_PROTOCOL_BY_DRIVER
634 if (EFI_ERROR (Status
)) {
638 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
642 Status
= UdpIo
->Protocol
.Udp4
->GetModeData (
643 UdpIo
->Protocol
.Udp4
,
650 if (EFI_ERROR (Status
)) {
656 Status
= NetLibCreateServiceChild (
659 &gEfiUdp6ServiceBindingProtocolGuid
,
663 if (EFI_ERROR (Status
)) {
667 Status
= gBS
->OpenProtocol (
669 &gEfiUdp6ProtocolGuid
,
670 (VOID
**) &UdpIo
->Protocol
.Udp6
,
673 EFI_OPEN_PROTOCOL_BY_DRIVER
676 if (EFI_ERROR (Status
)) {
680 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
684 Status
= UdpIo
->Protocol
.Udp6
->GetModeData (
685 UdpIo
->Protocol
.Udp6
,
692 if (EFI_ERROR (Status
)) {
700 if (UdpVersion
== UDP_IO_UDP4_VERSION
) {
701 gBS
->CloseProtocol (UdpIo
->UdpHandle
, &gEfiUdp4ProtocolGuid
, ImageHandle
, Controller
);
703 gBS
->CloseProtocol (UdpIo
->UdpHandle
, &gEfiUdp6ProtocolGuid
, ImageHandle
, Controller
);
707 if (UdpVersion
== UDP_IO_UDP4_VERSION
) {
708 NetLibDestroyServiceChild (
711 &gEfiUdp4ServiceBindingProtocolGuid
,
715 NetLibDestroyServiceChild (
718 &gEfiUdp6ServiceBindingProtocolGuid
,
729 Cancel all the sent datagram that pass the selection criteria of ToCancel.
730 If ToCancel is NULL, all the datagrams are cancelled.
732 @param[in] UdpIo The UDP_IO to cancel packet.
733 @param[in] IoStatus The IoStatus to return to the packet owners.
734 @param[in] ToCancel The select funtion to test whether to cancel this
736 @param[in] Context The opaque parameter to the ToCancel.
743 IN EFI_STATUS IoStatus
,
744 IN UDP_IO_TO_CANCEL ToCancel
, OPTIONAL
750 UDP_TX_TOKEN
*TxToken
;
752 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
753 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
755 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &UdpIo
->SentDatagram
) {
756 TxToken
= NET_LIST_USER_STRUCT (Entry
, UDP_TX_TOKEN
, Link
);
758 if ((ToCancel
== NULL
) || (ToCancel (TxToken
, Context
))) {
760 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
761 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &TxToken
->Token
.Udp4
);
763 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
770 Free the UDP_IO and all its related resources.
772 The function will cancel all sent datagram and receive request.
774 @param[in] UdpIo The UDP_IO to free.
776 @retval EFI_SUCCESS The UDP_IO is freed.
785 UDP_RX_TOKEN
*RxToken
;
787 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
788 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
791 // Cancel all the sent datagram and receive requests. The
792 // callbacks of transmit requests are executed to allow the
793 // caller to release the resource. The callback of receive
794 // request are NOT executed. This is because it is most
795 // likely that the current user of the UDP IO port is closing
798 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
800 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
802 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
803 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
807 // Close then destory the Udp4 child
811 &gEfiUdp4ProtocolGuid
,
816 NetLibDestroyServiceChild (
819 &gEfiUdp4ServiceBindingProtocolGuid
,
825 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
826 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
830 // Close then destory the Udp6 child
834 &gEfiUdp6ProtocolGuid
,
839 NetLibDestroyServiceChild (
842 &gEfiUdp6ServiceBindingProtocolGuid
,
847 if (!IsListEmpty(&UdpIo
->Link
)) {
848 RemoveEntryList (&UdpIo
->Link
);
857 Clean up the UDP_IO without freeing it. The function is called when
858 user wants to re-use the UDP_IO later.
860 It will release all the transmitted datagrams and receive request. It will
861 also configure NULL for the UDP instance.
863 @param[in] UdpIo The UDP_IO to clean up.
872 UDP_RX_TOKEN
*RxToken
;
874 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
875 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
878 // Cancel all the sent datagram and receive requests.
880 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
882 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
883 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
884 UdpIo
->Protocol
.Udp4
->Cancel (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
887 UdpIo
->Protocol
.Udp4
->Configure (UdpIo
->Protocol
.Udp4
, NULL
);
890 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
891 UdpIo
->Protocol
.Udp6
->Cancel (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
894 UdpIo
->Protocol
.Udp6
->Configure (UdpIo
->Protocol
.Udp6
, NULL
);
899 Send a packet through the UDP_IO.
901 The packet will be wrapped in UDP_TX_TOKEN. Function Callback will be called
902 when the packet is sent. The optional parameter EndPoint overrides the default
903 address pair if specified.
905 @param[in] UdpIo The UDP_IO to send the packet through.
906 @param[in] Packet The packet to send.
907 @param[in] EndPoint The local and remote access point. Override the
908 default address pair set during configuration.
909 @param[in] Gateway The gateway to use.
910 @param[in] CallBack The function being called when packet is
911 transmitted or failed.
912 @param[in] Context The opaque parameter passed to CallBack.
914 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet.
915 @retval EFI_SUCCESS The packet is successfully delivered to UDP for
924 IN UDP_END_POINT
*EndPoint OPTIONAL
,
925 IN EFI_IP_ADDRESS
*Gateway OPTIONAL
,
926 IN UDP_IO_CALLBACK CallBack
,
930 UDP_TX_TOKEN
*TxToken
;
933 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
934 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
936 TxToken
= UdpIoCreateTxToken (UdpIo
, Packet
, EndPoint
, Gateway
, CallBack
, Context
);
938 if (TxToken
== NULL
) {
939 return EFI_OUT_OF_RESOURCES
;
943 // Insert the tx token into SendDatagram list before transmitting it. Remove
944 // it from the list if the returned status is not EFI_SUCCESS.
946 InsertHeadList (&UdpIo
->SentDatagram
, &TxToken
->Link
);
948 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
949 Status
= UdpIo
->Protocol
.Udp4
->Transmit (UdpIo
->Protocol
.Udp4
, &TxToken
->Token
.Udp4
);
951 Status
= UdpIo
->Protocol
.Udp6
->Transmit (UdpIo
->Protocol
.Udp6
, &TxToken
->Token
.Udp6
);
954 if (EFI_ERROR (Status
)) {
955 RemoveEntryList (&TxToken
->Link
);
956 UdpIoFreeTxToken (TxToken
);
965 The select function to cancel a single sent datagram.
967 @param[in] Token The UDP_TX_TOKEN to test against
968 @param[in] Context The NET_BUF of the sent datagram
970 @retval TRUE The packet is to be cancelled.
971 @retval FALSE The packet is not to be cancelled.
974 UdpIoCancelSingleDgram (
975 IN UDP_TX_TOKEN
*Token
,
981 Packet
= (NET_BUF
*) Context
;
983 if (Token
->Packet
== Packet
) {
991 Cancel a single sent datagram.
993 @param[in] UdpIo The UDP_IO to cancel the packet from
994 @param[in] Packet The packet to cancel
999 UdpIoCancelSentDatagram (
1004 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, UdpIoCancelSingleDgram
, Packet
);
1008 Issue a receive request to the UDP_IO.
1010 This function is called when upper-layer needs packet from UDP for processing.
1011 Only one receive request is acceptable at a time so a common usage model is
1012 to invoke this function inside its Callback function when the former packet
1015 @param[in] UdpIo The UDP_IO to receive the packet from.
1016 @param[in] CallBack The call back function to execute when the packet
1018 @param[in] Context The opaque context passed to Callback.
1019 @param[in] HeadLen The length of the upper-layer's protocol header.
1021 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only
1022 one receive request is supported at a time.
1023 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
1024 @retval EFI_SUCCESS The receive request is issued successfully.
1025 @retval EFI_UNSUPPORTED The UDP version in UDP_IO is not supported.
1032 IN UDP_IO_CALLBACK CallBack
,
1037 UDP_RX_TOKEN
*RxToken
;
1040 ASSERT ((UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) ||
1041 (UdpIo
->UdpVersion
== UDP_IO_UDP6_VERSION
));
1043 if (UdpIo
->RecvRequest
!= NULL
) {
1044 return EFI_ALREADY_STARTED
;
1047 RxToken
= UdpIoCreateRxToken (UdpIo
, CallBack
, Context
, HeadLen
);
1049 if (RxToken
== NULL
) {
1050 return EFI_OUT_OF_RESOURCES
;
1053 UdpIo
->RecvRequest
= RxToken
;
1054 if (UdpIo
->UdpVersion
== UDP_IO_UDP4_VERSION
) {
1055 Status
= UdpIo
->Protocol
.Udp4
->Receive (UdpIo
->Protocol
.Udp4
, &RxToken
->Token
.Udp4
);
1057 Status
= UdpIo
->Protocol
.Udp6
->Receive (UdpIo
->Protocol
.Udp6
, &RxToken
->Token
.Udp6
);
1060 if (EFI_ERROR (Status
)) {
1061 UdpIo
->RecvRequest
= NULL
;
1062 UdpIoFreeRxToken (RxToken
);