3 Copyright (c) 2006 - 2007, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 Help functions to access UDP service, it is used by both the DHCP and MTFTP.
26 #include <Protocol/Udp4.h>
28 #include <Library/UdpIoLib.h>
29 #include <Library/BaseLib.h>
30 #include <Library/DebugLib.h>
31 #include <Library/UefiBootServicesTableLib.h>
32 #include <Library/MemoryAllocationLib.h>
52 Wrap a transmit request into a UDP_TX_TOKEN.
54 @param UdpIo The UdpIo port to send packet to
55 @param Packet The user's packet
56 @param EndPoint The local and remote access point
57 @param Gateway The overrided next hop
58 @param CallBack The function to call when transmission completed.
59 @param Context The opaque parameter to the call back
61 @return The wrapped transmission request or NULL if failed to allocate resources.
67 IN UDP_IO_PORT
*UdpIo
,
69 IN UDP_POINTS
*EndPoint
, OPTIONAL
71 IN UDP_IO_CALLBACK CallBack
,
76 EFI_UDP4_COMPLETION_TOKEN
*UdpToken
;
77 EFI_UDP4_TRANSMIT_DATA
*UdpTxData
;
81 Token
= NetAllocatePool (sizeof (UDP_TX_TOKEN
) +
82 sizeof (EFI_UDP4_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1));
88 Token
->Signature
= UDP_IO_TX_SIGNATURE
;
89 NetListInit (&Token
->Link
);
92 Token
->CallBack
= CallBack
;
93 Token
->Packet
= Packet
;
94 Token
->Context
= Context
;
96 UdpToken
= &(Token
->UdpToken
);
97 UdpToken
->Status
= EFI_NOT_READY
;
99 Status
= gBS
->CreateEvent (
107 if (EFI_ERROR (Status
)) {
112 UdpTxData
= &Token
->UdpTxData
;
113 UdpToken
->Packet
.TxData
= UdpTxData
;
115 UdpTxData
->UdpSessionData
= NULL
;
116 UdpTxData
->GatewayAddress
= NULL
;
118 if (EndPoint
!= NULL
) {
119 EFI_IP4 (Token
->UdpSession
.SourceAddress
) = HTONL (EndPoint
->LocalAddr
);
120 EFI_IP4 (Token
->UdpSession
.DestinationAddress
) = HTONL (EndPoint
->RemoteAddr
);
121 Token
->UdpSession
.SourcePort
= EndPoint
->LocalPort
;
122 Token
->UdpSession
.DestinationPort
= EndPoint
->RemotePort
;
123 UdpTxData
->UdpSessionData
= &Token
->UdpSession
;
127 EFI_IP4 (Token
->Gateway
) = HTONL (Gateway
);
128 UdpTxData
->GatewayAddress
= &Token
->Gateway
;
131 UdpTxData
->DataLength
= Packet
->TotalSize
;
132 Count
= Packet
->BlockOpNum
;
133 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) UdpTxData
->FragmentTable
, &Count
);
134 UdpTxData
->FragmentCount
= Count
;
141 Free a UDP_TX_TOKEN. The event is closed and memory released.
143 @param Token The UDP_TX_TOKEN to release.
150 IN UDP_TX_TOKEN
*Token
153 gBS
->CloseEvent (Token
->UdpToken
.Event
);
159 Create a UDP_RX_TOKEN to wrap the request.
161 @param UdpIo The UdpIo to receive packets from
162 @param CallBack The function to call when receive finished.
163 @param Context The opaque parameter to the CallBack
164 @param HeadLen The head length to reserver for the packet.
166 @return The Wrapped request or NULL if failed to allocate resources.
171 IN UDP_IO_PORT
*UdpIo
,
172 IN UDP_IO_CALLBACK CallBack
,
180 Token
= NetAllocatePool (sizeof (UDP_RX_TOKEN
));
186 Token
->Signature
= UDP_IO_RX_SIGNATURE
;
187 Token
->UdpIo
= UdpIo
;
188 Token
->CallBack
= CallBack
;
189 Token
->Context
= Context
;
190 Token
->HeadLen
= HeadLen
;
192 Token
->UdpToken
.Status
= EFI_NOT_READY
;
193 Token
->UdpToken
.Packet
.RxData
= NULL
;
195 Status
= gBS
->CreateEvent (
200 &Token
->UdpToken
.Event
203 if (EFI_ERROR (Status
)) {
213 Free a receive request wrap.
215 @param Token The receive request to release.
222 IN UDP_RX_TOKEN
*Token
225 gBS
->CloseEvent (Token
->UdpToken
.Event
);
231 Create a UDP IO port to access the UDP service. It will
232 create and configure a UDP child.
234 @param Controller The controller that has the UDP service binding
236 @param Image The image handle for the driver.
237 @param Configure The function to configure the created UDP child
238 @param Context The opaque parameter for the Configure funtion.
240 @return A point to just created UDP IO port or NULL if failed.
245 IN EFI_HANDLE Controller
,
247 IN UDP_IO_CONFIG Configure
,
254 ASSERT (Configure
!= NULL
);
256 UdpIo
= NetAllocatePool (sizeof (UDP_IO_PORT
));
262 UdpIo
->Signature
= UDP_IO_SIGNATURE
;
263 NetListInit (&UdpIo
->Link
);
266 UdpIo
->Controller
= Controller
;
267 UdpIo
->Image
= Image
;
269 NetListInit (&UdpIo
->SentDatagram
);
270 UdpIo
->RecvRequest
= NULL
;
271 UdpIo
->UdpHandle
= NULL
;
274 // Create a UDP child then open and configure it
276 Status
= NetLibCreateServiceChild (
279 &gEfiUdp4ServiceBindingProtocolGuid
,
283 if (EFI_ERROR (Status
)) {
287 Status
= gBS
->OpenProtocol (
289 &gEfiUdp4ProtocolGuid
,
293 EFI_OPEN_PROTOCOL_BY_DRIVER
296 if (EFI_ERROR (Status
)) {
300 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
304 Status
= UdpIo
->Udp
->GetModeData (UdpIo
->Udp
, NULL
, NULL
, NULL
, &UdpIo
->SnpMode
);
306 if (EFI_ERROR (Status
)) {
313 gBS
->CloseProtocol (UdpIo
->UdpHandle
, &gEfiUdp4ProtocolGuid
, Image
, Controller
);
316 NetLibDestroyServiceChild (
319 &gEfiUdp4ServiceBindingProtocolGuid
,
330 Cancel all the sent datagram that pass the selection of ToCancel.
331 If ToCancel is NULL, all the datagrams are cancelled.
333 @param UdpIo The UDP IO port to cancel packet
334 @param IoStatus The IoStatus to return to the packet owners.
335 @param ToCancel The select funtion to test whether to cancel this
337 @param Context The opaque parameter to the ToCancel.
345 IN UDP_IO_PORT
*UdpIo
,
346 IN EFI_STATUS IoStatus
,
347 IN UDP_IO_TO_CANCEL ToCancel
, OPTIONAL
351 NET_LIST_ENTRY
*Entry
;
352 NET_LIST_ENTRY
*Next
;
355 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &UdpIo
->SentDatagram
) {
356 Token
= NET_LIST_USER_STRUCT (Entry
, UDP_TX_TOKEN
, Link
);
358 if ((ToCancel
== NULL
) || (ToCancel (Token
, Context
))) {
359 NetListRemoveEntry (Entry
);
360 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &Token
->UdpToken
);
361 Token
->CallBack (Token
->Packet
, NULL
, IoStatus
, Token
->Context
);
362 UdpIoFreeTxToken (Token
);
369 Free the UDP IO port and all its related resources including
370 all the transmitted packet.
372 @param UdpIo The UDP IO port to free.
374 @retval EFI_SUCCESS The UDP IO port is freed.
379 IN UDP_IO_PORT
*UdpIo
382 UDP_RX_TOKEN
*RxToken
;
385 // Cancel all the sent datagram and receive requests. The
386 // callbacks of transmit requests are executed to allow the
387 // caller to release the resource. The callback of receive
388 // request are NOT executed. This is because it is most
389 // likely that the current user of the UDP IO port is closing
392 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
394 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
395 UdpIo
->RecvRequest
= NULL
;
396 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &RxToken
->UdpToken
);
397 UdpIoFreeRxToken (RxToken
);
401 // Close then destory the UDP child
405 &gEfiUdp4ProtocolGuid
,
410 NetLibDestroyServiceChild (
413 &gEfiUdp4ServiceBindingProtocolGuid
,
417 NetListRemoveEntry (&UdpIo
->Link
);
424 Clean up the UDP IO port. It will release all the transmitted
425 datagrams and receive request. It will also configure NULL the
428 @param UdpIo UDP IO port to clean up.
435 IN UDP_IO_PORT
*UdpIo
438 UDP_RX_TOKEN
*RxToken
;
441 // Cancel all the sent datagram and receive requests.
443 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
445 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
446 UdpIo
->RecvRequest
= NULL
;
447 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &RxToken
->UdpToken
);
448 UdpIoFreeRxToken (RxToken
);
451 UdpIo
->Udp
->Configure (UdpIo
->Udp
, NULL
);
456 The callback function when the packet is sent by UDP.
457 It will remove the packet from the local list then call
458 the packet owner's callback function.
460 @param Event The event signalled.
461 @param Context The UDP TX Token.
476 Token
= (UDP_TX_TOKEN
*) Context
;
477 ASSERT (Token
->Signature
== UDP_IO_TX_SIGNATURE
);
479 NetListRemoveEntry (&Token
->Link
);
480 Token
->CallBack (Token
->Packet
, NULL
, Token
->UdpToken
.Status
, Token
->Context
);
482 UdpIoFreeTxToken (Token
);
487 Send a packet through the UDP IO port.
489 @param UdpIo The UDP IO Port to send the packet through
490 @param Packet The packet to send
491 @param EndPoint The local and remote access point
492 @param Gateway The gateway to use
493 @param CallBack The call back function to call when packet is
494 transmitted or failed.
495 @param Context The opque parameter to the CallBack
497 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet
498 @retval EFI_SUCCESS The packet is successfully delivered to UDP for
504 IN UDP_IO_PORT
*UdpIo
,
506 IN UDP_POINTS
*EndPoint
, OPTIONAL
508 IN UDP_IO_CALLBACK CallBack
,
515 Token
= UdpIoWrapTx (UdpIo
, Packet
, EndPoint
, Gateway
, CallBack
, Context
);
518 return EFI_OUT_OF_RESOURCES
;
521 Status
= UdpIo
->Udp
->Transmit (UdpIo
->Udp
, &Token
->UdpToken
);
523 if (EFI_ERROR (Status
)) {
524 UdpIoFreeTxToken (Token
);
528 NetListInsertHead (&UdpIo
->SentDatagram
, &Token
->Link
);
534 The selection function to cancel a single sent datagram.
536 @param Token The UDP TX token to test againist.
537 @param Context The context
539 @return TRUE if the packet is to be cancelled, otherwise FALSE.
544 UdpIoCancelSingleDgram (
545 IN UDP_TX_TOKEN
*Token
,
551 Packet
= (NET_BUF
*) Context
;
553 if (Token
->Packet
== Packet
) {
562 Cancel a single sent datagram.
564 @param UdpIo The UDP IO port to cancel the packet from
565 @param Packet The packet to cancel
571 UdpIoCancelSentDatagram (
572 IN UDP_IO_PORT
*UdpIo
,
576 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, UdpIoCancelSingleDgram
, Packet
);
581 Recycle the received UDP data.
583 @param Context The UDP_RX_TOKEN
596 Token
= (UDP_RX_TOKEN
*) Context
;
597 gBS
->SignalEvent (Token
->UdpToken
.Packet
.RxData
->RecycleSignal
);
598 UdpIoFreeRxToken (Token
);
603 The event handle for UDP receive request. It will build
604 a NET_BUF from the recieved UDP data, then deliver it
607 @param Event The UDP receive request event
608 @param Context The UDP RX token.
621 EFI_UDP4_COMPLETION_TOKEN
*UdpToken
;
622 EFI_UDP4_RECEIVE_DATA
*UdpRxData
;
623 EFI_UDP4_SESSION_DATA
*UdpSession
;
628 Token
= (UDP_RX_TOKEN
*) Context
;
630 ASSERT ((Token
->Signature
== UDP_IO_RX_SIGNATURE
) &&
631 (Token
== Token
->UdpIo
->RecvRequest
));
634 // Clear the receive request first in case that the caller
635 // wants to restart the receive in the callback.
637 Token
->UdpIo
->RecvRequest
= NULL
;
639 UdpToken
= &Token
->UdpToken
;
640 UdpRxData
= UdpToken
->Packet
.RxData
;
642 if (EFI_ERROR (UdpToken
->Status
) || (UdpRxData
== NULL
)) {
643 Token
->CallBack (NULL
, NULL
, UdpToken
->Status
, Token
->Context
);
644 UdpIoFreeRxToken (Token
);
650 // Build a NET_BUF from the UDP receive data, then deliver it up.
652 Netbuf
= NetbufFromExt (
653 (NET_FRAGMENT
*) UdpRxData
->FragmentTable
,
654 UdpRxData
->FragmentCount
,
656 (UINT32
) Token
->HeadLen
,
661 if (Netbuf
== NULL
) {
662 gBS
->SignalEvent (UdpRxData
->RecycleSignal
);
663 Token
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, Token
->Context
);
665 UdpIoFreeRxToken (Token
);
669 UdpSession
= &UdpRxData
->UdpSession
;
670 Points
.LocalAddr
= EFI_NTOHL (UdpSession
->DestinationAddress
);
671 Points
.LocalPort
= UdpSession
->DestinationPort
;
672 Points
.RemoteAddr
= EFI_NTOHL (UdpSession
->SourceAddress
);
673 Points
.RemotePort
= UdpSession
->SourcePort
;
675 Token
->CallBack (Netbuf
, &Points
, EFI_SUCCESS
, Token
->Context
);
683 Issue a receive request to the UDP IO port.
685 @param UdpIo The UDP IO port to recieve the packet from.
686 @param CallBack The call back function to execute when receive
688 @param Context The opque context to the call back
689 @param HeadLen The lenght of the application's header
691 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only
692 one receive request is supported.
693 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource.
694 @retval EFI_SUCCESS The receive request is issued successfully.
699 IN UDP_IO_PORT
*UdpIo
,
700 IN UDP_IO_CALLBACK CallBack
,
708 if (UdpIo
->RecvRequest
!= NULL
) {
709 return EFI_ALREADY_STARTED
;
712 Token
= UdpIoCreateRxToken (UdpIo
, CallBack
, Context
, HeadLen
);
715 return EFI_OUT_OF_RESOURCES
;
718 Status
= UdpIo
->Udp
->Receive (UdpIo
->Udp
, &Token
->UdpToken
);
720 if (EFI_ERROR (Status
)) {
721 UdpIoFreeRxToken (Token
);
725 UdpIo
->RecvRequest
= Token
;