]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Library/DxeUdpIoLib/DxeUdpIoLib.c
NetworkPkg/Library: Fix various typos
[mirror_edk2.git] / NetworkPkg / 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
e2851998 3\r
6d88babb 4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
cbf316f2 6**/\r
7\r
6c5dc2b0 8#include <Uefi.h>\r
cbf316f2 9\r
10#include <Protocol/Udp4.h>\r
b45b45b2 11#include <Protocol/Udp6.h>\r
cbf316f2 12\r
13#include <Library/UdpIoLib.h>\r
14#include <Library/BaseLib.h>\r
15#include <Library/DebugLib.h>\r
16#include <Library/UefiBootServicesTableLib.h>\r
17#include <Library/MemoryAllocationLib.h>\r
ba0f75a3 18#include <Library/BaseMemoryLib.h>\r
d8d26fb2 19#include <Library/DpcLib.h>\r
cbf316f2 20\r
9a3293ac 21\r
22/**\r
cab450cc 23 Free a UDP_TX_TOKEN. The TX event is closed.\r
9a3293ac 24\r
b45b45b2 25 @param[in] TxToken The UDP_TX_TOKEN to release.\r
9a3293ac 26\r
27**/\r
28VOID\r
29UdpIoFreeTxToken (\r
b45b45b2 30 IN UDP_TX_TOKEN *TxToken\r
9a3293ac 31 )\r
32{\r
b45b45b2 33\r
34 if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
35 gBS->CloseEvent (TxToken->Token.Udp4.Event);\r
36 } else if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {\r
37 gBS->CloseEvent (TxToken->Token.Udp6.Event);\r
38 } else {\r
39 ASSERT (FALSE);\r
40 }\r
e2851998 41\r
b45b45b2 42 FreePool (TxToken);\r
9a3293ac 43}\r
44\r
45/**\r
cab450cc 46 Free a UDP_RX_TOKEN. The RX event is closed.\r
9a3293ac 47\r
b45b45b2 48 @param[in] RxToken The UDP_RX_TOKEN to release.\r
9a3293ac 49\r
50**/\r
51VOID\r
52UdpIoFreeRxToken (\r
b45b45b2 53 IN UDP_RX_TOKEN *RxToken\r
9a3293ac 54 )\r
55{\r
b45b45b2 56 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
57 gBS->CloseEvent (RxToken->Token.Udp4.Event);\r
58 } else if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {\r
59 gBS->CloseEvent (RxToken->Token.Udp6.Event);\r
60 } else {\r
61 ASSERT (FALSE);\r
e2851998 62 }\r
b45b45b2 63\r
64 FreePool (RxToken);\r
9a3293ac 65}\r
66\r
67/**\r
68 The callback function when the packet is sent by UDP.\r
e2851998 69\r
9a3293ac 70 It will remove the packet from the local list then call\r
cab450cc 71 the packet owner's callback function set by UdpIoSendDatagram.\r
9a3293ac 72\r
8f5e6151 73 @param[in] Context The UDP TX Token.\r
9a3293ac 74\r
75**/\r
36ee91ca 76VOID\r
77EFIAPI\r
78UdpIoOnDgramSentDpc (\r
79 IN VOID *Context\r
9a3293ac 80 )\r
81{\r
b45b45b2 82 UDP_TX_TOKEN *TxToken;\r
9a3293ac 83\r
b45b45b2 84 TxToken = (UDP_TX_TOKEN *) Context;\r
85 ASSERT (TxToken->Signature == UDP_IO_TX_SIGNATURE);\r
86 ASSERT ((TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
87 (TxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
e2851998 88\r
b45b45b2 89 RemoveEntryList (&TxToken->Link);\r
9a3293ac 90\r
b45b45b2 91 if (TxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
92 TxToken->CallBack (TxToken->Packet, NULL, TxToken->Token.Udp4.Status, TxToken->Context);\r
93 } else {\r
94 TxToken->CallBack (TxToken->Packet, NULL, TxToken->Token.Udp6.Status, TxToken->Context);\r
95 }\r
9a3293ac 96\r
b45b45b2 97 UdpIoFreeTxToken (TxToken);\r
9a3293ac 98}\r
99\r
100/**\r
101 Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK.\r
e2851998 102\r
8f5e6151 103 @param[in] Event The event signaled.\r
104 @param[in] Context The UDP TX Token.\r
36ee91ca 105\r
9a3293ac 106**/\r
cbf316f2 107VOID\r
108EFIAPI\r
109UdpIoOnDgramSent (\r
110 IN EFI_EVENT Event,\r
111 IN VOID *Context\r
9a3293ac 112 )\r
113{\r
114 //\r
115 // Request UdpIoOnDgramSentDpc as a DPC at TPL_CALLBACK\r
116 //\r
d8d26fb2 117 QueueDpc (TPL_CALLBACK, UdpIoOnDgramSentDpc, Context);\r
9a3293ac 118}\r
119\r
120/**\r
121 Recycle the received UDP data.\r
122\r
8f5e6151 123 @param[in] Context The UDP_RX_TOKEN.\r
cbf316f2 124\r
9a3293ac 125**/\r
126VOID\r
e798cd87 127EFIAPI\r
9a3293ac 128UdpIoRecycleDgram (\r
129 IN VOID *Context\r
130 )\r
e2851998 131{\r
b45b45b2 132 UDP_RX_TOKEN *RxToken;\r
133\r
134 RxToken = (UDP_RX_TOKEN *) Context;\r
135\r
136 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
137 gBS->SignalEvent (RxToken->Token.Udp4.Packet.RxData->RecycleSignal);\r
138 } else if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION) {\r
139 gBS->SignalEvent (RxToken->Token.Udp6.Packet.RxData->RecycleSignal);\r
140 } else {\r
141 ASSERT (FALSE);\r
142 }\r
9a3293ac 143\r
b45b45b2 144 UdpIoFreeRxToken (RxToken);\r
9a3293ac 145}\r
146\r
147/**\r
cab450cc 148 The event handle for UDP receive request.\r
e2851998 149\r
6deb4baa 150 It will build a NET_BUF from the received UDP data, then deliver it\r
9a3293ac 151 to the receiver.\r
152\r
8f5e6151 153 @param[in] Context The UDP RX token.\r
9a3293ac 154\r
155**/\r
156VOID\r
157EFIAPI\r
158UdpIoOnDgramRcvdDpc (\r
159 IN VOID *Context\r
160 )\r
161{\r
b45b45b2 162 EFI_STATUS Status;\r
163 VOID *Token;\r
164 VOID *RxData;\r
165 VOID *Session;\r
166 UDP_RX_TOKEN *RxToken;\r
167 UDP_END_POINT EndPoint;\r
9a3293ac 168 NET_BUF *Netbuf;\r
169\r
b45b45b2 170 RxToken = (UDP_RX_TOKEN *) Context;\r
9a3293ac 171\r
b45b45b2 172 ZeroMem (&EndPoint, sizeof(UDP_END_POINT));\r
173\r
e2851998 174 ASSERT ((RxToken->Signature == UDP_IO_RX_SIGNATURE) &&\r
b45b45b2 175 (RxToken == RxToken->UdpIo->RecvRequest));\r
176\r
177 ASSERT ((RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
178 (RxToken->UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
9a3293ac 179\r
180 //\r
181 // Clear the receive request first in case that the caller\r
182 // wants to restart the receive in the callback.\r
183 //\r
b45b45b2 184 RxToken->UdpIo->RecvRequest = NULL;\r
185\r
186 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
187 Token = &RxToken->Token.Udp4;\r
188 RxData = ((EFI_UDP4_COMPLETION_TOKEN *) Token)->Packet.RxData;\r
189 Status = ((EFI_UDP4_COMPLETION_TOKEN *) Token)->Status;\r
190 } else {\r
191 Token = &RxToken->Token.Udp6;\r
192 RxData = ((EFI_UDP6_COMPLETION_TOKEN *) Token)->Packet.RxData;\r
193 Status = ((EFI_UDP6_COMPLETION_TOKEN *) Token)->Status;\r
194 }\r
9a3293ac 195\r
b45b45b2 196 if (EFI_ERROR (Status) || RxData == NULL) {\r
197 if (Status != EFI_ABORTED) {\r
9a3293ac 198 //\r
199 // Invoke the CallBack only if the reception is not actively aborted.\r
200 //\r
b45b45b2 201 RxToken->CallBack (NULL, NULL, Status, RxToken->Context);\r
9a3293ac 202 }\r
203\r
b45b45b2 204 UdpIoFreeRxToken (RxToken);\r
9a3293ac 205 return;\r
206 }\r
207\r
208 //\r
209 // Build a NET_BUF from the UDP receive data, then deliver it up.\r
210 //\r
b45b45b2 211 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
1b31acb6
FS
212 if (((EFI_UDP4_RECEIVE_DATA *) RxData)->DataLength == 0) {\r
213 //\r
214 // Discard zero length data payload packet.\r
215 //\r
216 goto Resume;\r
217 }\r
e2851998 218\r
b45b45b2 219 Netbuf = NetbufFromExt (\r
220 (NET_FRAGMENT *)((EFI_UDP4_RECEIVE_DATA *) RxData)->FragmentTable,\r
221 ((EFI_UDP4_RECEIVE_DATA *) RxData)->FragmentCount,\r
222 0,\r
223 (UINT32) RxToken->HeadLen,\r
224 UdpIoRecycleDgram,\r
225 RxToken\r
226 );\r
227\r
228 if (Netbuf == NULL) {\r
229 gBS->SignalEvent (((EFI_UDP4_RECEIVE_DATA *) RxData)->RecycleSignal);\r
230 RxToken->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, RxToken->Context);\r
231\r
232 UdpIoFreeRxToken (RxToken);\r
233 return;\r
234 }\r
9a3293ac 235\r
b45b45b2 236 Session = &((EFI_UDP4_RECEIVE_DATA *) RxData)->UdpSession;\r
237 EndPoint.LocalPort = ((EFI_UDP4_SESSION_DATA *) Session)->DestinationPort;\r
238 EndPoint.RemotePort = ((EFI_UDP4_SESSION_DATA *) Session)->SourcePort;\r
239\r
240 CopyMem (\r
241 &EndPoint.LocalAddr,\r
242 &((EFI_UDP4_SESSION_DATA *) Session)->DestinationAddress,\r
243 sizeof (EFI_IPv4_ADDRESS)\r
244 );\r
245\r
246 CopyMem (\r
247 &EndPoint.RemoteAddr,\r
248 &((EFI_UDP4_SESSION_DATA *) Session)->SourceAddress,\r
249 sizeof (EFI_IPv4_ADDRESS)\r
250 );\r
251\r
252 EndPoint.LocalAddr.Addr[0] = NTOHL (EndPoint.LocalAddr.Addr[0]);\r
253 EndPoint.RemoteAddr.Addr[0] = NTOHL (EndPoint.RemoteAddr.Addr[0]);\r
254 } else {\r
1b31acb6
FS
255 if (((EFI_UDP6_RECEIVE_DATA *) RxData)->DataLength == 0) {\r
256 //\r
257 // Discard zero length data payload packet.\r
258 //\r
259 goto Resume;\r
260 }\r
e2851998 261\r
b45b45b2 262 Netbuf = NetbufFromExt (\r
263 (NET_FRAGMENT *)((EFI_UDP6_RECEIVE_DATA *) RxData)->FragmentTable,\r
264 ((EFI_UDP6_RECEIVE_DATA *) RxData)->FragmentCount,\r
265 0,\r
266 (UINT32) RxToken->HeadLen,\r
267 UdpIoRecycleDgram,\r
268 RxToken\r
269 );\r
e2851998 270\r
b45b45b2 271 if (Netbuf == NULL) {\r
272 gBS->SignalEvent (((EFI_UDP6_RECEIVE_DATA *) RxData)->RecycleSignal);\r
273 RxToken->CallBack (NULL, NULL, EFI_OUT_OF_RESOURCES, RxToken->Context);\r
e2851998 274\r
b45b45b2 275 UdpIoFreeRxToken (RxToken);\r
276 return;\r
277 }\r
e2851998 278\r
b45b45b2 279 Session = &((EFI_UDP6_RECEIVE_DATA *) RxData)->UdpSession;\r
280 EndPoint.LocalPort = ((EFI_UDP6_SESSION_DATA *) Session)->DestinationPort;\r
281 EndPoint.RemotePort = ((EFI_UDP6_SESSION_DATA *) Session)->SourcePort;\r
e2851998 282\r
b45b45b2 283 CopyMem (\r
284 &EndPoint.LocalAddr,\r
285 &((EFI_UDP6_SESSION_DATA *) Session)->DestinationAddress,\r
286 sizeof (EFI_IPv6_ADDRESS)\r
287 );\r
288\r
289 CopyMem (\r
290 &EndPoint.RemoteAddr,\r
291 &((EFI_UDP6_SESSION_DATA *) Session)->SourceAddress,\r
292 sizeof (EFI_IPv6_ADDRESS)\r
293 );\r
294\r
295 Ip6Swap128 (&EndPoint.LocalAddr.v6);\r
296 Ip6Swap128 (&EndPoint.RemoteAddr.v6);\r
297 }\r
9a3293ac 298\r
b45b45b2 299 RxToken->CallBack (Netbuf, &EndPoint, EFI_SUCCESS, RxToken->Context);\r
166a6552 300 return;\r
1b31acb6
FS
301\r
302Resume:\r
303 if (RxToken->UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
304 gBS->SignalEvent (((EFI_UDP4_RECEIVE_DATA *) RxData)->RecycleSignal);\r
305 RxToken->UdpIo->Protocol.Udp4->Receive (RxToken->UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);\r
306 } else {\r
307 gBS->SignalEvent (((EFI_UDP6_RECEIVE_DATA *) RxData)->RecycleSignal);\r
308 RxToken->UdpIo->Protocol.Udp6->Receive (RxToken->UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);\r
309 }\r
9a3293ac 310}\r
311\r
312/**\r
ca9d3a9d 313 Request UdpIoOnDgramRcvdDpc() as a DPC at TPL_CALLBACK.\r
9a3293ac 314\r
8f5e6151 315 @param[in] Event The UDP receive request event.\r
316 @param[in] Context The UDP RX token.\r
9a3293ac 317\r
318**/\r
cbf316f2 319VOID\r
320EFIAPI\r
321UdpIoOnDgramRcvd (\r
322 IN EFI_EVENT Event,\r
323 IN VOID *Context\r
9a3293ac 324 )\r
325{\r
326 //\r
327 // Request UdpIoOnDgramRcvdDpc as a DPC at TPL_CALLBACK\r
328 //\r
d8d26fb2 329 QueueDpc (TPL_CALLBACK, UdpIoOnDgramRcvdDpc, Context);\r
9a3293ac 330}\r
cbf316f2 331\r
9a3293ac 332/**\r
333 Create a UDP_RX_TOKEN to wrap the request.\r
334\r
8f5e6151 335 @param[in] UdpIo The UdpIo to receive packets from.\r
336 @param[in] CallBack The function to call when receive finished.\r
337 @param[in] Context The opaque parameter to the CallBack.\r
6deb4baa 338 @param[in] HeadLen The head length to reserve for the packet.\r
9a3293ac 339\r
340 @return The Wrapped request or NULL if failed to allocate resources or some errors happened.\r
341\r
342**/\r
343UDP_RX_TOKEN *\r
344UdpIoCreateRxToken (\r
b45b45b2 345 IN UDP_IO *UdpIo,\r
9a3293ac 346 IN UDP_IO_CALLBACK CallBack,\r
347 IN VOID *Context,\r
348 IN UINT32 HeadLen\r
349 )\r
350{\r
351 UDP_RX_TOKEN *Token;\r
352 EFI_STATUS Status;\r
353\r
b45b45b2 354 ASSERT ((UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
355 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
356\r
9a3293ac 357 Token = AllocatePool (sizeof (UDP_RX_TOKEN));\r
358\r
359 if (Token == NULL) {\r
360 return NULL;\r
361 }\r
362\r
363 Token->Signature = UDP_IO_RX_SIGNATURE;\r
364 Token->UdpIo = UdpIo;\r
365 Token->CallBack = CallBack;\r
366 Token->Context = Context;\r
367 Token->HeadLen = HeadLen;\r
368\r
b45b45b2 369 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
370\r
371 Token->Token.Udp4.Status = EFI_NOT_READY;\r
372 Token->Token.Udp4.Packet.RxData = NULL;\r
373\r
374 Status = gBS->CreateEvent (\r
375 EVT_NOTIFY_SIGNAL,\r
376 TPL_NOTIFY,\r
377 UdpIoOnDgramRcvd,\r
378 Token,\r
379 &Token->Token.Udp4.Event\r
380 );\r
381 } else {\r
e2851998 382\r
b45b45b2 383 Token->Token.Udp6.Status = EFI_NOT_READY;\r
384 Token->Token.Udp6.Packet.RxData = NULL;\r
385\r
386 Status = gBS->CreateEvent (\r
387 EVT_NOTIFY_SIGNAL,\r
388 TPL_NOTIFY,\r
389 UdpIoOnDgramRcvd,\r
390 Token,\r
391 &Token->Token.Udp6.Event\r
392 );\r
e2851998 393 }\r
9a3293ac 394\r
9a3293ac 395\r
396 if (EFI_ERROR (Status)) {\r
b45b45b2 397 FreePool (Token);\r
9a3293ac 398 return NULL;\r
399 }\r
400\r
401 return Token;\r
402}\r
cbf316f2 403\r
404/**\r
b45b45b2 405 Wrap a transmit request into a new created UDP_TX_TOKEN.\r
cbf316f2 406\r
6d88babb
WF
407 If Packet is NULL, then ASSERT().\r
408 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().\r
409\r
b45b45b2 410 @param[in] UdpIo The UdpIo to send packet to.\r
8f5e6151 411 @param[in] Packet The user's packet.\r
412 @param[in] EndPoint The local and remote access point.\r
6deb4baa 413 @param[in] Gateway The overridden next hop.\r
8f5e6151 414 @param[in] CallBack The function to call when transmission completed.\r
415 @param[in] Context The opaque parameter to the call back.\r
cbf316f2 416\r
e2851998 417 @return The wrapped transmission request or NULL if failed to allocate resources\r
9a3293ac 418 or for some errors.\r
cbf316f2 419\r
420**/\r
cbf316f2 421UDP_TX_TOKEN *\r
b45b45b2 422UdpIoCreateTxToken (\r
423 IN UDP_IO *UdpIo,\r
cbf316f2 424 IN NET_BUF *Packet,\r
b45b45b2 425 IN UDP_END_POINT *EndPoint OPTIONAL,\r
426 IN EFI_IP_ADDRESS *Gateway OPTIONAL,\r
cbf316f2 427 IN UDP_IO_CALLBACK CallBack,\r
428 IN VOID *Context\r
429 )\r
430{\r
b45b45b2 431 UDP_TX_TOKEN *TxToken;\r
432 VOID *Token;\r
433 VOID *Data;\r
cbf316f2 434 EFI_STATUS Status;\r
435 UINT32 Count;\r
b45b45b2 436 UINTN Size;\r
e2851998 437 IP4_ADDR Ip;\r
cbf316f2 438\r
b45b45b2 439 ASSERT (Packet != NULL);\r
440 ASSERT ((UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
441 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
cbf316f2 442\r
b45b45b2 443 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
444 Size = sizeof (UDP_TX_TOKEN) + sizeof (EFI_UDP4_FRAGMENT_DATA) * (Packet->BlockOpNum - 1);\r
445 } else {\r
446 Size = sizeof (UDP_TX_TOKEN) + sizeof (EFI_UDP6_FRAGMENT_DATA) * (Packet->BlockOpNum - 1);\r
cbf316f2 447 }\r
448\r
b45b45b2 449 TxToken = AllocatePool (Size);\r
cbf316f2 450\r
b45b45b2 451 if (TxToken == NULL) {\r
452 return NULL;\r
453 }\r
cbf316f2 454\r
b45b45b2 455 TxToken->Signature = UDP_IO_TX_SIGNATURE;\r
456 InitializeListHead (&TxToken->Link);\r
cbf316f2 457\r
b45b45b2 458 TxToken->UdpIo = UdpIo;\r
459 TxToken->CallBack = CallBack;\r
460 TxToken->Packet = Packet;\r
461 TxToken->Context = Context;\r
cbf316f2 462\r
b45b45b2 463 Token = &(TxToken->Token);\r
464 Count = Packet->BlockOpNum;\r
cbf316f2 465\r
b45b45b2 466 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
cbf316f2 467\r
b45b45b2 468 ((EFI_UDP4_COMPLETION_TOKEN *) Token)->Status = EFI_NOT_READY;\r
cbf316f2 469\r
b45b45b2 470 Status = gBS->CreateEvent (\r
471 EVT_NOTIFY_SIGNAL,\r
472 TPL_NOTIFY,\r
473 UdpIoOnDgramSent,\r
474 TxToken,\r
475 &((EFI_UDP4_COMPLETION_TOKEN *) Token)->Event\r
476 );\r
b61439a7 477\r
b45b45b2 478 if (EFI_ERROR (Status)) {\r
479 FreePool (TxToken);\r
480 return NULL;\r
481 }\r
b61439a7 482\r
b45b45b2 483 Data = &(TxToken->Data.Udp4);\r
484 ((EFI_UDP4_COMPLETION_TOKEN *) Token)->Packet.TxData = Data;\r
485\r
486 ((EFI_UDP4_TRANSMIT_DATA *) Data)->UdpSessionData = NULL;\r
487 ((EFI_UDP4_TRANSMIT_DATA *) Data)->GatewayAddress = NULL;\r
488 ((EFI_UDP4_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize;\r
489\r
490 NetbufBuildExt (\r
491 Packet,\r
492 (NET_FRAGMENT *)((EFI_UDP4_TRANSMIT_DATA *) Data)->FragmentTable,\r
493 &Count\r
494 );\r
495\r
496 ((EFI_UDP4_TRANSMIT_DATA *) Data)->FragmentCount = Count;\r
497\r
498 if (EndPoint != NULL) {\r
499 Ip = HTONL (EndPoint->LocalAddr.Addr[0]);\r
500 CopyMem (\r
e2851998 501 &TxToken->Session.Udp4.SourceAddress,\r
502 &Ip,\r
b45b45b2 503 sizeof (EFI_IPv4_ADDRESS)\r
504 );\r
505\r
506 Ip = HTONL (EndPoint->RemoteAddr.Addr[0]);\r
507 CopyMem (\r
e2851998 508 &TxToken->Session.Udp4.DestinationAddress,\r
509 &Ip,\r
b45b45b2 510 sizeof (EFI_IPv4_ADDRESS)\r
511 );\r
512\r
513 TxToken->Session.Udp4.SourcePort = EndPoint->LocalPort;\r
514 TxToken->Session.Udp4.DestinationPort = EndPoint->RemotePort;\r
515 ((EFI_UDP4_TRANSMIT_DATA *) Data)->UdpSessionData = &(TxToken->Session.Udp4);\r
516 }\r
cbf316f2 517\r
b45b45b2 518 if (Gateway != NULL && (Gateway->Addr[0] != 0)) {\r
519 Ip = HTONL (Gateway->Addr[0]);\r
520 CopyMem (&TxToken->Gateway, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
e2851998 521 ((EFI_UDP4_TRANSMIT_DATA *) Data)->GatewayAddress = &TxToken->Gateway;\r
b45b45b2 522 }\r
b61439a7 523\r
b45b45b2 524 } else {\r
e2851998 525\r
b45b45b2 526 ((EFI_UDP6_COMPLETION_TOKEN *) Token)->Status = EFI_NOT_READY;\r
e2851998 527\r
b45b45b2 528 Status = gBS->CreateEvent (\r
529 EVT_NOTIFY_SIGNAL,\r
530 TPL_NOTIFY,\r
531 UdpIoOnDgramSent,\r
532 TxToken,\r
533 &((EFI_UDP6_COMPLETION_TOKEN *) Token)->Event\r
534 );\r
535\r
536 if (EFI_ERROR (Status)) {\r
537 FreePool (TxToken);\r
538 return NULL;\r
539 }\r
e2851998 540\r
b45b45b2 541 Data = &(TxToken->Data.Udp6);\r
542 ((EFI_UDP6_COMPLETION_TOKEN *) Token)->Packet.TxData = Data;\r
543 ((EFI_UDP6_TRANSMIT_DATA *) Data)->UdpSessionData = NULL;\r
544 ((EFI_UDP6_TRANSMIT_DATA *) Data)->DataLength = Packet->TotalSize;\r
545\r
546 NetbufBuildExt (\r
547 Packet,\r
548 (NET_FRAGMENT *)((EFI_UDP6_TRANSMIT_DATA *) Data)->FragmentTable,\r
549 &Count\r
550 );\r
551\r
552 ((EFI_UDP6_TRANSMIT_DATA *) Data)->FragmentCount = Count;\r
553\r
554 if (EndPoint != NULL) {\r
555 CopyMem (\r
e2851998 556 &TxToken->Session.Udp6.SourceAddress,\r
557 &EndPoint->LocalAddr.v6,\r
b45b45b2 558 sizeof(EFI_IPv6_ADDRESS)\r
559 );\r
560\r
561 CopyMem (\r
e2851998 562 &TxToken->Session.Udp6.DestinationAddress,\r
563 &EndPoint->RemoteAddr.v6,\r
b45b45b2 564 sizeof(EFI_IPv6_ADDRESS)\r
565 );\r
566\r
567 TxToken->Session.Udp6.SourcePort = EndPoint->LocalPort;\r
568 TxToken->Session.Udp6.DestinationPort = EndPoint->RemotePort;\r
569 ((EFI_UDP6_TRANSMIT_DATA *) Data)->UdpSessionData = &(TxToken->Session.Udp6);\r
e2851998 570 }\r
cbf316f2 571 }\r
572\r
b45b45b2 573 return TxToken;\r
cbf316f2 574}\r
575\r
cbf316f2 576/**\r
b45b45b2 577 Creates a UDP_IO to access the UDP service. It creates and configures\r
cab450cc 578 a UDP child.\r
e2851998 579\r
6d88babb
WF
580 If Configure is NULL, then ASSERT().\r
581 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().\r
582\r
e2851998 583 It locates the UDP service binding prototype on the Controller parameter\r
584 uses the UDP service binding prototype to create a UDP child (also known as\r
585 a UDP instance) configures the UDP child by calling Configure function prototype.\r
586 Any failures in creating or configuring the UDP child return NULL for failure.\r
cbf316f2 587\r
8f5e6151 588 @param[in] Controller The controller that has the UDP service binding.\r
589 protocol installed.\r
b45b45b2 590 @param[in] ImageHandle The image handle for the driver.\r
8f5e6151 591 @param[in] Configure The function to configure the created UDP child.\r
b45b45b2 592 @param[in] UdpVersion The UDP protocol version, UDP4 or UDP6.\r
6deb4baa 593 @param[in] Context The opaque parameter for the Configure function.\r
cbf316f2 594\r
b45b45b2 595 @return Newly-created UDP_IO or NULL if failed.\r
cbf316f2 596\r
597**/\r
b45b45b2 598UDP_IO *\r
7b414b4e 599EFIAPI\r
b45b45b2 600UdpIoCreateIo (\r
cbf316f2 601 IN EFI_HANDLE Controller,\r
b45b45b2 602 IN EFI_HANDLE ImageHandle,\r
cbf316f2 603 IN UDP_IO_CONFIG Configure,\r
b45b45b2 604 IN UINT8 UdpVersion,\r
cbf316f2 605 IN VOID *Context\r
606 )\r
607{\r
b45b45b2 608 UDP_IO *UdpIo;\r
cbf316f2 609 EFI_STATUS Status;\r
610\r
611 ASSERT (Configure != NULL);\r
b45b45b2 612 ASSERT ((UdpVersion == UDP_IO_UDP4_VERSION) || (UdpVersion == UDP_IO_UDP6_VERSION));\r
cbf316f2 613\r
b45b45b2 614 UdpIo = AllocatePool (sizeof (UDP_IO));\r
cbf316f2 615\r
616 if (UdpIo == NULL) {\r
617 return NULL;\r
618 }\r
619\r
b45b45b2 620 UdpIo->UdpVersion = UdpVersion;\r
cbf316f2 621 UdpIo->Signature = UDP_IO_SIGNATURE;\r
e48e37fc 622 InitializeListHead (&UdpIo->Link);\r
cbf316f2 623 UdpIo->RefCnt = 1;\r
624\r
625 UdpIo->Controller = Controller;\r
b45b45b2 626 UdpIo->Image = ImageHandle;\r
cbf316f2 627\r
e48e37fc 628 InitializeListHead (&UdpIo->SentDatagram);\r
cbf316f2 629 UdpIo->RecvRequest = NULL;\r
630 UdpIo->UdpHandle = NULL;\r
631\r
b45b45b2 632 if (UdpVersion == UDP_IO_UDP4_VERSION) {\r
633 //\r
634 // Create a UDP child then open and configure it\r
635 //\r
636 Status = NetLibCreateServiceChild (\r
637 Controller,\r
638 ImageHandle,\r
639 &gEfiUdp4ServiceBindingProtocolGuid,\r
640 &UdpIo->UdpHandle\r
641 );\r
e2851998 642\r
b45b45b2 643 if (EFI_ERROR (Status)) {\r
644 goto FREE_MEM;\r
645 }\r
cbf316f2 646\r
b45b45b2 647 Status = gBS->OpenProtocol (\r
648 UdpIo->UdpHandle,\r
649 &gEfiUdp4ProtocolGuid,\r
650 (VOID **) &UdpIo->Protocol.Udp4,\r
651 ImageHandle,\r
652 Controller,\r
653 EFI_OPEN_PROTOCOL_BY_DRIVER\r
654 );\r
655\r
656 if (EFI_ERROR (Status)) {\r
657 goto FREE_CHILD;\r
658 }\r
cbf316f2 659\r
b45b45b2 660 if (EFI_ERROR (Configure (UdpIo, Context))) {\r
661 goto CLOSE_PROTOCOL;\r
662 }\r
e2851998 663\r
b45b45b2 664 Status = UdpIo->Protocol.Udp4->GetModeData (\r
e2851998 665 UdpIo->Protocol.Udp4,\r
666 NULL,\r
667 NULL,\r
668 NULL,\r
b45b45b2 669 &UdpIo->SnpMode\r
670 );\r
e2851998 671\r
b45b45b2 672 if (EFI_ERROR (Status)) {\r
673 goto CLOSE_PROTOCOL;\r
674 }\r
cbf316f2 675\r
b45b45b2 676 } else {\r
e2851998 677\r
b45b45b2 678 Status = NetLibCreateServiceChild (\r
679 Controller,\r
680 ImageHandle,\r
681 &gEfiUdp6ServiceBindingProtocolGuid,\r
682 &UdpIo->UdpHandle\r
683 );\r
e2851998 684\r
b45b45b2 685 if (EFI_ERROR (Status)) {\r
686 goto FREE_MEM;\r
687 }\r
e2851998 688\r
b45b45b2 689 Status = gBS->OpenProtocol (\r
690 UdpIo->UdpHandle,\r
691 &gEfiUdp6ProtocolGuid,\r
692 (VOID **) &UdpIo->Protocol.Udp6,\r
693 ImageHandle,\r
694 Controller,\r
695 EFI_OPEN_PROTOCOL_BY_DRIVER\r
696 );\r
e2851998 697\r
b45b45b2 698 if (EFI_ERROR (Status)) {\r
699 goto FREE_CHILD;\r
700 }\r
e2851998 701\r
b45b45b2 702 if (EFI_ERROR (Configure (UdpIo, Context))) {\r
703 goto CLOSE_PROTOCOL;\r
704 }\r
e2851998 705\r
b45b45b2 706 Status = UdpIo->Protocol.Udp6->GetModeData (\r
e2851998 707 UdpIo->Protocol.Udp6,\r
708 NULL,\r
709 NULL,\r
710 NULL,\r
b45b45b2 711 &UdpIo->SnpMode\r
712 );\r
e2851998 713\r
b45b45b2 714 if (EFI_ERROR (Status)) {\r
715 goto CLOSE_PROTOCOL;\r
716 }\r
cbf316f2 717 }\r
718\r
719 return UdpIo;\r
720\r
721CLOSE_PROTOCOL:\r
b45b45b2 722 if (UdpVersion == UDP_IO_UDP4_VERSION) {\r
723 gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp4ProtocolGuid, ImageHandle, Controller);\r
724 } else {\r
725 gBS->CloseProtocol (UdpIo->UdpHandle, &gEfiUdp6ProtocolGuid, ImageHandle, Controller);\r
726 }\r
cbf316f2 727\r
728FREE_CHILD:\r
b45b45b2 729 if (UdpVersion == UDP_IO_UDP4_VERSION) {\r
730 NetLibDestroyServiceChild (\r
731 Controller,\r
732 ImageHandle,\r
733 &gEfiUdp4ServiceBindingProtocolGuid,\r
734 UdpIo->UdpHandle\r
735 );\r
736 } else {\r
737 NetLibDestroyServiceChild (\r
738 Controller,\r
739 ImageHandle,\r
740 &gEfiUdp6ServiceBindingProtocolGuid,\r
741 UdpIo->UdpHandle\r
742 );\r
743 }\r
cbf316f2 744\r
745FREE_MEM:\r
b45b45b2 746 FreePool (UdpIo);\r
cbf316f2 747 return NULL;\r
748}\r
749\r
cbf316f2 750/**\r
cab450cc 751 Cancel all the sent datagram that pass the selection criteria of ToCancel.\r
6d88babb 752\r
cbf316f2 753 If ToCancel is NULL, all the datagrams are cancelled.\r
6d88babb 754 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().\r
cbf316f2 755\r
b45b45b2 756 @param[in] UdpIo The UDP_IO to cancel packet.\r
8f5e6151 757 @param[in] IoStatus The IoStatus to return to the packet owners.\r
6deb4baa 758 @param[in] ToCancel The select function to test whether to cancel this\r
8f5e6151 759 packet or not.\r
760 @param[in] Context The opaque parameter to the ToCancel.\r
cbf316f2 761\r
cbf316f2 762**/\r
cbf316f2 763VOID\r
e4b99ad9 764EFIAPI\r
cbf316f2 765UdpIoCancelDgrams (\r
b45b45b2 766 IN UDP_IO *UdpIo,\r
cbf316f2 767 IN EFI_STATUS IoStatus,\r
768 IN UDP_IO_TO_CANCEL ToCancel, OPTIONAL\r
6d88babb 769 IN VOID *Context OPTIONAL\r
cbf316f2 770 )\r
771{\r
e48e37fc 772 LIST_ENTRY *Entry;\r
773 LIST_ENTRY *Next;\r
b45b45b2 774 UDP_TX_TOKEN *TxToken;\r
775\r
776 ASSERT ((UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
777 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
cbf316f2 778\r
779 NET_LIST_FOR_EACH_SAFE (Entry, Next, &UdpIo->SentDatagram) {\r
b45b45b2 780 TxToken = NET_LIST_USER_STRUCT (Entry, UDP_TX_TOKEN, Link);\r
781\r
782 if ((ToCancel == NULL) || (ToCancel (TxToken, Context))) {\r
cbf316f2 783\r
b45b45b2 784 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
785 UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &TxToken->Token.Udp4);\r
786 } else {\r
787 UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &TxToken->Token.Udp6);\r
788 }\r
cbf316f2 789 }\r
e2851998 790 }\r
cbf316f2 791}\r
792\r
cbf316f2 793/**\r
b45b45b2 794 Free the UDP_IO and all its related resources.\r
e2851998 795\r
6d88babb
WF
796 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().\r
797\r
cab450cc 798 The function will cancel all sent datagram and receive request.\r
cbf316f2 799\r
b45b45b2 800 @param[in] UdpIo The UDP_IO to free.\r
cbf316f2 801\r
b45b45b2 802 @retval EFI_SUCCESS The UDP_IO is freed.\r
6d88babb 803 @retval Others Failed to free UDP_IO.\r
cbf316f2 804\r
805**/\r
806EFI_STATUS\r
7b414b4e 807EFIAPI\r
b45b45b2 808UdpIoFreeIo (\r
809 IN UDP_IO *UdpIo\r
cbf316f2 810 )\r
811{\r
6d88babb 812 EFI_STATUS Status;\r
b45b45b2 813 UDP_RX_TOKEN *RxToken;\r
814\r
815 ASSERT ((UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
816 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
cbf316f2 817\r
818 //\r
819 // Cancel all the sent datagram and receive requests. The\r
820 // callbacks of transmit requests are executed to allow the\r
821 // caller to release the resource. The callback of receive\r
822 // request are NOT executed. This is because it is most\r
823 // likely that the current user of the UDP IO port is closing\r
824 // itself.\r
825 //\r
826 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
827\r
b45b45b2 828 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
cbf316f2 829\r
b45b45b2 830 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
6d88babb
WF
831 Status = UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);\r
832 if (EFI_ERROR (Status)) {\r
833 return Status;\r
834 }\r
b45b45b2 835 }\r
836\r
837 //\r
75dce340 838 // Close then destroy the Udp4 child\r
b45b45b2 839 //\r
6d88babb
WF
840 Status = gBS->CloseProtocol (\r
841 UdpIo->UdpHandle,\r
842 &gEfiUdp4ProtocolGuid,\r
843 UdpIo->Image,\r
844 UdpIo->Controller\r
845 );\r
846 if (EFI_ERROR (Status)) {\r
847 return Status;\r
848 }\r
b45b45b2 849\r
6d88babb
WF
850 Status = NetLibDestroyServiceChild (\r
851 UdpIo->Controller,\r
852 UdpIo->Image,\r
853 &gEfiUdp4ServiceBindingProtocolGuid,\r
854 UdpIo->UdpHandle\r
855 );\r
856 if (EFI_ERROR (Status)) {\r
857 return Status;\r
858 }\r
b45b45b2 859\r
860 } else {\r
861\r
862 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
6d88babb
WF
863 Status = UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);\r
864 if (EFI_ERROR (Status)) {\r
865 return Status;\r
866 }\r
b45b45b2 867 }\r
e2851998 868\r
b45b45b2 869 //\r
75dce340 870 // Close then destroy the Udp6 child\r
b45b45b2 871 //\r
6d88babb
WF
872 Status = gBS->CloseProtocol (\r
873 UdpIo->UdpHandle,\r
874 &gEfiUdp6ProtocolGuid,\r
875 UdpIo->Image,\r
876 UdpIo->Controller\r
877 );\r
878 if (EFI_ERROR (Status)) {\r
879 return Status;\r
880 }\r
e2851998 881\r
6d88babb
WF
882 Status = NetLibDestroyServiceChild (\r
883 UdpIo->Controller,\r
884 UdpIo->Image,\r
885 &gEfiUdp6ServiceBindingProtocolGuid,\r
886 UdpIo->UdpHandle\r
887 );\r
888 if (EFI_ERROR (Status)) {\r
889 return Status;\r
b45b45b2 890 }\r
6d88babb 891 }\r
cbf316f2 892\r
687a2e5f 893 if (!IsListEmpty(&UdpIo->Link)) {\r
e48e37fc 894 RemoveEntryList (&UdpIo->Link);\r
687a2e5f 895 }\r
896\r
b45b45b2 897 FreePool (UdpIo);\r
cbf316f2 898 return EFI_SUCCESS;\r
899}\r
900\r
901\r
902/**\r
b45b45b2 903 Clean up the UDP_IO without freeing it. The function is called when\r
904 user wants to re-use the UDP_IO later.\r
e2851998 905\r
6d88babb
WF
906 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().\r
907\r
cab450cc 908 It will release all the transmitted datagrams and receive request. It will\r
909 also configure NULL for the UDP instance.\r
cbf316f2 910\r
b45b45b2 911 @param[in] UdpIo The UDP_IO to clean up.\r
cbf316f2 912\r
cbf316f2 913**/\r
914VOID\r
7b414b4e 915EFIAPI\r
b45b45b2 916UdpIoCleanIo (\r
917 IN UDP_IO *UdpIo\r
cbf316f2 918 )\r
919{\r
920 UDP_RX_TOKEN *RxToken;\r
921\r
b45b45b2 922 ASSERT ((UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
923 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
924\r
cbf316f2 925 //\r
926 // Cancel all the sent datagram and receive requests.\r
927 //\r
928 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, NULL, NULL);\r
929\r
b45b45b2 930 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
931 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
932 UdpIo->Protocol.Udp4->Cancel (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);\r
933 }\r
934\r
935 UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, NULL);\r
cbf316f2 936\r
b45b45b2 937 } else {\r
938 if ((RxToken = UdpIo->RecvRequest) != NULL) {\r
939 UdpIo->Protocol.Udp6->Cancel (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);\r
940 }\r
941\r
942 UdpIo->Protocol.Udp6->Configure (UdpIo->Protocol.Udp6, NULL);\r
943 }\r
cbf316f2 944}\r
945\r
cbf316f2 946/**\r
b45b45b2 947 Send a packet through the UDP_IO.\r
e2851998 948\r
6d88babb
WF
949 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().\r
950\r
cab450cc 951 The packet will be wrapped in UDP_TX_TOKEN. Function Callback will be called\r
952 when the packet is sent. The optional parameter EndPoint overrides the default\r
953 address pair if specified.\r
cbf316f2 954\r
b45b45b2 955 @param[in] UdpIo The UDP_IO to send the packet through.\r
8f5e6151 956 @param[in] Packet The packet to send.\r
957 @param[in] EndPoint The local and remote access point. Override the\r
958 default address pair set during configuration.\r
e2851998 959 @param[in] Gateway The gateway to use.\r
8f5e6151 960 @param[in] CallBack The function being called when packet is\r
961 transmitted or failed.\r
962 @param[in] Context The opaque parameter passed to CallBack.\r
cbf316f2 963\r
8f5e6151 964 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the packet.\r
cbf316f2 965 @retval EFI_SUCCESS The packet is successfully delivered to UDP for\r
966 transmission.\r
967\r
968**/\r
969EFI_STATUS\r
7b414b4e 970EFIAPI\r
cbf316f2 971UdpIoSendDatagram (\r
b45b45b2 972 IN UDP_IO *UdpIo,\r
cbf316f2 973 IN NET_BUF *Packet,\r
b45b45b2 974 IN UDP_END_POINT *EndPoint OPTIONAL,\r
975 IN EFI_IP_ADDRESS *Gateway OPTIONAL,\r
cbf316f2 976 IN UDP_IO_CALLBACK CallBack,\r
977 IN VOID *Context\r
978 )\r
979{\r
b45b45b2 980 UDP_TX_TOKEN *TxToken;\r
cbf316f2 981 EFI_STATUS Status;\r
982\r
b45b45b2 983 ASSERT ((UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
984 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
cbf316f2 985\r
b45b45b2 986 TxToken = UdpIoCreateTxToken (UdpIo, Packet, EndPoint, Gateway, CallBack, Context);\r
987\r
988 if (TxToken == NULL) {\r
cbf316f2 989 return EFI_OUT_OF_RESOURCES;\r
990 }\r
991\r
36ee91ca 992 //\r
993 // Insert the tx token into SendDatagram list before transmitting it. Remove\r
994 // it from the list if the returned status is not EFI_SUCCESS.\r
995 //\r
b45b45b2 996 InsertHeadList (&UdpIo->SentDatagram, &TxToken->Link);\r
997\r
998 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
999 Status = UdpIo->Protocol.Udp4->Transmit (UdpIo->Protocol.Udp4, &TxToken->Token.Udp4);\r
1000 } else {\r
1001 Status = UdpIo->Protocol.Udp6->Transmit (UdpIo->Protocol.Udp6, &TxToken->Token.Udp6);\r
1002 }\r
1003\r
cbf316f2 1004 if (EFI_ERROR (Status)) {\r
b45b45b2 1005 RemoveEntryList (&TxToken->Link);\r
1006 UdpIoFreeTxToken (TxToken);\r
cbf316f2 1007 return Status;\r
1008 }\r
1009\r
cbf316f2 1010 return EFI_SUCCESS;\r
1011}\r
1012\r
1013\r
1014/**\r
cab450cc 1015 The select function to cancel a single sent datagram.\r
cbf316f2 1016\r
8f5e6151 1017 @param[in] Token The UDP_TX_TOKEN to test against\r
1018 @param[in] Context The NET_BUF of the sent datagram\r
cbf316f2 1019\r
9a3293ac 1020 @retval TRUE The packet is to be cancelled.\r
1021 @retval FALSE The packet is not to be cancelled.\r
cbf316f2 1022**/\r
cbf316f2 1023BOOLEAN\r
e798cd87 1024EFIAPI\r
cbf316f2 1025UdpIoCancelSingleDgram (\r
1026 IN UDP_TX_TOKEN *Token,\r
1027 IN VOID *Context\r
1028 )\r
1029{\r
1030 NET_BUF *Packet;\r
1031\r
1032 Packet = (NET_BUF *) Context;\r
1033\r
1034 if (Token->Packet == Packet) {\r
1035 return TRUE;\r
1036 }\r
1037\r
1038 return FALSE;\r
1039}\r
1040\r
cbf316f2 1041/**\r
1042 Cancel a single sent datagram.\r
1043\r
b45b45b2 1044 @param[in] UdpIo The UDP_IO to cancel the packet from\r
8f5e6151 1045 @param[in] Packet The packet to cancel\r
cbf316f2 1046\r
cbf316f2 1047**/\r
1048VOID\r
7b414b4e 1049EFIAPI\r
cbf316f2 1050UdpIoCancelSentDatagram (\r
b45b45b2 1051 IN UDP_IO *UdpIo,\r
cbf316f2 1052 IN NET_BUF *Packet\r
1053 )\r
1054{\r
1055 UdpIoCancelDgrams (UdpIo, EFI_ABORTED, UdpIoCancelSingleDgram, Packet);\r
1056}\r
1057\r
cbf316f2 1058/**\r
b45b45b2 1059 Issue a receive request to the UDP_IO.\r
e2851998 1060\r
6d88babb
WF
1061 If Udp version is not UDP_IO_UDP4_VERSION or UDP_IO_UDP6_VERSION, then ASSERT().\r
1062\r
cab450cc 1063 This function is called when upper-layer needs packet from UDP for processing.\r
1064 Only one receive request is acceptable at a time so a common usage model is\r
1065 to invoke this function inside its Callback function when the former packet\r
1066 is processed.\r
cbf316f2 1067\r
b45b45b2 1068 @param[in] UdpIo The UDP_IO to receive the packet from.\r
8f5e6151 1069 @param[in] CallBack The call back function to execute when the packet\r
1070 is received.\r
1071 @param[in] Context The opaque context passed to Callback.\r
b45b45b2 1072 @param[in] HeadLen The length of the upper-layer's protocol header.\r
cbf316f2 1073\r
1074 @retval EFI_ALREADY_STARTED There is already a pending receive request. Only\r
cab450cc 1075 one receive request is supported at a time.\r
1076 @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.\r
cbf316f2 1077 @retval EFI_SUCCESS The receive request is issued successfully.\r
b45b45b2 1078 @retval EFI_UNSUPPORTED The UDP version in UDP_IO is not supported.\r
cbf316f2 1079\r
1080**/\r
1081EFI_STATUS\r
7b414b4e 1082EFIAPI\r
cbf316f2 1083UdpIoRecvDatagram (\r
b45b45b2 1084 IN UDP_IO *UdpIo,\r
cbf316f2 1085 IN UDP_IO_CALLBACK CallBack,\r
1086 IN VOID *Context,\r
1087 IN UINT32 HeadLen\r
1088 )\r
1089{\r
b45b45b2 1090 UDP_RX_TOKEN *RxToken;\r
cbf316f2 1091 EFI_STATUS Status;\r
1092\r
b45b45b2 1093 ASSERT ((UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) ||\r
1094 (UdpIo->UdpVersion == UDP_IO_UDP6_VERSION));\r
1095\r
cbf316f2 1096 if (UdpIo->RecvRequest != NULL) {\r
1097 return EFI_ALREADY_STARTED;\r
1098 }\r
1099\r
b45b45b2 1100 RxToken = UdpIoCreateRxToken (UdpIo, CallBack, Context, HeadLen);\r
cbf316f2 1101\r
b45b45b2 1102 if (RxToken == NULL) {\r
cbf316f2 1103 return EFI_OUT_OF_RESOURCES;\r
1104 }\r
1105\r
b45b45b2 1106 UdpIo->RecvRequest = RxToken;\r
1107 if (UdpIo->UdpVersion == UDP_IO_UDP4_VERSION) {\r
1108 Status = UdpIo->Protocol.Udp4->Receive (UdpIo->Protocol.Udp4, &RxToken->Token.Udp4);\r
1109 } else {\r
1110 Status = UdpIo->Protocol.Udp6->Receive (UdpIo->Protocol.Udp6, &RxToken->Token.Udp6);\r
1111 }\r
cbf316f2 1112\r
1113 if (EFI_ERROR (Status)) {\r
36ee91ca 1114 UdpIo->RecvRequest = NULL;\r
b45b45b2 1115 UdpIoFreeRxToken (RxToken);\r
cbf316f2 1116 }\r
1117\r
36ee91ca 1118 return Status;\r
cbf316f2 1119}\r