]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.c
1. add public functions header.
[mirror_edk2.git] / MdeModulePkg / Library / DxeUdpIoLib / DxeUdpIoLib.c
CommitLineData
cbf316f2 1/** @file\r
2\r
3Copyright (c) 2006 - 2007, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12\r
13Module Name:\r
14\r
15 Udp4Io.c\r
16\r
17Abstract:\r
18\r
19 Help functions to access UDP service, it is used by both the DHCP and MTFTP.\r
20\r
21\r
22**/\r
23\r
24#include <PiDxe.h>\r
25\r
26#include <Protocol/Udp4.h>\r
27\r
28#include <Library/UdpIoLib.h>\r
29#include <Library/BaseLib.h>\r
30#include <Library/DebugLib.h>\r
31#include <Library/UefiBootServicesTableLib.h>\r
32#include <Library/MemoryAllocationLib.h>\r
ba0f75a3 33#include <Library/BaseMemoryLib.h>\r
cbf316f2 34\r
36ee91ca 35STATIC\r
36VOID\r
37EFIAPI\r
38UdpIoOnDgramSentDpc (\r
39 IN VOID *Context\r
40 );\r
41\r
cbf316f2 42STATIC\r
43VOID\r
44EFIAPI\r
45UdpIoOnDgramSent (\r
46 IN EFI_EVENT Event,\r
47 IN VOID *Context\r
48 );\r
49\r
50STATIC\r
51VOID\r
52EFIAPI\r
53UdpIoOnDgramRcvd (\r
54 IN EFI_EVENT Event,\r
55 IN VOID *Context\r
56 );\r
57\r
58\r
59/**\r
60 Wrap a transmit request into a UDP_TX_TOKEN.\r
61\r
62 @param UdpIo The UdpIo port to send packet to\r
63 @param Packet The user's packet\r
64 @param EndPoint The local and remote access point\r
65 @param Gateway The overrided next hop\r
66 @param CallBack The function to call when transmission completed.\r
67 @param Context The opaque parameter to the call back\r
68\r
69 @return The wrapped transmission request or NULL if failed to allocate resources.\r
70\r
71**/\r
72STATIC\r
73UDP_TX_TOKEN *\r
74UdpIoWrapTx (\r
75 IN UDP_IO_PORT *UdpIo,\r
76 IN NET_BUF *Packet,\r
77 IN UDP_POINTS *EndPoint, OPTIONAL\r
78 IN IP4_ADDR Gateway,\r
79 IN UDP_IO_CALLBACK CallBack,\r
80 IN VOID *Context\r
81 )\r
82{\r
83 UDP_TX_TOKEN *Token;\r
84 EFI_UDP4_COMPLETION_TOKEN *UdpToken;\r
85 EFI_UDP4_TRANSMIT_DATA *UdpTxData;\r
86 EFI_STATUS Status;\r
87 UINT32 Count;\r
b61439a7 88 IP4_ADDR Ip;\r
cbf316f2 89\r
e48e37fc 90 Token = AllocatePool (sizeof (UDP_TX_TOKEN) +\r
cbf316f2 91 sizeof (EFI_UDP4_FRAGMENT_DATA) * (Packet->BlockOpNum - 1));\r
92\r
93 if (Token == NULL) {\r
94 return NULL;\r
95 }\r
96\r
97 Token->Signature = UDP_IO_TX_SIGNATURE;\r
e48e37fc 98 InitializeListHead (&Token->Link);\r
cbf316f2 99\r
100 Token->UdpIo = UdpIo;\r
101 Token->CallBack = CallBack;\r
102 Token->Packet = Packet;\r
103 Token->Context = Context;\r
104\r
105 UdpToken = &(Token->UdpToken);\r
106 UdpToken->Status = EFI_NOT_READY;\r
107\r
108 Status = gBS->CreateEvent (\r
109 EVT_NOTIFY_SIGNAL,\r
e48e37fc 110 TPL_NOTIFY,\r
cbf316f2 111 UdpIoOnDgramSent,\r
112 Token,\r
113 &UdpToken->Event\r
114 );\r
115\r
116 if (EFI_ERROR (Status)) {\r
e48e37fc 117 gBS->FreePool (Token);\r
cbf316f2 118 return NULL;\r
119 }\r
120\r
121 UdpTxData = &Token->UdpTxData;\r
122 UdpToken->Packet.TxData = UdpTxData;\r
123\r
124 UdpTxData->UdpSessionData = NULL;\r
125 UdpTxData->GatewayAddress = NULL;\r
126\r
127 if (EndPoint != NULL) {\r
b61439a7 128 Ip = HTONL (EndPoint->LocalAddr);\r
e48e37fc 129 CopyMem (&Token->UdpSession.SourceAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
b61439a7 130\r
131 Ip = HTONL (EndPoint->RemoteAddr);\r
e48e37fc 132 CopyMem (&Token->UdpSession.DestinationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
b61439a7 133\r
134 Token->UdpSession.SourcePort = EndPoint->LocalPort;\r
135 Token->UdpSession.DestinationPort = EndPoint->RemotePort;\r
136 UdpTxData->UdpSessionData = &Token->UdpSession;\r
cbf316f2 137 }\r
138\r
139 if (Gateway != 0) {\r
b61439a7 140 Ip = HTONL (Gateway);\r
e48e37fc 141 CopyMem (&Token->Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
b61439a7 142\r
cbf316f2 143 UdpTxData->GatewayAddress = &Token->Gateway;\r
144 }\r
145\r
146 UdpTxData->DataLength = Packet->TotalSize;\r
147 Count = Packet->BlockOpNum;\r
148 NetbufBuildExt (Packet, (NET_FRAGMENT *) UdpTxData->FragmentTable, &Count);\r
149 UdpTxData->FragmentCount = Count;\r
150\r
151 return Token;\r
152}\r
153\r
154\r
155/**\r
156 Free a UDP_TX_TOKEN. The event is closed and memory released.\r
157\r
158 @param Token The UDP_TX_TOKEN to release.\r
159\r
160 @return None\r
161\r
162**/\r
163VOID\r
164UdpIoFreeTxToken (\r
165 IN UDP_TX_TOKEN *Token\r
166 )\r
167{\r
168 gBS->CloseEvent (Token->UdpToken.Event);\r
e48e37fc 169 gBS->FreePool (Token);\r
cbf316f2 170}\r
171\r
172\r
173/**\r
174 Create a UDP_RX_TOKEN to wrap the request.\r
175\r
176 @param UdpIo The UdpIo to receive packets from\r
177 @param CallBack The function to call when receive finished.\r
178 @param Context The opaque parameter to the CallBack\r
179 @param HeadLen The head length to reserver for the packet.\r
180\r
181 @return The Wrapped request or NULL if failed to allocate resources.\r
182\r
183**/\r
184UDP_RX_TOKEN *\r
185UdpIoCreateRxToken (\r
186 IN UDP_IO_PORT *UdpIo,\r
187 IN UDP_IO_CALLBACK CallBack,\r
188 IN VOID *Context,\r
189 IN UINT32 HeadLen\r
190 )\r
191{\r
192 UDP_RX_TOKEN *Token;\r
193 EFI_STATUS Status;\r
194\r
e48e37fc 195 Token = AllocatePool (sizeof (UDP_RX_TOKEN));\r
cbf316f2 196\r
197 if (Token == NULL) {\r
198 return NULL;\r
199 }\r
200\r
201 Token->Signature = UDP_IO_RX_SIGNATURE;\r
202 Token->UdpIo = UdpIo;\r
203 Token->CallBack = CallBack;\r
204 Token->Context = Context;\r
205 Token->HeadLen = HeadLen;\r
206\r
207 Token->UdpToken.Status = EFI_NOT_READY;\r
208 Token->UdpToken.Packet.RxData = NULL;\r
209\r
210 Status = gBS->CreateEvent (\r
211 EVT_NOTIFY_SIGNAL,\r
e48e37fc 212 TPL_NOTIFY,\r
cbf316f2 213 UdpIoOnDgramRcvd,\r
214 Token,\r
215 &Token->UdpToken.Event\r
216 );\r
217\r
218 if (EFI_ERROR (Status)) {\r
e48e37fc 219 gBS->FreePool (Token);\r
cbf316f2 220 return NULL;\r
221 }\r
222\r
223 return Token;\r
224}\r
225\r
226\r
227/**\r
228 Free a receive request wrap.\r
229\r
230 @param Token The receive request to release.\r
231\r
232 @return None\r
233\r
234**/\r
235VOID\r
236UdpIoFreeRxToken (\r
237 IN UDP_RX_TOKEN *Token\r
238 )\r
239{\r
240 gBS->CloseEvent (Token->UdpToken.Event);\r
e48e37fc 241 gBS->FreePool (Token);\r
cbf316f2 242}\r
243\r
244\r
245/**\r
246 Create a UDP IO port to access the UDP service. It will\r
247 create and configure a UDP child.\r
248\r
249 @param Controller The controller that has the UDP service binding\r
250 protocol installed.\r
251 @param Image The image handle for the driver.\r
252 @param Configure The function to configure the created UDP child\r
253 @param Context The opaque parameter for the Configure funtion.\r
254\r
255 @return A point to just created UDP IO port or NULL if failed.\r
256\r
257**/\r
258UDP_IO_PORT *\r
7b414b4e 259EFIAPI\r
cbf316f2 260UdpIoCreatePort (\r
261 IN EFI_HANDLE Controller,\r
262 IN EFI_HANDLE Image,\r
263 IN UDP_IO_CONFIG Configure,\r
264 IN VOID *Context\r
265 )\r
266{\r
267 UDP_IO_PORT *UdpIo;\r
268 EFI_STATUS Status;\r
269\r
270 ASSERT (Configure != NULL);\r
271\r
e48e37fc 272 UdpIo = AllocatePool (sizeof (UDP_IO_PORT));\r
cbf316f2 273\r
274 if (UdpIo == NULL) {\r
275 return NULL;\r
276 }\r
277\r
278 UdpIo->Signature = UDP_IO_SIGNATURE;\r
e48e37fc 279 InitializeListHead (&UdpIo->Link);\r
cbf316f2 280 UdpIo->RefCnt = 1;\r
281\r
282 UdpIo->Controller = Controller;\r
283 UdpIo->Image = Image;\r
284\r
e48e37fc 285 InitializeListHead (&UdpIo->SentDatagram);\r
cbf316f2 286 UdpIo->RecvRequest = NULL;\r
287 UdpIo->UdpHandle = NULL;\r
288\r
289 //\r
290 // Create a UDP child then open and configure it\r
291 //\r
292 Status = NetLibCreateServiceChild (\r
293 Controller,\r
294 Image,\r
295 &gEfiUdp4ServiceBindingProtocolGuid,\r
296 &UdpIo->UdpHandle\r
297 );\r
298\r
299 if (EFI_ERROR (Status)) {\r
300 goto FREE_MEM;\r
301 }\r
302\r
303 Status = gBS->OpenProtocol (\r
304 UdpIo->UdpHandle,\r
305 &gEfiUdp4ProtocolGuid,\r
4eb65aff 306 (VOID **) &UdpIo->Udp,\r
cbf316f2 307 Image,\r
308 Controller,\r
309 EFI_OPEN_PROTOCOL_BY_DRIVER\r
310 );\r
311\r
312 if (EFI_ERROR (Status)) {\r
313 goto FREE_CHILD;\r
314 }\r
315\r
316 if (EFI_ERROR (Configure (UdpIo, Context))) {\r
317 goto CLOSE_PROTOCOL;\r
318 }\r
319\r
320 Status = UdpIo->Udp->GetModeData (UdpIo->Udp, NULL, NULL, NULL, &UdpIo->SnpMode);\r
321\r
322 if (EFI_ERROR (Status)) {\r
323 goto CLOSE_PROTOCOL;\r
324 }\r
325\r
326 return UdpIo;\r
327\r
328CLOSE_PROTOCOL:\r
329 gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp4ProtocolGuid, Image, Controller);\r
330\r
331FREE_CHILD:\r
332 NetLibDestroyServiceChild (\r
333 Controller,\r
334 Image,\r
335 &gEfiUdp4ServiceBindingProtocolGuid,\r
336 UdpIo->UdpHandle\r
337 );\r
338\r
339FREE_MEM:\r
e48e37fc 340 gBS->FreePool (UdpIo);\r
cbf316f2 341 return NULL;\r
342}\r
343\r
344\r
345/**\r
346 Cancel all the sent datagram that pass the selection of ToCancel.\r
347 If ToCancel is NULL, all the datagrams are cancelled.\r
348\r
349 @param UdpIo The UDP IO port to cancel packet\r
350 @param IoStatus The IoStatus to return to the packet owners.\r
351 @param ToCancel The select funtion to test whether to cancel this\r
352 packet or not.\r
353 @param Context The opaque parameter to the ToCancel.\r
354\r
355 @return None\r
356\r
357**/\r
358STATIC\r
359VOID\r
360UdpIoCancelDgrams (\r
361 IN UDP_IO_PORT *UdpIo,\r
362 IN EFI_STATUS IoStatus,\r
363 IN UDP_IO_TO_CANCEL ToCancel, OPTIONAL\r
364 IN VOID *Context\r
365 )\r
366{\r
e48e37fc 367 LIST_ENTRY *Entry;\r
368 LIST_ENTRY *Next;\r
cbf316f2 369 UDP_TX_TOKEN *Token;\r
370\r
371 NET_LIST_FOR_EACH_SAFE (Entry, Next, &UdpIo->SentDatagram) {\r
372 Token = NET_LIST_USER_STRUCT (Entry, UDP_TX_TOKEN, Link);\r
373\r
374 if ((ToCancel == NULL) || (ToCancel (Token, Context))) {\r
cbf316f2 375 UdpIo->Udp->Cancel (UdpIo->Udp, &Token->UdpToken);\r
cbf316f2 376 }\r
377 }\r
378}\r
379\r
380\r
381/**\r
382 Free the UDP IO port and all its related resources including\r
383 all the transmitted packet.\r
384\r
385 @param UdpIo The UDP IO port to free.\r
386\r
387 @retval EFI_SUCCESS The UDP IO port is freed.\r
388\r
389**/\r
390EFI_STATUS\r
7b414b4e 391EFIAPI\r
cbf316f2 392UdpIoFreePort (\r
393 IN UDP_IO_PORT *UdpIo\r
394 )\r
395{\r
396 UDP_RX_TOKEN *RxToken;\r
397\r
398 //\r
399 // Cancel all the sent datagram and receive requests. The\r
400 // callbacks of transmit requests are executed to allow the\r
401 // caller to release the resource. The callback of receive\r
402 // request are NOT executed. This is because it is most\r
403 // likely that the current user of the UDP IO port is closing\r
404 // itself.\r
405 //\r
406 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
407\r
408 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
cbf316f2 409 UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);\r
cbf316f2 410 }\r
411\r
412 //\r
413 // Close then destory the UDP child\r
414 //\r
415 gBS->CloseProtocol (\r
416 UdpIo->UdpHandle,\r
417 &gEfiUdp4ProtocolGuid,\r
418 UdpIo->Image,\r
419 UdpIo->Controller\r
420 );\r
421\r
422 NetLibDestroyServiceChild (\r
423 UdpIo->Controller,\r
424 UdpIo->Image,\r
425 &gEfiUdp4ServiceBindingProtocolGuid,\r
426 UdpIo->UdpHandle\r
427 );\r
428\r
687a2e5f 429 if (!IsListEmpty(&UdpIo->Link)) {\r
e48e37fc 430 RemoveEntryList (&UdpIo->Link);\r
687a2e5f 431 }\r
432\r
e48e37fc 433 gBS->FreePool (UdpIo);\r
cbf316f2 434 return EFI_SUCCESS;\r
435}\r
436\r
437\r
438/**\r
439 Clean up the UDP IO port. It will release all the transmitted\r
440 datagrams and receive request. It will also configure NULL the\r
441 UDP child.\r
442\r
443 @param UdpIo UDP IO port to clean up.\r
444\r
445 @return None\r
446\r
447**/\r
448VOID\r
7b414b4e 449EFIAPI\r
cbf316f2 450UdpIoCleanPort (\r
451 IN UDP_IO_PORT *UdpIo\r
452 )\r
453{\r
454 UDP_RX_TOKEN *RxToken;\r
455\r
456 //\r
457 // Cancel all the sent datagram and receive requests.\r
458 //\r
459 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
460\r
461 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
cbf316f2 462 UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);\r
cbf316f2 463 }\r
464\r
465 UdpIo->Udp->Configure (UdpIo->Udp, NULL);\r
466}\r
467\r
468\r
469/**\r
470 The callback function when the packet is sent by UDP.\r
471 It will remove the packet from the local list then call\r
472 the packet owner's callback function.\r
473\r
cbf316f2 474 @param Context The UDP TX Token.\r
475\r
476 @return None\r
477\r
478**/\r
479STATIC\r
480VOID\r
481EFIAPI\r
36ee91ca 482UdpIoOnDgramSentDpc (\r
cbf316f2 483 IN VOID *Context\r
484 )\r
485{\r
486 UDP_TX_TOKEN *Token;\r
487\r
488 Token = (UDP_TX_TOKEN *) Context;\r
489 ASSERT (Token->Signature == UDP_IO_TX_SIGNATURE);\r
490\r
e48e37fc 491 RemoveEntryList (&Token->Link);\r
cbf316f2 492 Token->CallBack (Token->Packet, NULL, Token->UdpToken.Status, Token->Context);\r
493\r
494 UdpIoFreeTxToken (Token);\r
495}\r
496\r
36ee91ca 497/**\r
498 Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.\r
499\r
500 @param Event The event signalled.\r
501 @param Context The UDP TX Token.\r
502\r
503 @return None\r
504\r
505**/\r
506STATIC\r
507VOID\r
508EFIAPI\r
509UdpIoOnDgramSent (\r
510 IN EFI_EVENT Event,\r
511 IN VOID *Context\r
512 )\r
513{\r
514 //\r
515 // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK\r
516 //\r
517 NetLibQueueDpc (TPL_CALLBACK, UdpIoOnDgramSentDpc, Context);\r
518}\r
519\r
cbf316f2 520\r
521/**\r
522 Send a packet through the UDP IO port.\r
523\r
524 @param UdpIo The UDP IO Port to send the packet through\r
525 @param Packet The packet to send\r
526 @param EndPoint The local and remote access point\r
527 @param Gateway The gateway to use\r
528 @param CallBack The call back function to call when packet is\r
529 transmitted or failed.\r
530 @param Context The opque parameter to the CallBack\r
531\r
532 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet\r
533 @retval EFI_SUCCESS The packet is successfully delivered to UDP for\r
534 transmission.\r
535\r
536**/\r
537EFI_STATUS\r
7b414b4e 538EFIAPI\r
cbf316f2 539UdpIoSendDatagram (\r
540 IN UDP_IO_PORT *UdpIo,\r
541 IN NET_BUF *Packet,\r
542 IN UDP_POINTS *EndPoint, OPTIONAL\r
543 IN IP4_ADDR Gateway,\r
544 IN UDP_IO_CALLBACK CallBack,\r
545 IN VOID *Context\r
546 )\r
547{\r
548 UDP_TX_TOKEN *Token;\r
549 EFI_STATUS Status;\r
550\r
551 Token = UdpIoWrapTx (UdpIo, Packet, EndPoint, Gateway, CallBack, Context);\r
552\r
553 if (Token == NULL) {\r
554 return EFI_OUT_OF_RESOURCES;\r
555 }\r
556\r
36ee91ca 557 //\r
558 // Insert the tx token into SendDatagram list before transmitting it. Remove\r
559 // it from the list if the returned status is not EFI_SUCCESS.\r
560 //\r
e48e37fc 561 InsertHeadList (&UdpIo->SentDatagram, &Token->Link);\r
cbf316f2 562 Status = UdpIo->Udp->Transmit (UdpIo->Udp, &Token->UdpToken);\r
cbf316f2 563 if (EFI_ERROR (Status)) {\r
e48e37fc 564 RemoveEntryList (&Token->Link);\r
cbf316f2 565 UdpIoFreeTxToken (Token);\r
566 return Status;\r
567 }\r
568\r
cbf316f2 569 return EFI_SUCCESS;\r
570}\r
571\r
572\r
573/**\r
574 The selection function to cancel a single sent datagram.\r
575\r
576 @param Token The UDP TX token to test againist.\r
577 @param Context The context\r
578\r
579 @return TRUE if the packet is to be cancelled, otherwise FALSE.\r
580\r
581**/\r
582STATIC\r
583BOOLEAN\r
584UdpIoCancelSingleDgram (\r
585 IN UDP_TX_TOKEN *Token,\r
586 IN VOID *Context\r
587 )\r
588{\r
589 NET_BUF *Packet;\r
590\r
591 Packet = (NET_BUF *) Context;\r
592\r
593 if (Token->Packet == Packet) {\r
594 return TRUE;\r
595 }\r
596\r
597 return FALSE;\r
598}\r
599\r
600\r
601/**\r
602 Cancel a single sent datagram.\r
603\r
604 @param UdpIo The UDP IO port to cancel the packet from\r
605 @param Packet The packet to cancel\r
606\r
607 @return None\r
608\r
609**/\r
610VOID\r
7b414b4e 611EFIAPI\r
cbf316f2 612UdpIoCancelSentDatagram (\r
613 IN UDP_IO_PORT *UdpIo,\r
614 IN NET_BUF *Packet\r
615 )\r
616{\r
617 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, UdpIoCancelSingleDgram, Packet);\r
618}\r
619\r
620\r
621/**\r
622 Recycle the received UDP data.\r
623\r
624 @param Context The UDP_RX_TOKEN\r
625\r
626 @return None\r
627\r
628**/\r
629STATIC\r
630VOID\r
631UdpIoRecycleDgram (\r
632 IN VOID *Context\r
633 )\r
634{\r
635 UDP_RX_TOKEN *Token;\r
636\r
637 Token = (UDP_RX_TOKEN *) Context;\r
638 gBS->SignalEvent (Token->UdpToken.Packet.RxData->RecycleSignal);\r
639 UdpIoFreeRxToken (Token);\r
640}\r
641\r
cbf316f2 642/**\r
643 The event handle for UDP receive request. It will build\r
644 a NET_BUF from the recieved UDP data, then deliver it\r
645 to the receiver.\r
646\r
cbf316f2 647 @param Context The UDP RX token.\r
648\r
649 @return None\r
650\r
651**/\r
652STATIC\r
653VOID\r
654EFIAPI\r
36ee91ca 655UdpIoOnDgramRcvdDpc (\r
cbf316f2 656 IN VOID *Context\r
657 )\r
658{\r
659 EFI_UDP4_COMPLETION_TOKEN *UdpToken;\r
660 EFI_UDP4_RECEIVE_DATA *UdpRxData;\r
661 EFI_UDP4_SESSION_DATA *UdpSession;\r
662 UDP_RX_TOKEN *Token;\r
663 UDP_POINTS Points;\r
664 NET_BUF *Netbuf;\r
665\r
666 Token = (UDP_RX_TOKEN *) Context;\r
667\r
668 ASSERT ((Token->Signature == UDP_IO_RX_SIGNATURE) &&\r
669 (Token == Token->UdpIo->RecvRequest));\r
670\r
671 //\r
672 // Clear the receive request first in case that the caller\r
673 // wants to restart the receive in the callback.\r
674 //\r
675 Token->UdpIo->RecvRequest = NULL;\r
676\r
677 UdpToken = &Token->UdpToken;\r
678 UdpRxData = UdpToken->Packet.RxData;\r
679\r
680 if (EFI_ERROR (UdpToken->Status) || (UdpRxData == NULL)) {\r
36ee91ca 681 if (UdpToken->Status != EFI_ABORTED) {\r
682 //\r
683 // Invoke the CallBack only if the reception is not actively aborted.\r
684 //\r
685 Token->CallBack (NULL, NULL, UdpToken->Status, Token->Context);\r
686 }\r
cbf316f2 687\r
36ee91ca 688 UdpIoFreeRxToken (Token);\r
689 return;\r
cbf316f2 690 }\r
691\r
692 //\r
693 // Build a NET_BUF from the UDP receive data, then deliver it up.\r
694 //\r
695 Netbuf = NetbufFromExt (\r
696 (NET_FRAGMENT *) UdpRxData->FragmentTable,\r
697 UdpRxData->FragmentCount,\r
698 0,\r
699 (UINT32) Token->HeadLen,\r
700 UdpIoRecycleDgram,\r
701 Token\r
702 );\r
703\r
704 if (Netbuf == NULL) {\r
705 gBS->SignalEvent (UdpRxData->RecycleSignal);\r
706 Token->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, Token->Context);\r
707\r
708 UdpIoFreeRxToken (Token);\r
36ee91ca 709 return;\r
cbf316f2 710 }\r
711\r
712 UdpSession = &UdpRxData->UdpSession;\r
cbf316f2 713 Points.LocalPort = UdpSession->DestinationPort;\r
cbf316f2 714 Points.RemotePort = UdpSession->SourcePort;\r
715\r
e48e37fc 716 CopyMem (&Points.LocalAddr, &UdpSession->DestinationAddress, sizeof (IP4_ADDR));\r
717 CopyMem (&Points.RemoteAddr, &UdpSession->SourceAddress, sizeof (IP4_ADDR));\r
b61439a7 718 Points.LocalAddr = NTOHL (Points.LocalAddr);\r
719 Points.RemoteAddr = NTOHL (Points.RemoteAddr);\r
720\r
cbf316f2 721 Token->CallBack (Netbuf, &Points, EFI_SUCCESS, Token->Context);\r
36ee91ca 722}\r
723\r
724/**\r
725 Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK.\r
726\r
727 @param Event The UDP receive request event.\r
728 @param Context The UDP RX token.\r
729\r
730 @return None\r
731\r
732**/\r
733STATIC\r
734VOID\r
735EFIAPI\r
736UdpIoOnDgramRcvd (\r
737 IN EFI_EVENT Event,\r
738 IN VOID *Context\r
739 )\r
740/*++\r
741\r
742Routine Description:\r
743\r
744 Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK\r
745\r
746Arguments:\r
747\r
748 Event - The UDP receive request event\r
749 Context - The UDP RX token.\r
750\r
751Returns:\r
cbf316f2 752\r
36ee91ca 753 None\r
754\r
755--*/\r
756{\r
757 //\r
758 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK\r
759 //\r
760 NetLibQueueDpc (TPL_CALLBACK, UdpIoOnDgramRcvdDpc, Context);\r
cbf316f2 761}\r
762\r
763\r
764/**\r
765 Issue a receive request to the UDP IO port.\r
766\r
767 @param UdpIo The UDP IO port to recieve the packet from.\r
768 @param CallBack The call back function to execute when receive\r
769 finished.\r
770 @param Context The opque context to the call back\r
771 @param HeadLen The lenght of the application's header\r
772\r
773 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only\r
774 one receive request is supported.\r
775 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource.\r
776 @retval EFI_SUCCESS The receive request is issued successfully.\r
777\r
778**/\r
779EFI_STATUS\r
7b414b4e 780EFIAPI\r
cbf316f2 781UdpIoRecvDatagram (\r
782 IN UDP_IO_PORT *UdpIo,\r
783 IN UDP_IO_CALLBACK CallBack,\r
784 IN VOID *Context,\r
785 IN UINT32 HeadLen\r
786 )\r
787{\r
788 UDP_RX_TOKEN *Token;\r
789 EFI_STATUS Status;\r
790\r
791 if (UdpIo->RecvRequest != NULL) {\r
792 return EFI_ALREADY_STARTED;\r
793 }\r
794\r
795 Token = UdpIoCreateRxToken (UdpIo, CallBack, Context, HeadLen);\r
796\r
797 if (Token == NULL) {\r
798 return EFI_OUT_OF_RESOURCES;\r
799 }\r
800\r
36ee91ca 801 UdpIo->RecvRequest = Token;\r
cbf316f2 802 Status = UdpIo->Udp->Receive (UdpIo->Udp, &Token->UdpToken);\r
803\r
804 if (EFI_ERROR (Status)) {\r
36ee91ca 805 UdpIo->RecvRequest = NULL;\r
cbf316f2 806 UdpIoFreeRxToken (Token);\r
cbf316f2 807 }\r
808\r
36ee91ca 809 return Status;\r
cbf316f2 810}\r