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