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