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>
33 #include <library/BaseMemoryLib.h>
53 Wrap a transmit request into a UDP_TX_TOKEN.
55 @param UdpIo The UdpIo port to send packet to
56 @param Packet The user's packet
57 @param EndPoint The local and remote access point
58 @param Gateway The overrided next hop
59 @param CallBack The function to call when transmission completed.
60 @param Context The opaque parameter to the call back
62 @return The wrapped transmission request or NULL if failed to allocate resources.
68 IN UDP_IO_PORT
*UdpIo
,
70 IN UDP_POINTS
*EndPoint
, OPTIONAL
72 IN UDP_IO_CALLBACK CallBack
,
77 EFI_UDP4_COMPLETION_TOKEN
*UdpToken
;
78 EFI_UDP4_TRANSMIT_DATA
*UdpTxData
;
83 Token
= NetAllocatePool (sizeof (UDP_TX_TOKEN
) +
84 sizeof (EFI_UDP4_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1));
90 Token
->Signature
= UDP_IO_TX_SIGNATURE
;
91 NetListInit (&Token
->Link
);
94 Token
->CallBack
= CallBack
;
95 Token
->Packet
= Packet
;
96 Token
->Context
= Context
;
98 UdpToken
= &(Token
->UdpToken
);
99 UdpToken
->Status
= EFI_NOT_READY
;
101 Status
= gBS
->CreateEvent (
109 if (EFI_ERROR (Status
)) {
114 UdpTxData
= &Token
->UdpTxData
;
115 UdpToken
->Packet
.TxData
= UdpTxData
;
117 UdpTxData
->UdpSessionData
= NULL
;
118 UdpTxData
->GatewayAddress
= NULL
;
120 if (EndPoint
!= NULL
) {
121 Ip
= HTONL (EndPoint
->LocalAddr
);
122 NetCopyMem (&Token
->UdpSession
.SourceAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
124 Ip
= HTONL (EndPoint
->RemoteAddr
);
125 NetCopyMem (&Token
->UdpSession
.DestinationAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
127 Token
->UdpSession
.SourcePort
= EndPoint
->LocalPort
;
128 Token
->UdpSession
.DestinationPort
= EndPoint
->RemotePort
;
129 UdpTxData
->UdpSessionData
= &Token
->UdpSession
;
133 Ip
= HTONL (Gateway
);
134 NetCopyMem (&Token
->Gateway
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
136 UdpTxData
->GatewayAddress
= &Token
->Gateway
;
139 UdpTxData
->DataLength
= Packet
->TotalSize
;
140 Count
= Packet
->BlockOpNum
;
141 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) UdpTxData
->FragmentTable
, &Count
);
142 UdpTxData
->FragmentCount
= Count
;
149 Free a UDP_TX_TOKEN. The event is closed and memory released.
151 @param Token The UDP_TX_TOKEN to release.
158 IN UDP_TX_TOKEN
*Token
161 gBS
->CloseEvent (Token
->UdpToken
.Event
);
167 Create a UDP_RX_TOKEN to wrap the request.
169 @param UdpIo The UdpIo to receive packets from
170 @param CallBack The function to call when receive finished.
171 @param Context The opaque parameter to the CallBack
172 @param HeadLen The head length to reserver for the packet.
174 @return The Wrapped request or NULL if failed to allocate resources.
179 IN UDP_IO_PORT
*UdpIo
,
180 IN UDP_IO_CALLBACK CallBack
,
188 Token
= NetAllocatePool (sizeof (UDP_RX_TOKEN
));
194 Token
->Signature
= UDP_IO_RX_SIGNATURE
;
195 Token
->UdpIo
= UdpIo
;
196 Token
->CallBack
= CallBack
;
197 Token
->Context
= Context
;
198 Token
->HeadLen
= HeadLen
;
200 Token
->UdpToken
.Status
= EFI_NOT_READY
;
201 Token
->UdpToken
.Packet
.RxData
= NULL
;
203 Status
= gBS
->CreateEvent (
208 &Token
->UdpToken
.Event
211 if (EFI_ERROR (Status
)) {
221 Free a receive request wrap.
223 @param Token The receive request to release.
230 IN UDP_RX_TOKEN
*Token
233 gBS
->CloseEvent (Token
->UdpToken
.Event
);
239 Create a UDP IO port to access the UDP service. It will
240 create and configure a UDP child.
242 @param Controller The controller that has the UDP service binding
244 @param Image The image handle for the driver.
245 @param Configure The function to configure the created UDP child
246 @param Context The opaque parameter for the Configure funtion.
248 @return A point to just created UDP IO port or NULL if failed.
253 IN EFI_HANDLE Controller
,
255 IN UDP_IO_CONFIG Configure
,
262 ASSERT (Configure
!= NULL
);
264 UdpIo
= NetAllocatePool (sizeof (UDP_IO_PORT
));
270 UdpIo
->Signature
= UDP_IO_SIGNATURE
;
271 NetListInit (&UdpIo
->Link
);
274 UdpIo
->Controller
= Controller
;
275 UdpIo
->Image
= Image
;
277 NetListInit (&UdpIo
->SentDatagram
);
278 UdpIo
->RecvRequest
= NULL
;
279 UdpIo
->UdpHandle
= NULL
;
282 // Create a UDP child then open and configure it
284 Status
= NetLibCreateServiceChild (
287 &gEfiUdp4ServiceBindingProtocolGuid
,
291 if (EFI_ERROR (Status
)) {
295 Status
= gBS
->OpenProtocol (
297 &gEfiUdp4ProtocolGuid
,
298 (VOID
**) &UdpIo
->Udp
,
301 EFI_OPEN_PROTOCOL_BY_DRIVER
304 if (EFI_ERROR (Status
)) {
308 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
312 Status
= UdpIo
->Udp
->GetModeData (UdpIo
->Udp
, NULL
, NULL
, NULL
, &UdpIo
->SnpMode
);
314 if (EFI_ERROR (Status
)) {
321 gBS
->CloseProtocol (UdpIo
->UdpHandle
, &gEfiUdp4ProtocolGuid
, Image
, Controller
);
324 NetLibDestroyServiceChild (
327 &gEfiUdp4ServiceBindingProtocolGuid
,
338 Cancel all the sent datagram that pass the selection of ToCancel.
339 If ToCancel is NULL, all the datagrams are cancelled.
341 @param UdpIo The UDP IO port to cancel packet
342 @param IoStatus The IoStatus to return to the packet owners.
343 @param ToCancel The select funtion to test whether to cancel this
345 @param Context The opaque parameter to the ToCancel.
353 IN UDP_IO_PORT
*UdpIo
,
354 IN EFI_STATUS IoStatus
,
355 IN UDP_IO_TO_CANCEL ToCancel
, OPTIONAL
359 NET_LIST_ENTRY
*Entry
;
360 NET_LIST_ENTRY
*Next
;
363 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &UdpIo
->SentDatagram
) {
364 Token
= NET_LIST_USER_STRUCT (Entry
, UDP_TX_TOKEN
, Link
);
366 if ((ToCancel
== NULL
) || (ToCancel (Token
, Context
))) {
367 NetListRemoveEntry (Entry
);
368 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &Token
->UdpToken
);
369 Token
->CallBack (Token
->Packet
, NULL
, IoStatus
, Token
->Context
);
370 UdpIoFreeTxToken (Token
);
377 Free the UDP IO port and all its related resources including
378 all the transmitted packet.
380 @param UdpIo The UDP IO port to free.
382 @retval EFI_SUCCESS The UDP IO port is freed.
387 IN UDP_IO_PORT
*UdpIo
390 UDP_RX_TOKEN
*RxToken
;
393 // Cancel all the sent datagram and receive requests. The
394 // callbacks of transmit requests are executed to allow the
395 // caller to release the resource. The callback of receive
396 // request are NOT executed. This is because it is most
397 // likely that the current user of the UDP IO port is closing
400 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
402 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
403 UdpIo
->RecvRequest
= NULL
;
404 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &RxToken
->UdpToken
);
405 UdpIoFreeRxToken (RxToken
);
409 // Close then destory the UDP child
413 &gEfiUdp4ProtocolGuid
,
418 NetLibDestroyServiceChild (
421 &gEfiUdp4ServiceBindingProtocolGuid
,
425 if (!IsListEmpty(&UdpIo
->Link
)) {
426 NetListRemoveEntry (&UdpIo
->Link
);
435 Clean up the UDP IO port. It will release all the transmitted
436 datagrams and receive request. It will also configure NULL the
439 @param UdpIo UDP IO port to clean up.
446 IN UDP_IO_PORT
*UdpIo
449 UDP_RX_TOKEN
*RxToken
;
452 // Cancel all the sent datagram and receive requests.
454 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
456 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
457 UdpIo
->RecvRequest
= NULL
;
458 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &RxToken
->UdpToken
);
459 UdpIoFreeRxToken (RxToken
);
462 UdpIo
->Udp
->Configure (UdpIo
->Udp
, NULL
);
467 The callback function when the packet is sent by UDP.
468 It will remove the packet from the local list then call
469 the packet owner's callback function.
471 @param Event The event signalled.
472 @param Context The UDP TX Token.
487 Token
= (UDP_TX_TOKEN
*) Context
;
488 ASSERT (Token
->Signature
== UDP_IO_TX_SIGNATURE
);
490 NetListRemoveEntry (&Token
->Link
);
491 Token
->CallBack (Token
->Packet
, NULL
, Token
->UdpToken
.Status
, Token
->Context
);
493 UdpIoFreeTxToken (Token
);
498 Send a packet through the UDP IO port.
500 @param UdpIo The UDP IO Port to send the packet through
501 @param Packet The packet to send
502 @param EndPoint The local and remote access point
503 @param Gateway The gateway to use
504 @param CallBack The call back function to call when packet is
505 transmitted or failed.
506 @param Context The opque parameter to the CallBack
508 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet
509 @retval EFI_SUCCESS The packet is successfully delivered to UDP for
515 IN UDP_IO_PORT
*UdpIo
,
517 IN UDP_POINTS
*EndPoint
, OPTIONAL
519 IN UDP_IO_CALLBACK CallBack
,
526 Token
= UdpIoWrapTx (UdpIo
, Packet
, EndPoint
, Gateway
, CallBack
, Context
);
529 return EFI_OUT_OF_RESOURCES
;
532 Status
= UdpIo
->Udp
->Transmit (UdpIo
->Udp
, &Token
->UdpToken
);
534 if (EFI_ERROR (Status
)) {
535 UdpIoFreeTxToken (Token
);
539 NetListInsertHead (&UdpIo
->SentDatagram
, &Token
->Link
);
545 The selection function to cancel a single sent datagram.
547 @param Token The UDP TX token to test againist.
548 @param Context The context
550 @return TRUE if the packet is to be cancelled, otherwise FALSE.
555 UdpIoCancelSingleDgram (
556 IN UDP_TX_TOKEN
*Token
,
562 Packet
= (NET_BUF
*) Context
;
564 if (Token
->Packet
== Packet
) {
573 Cancel a single sent datagram.
575 @param UdpIo The UDP IO port to cancel the packet from
576 @param Packet The packet to cancel
582 UdpIoCancelSentDatagram (
583 IN UDP_IO_PORT
*UdpIo
,
587 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, UdpIoCancelSingleDgram
, Packet
);
592 Recycle the received UDP data.
594 @param Context The UDP_RX_TOKEN
607 Token
= (UDP_RX_TOKEN
*) Context
;
608 gBS
->SignalEvent (Token
->UdpToken
.Packet
.RxData
->RecycleSignal
);
609 UdpIoFreeRxToken (Token
);
614 The event handle for UDP receive request. It will build
615 a NET_BUF from the recieved UDP data, then deliver it
618 @param Event The UDP receive request event
619 @param Context The UDP RX token.
632 EFI_UDP4_COMPLETION_TOKEN
*UdpToken
;
633 EFI_UDP4_RECEIVE_DATA
*UdpRxData
;
634 EFI_UDP4_SESSION_DATA
*UdpSession
;
639 Token
= (UDP_RX_TOKEN
*) Context
;
641 ASSERT ((Token
->Signature
== UDP_IO_RX_SIGNATURE
) &&
642 (Token
== Token
->UdpIo
->RecvRequest
));
645 // Clear the receive request first in case that the caller
646 // wants to restart the receive in the callback.
648 Token
->UdpIo
->RecvRequest
= NULL
;
650 UdpToken
= &Token
->UdpToken
;
651 UdpRxData
= UdpToken
->Packet
.RxData
;
653 if (EFI_ERROR (UdpToken
->Status
) || (UdpRxData
== NULL
)) {
654 Token
->CallBack (NULL
, NULL
, UdpToken
->Status
, Token
->Context
);
655 UdpIoFreeRxToken (Token
);
661 // Build a NET_BUF from the UDP receive data, then deliver it up.
663 Netbuf
= NetbufFromExt (
664 (NET_FRAGMENT
*) UdpRxData
->FragmentTable
,
665 UdpRxData
->FragmentCount
,
667 (UINT32
) Token
->HeadLen
,
672 if (Netbuf
== NULL
) {
673 gBS
->SignalEvent (UdpRxData
->RecycleSignal
);
674 Token
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, Token
->Context
);
676 UdpIoFreeRxToken (Token
);
680 UdpSession
= &UdpRxData
->UdpSession
;
681 Points
.LocalPort
= UdpSession
->DestinationPort
;
682 Points
.RemotePort
= UdpSession
->SourcePort
;
684 NetCopyMem (&Points
.LocalAddr
, &UdpSession
->DestinationAddress
, sizeof (IP4_ADDR
));
685 NetCopyMem (&Points
.RemoteAddr
, &UdpSession
->SourceAddress
, sizeof (IP4_ADDR
));
686 Points
.LocalAddr
= NTOHL (Points
.LocalAddr
);
687 Points
.RemoteAddr
= NTOHL (Points
.RemoteAddr
);
689 Token
->CallBack (Netbuf
, &Points
, EFI_SUCCESS
, Token
->Context
);
697 Issue a receive request to the UDP IO port.
699 @param UdpIo The UDP IO port to recieve the packet from.
700 @param CallBack The call back function to execute when receive
702 @param Context The opque context to the call back
703 @param HeadLen The lenght of the application's header
705 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only
706 one receive request is supported.
707 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource.
708 @retval EFI_SUCCESS The receive request is issued successfully.
713 IN UDP_IO_PORT
*UdpIo
,
714 IN UDP_IO_CALLBACK CallBack
,
722 if (UdpIo
->RecvRequest
!= NULL
) {
723 return EFI_ALREADY_STARTED
;
726 Token
= UdpIoCreateRxToken (UdpIo
, CallBack
, Context
, HeadLen
);
729 return EFI_OUT_OF_RESOURCES
;
732 Status
= UdpIo
->Udp
->Receive (UdpIo
->Udp
, &Token
->UdpToken
);
734 if (EFI_ERROR (Status
)) {
735 UdpIoFreeRxToken (Token
);
739 UdpIo
->RecvRequest
= Token
;