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