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