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