]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Library/DxeUdpIoLib/DxeUdpIoLib.c
Use Mde library and definition instead of some native definitions in NetLib, to simpl...
[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
259UdpIoCreatePort (\r
260 IN EFI_HANDLE Controller,\r
261 IN EFI_HANDLE Image,\r
262 IN UDP_IO_CONFIG Configure,\r
263 IN VOID *Context\r
264 )\r
265{\r
266 UDP_IO_PORT *UdpIo;\r
267 EFI_STATUS Status;\r
268\r
269 ASSERT (Configure != NULL);\r
270\r
e48e37fc 271 UdpIo = AllocatePool (sizeof (UDP_IO_PORT));\r
cbf316f2 272\r
273 if (UdpIo == NULL) {\r
274 return NULL;\r
275 }\r
276\r
277 UdpIo->Signature = UDP_IO_SIGNATURE;\r
e48e37fc 278 InitializeListHead (&UdpIo->Link);\r
cbf316f2 279 UdpIo->RefCnt = 1;\r
280\r
281 UdpIo->Controller = Controller;\r
282 UdpIo->Image = Image;\r
283\r
e48e37fc 284 InitializeListHead (&UdpIo->SentDatagram);\r
cbf316f2 285 UdpIo->RecvRequest = NULL;\r
286 UdpIo->UdpHandle = NULL;\r
287\r
288 //\r
289 // Create a UDP child then open and configure it\r
290 //\r
291 Status = NetLibCreateServiceChild (\r
292 Controller,\r
293 Image,\r
294 &gEfiUdp4ServiceBindingProtocolGuid,\r
295 &UdpIo->UdpHandle\r
296 );\r
297\r
298 if (EFI_ERROR (Status)) {\r
299 goto FREE_MEM;\r
300 }\r
301\r
302 Status = gBS->OpenProtocol (\r
303 UdpIo->UdpHandle,\r
304 &gEfiUdp4ProtocolGuid,\r
4eb65aff 305 (VOID **) &UdpIo->Udp,\r
cbf316f2 306 Image,\r
307 Controller,\r
308 EFI_OPEN_PROTOCOL_BY_DRIVER\r
309 );\r
310\r
311 if (EFI_ERROR (Status)) {\r
312 goto FREE_CHILD;\r
313 }\r
314\r
315 if (EFI_ERROR (Configure (UdpIo, Context))) {\r
316 goto CLOSE_PROTOCOL;\r
317 }\r
318\r
319 Status = UdpIo->Udp->GetModeData (UdpIo->Udp, NULL, NULL, NULL, &UdpIo->SnpMode);\r
320\r
321 if (EFI_ERROR (Status)) {\r
322 goto CLOSE_PROTOCOL;\r
323 }\r
324\r
325 return UdpIo;\r
326\r
327CLOSE_PROTOCOL:\r
328 gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp4ProtocolGuid, Image, Controller);\r
329\r
330FREE_CHILD:\r
331 NetLibDestroyServiceChild (\r
332 Controller,\r
333 Image,\r
334 &gEfiUdp4ServiceBindingProtocolGuid,\r
335 UdpIo->UdpHandle\r
336 );\r
337\r
338FREE_MEM:\r
e48e37fc 339 gBS->FreePool (UdpIo);\r
cbf316f2 340 return NULL;\r
341}\r
342\r
343\r
344/**\r
345 Cancel all the sent datagram that pass the selection of ToCancel.\r
346 If ToCancel is NULL, all the datagrams are cancelled.\r
347\r
348 @param UdpIo The UDP IO port to cancel packet\r
349 @param IoStatus The IoStatus to return to the packet owners.\r
350 @param ToCancel The select funtion to test whether to cancel this\r
351 packet or not.\r
352 @param Context The opaque parameter to the ToCancel.\r
353\r
354 @return None\r
355\r
356**/\r
357STATIC\r
358VOID\r
359UdpIoCancelDgrams (\r
360 IN UDP_IO_PORT *UdpIo,\r
361 IN EFI_STATUS IoStatus,\r
362 IN UDP_IO_TO_CANCEL ToCancel, OPTIONAL\r
363 IN VOID *Context\r
364 )\r
365{\r
e48e37fc 366 LIST_ENTRY *Entry;\r
367 LIST_ENTRY *Next;\r
cbf316f2 368 UDP_TX_TOKEN *Token;\r
369\r
370 NET_LIST_FOR_EACH_SAFE (Entry, Next, &UdpIo->SentDatagram) {\r
371 Token = NET_LIST_USER_STRUCT (Entry, UDP_TX_TOKEN, Link);\r
372\r
373 if ((ToCancel == NULL) || (ToCancel (Token, Context))) {\r
cbf316f2 374 UdpIo->Udp->Cancel (UdpIo->Udp, &Token->UdpToken);\r
cbf316f2 375 }\r
376 }\r
377}\r
378\r
379\r
380/**\r
381 Free the UDP IO port and all its related resources including\r
382 all the transmitted packet.\r
383\r
384 @param UdpIo The UDP IO port to free.\r
385\r
386 @retval EFI_SUCCESS The UDP IO port is freed.\r
387\r
388**/\r
389EFI_STATUS\r
390UdpIoFreePort (\r
391 IN UDP_IO_PORT *UdpIo\r
392 )\r
393{\r
394 UDP_RX_TOKEN *RxToken;\r
395\r
396 //\r
397 // Cancel all the sent datagram and receive requests. The\r
398 // callbacks of transmit requests are executed to allow the\r
399 // caller to release the resource. The callback of receive\r
400 // request are NOT executed. This is because it is most\r
401 // likely that the current user of the UDP IO port is closing\r
402 // itself.\r
403 //\r
404 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
405\r
406 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
cbf316f2 407 UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);\r
cbf316f2 408 }\r
409\r
410 //\r
411 // Close then destory the UDP child\r
412 //\r
413 gBS->CloseProtocol (\r
414 UdpIo->UdpHandle,\r
415 &gEfiUdp4ProtocolGuid,\r
416 UdpIo->Image,\r
417 UdpIo->Controller\r
418 );\r
419\r
420 NetLibDestroyServiceChild (\r
421 UdpIo->Controller,\r
422 UdpIo->Image,\r
423 &gEfiUdp4ServiceBindingProtocolGuid,\r
424 UdpIo->UdpHandle\r
425 );\r
426\r
687a2e5f 427 if (!IsListEmpty(&UdpIo->Link)) {\r
e48e37fc 428 RemoveEntryList (&UdpIo->Link);\r
687a2e5f 429 }\r
430\r
e48e37fc 431 gBS->FreePool (UdpIo);\r
cbf316f2 432 return EFI_SUCCESS;\r
433}\r
434\r
435\r
436/**\r
437 Clean up the UDP IO port. It will release all the transmitted\r
438 datagrams and receive request. It will also configure NULL the\r
439 UDP child.\r
440\r
441 @param UdpIo UDP IO port to clean up.\r
442\r
443 @return None\r
444\r
445**/\r
446VOID\r
447UdpIoCleanPort (\r
448 IN UDP_IO_PORT *UdpIo\r
449 )\r
450{\r
451 UDP_RX_TOKEN *RxToken;\r
452\r
453 //\r
454 // Cancel all the sent datagram and receive requests.\r
455 //\r
456 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
457\r
458 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
cbf316f2 459 UdpIo->Udp->Cancel (UdpIo->Udp, &RxToken->UdpToken);\r
cbf316f2 460 }\r
461\r
462 UdpIo->Udp->Configure (UdpIo->Udp, NULL);\r
463}\r
464\r
465\r
466/**\r
467 The callback function when the packet is sent by UDP.\r
468 It will remove the packet from the local list then call\r
469 the packet owner's callback function.\r
470\r
cbf316f2 471 @param Context The UDP TX Token.\r
472\r
473 @return None\r
474\r
475**/\r
476STATIC\r
477VOID\r
478EFIAPI\r
36ee91ca 479UdpIoOnDgramSentDpc (\r
cbf316f2 480 IN VOID *Context\r
481 )\r
482{\r
483 UDP_TX_TOKEN *Token;\r
484\r
485 Token = (UDP_TX_TOKEN *) Context;\r
486 ASSERT (Token->Signature == UDP_IO_TX_SIGNATURE);\r
487\r
e48e37fc 488 RemoveEntryList (&Token->Link);\r
cbf316f2 489 Token->CallBack (Token->Packet, NULL, Token->UdpToken.Status, Token->Context);\r
490\r
491 UdpIoFreeTxToken (Token);\r
492}\r
493\r
36ee91ca 494/**\r
495 Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.\r
496\r
497 @param Event The event signalled.\r
498 @param Context The UDP TX Token.\r
499\r
500 @return None\r
501\r
502**/\r
503STATIC\r
504VOID\r
505EFIAPI\r
506UdpIoOnDgramSent (\r
507 IN EFI_EVENT Event,\r
508 IN VOID *Context\r
509 )\r
510{\r
511 //\r
512 // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK\r
513 //\r
514 NetLibQueueDpc (TPL_CALLBACK, UdpIoOnDgramSentDpc, Context);\r
515}\r
516\r
cbf316f2 517\r
518/**\r
519 Send a packet through the UDP IO port.\r
520\r
521 @param UdpIo The UDP IO Port to send the packet through\r
522 @param Packet The packet to send\r
523 @param EndPoint The local and remote access point\r
524 @param Gateway The gateway to use\r
525 @param CallBack The call back function to call when packet is\r
526 transmitted or failed.\r
527 @param Context The opque parameter to the CallBack\r
528\r
529 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet\r
530 @retval EFI_SUCCESS The packet is successfully delivered to UDP for\r
531 transmission.\r
532\r
533**/\r
534EFI_STATUS\r
535UdpIoSendDatagram (\r
536 IN UDP_IO_PORT *UdpIo,\r
537 IN NET_BUF *Packet,\r
538 IN UDP_POINTS *EndPoint, OPTIONAL\r
539 IN IP4_ADDR Gateway,\r
540 IN UDP_IO_CALLBACK CallBack,\r
541 IN VOID *Context\r
542 )\r
543{\r
544 UDP_TX_TOKEN *Token;\r
545 EFI_STATUS Status;\r
546\r
547 Token = UdpIoWrapTx (UdpIo, Packet, EndPoint, Gateway, CallBack, Context);\r
548\r
549 if (Token == NULL) {\r
550 return EFI_OUT_OF_RESOURCES;\r
551 }\r
552\r
36ee91ca 553 //\r
554 // Insert the tx token into SendDatagram list before transmitting it. Remove\r
555 // it from the list if the returned status is not EFI_SUCCESS.\r
556 //\r
e48e37fc 557 InsertHeadList (&UdpIo->SentDatagram, &Token->Link);\r
cbf316f2 558 Status = UdpIo->Udp->Transmit (UdpIo->Udp, &Token->UdpToken);\r
cbf316f2 559 if (EFI_ERROR (Status)) {\r
e48e37fc 560 RemoveEntryList (&Token->Link);\r
cbf316f2 561 UdpIoFreeTxToken (Token);\r
562 return Status;\r
563 }\r
564\r
cbf316f2 565 return EFI_SUCCESS;\r
566}\r
567\r
568\r
569/**\r
570 The selection function to cancel a single sent datagram.\r
571\r
572 @param Token The UDP TX token to test againist.\r
573 @param Context The context\r
574\r
575 @return TRUE if the packet is to be cancelled, otherwise FALSE.\r
576\r
577**/\r
578STATIC\r
579BOOLEAN\r
580UdpIoCancelSingleDgram (\r
581 IN UDP_TX_TOKEN *Token,\r
582 IN VOID *Context\r
583 )\r
584{\r
585 NET_BUF *Packet;\r
586\r
587 Packet = (NET_BUF *) Context;\r
588\r
589 if (Token->Packet == Packet) {\r
590 return TRUE;\r
591 }\r
592\r
593 return FALSE;\r
594}\r
595\r
596\r
597/**\r
598 Cancel a single sent datagram.\r
599\r
600 @param UdpIo The UDP IO port to cancel the packet from\r
601 @param Packet The packet to cancel\r
602\r
603 @return None\r
604\r
605**/\r
606VOID\r
607UdpIoCancelSentDatagram (\r
608 IN UDP_IO_PORT *UdpIo,\r
609 IN NET_BUF *Packet\r
610 )\r
611{\r
612 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, UdpIoCancelSingleDgram, Packet);\r
613}\r
614\r
615\r
616/**\r
617 Recycle the received UDP data.\r
618\r
619 @param Context The UDP_RX_TOKEN\r
620\r
621 @return None\r
622\r
623**/\r
624STATIC\r
625VOID\r
626UdpIoRecycleDgram (\r
627 IN VOID *Context\r
628 )\r
629{\r
630 UDP_RX_TOKEN *Token;\r
631\r
632 Token = (UDP_RX_TOKEN *) Context;\r
633 gBS->SignalEvent (Token->UdpToken.Packet.RxData->RecycleSignal);\r
634 UdpIoFreeRxToken (Token);\r
635}\r
636\r
cbf316f2 637/**\r
638 The event handle for UDP receive request. It will build\r
639 a NET_BUF from the recieved UDP data, then deliver it\r
640 to the receiver.\r
641\r
cbf316f2 642 @param Context The UDP RX token.\r
643\r
644 @return None\r
645\r
646**/\r
647STATIC\r
648VOID\r
649EFIAPI\r
36ee91ca 650UdpIoOnDgramRcvdDpc (\r
cbf316f2 651 IN VOID *Context\r
652 )\r
653{\r
654 EFI_UDP4_COMPLETION_TOKEN *UdpToken;\r
655 EFI_UDP4_RECEIVE_DATA *UdpRxData;\r
656 EFI_UDP4_SESSION_DATA *UdpSession;\r
657 UDP_RX_TOKEN *Token;\r
658 UDP_POINTS Points;\r
659 NET_BUF *Netbuf;\r
660\r
661 Token = (UDP_RX_TOKEN *) Context;\r
662\r
663 ASSERT ((Token->Signature == UDP_IO_RX_SIGNATURE) &&\r
664 (Token == Token->UdpIo->RecvRequest));\r
665\r
666 //\r
667 // Clear the receive request first in case that the caller\r
668 // wants to restart the receive in the callback.\r
669 //\r
670 Token->UdpIo->RecvRequest = NULL;\r
671\r
672 UdpToken = &Token->UdpToken;\r
673 UdpRxData = UdpToken->Packet.RxData;\r
674\r
675 if (EFI_ERROR (UdpToken->Status) || (UdpRxData == NULL)) {\r
36ee91ca 676 if (UdpToken->Status != EFI_ABORTED) {\r
677 //\r
678 // Invoke the CallBack only if the reception is not actively aborted.\r
679 //\r
680 Token->CallBack (NULL, NULL, UdpToken->Status, Token->Context);\r
681 }\r
cbf316f2 682\r
36ee91ca 683 UdpIoFreeRxToken (Token);\r
684 return;\r
cbf316f2 685 }\r
686\r
687 //\r
688 // Build a NET_BUF from the UDP receive data, then deliver it up.\r
689 //\r
690 Netbuf = NetbufFromExt (\r
691 (NET_FRAGMENT *) UdpRxData->FragmentTable,\r
692 UdpRxData->FragmentCount,\r
693 0,\r
694 (UINT32) Token->HeadLen,\r
695 UdpIoRecycleDgram,\r
696 Token\r
697 );\r
698\r
699 if (Netbuf == NULL) {\r
700 gBS->SignalEvent (UdpRxData->RecycleSignal);\r
701 Token->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, Token->Context);\r
702\r
703 UdpIoFreeRxToken (Token);\r
36ee91ca 704 return;\r
cbf316f2 705 }\r
706\r
707 UdpSession = &UdpRxData->UdpSession;\r
cbf316f2 708 Points.LocalPort = UdpSession->DestinationPort;\r
cbf316f2 709 Points.RemotePort = UdpSession->SourcePort;\r
710\r
e48e37fc 711 CopyMem (&Points.LocalAddr, &UdpSession->DestinationAddress, sizeof (IP4_ADDR));\r
712 CopyMem (&Points.RemoteAddr, &UdpSession->SourceAddress, sizeof (IP4_ADDR));\r
b61439a7 713 Points.LocalAddr = NTOHL (Points.LocalAddr);\r
714 Points.RemoteAddr = NTOHL (Points.RemoteAddr);\r
715\r
cbf316f2 716 Token->CallBack (Netbuf, &Points, EFI_SUCCESS, Token->Context);\r
36ee91ca 717}\r
718\r
719/**\r
720 Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK.\r
721\r
722 @param Event The UDP receive request event.\r
723 @param Context The UDP RX token.\r
724\r
725 @return None\r
726\r
727**/\r
728STATIC\r
729VOID\r
730EFIAPI\r
731UdpIoOnDgramRcvd (\r
732 IN EFI_EVENT Event,\r
733 IN VOID *Context\r
734 )\r
735/*++\r
736\r
737Routine Description:\r
738\r
739 Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK\r
740\r
741Arguments:\r
742\r
743 Event - The UDP receive request event\r
744 Context - The UDP RX token.\r
745\r
746Returns:\r
cbf316f2 747\r
36ee91ca 748 None\r
749\r
750--*/\r
751{\r
752 //\r
753 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK\r
754 //\r
755 NetLibQueueDpc (TPL_CALLBACK, UdpIoOnDgramRcvdDpc, Context);\r
cbf316f2 756}\r
757\r
758\r
759/**\r
760 Issue a receive request to the UDP IO port.\r
761\r
762 @param UdpIo The UDP IO port to recieve the packet from.\r
763 @param CallBack The call back function to execute when receive\r
764 finished.\r
765 @param Context The opque context to the call back\r
766 @param HeadLen The lenght of the application's header\r
767\r
768 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only\r
769 one receive request is supported.\r
770 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource.\r
771 @retval EFI_SUCCESS The receive request is issued successfully.\r
772\r
773**/\r
774EFI_STATUS\r
775UdpIoRecvDatagram (\r
776 IN UDP_IO_PORT *UdpIo,\r
777 IN UDP_IO_CALLBACK CallBack,\r
778 IN VOID *Context,\r
779 IN UINT32 HeadLen\r
780 )\r
781{\r
782 UDP_RX_TOKEN *Token;\r
783 EFI_STATUS Status;\r
784\r
785 if (UdpIo->RecvRequest != NULL) {\r
786 return EFI_ALREADY_STARTED;\r
787 }\r
788\r
789 Token = UdpIoCreateRxToken (UdpIo, CallBack, Context, HeadLen);\r
790\r
791 if (Token == NULL) {\r
792 return EFI_OUT_OF_RESOURCES;\r
793 }\r
794\r
36ee91ca 795 UdpIo->RecvRequest = Token;\r
cbf316f2 796 Status = UdpIo->Udp->Receive (UdpIo->Udp, &Token->UdpToken);\r
797\r
798 if (EFI_ERROR (Status)) {\r
36ee91ca 799 UdpIo->RecvRequest = NULL;\r
cbf316f2 800 UdpIoFreeRxToken (Token);\r
cbf316f2 801 }\r
802\r
36ee91ca 803 return Status;\r
cbf316f2 804}\r