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