2 Help functions to access UDP service, it is used by both the DHCP and MTFTP.
4 Copyright (c) 2005 - 2007, 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
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>
18 #include <Library/UdpIoLib.h>
19 #include <Library/BaseLib.h>
20 #include <Library/DebugLib.h>
21 #include <Library/UefiBootServicesTableLib.h>
22 #include <Library/MemoryAllocationLib.h>
23 #include <Library/BaseMemoryLib.h>
27 Free a UDP_TX_TOKEN. The event is closed and memory released.
29 @param Token The UDP_TX_TOKEN to release.
34 IN UDP_TX_TOKEN
*Token
37 gBS
->CloseEvent (Token
->UdpToken
.Event
);
38 gBS
->FreePool (Token
);
42 Free a receive request wrap.
44 @param Token The receive request to release.
49 IN UDP_RX_TOKEN
*Token
52 gBS
->CloseEvent (Token
->UdpToken
.Event
);
53 gBS
->FreePool (Token
);
57 The callback function when the packet is sent by UDP.
58 It will remove the packet from the local list then call
59 the packet owner's callback function.
61 @param Context The UDP TX Token.
72 Token
= (UDP_TX_TOKEN
*) Context
;
73 ASSERT (Token
->Signature
== UDP_IO_TX_SIGNATURE
);
75 RemoveEntryList (&Token
->Link
);
76 Token
->CallBack (Token
->Packet
, NULL
, Token
->UdpToken
.Status
, Token
->Context
);
78 UdpIoFreeTxToken (Token
);
82 Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.
84 @param Event The event signaled.
85 @param Context The UDP TX Token.
96 // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK
98 NetLibQueueDpc (TPL_CALLBACK
, UdpIoOnDgramSentDpc
, Context
);
102 Recycle the received UDP data.
104 @param Context The UDP_RX_TOKEN
114 Token
= (UDP_RX_TOKEN
*) Context
;
115 gBS
->SignalEvent (Token
->UdpToken
.Packet
.RxData
->RecycleSignal
);
116 UdpIoFreeRxToken (Token
);
120 The event handle for UDP receive request. It will build
121 a NET_BUF from the recieved UDP data, then deliver it
124 @param Context The UDP RX token.
129 UdpIoOnDgramRcvdDpc (
133 EFI_UDP4_COMPLETION_TOKEN
*UdpToken
;
134 EFI_UDP4_RECEIVE_DATA
*UdpRxData
;
135 EFI_UDP4_SESSION_DATA
*UdpSession
;
140 Token
= (UDP_RX_TOKEN
*) Context
;
142 ASSERT ((Token
->Signature
== UDP_IO_RX_SIGNATURE
) &&
143 (Token
== Token
->UdpIo
->RecvRequest
));
146 // Clear the receive request first in case that the caller
147 // wants to restart the receive in the callback.
149 Token
->UdpIo
->RecvRequest
= NULL
;
151 UdpToken
= &Token
->UdpToken
;
152 UdpRxData
= UdpToken
->Packet
.RxData
;
154 if (EFI_ERROR (UdpToken
->Status
) || (UdpRxData
== NULL
)) {
155 if (UdpToken
->Status
!= EFI_ABORTED
) {
157 // Invoke the CallBack only if the reception is not actively aborted.
159 Token
->CallBack (NULL
, NULL
, UdpToken
->Status
, Token
->Context
);
162 UdpIoFreeRxToken (Token
);
167 // Build a NET_BUF from the UDP receive data, then deliver it up.
169 Netbuf
= NetbufFromExt (
170 (NET_FRAGMENT
*) UdpRxData
->FragmentTable
,
171 UdpRxData
->FragmentCount
,
173 (UINT32
) Token
->HeadLen
,
178 if (Netbuf
== NULL
) {
179 gBS
->SignalEvent (UdpRxData
->RecycleSignal
);
180 Token
->CallBack (NULL
, NULL
, EFI_OUT_OF_RESOURCES
, Token
->Context
);
182 UdpIoFreeRxToken (Token
);
186 UdpSession
= &UdpRxData
->UdpSession
;
187 Points
.LocalPort
= UdpSession
->DestinationPort
;
188 Points
.RemotePort
= UdpSession
->SourcePort
;
190 CopyMem (&Points
.LocalAddr
, &UdpSession
->DestinationAddress
, sizeof (IP4_ADDR
));
191 CopyMem (&Points
.RemoteAddr
, &UdpSession
->SourceAddress
, sizeof (IP4_ADDR
));
192 Points
.LocalAddr
= NTOHL (Points
.LocalAddr
);
193 Points
.RemoteAddr
= NTOHL (Points
.RemoteAddr
);
195 Token
->CallBack (Netbuf
, &Points
, EFI_SUCCESS
, Token
->Context
);
199 Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK.
201 @param Event The UDP receive request event.
202 @param Context The UDP RX token.
213 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK
215 NetLibQueueDpc (TPL_CALLBACK
, UdpIoOnDgramRcvdDpc
, Context
);
219 Create a UDP_RX_TOKEN to wrap the request.
221 @param UdpIo The UdpIo to receive packets from
222 @param CallBack The function to call when receive finished.
223 @param Context The opaque parameter to the CallBack
224 @param HeadLen The head length to reserver for the packet.
226 @return The Wrapped request or NULL if failed to allocate resources or some errors happened.
231 IN UDP_IO_PORT
*UdpIo
,
232 IN UDP_IO_CALLBACK CallBack
,
240 Token
= AllocatePool (sizeof (UDP_RX_TOKEN
));
246 Token
->Signature
= UDP_IO_RX_SIGNATURE
;
247 Token
->UdpIo
= UdpIo
;
248 Token
->CallBack
= CallBack
;
249 Token
->Context
= Context
;
250 Token
->HeadLen
= HeadLen
;
252 Token
->UdpToken
.Status
= EFI_NOT_READY
;
253 Token
->UdpToken
.Packet
.RxData
= NULL
;
255 Status
= gBS
->CreateEvent (
260 &Token
->UdpToken
.Event
263 if (EFI_ERROR (Status
)) {
264 gBS
->FreePool (Token
);
272 Wrap a transmit request into a UDP_TX_TOKEN.
274 @param UdpIo The UdpIo port to send packet to
275 @param Packet The user's packet
276 @param EndPoint The local and remote access point
277 @param Gateway The overrided next hop
278 @param CallBack The function to call when transmission completed.
279 @param Context The opaque parameter to the call back
281 @return The wrapped transmission request or NULL if failed to allocate resources
287 IN UDP_IO_PORT
*UdpIo
,
289 IN UDP_POINTS
*EndPoint
, OPTIONAL
291 IN UDP_IO_CALLBACK CallBack
,
296 EFI_UDP4_COMPLETION_TOKEN
*UdpToken
;
297 EFI_UDP4_TRANSMIT_DATA
*UdpTxData
;
302 Token
= AllocatePool (sizeof (UDP_TX_TOKEN
) +
303 sizeof (EFI_UDP4_FRAGMENT_DATA
) * (Packet
->BlockOpNum
- 1));
309 Token
->Signature
= UDP_IO_TX_SIGNATURE
;
310 InitializeListHead (&Token
->Link
);
312 Token
->UdpIo
= UdpIo
;
313 Token
->CallBack
= CallBack
;
314 Token
->Packet
= Packet
;
315 Token
->Context
= Context
;
317 UdpToken
= &(Token
->UdpToken
);
318 UdpToken
->Status
= EFI_NOT_READY
;
320 Status
= gBS
->CreateEvent (
328 if (EFI_ERROR (Status
)) {
329 gBS
->FreePool (Token
);
333 UdpTxData
= &Token
->UdpTxData
;
334 UdpToken
->Packet
.TxData
= UdpTxData
;
336 UdpTxData
->UdpSessionData
= NULL
;
337 UdpTxData
->GatewayAddress
= NULL
;
339 if (EndPoint
!= NULL
) {
340 Ip
= HTONL (EndPoint
->LocalAddr
);
341 CopyMem (&Token
->UdpSession
.SourceAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
343 Ip
= HTONL (EndPoint
->RemoteAddr
);
344 CopyMem (&Token
->UdpSession
.DestinationAddress
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
346 Token
->UdpSession
.SourcePort
= EndPoint
->LocalPort
;
347 Token
->UdpSession
.DestinationPort
= EndPoint
->RemotePort
;
348 UdpTxData
->UdpSessionData
= &Token
->UdpSession
;
352 Ip
= HTONL (Gateway
);
353 CopyMem (&Token
->Gateway
, &Ip
, sizeof (EFI_IPv4_ADDRESS
));
355 UdpTxData
->GatewayAddress
= &Token
->Gateway
;
358 UdpTxData
->DataLength
= Packet
->TotalSize
;
359 Count
= Packet
->BlockOpNum
;
360 NetbufBuildExt (Packet
, (NET_FRAGMENT
*) UdpTxData
->FragmentTable
, &Count
);
361 UdpTxData
->FragmentCount
= Count
;
370 Create a UDP IO port to access the UDP service. It will
371 create and configure a UDP child.
373 @param Controller The controller that has the UDP service binding
375 @param Image The image handle for the driver.
376 @param Configure The function to configure the created UDP child
377 @param Context The opaque parameter for the Configure funtion.
379 @return A point to just created UDP IO port or NULL if some error happened.
385 IN EFI_HANDLE Controller
,
387 IN UDP_IO_CONFIG Configure
,
394 ASSERT (Configure
!= NULL
);
396 UdpIo
= AllocatePool (sizeof (UDP_IO_PORT
));
402 UdpIo
->Signature
= UDP_IO_SIGNATURE
;
403 InitializeListHead (&UdpIo
->Link
);
406 UdpIo
->Controller
= Controller
;
407 UdpIo
->Image
= Image
;
409 InitializeListHead (&UdpIo
->SentDatagram
);
410 UdpIo
->RecvRequest
= NULL
;
411 UdpIo
->UdpHandle
= NULL
;
414 // Create a UDP child then open and configure it
416 Status
= NetLibCreateServiceChild (
419 &gEfiUdp4ServiceBindingProtocolGuid
,
423 if (EFI_ERROR (Status
)) {
427 Status
= gBS
->OpenProtocol (
429 &gEfiUdp4ProtocolGuid
,
430 (VOID
**) &UdpIo
->Udp
,
433 EFI_OPEN_PROTOCOL_BY_DRIVER
436 if (EFI_ERROR (Status
)) {
440 if (EFI_ERROR (Configure (UdpIo
, Context
))) {
444 Status
= UdpIo
->Udp
->GetModeData (UdpIo
->Udp
, NULL
, NULL
, NULL
, &UdpIo
->SnpMode
);
446 if (EFI_ERROR (Status
)) {
453 gBS
->CloseProtocol (UdpIo
->UdpHandle
, &gEfiUdp4ProtocolGuid
, Image
, Controller
);
456 NetLibDestroyServiceChild (
459 &gEfiUdp4ServiceBindingProtocolGuid
,
464 gBS
->FreePool (UdpIo
);
470 Cancel all the sent datagram that pass the selection of ToCancel.
471 If ToCancel is NULL, all the datagrams are cancelled.
473 @param UdpIo The UDP IO port to cancel packet
474 @param IoStatus The IoStatus to return to the packet owners.
475 @param ToCancel The select funtion to test whether to cancel this
477 @param Context The opaque parameter to the ToCancel.
482 IN UDP_IO_PORT
*UdpIo
,
483 IN EFI_STATUS IoStatus
,
484 IN UDP_IO_TO_CANCEL ToCancel
, OPTIONAL
492 NET_LIST_FOR_EACH_SAFE (Entry
, Next
, &UdpIo
->SentDatagram
) {
493 Token
= NET_LIST_USER_STRUCT (Entry
, UDP_TX_TOKEN
, Link
);
495 if ((ToCancel
== NULL
) || (ToCancel (Token
, Context
))) {
496 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &Token
->UdpToken
);
503 Free the UDP IO port and all its related resources including
504 all the transmitted packet.
506 @param UdpIo The UDP IO port to free.
508 @retval EFI_SUCCESS The UDP IO port is freed.
514 IN UDP_IO_PORT
*UdpIo
517 UDP_RX_TOKEN
*RxToken
;
520 // Cancel all the sent datagram and receive requests. The
521 // callbacks of transmit requests are executed to allow the
522 // caller to release the resource. The callback of receive
523 // request are NOT executed. This is because it is most
524 // likely that the current user of the UDP IO port is closing
527 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
529 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
530 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &RxToken
->UdpToken
);
534 // Close then destory the UDP child
538 &gEfiUdp4ProtocolGuid
,
543 NetLibDestroyServiceChild (
546 &gEfiUdp4ServiceBindingProtocolGuid
,
550 if (!IsListEmpty(&UdpIo
->Link
)) {
551 RemoveEntryList (&UdpIo
->Link
);
554 gBS
->FreePool (UdpIo
);
560 Clean up the UDP IO port. It will release all the transmitted
561 datagrams and receive request. It will also configure NULL the
564 @param UdpIo UDP IO port to clean up.
570 IN UDP_IO_PORT
*UdpIo
573 UDP_RX_TOKEN
*RxToken
;
576 // Cancel all the sent datagram and receive requests.
578 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, NULL
, NULL
);
580 if ((RxToken
= UdpIo
->RecvRequest
) != NULL
) {
581 UdpIo
->Udp
->Cancel (UdpIo
->Udp
, &RxToken
->UdpToken
);
584 UdpIo
->Udp
->Configure (UdpIo
->Udp
, NULL
);
588 Send a packet through the UDP IO port.
590 @param UdpIo The UDP IO Port to send the packet through
591 @param Packet The packet to send
592 @param EndPoint The local and remote access point
593 @param Gateway The gateway to use
594 @param CallBack The call back function to call when packet is
595 transmitted or failed.
596 @param Context The opque parameter to the CallBack
598 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet
599 @retval EFI_SUCCESS The packet is successfully delivered to UDP for
606 IN UDP_IO_PORT
*UdpIo
,
608 IN UDP_POINTS
*EndPoint
, OPTIONAL
610 IN UDP_IO_CALLBACK CallBack
,
617 Token
= UdpIoWrapTx (UdpIo
, Packet
, EndPoint
, Gateway
, CallBack
, Context
);
620 return EFI_OUT_OF_RESOURCES
;
624 // Insert the tx token into SendDatagram list before transmitting it. Remove
625 // it from the list if the returned status is not EFI_SUCCESS.
627 InsertHeadList (&UdpIo
->SentDatagram
, &Token
->Link
);
628 Status
= UdpIo
->Udp
->Transmit (UdpIo
->Udp
, &Token
->UdpToken
);
629 if (EFI_ERROR (Status
)) {
630 RemoveEntryList (&Token
->Link
);
631 UdpIoFreeTxToken (Token
);
640 The selection function to cancel a single sent datagram.
642 @param Token The UDP TX token to test againist.
643 @param Context The context
645 @retval TRUE The packet is to be cancelled.
646 @retval FALSE The packet is not to be cancelled.
649 UdpIoCancelSingleDgram (
650 IN UDP_TX_TOKEN
*Token
,
656 Packet
= (NET_BUF
*) Context
;
658 if (Token
->Packet
== Packet
) {
667 Cancel a single sent datagram.
669 @param UdpIo The UDP IO port to cancel the packet from
670 @param Packet The packet to cancel
675 UdpIoCancelSentDatagram (
676 IN UDP_IO_PORT
*UdpIo
,
680 UdpIoCancelDgrams (UdpIo
, EFI_ABORTED
, UdpIoCancelSingleDgram
, Packet
);
684 Issue a receive request to the UDP IO port.
686 @param UdpIo The UDP IO port to recieve the packet from.
687 @param CallBack The call back function to execute when receive
689 @param Context The opque context to the call back
690 @param HeadLen The lenght of the application's header
692 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only
693 one receive request is supported.
694 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource.
695 @retval EFI_SUCCESS The receive request is issued successfully.
701 IN UDP_IO_PORT
*UdpIo
,
702 IN UDP_IO_CALLBACK CallBack
,
710 if (UdpIo
->RecvRequest
!= NULL
) {
711 return EFI_ALREADY_STARTED
;
714 Token
= UdpIoCreateRxToken (UdpIo
, CallBack
, Context
, HeadLen
);
717 return EFI_OUT_OF_RESOURCES
;
720 UdpIo
->RecvRequest
= Token
;
721 Status
= UdpIo
->Udp
->Receive (UdpIo
->Udp
, &Token
->UdpToken
);
723 if (EFI_ERROR (Status
)) {
724 UdpIo
->RecvRequest
= NULL
;
725 UdpIoFreeRxToken (Token
);