]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Ip4Dxe/Ip4If.c
MdeModulePkg/DisplayEngine: Add Debug message to show mismatch menu info
[mirror_edk2.git] / NetworkPkg / Ip4Dxe / Ip4If.c
CommitLineData
772db4bb 1/** @file\r
6c585b52 2 Implement IP4 pseudo interface.\r
d1102dba
LG
3\r
4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
9d510e61 5SPDX-License-Identifier: BSD-2-Clause-Patent\r
772db4bb 6\r
772db4bb 7**/\r
8\r
9#include "Ip4Impl.h"\r
10\r
11//\r
6c585b52 12// Mac address with all zero, used to determine whether the ARP\r
772db4bb 13// resolve succeeded. Failed ARP requests zero the MAC address buffer.\r
14//\r
fe1e36e5 15EFI_MAC_ADDRESS mZeroMacAddress;\r
772db4bb 16\r
2ff29212 17/**\r
6c585b52 18 Callback function when frame transmission is finished. It will\r
2ff29212 19 call the frame owner's callback function to tell it the result.\r
20\r
3e8c18da 21 @param[in] Context Context which is point to the token.\r
2ff29212 22\r
23**/\r
36ee91ca 24VOID\r
25EFIAPI\r
26Ip4OnFrameSentDpc (\r
2ff29212 27 IN VOID *Context\r
36ee91ca 28 );\r
29\r
2ff29212 30/**\r
31 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.\r
32\r
3e8c18da 33 @param[in] Event The transmit token's event.\r
34 @param[in] Context Context which is point to the token.\r
2ff29212 35\r
36**/\r
772db4bb 37VOID\r
38EFIAPI\r
39Ip4OnFrameSent (\r
2ff29212 40 IN EFI_EVENT Event,\r
41 IN VOID *Context\r
772db4bb 42 );\r
43\r
2ff29212 44/**\r
45 Callback function when ARP request are finished. It will cancelled\r
46 all the queued frame if the ARP requests failed. Or transmit them\r
47 if the request succeed.\r
48\r
3e8c18da 49 @param[in] Context The context of the callback, a point to the ARP\r
2ff29212 50 queue\r
51\r
2ff29212 52**/\r
36ee91ca 53VOID\r
54EFIAPI\r
55Ip4OnArpResolvedDpc (\r
56 IN VOID *Context\r
57 );\r
58\r
2ff29212 59/**\r
60 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.\r
61\r
3e8c18da 62 @param Event The Arp request event.\r
63 @param Context The context of the callback, a point to the ARP\r
64 queue.\r
d1102dba 65\r
2ff29212 66**/\r
772db4bb 67VOID\r
68EFIAPI\r
69Ip4OnArpResolved (\r
70 IN EFI_EVENT Event,\r
71 IN VOID *Context\r
72 );\r
73\r
2ff29212 74/**\r
75 Received a frame from MNP, wrap it in net buffer then deliver\r
76 it to IP's input function. The ownship of the packet also\r
77 transferred to IP. When Ip is finished with this packet, it\r
78 will call NetbufFree to release the packet, NetbufFree will\r
79 again call the Ip4RecycleFrame to signal MNP's event and free\r
80 the token used.\r
81\r
82 @param Context Context for the callback.\r
83\r
2ff29212 84**/\r
36ee91ca 85VOID\r
86EFIAPI\r
87Ip4OnFrameReceivedDpc (\r
2ff29212 88 IN VOID *Context\r
36ee91ca 89 );\r
90\r
2ff29212 91/**\r
2ff29212 92 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.\r
93\r
94 @param Event The receive event delivered to MNP for receive.\r
95 @param Context Context for the callback.\r
2ff29212 96\r
97**/\r
772db4bb 98VOID\r
99EFIAPI\r
100Ip4OnFrameReceived (\r
2ff29212 101 IN EFI_EVENT Event,\r
102 IN VOID *Context\r
772db4bb 103 );\r
104\r
2ff29212 105/**\r
106 Remove all the frames on the ARP queue that pass the FrameToCancel,\r
107 that is, either FrameToCancel is NULL or it returns true for the frame.\r
108\r
3e8c18da 109 @param[in] ArpQue ARP frame to remove the frames from.\r
110 @param[in] IoStatus The status returned to the cancelled frames'\r
2ff29212 111 callback function.\r
3e8c18da 112 @param[in] FrameToCancel Function to select which frame to cancel.\r
113 @param[in] Context Opaque parameter to the FrameToCancel.\r
2ff29212 114\r
115**/\r
772db4bb 116VOID\r
117Ip4CancelFrameArp (\r
118 IN IP4_ARP_QUE *ArpQue,\r
119 IN EFI_STATUS IoStatus,\r
24af132f 120 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,\r
772db4bb 121 IN VOID *Context\r
122 );\r
123\r
124\r
125/**\r
126 Wrap a transmit request into a newly allocated IP4_LINK_TX_TOKEN.\r
127\r
3e8c18da 128 @param[in] Interface The interface to send out to.\r
129 @param[in] IpInstance The IpInstance that transmit the packet. NULL if\r
772db4bb 130 the packet is sent by the IP4 driver itself.\r
3e8c18da 131 @param[in] Packet The packet to transmit\r
132 @param[in] CallBack Call back function to execute if transmission\r
772db4bb 133 finished.\r
3e8c18da 134 @param[in] Context Opaque parameter to the call back.\r
12ae56cf 135 @param[in] IpSb The pointer to the IP4 service binding instance.\r
772db4bb 136\r
d1102dba 137 @retval Token The wrapped token if succeed\r
3e8c18da 138 @retval NULL The wrapped token if NULL\r
772db4bb 139\r
140**/\r
772db4bb 141IP4_LINK_TX_TOKEN *\r
142Ip4WrapLinkTxToken (\r
143 IN IP4_INTERFACE *Interface,\r
24af132f 144 IN IP4_PROTOCOL *IpInstance OPTIONAL,\r
772db4bb 145 IN NET_BUF *Packet,\r
146 IN IP4_FRAME_CALLBACK CallBack,\r
12ae56cf
FS
147 IN VOID *Context,\r
148 IN IP4_SERVICE *IpSb\r
772db4bb 149 )\r
150{\r
151 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
152 EFI_MANAGED_NETWORK_TRANSMIT_DATA *MnpTxData;\r
153 IP4_LINK_TX_TOKEN *Token;\r
154 EFI_STATUS Status;\r
155 UINT32 Count;\r
156\r
e48e37fc 157 Token = AllocatePool (sizeof (IP4_LINK_TX_TOKEN) + \\r
772db4bb 158 (Packet->BlockOpNum - 1) * sizeof (EFI_MANAGED_NETWORK_FRAGMENT_DATA));\r
159\r
160 if (Token == NULL) {\r
161 return NULL;\r
162 }\r
163\r
164 Token->Signature = IP4_FRAME_TX_SIGNATURE;\r
e48e37fc 165 InitializeListHead (&Token->Link);\r
772db4bb 166\r
167 Token->Interface = Interface;\r
168 Token->IpInstance = IpInstance;\r
12ae56cf 169 Token->IpSb = IpSb;\r
772db4bb 170 Token->CallBack = CallBack;\r
171 Token->Packet = Packet;\r
172 Token->Context = Context;\r
687a2e5f 173 CopyMem (&Token->DstMac, &mZeroMacAddress, sizeof (Token->DstMac));\r
174 CopyMem (&Token->SrcMac, &Interface->Mac, sizeof (Token->SrcMac));\r
772db4bb 175\r
176 MnpToken = &(Token->MnpToken);\r
177 MnpToken->Status = EFI_NOT_READY;\r
178\r
179 Status = gBS->CreateEvent (\r
180 EVT_NOTIFY_SIGNAL,\r
e48e37fc 181 TPL_NOTIFY,\r
772db4bb 182 Ip4OnFrameSent,\r
183 Token,\r
184 &MnpToken->Event\r
185 );\r
186\r
187 if (EFI_ERROR (Status)) {\r
766c7483 188 FreePool (Token);\r
772db4bb 189 return NULL;\r
190 }\r
191\r
192 MnpTxData = &Token->MnpTxData;\r
193 MnpToken->Packet.TxData = MnpTxData;\r
194\r
195 MnpTxData->DestinationAddress = &Token->DstMac;\r
196 MnpTxData->SourceAddress = &Token->SrcMac;\r
197 MnpTxData->ProtocolType = IP4_ETHER_PROTO;\r
198 MnpTxData->DataLength = Packet->TotalSize;\r
199 MnpTxData->HeaderLength = 0;\r
200\r
201 Count = Packet->BlockOpNum;\r
202\r
203 NetbufBuildExt (Packet, (NET_FRAGMENT *) MnpTxData->FragmentTable, &Count);\r
204 MnpTxData->FragmentCount = (UINT16)Count;\r
205\r
206 return Token;\r
207}\r
208\r
209\r
210/**\r
211 Free the link layer transmit token. It will close the event\r
212 then free the memory used.\r
213\r
3e8c18da 214 @param[in] Token Token to free\r
772db4bb 215\r
216**/\r
772db4bb 217VOID\r
218Ip4FreeLinkTxToken (\r
219 IN IP4_LINK_TX_TOKEN *Token\r
220 )\r
221{\r
222 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);\r
223\r
224 gBS->CloseEvent (Token->MnpToken.Event);\r
766c7483 225 FreePool (Token);\r
772db4bb 226}\r
227\r
228\r
229/**\r
230 Create an IP_ARP_QUE structure to request ARP service.\r
231\r
3e8c18da 232 @param[in] Interface The interface to send ARP from.\r
233 @param[in] DestIp The destination IP (host byte order) to request MAC\r
772db4bb 234 for\r
235\r
236 @return Point to newly created IP4_ARP_QUE if succeed, otherwise NULL.\r
237\r
238**/\r
772db4bb 239IP4_ARP_QUE *\r
240Ip4CreateArpQue (\r
241 IN IP4_INTERFACE *Interface,\r
242 IN IP4_ADDR DestIp\r
243 )\r
244{\r
245 IP4_ARP_QUE *ArpQue;\r
246 EFI_STATUS Status;\r
247\r
e48e37fc 248 ArpQue = AllocatePool (sizeof (IP4_ARP_QUE));\r
772db4bb 249\r
250 if (ArpQue == NULL) {\r
251 return NULL;\r
252 }\r
253\r
254 ArpQue->Signature = IP4_FRAME_ARP_SIGNATURE;\r
e48e37fc 255 InitializeListHead (&ArpQue->Link);\r
772db4bb 256\r
e48e37fc 257 InitializeListHead (&ArpQue->Frames);\r
772db4bb 258 ArpQue->Interface = Interface;\r
259\r
260 Status = gBS->CreateEvent (\r
261 EVT_NOTIFY_SIGNAL,\r
e48e37fc 262 TPL_NOTIFY,\r
772db4bb 263 Ip4OnArpResolved,\r
264 ArpQue,\r
265 &ArpQue->OnResolved\r
266 );\r
267\r
268 if (EFI_ERROR (Status)) {\r
766c7483 269 FreePool (ArpQue);\r
772db4bb 270 return NULL;\r
271 }\r
272\r
273 ArpQue->Ip = DestIp;\r
687a2e5f 274 CopyMem (&ArpQue->Mac, &mZeroMacAddress, sizeof (ArpQue->Mac));\r
772db4bb 275\r
276 return ArpQue;\r
277}\r
278\r
279\r
280/**\r
281 Remove all the transmit requests queued on the ARP queue, then free it.\r
282\r
3e8c18da 283 @param[in] ArpQue Arp queue to free\r
284 @param[in] IoStatus The transmit status returned to transmit requests'\r
772db4bb 285 callback.\r
286\r
772db4bb 287**/\r
772db4bb 288VOID\r
289Ip4FreeArpQue (\r
290 IN IP4_ARP_QUE *ArpQue,\r
291 IN EFI_STATUS IoStatus\r
292 )\r
293{\r
294 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);\r
295\r
296 //\r
297 // Remove all the frame waiting the ARP response\r
298 //\r
299 Ip4CancelFrameArp (ArpQue, IoStatus, NULL, NULL);\r
300\r
301 gBS->CloseEvent (ArpQue->OnResolved);\r
766c7483 302 FreePool (ArpQue);\r
772db4bb 303}\r
304\r
305\r
306/**\r
307 Create a link layer receive token to wrap the receive request\r
308\r
3e8c18da 309 @param[in] Interface The interface to receive from\r
310 @param[in] IpInstance The instance that request the receive (NULL for IP4\r
772db4bb 311 driver itself)\r
3e8c18da 312 @param[in] CallBack Call back function to execute when finished.\r
313 @param[in] Context Opaque parameters to the callback\r
772db4bb 314\r
315 @return Point to created IP4_LINK_RX_TOKEN if succeed, otherwise NULL.\r
316\r
317**/\r
772db4bb 318IP4_LINK_RX_TOKEN *\r
319Ip4CreateLinkRxToken (\r
320 IN IP4_INTERFACE *Interface,\r
321 IN IP4_PROTOCOL *IpInstance,\r
322 IN IP4_FRAME_CALLBACK CallBack,\r
323 IN VOID *Context\r
324 )\r
325{\r
326 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
327 IP4_LINK_RX_TOKEN *Token;\r
328 EFI_STATUS Status;\r
329\r
e48e37fc 330 Token = AllocatePool (sizeof (IP4_LINK_RX_TOKEN));\r
772db4bb 331 if (Token == NULL) {\r
332 return NULL;\r
333 }\r
334\r
335 Token->Signature = IP4_FRAME_RX_SIGNATURE;\r
336 Token->Interface = Interface;\r
337 Token->IpInstance = IpInstance;\r
338 Token->CallBack = CallBack;\r
339 Token->Context = Context;\r
340\r
341 MnpToken = &Token->MnpToken;\r
342 MnpToken->Status = EFI_NOT_READY;\r
343\r
344 Status = gBS->CreateEvent (\r
345 EVT_NOTIFY_SIGNAL,\r
e48e37fc 346 TPL_NOTIFY,\r
772db4bb 347 Ip4OnFrameReceived,\r
348 Token,\r
349 &MnpToken->Event\r
350 );\r
351\r
352 if (EFI_ERROR (Status)) {\r
766c7483 353 FreePool (Token);\r
772db4bb 354 return NULL;\r
355 }\r
356\r
357 MnpToken->Packet.RxData = NULL;\r
358 return Token;\r
359}\r
360\r
361\r
362/**\r
363 Free the link layer request token. It will close the event\r
364 then free the memory used.\r
365\r
3e8c18da 366 @param[in] Token Request token to free.\r
772db4bb 367\r
368**/\r
772db4bb 369VOID\r
370Ip4FreeFrameRxToken (\r
371 IN IP4_LINK_RX_TOKEN *Token\r
372 )\r
373{\r
374\r
375 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);\r
376\r
377 gBS->CloseEvent (Token->MnpToken.Event);\r
766c7483 378 FreePool (Token);\r
772db4bb 379}\r
380\r
381\r
382/**\r
383 Remove all the frames on the ARP queue that pass the FrameToCancel,\r
384 that is, either FrameToCancel is NULL or it returns true for the frame.\r
385\r
3e8c18da 386 @param[in] ArpQue ARP frame to remove the frames from.\r
387 @param[in] IoStatus The status returned to the cancelled frames'\r
772db4bb 388 callback function.\r
3e8c18da 389 @param[in] FrameToCancel Function to select which frame to cancel.\r
390 @param[in] Context Opaque parameter to the FrameToCancel.\r
772db4bb 391\r
392**/\r
772db4bb 393VOID\r
394Ip4CancelFrameArp (\r
395 IN IP4_ARP_QUE *ArpQue,\r
396 IN EFI_STATUS IoStatus,\r
24af132f 397 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,\r
772db4bb 398 IN VOID *Context\r
399 )\r
400{\r
e48e37fc 401 LIST_ENTRY *Entry;\r
402 LIST_ENTRY *Next;\r
772db4bb 403 IP4_LINK_TX_TOKEN *Token;\r
404\r
405 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
406 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
407\r
408 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {\r
e48e37fc 409 RemoveEntryList (Entry);\r
772db4bb 410\r
411 Token->CallBack (Token->IpInstance, Token->Packet, IoStatus, 0, Token->Context);\r
412 Ip4FreeLinkTxToken (Token);\r
413 }\r
414 }\r
415}\r
416\r
417\r
418/**\r
419 Remove all the frames on the interface that pass the FrameToCancel,\r
420 either queued on ARP queues or that have already been delivered to\r
421 MNP and not yet recycled.\r
422\r
1f6729ff 423 @param[in] Interface Interface to remove the frames from.\r
3e8c18da 424 @param[in] IoStatus The transmit status returned to the frames'\r
1f6729ff 425 callback.\r
3e8c18da 426 @param[in] FrameToCancel Function to select the frame to cancel, NULL to\r
1f6729ff 427 select all.\r
428 @param[in] Context Opaque parameters passed to FrameToCancel.\r
772db4bb 429\r
430**/\r
431VOID\r
432Ip4CancelFrames (\r
433 IN IP4_INTERFACE *Interface,\r
434 IN EFI_STATUS IoStatus,\r
24af132f 435 IN IP4_FRAME_TO_CANCEL FrameToCancel OPTIONAL,\r
772db4bb 436 IN VOID *Context\r
437 )\r
438{\r
e48e37fc 439 LIST_ENTRY *Entry;\r
440 LIST_ENTRY *Next;\r
772db4bb 441 IP4_ARP_QUE *ArpQue;\r
442 IP4_LINK_TX_TOKEN *Token;\r
443\r
444 //\r
445 // Cancel all the pending frames on ARP requests\r
446 //\r
447 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->ArpQues) {\r
448 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);\r
449\r
450 Ip4CancelFrameArp (ArpQue, IoStatus, FrameToCancel, Context);\r
451\r
e48e37fc 452 if (IsListEmpty (&ArpQue->Frames)) {\r
772db4bb 453 Interface->Arp->Cancel (Interface->Arp, &ArpQue->Ip, ArpQue->OnResolved);\r
772db4bb 454 }\r
455 }\r
456\r
457 //\r
458 // Cancel all the frames that have been delivered to MNP\r
459 // but not yet recycled.\r
460 //\r
461 NET_LIST_FOR_EACH_SAFE (Entry, Next, &Interface->SentFrames) {\r
462 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
463\r
464 if ((FrameToCancel == NULL) || FrameToCancel (Token, Context)) {\r
772db4bb 465 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);\r
772db4bb 466 }\r
467 }\r
468}\r
469\r
470\r
471/**\r
472 Create an IP4_INTERFACE. Delay the creation of ARP instance until\r
473 the interface is configured.\r
474\r
3e8c18da 475 @param[in] Mnp The shared MNP child of this IP4 service binding\r
1f6729ff 476 instance.\r
3e8c18da 477 @param[in] Controller The controller this IP4 service binding instance\r
772db4bb 478 is installed. Most like the UNDI handle.\r
1f6729ff 479 @param[in] ImageHandle This driver's image handle.\r
772db4bb 480\r
481 @return Point to the created IP4_INTERFACE, otherwise NULL.\r
482\r
483**/\r
484IP4_INTERFACE *\r
485Ip4CreateInterface (\r
486 IN EFI_MANAGED_NETWORK_PROTOCOL *Mnp,\r
487 IN EFI_HANDLE Controller,\r
488 IN EFI_HANDLE ImageHandle\r
489 )\r
490{\r
491 IP4_INTERFACE *Interface;\r
492 EFI_SIMPLE_NETWORK_MODE SnpMode;\r
493\r
4f47eaf9
MR
494 if (Mnp == NULL) {\r
495 return NULL;\r
496 }\r
497\r
e48e37fc 498 Interface = AllocatePool (sizeof (IP4_INTERFACE));\r
772db4bb 499\r
4f47eaf9 500 if (Interface == NULL) {\r
772db4bb 501 return NULL;\r
502 }\r
503\r
504 Interface->Signature = IP4_INTERFACE_SIGNATURE;\r
e48e37fc 505 InitializeListHead (&Interface->Link);\r
772db4bb 506 Interface->RefCnt = 1;\r
507\r
508 Interface->Ip = IP4_ALLZERO_ADDRESS;\r
509 Interface->SubnetMask = IP4_ALLZERO_ADDRESS;\r
510 Interface->Configured = FALSE;\r
511\r
512 Interface->Controller = Controller;\r
513 Interface->Image = ImageHandle;\r
514 Interface->Mnp = Mnp;\r
515 Interface->Arp = NULL;\r
516 Interface->ArpHandle = NULL;\r
517\r
e48e37fc 518 InitializeListHead (&Interface->ArpQues);\r
519 InitializeListHead (&Interface->SentFrames);\r
772db4bb 520\r
521 Interface->RecvRequest = NULL;\r
522\r
523 //\r
524 // Get the interface's Mac address and broadcast mac address from SNP\r
525 //\r
526 if (EFI_ERROR (Mnp->GetModeData (Mnp, NULL, &SnpMode))) {\r
766c7483 527 FreePool (Interface);\r
772db4bb 528 return NULL;\r
529 }\r
530\r
687a2e5f 531 CopyMem (&Interface->Mac, &SnpMode.CurrentAddress, sizeof (Interface->Mac));\r
532 CopyMem (&Interface->BroadcastMac, &SnpMode.BroadcastAddress, sizeof (Interface->BroadcastMac));\r
772db4bb 533 Interface->HwaddrLen = SnpMode.HwAddressSize;\r
534\r
e48e37fc 535 InitializeListHead (&Interface->IpInstances);\r
772db4bb 536 Interface->PromiscRecv = FALSE;\r
537\r
538 return Interface;\r
539}\r
540\r
541\r
542/**\r
543 Set the interface's address, create and configure\r
544 the ARP child if necessary.\r
545\r
1f6729ff 546 @param Interface The interface to set the address.\r
547 @param IpAddr The interface's IP address.\r
548 @param SubnetMask The interface's netmask.\r
772db4bb 549\r
550 @retval EFI_SUCCESS The interface is configured with Ip/netmask pair,\r
551 and a ARP is created for it.\r
552 @retval Others Failed to set the interface's address.\r
553\r
554**/\r
555EFI_STATUS\r
556Ip4SetAddress (\r
5405e9a6 557 IN OUT IP4_INTERFACE *Interface,\r
558 IN IP4_ADDR IpAddr,\r
559 IN IP4_ADDR SubnetMask\r
772db4bb 560 )\r
561{\r
562 EFI_ARP_CONFIG_DATA ArpConfig;\r
563 EFI_STATUS Status;\r
772db4bb 564\r
565 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
566\r
772db4bb 567 //\r
568 // Set the ip/netmask, then compute the subnet broadcast\r
569 // and network broadcast for easy access. When computing\r
6c585b52 570 // network broadcast, the subnet mask is most like longer\r
772db4bb 571 // than the default netmask (not subneted) as defined in\r
572 // RFC793. If that isn't the case, we are aggregating the\r
573 // networks, use the subnet's mask instead.\r
574 //\r
575 Interface->Ip = IpAddr;\r
576 Interface->SubnetMask = SubnetMask;\r
577 Interface->SubnetBrdcast = (IpAddr | ~SubnetMask);\r
01b5ac88 578 Interface->NetBrdcast = (IpAddr | ~SubnetMask);\r
772db4bb 579\r
1f6729ff 580 //\r
581 // Do clean up for Arp child\r
582 //\r
583 if (Interface->ArpHandle != NULL) {\r
584 if (Interface->Arp != NULL) {\r
585 gBS->CloseProtocol (\r
586 Interface->ArpHandle,\r
587 &gEfiArpProtocolGuid,\r
588 Interface->Image,\r
589 Interface->Controller\r
590 );\r
d1102dba 591\r
1f6729ff 592 Interface->Arp = NULL;\r
593 }\r
d1102dba 594\r
1f6729ff 595 NetLibDestroyServiceChild (\r
596 Interface->Controller,\r
597 Interface->Image,\r
598 &gEfiArpServiceBindingProtocolGuid,\r
2c9abfd5 599 Interface->ArpHandle\r
1f6729ff 600 );\r
601\r
602 Interface->ArpHandle = NULL;\r
603 }\r
604\r
772db4bb 605 //\r
606 // If the address is NOT all zero, create then configure an ARP child.\r
607 // Pay attention: DHCP configures its station address as 0.0.0.0/0\r
608 //\r
772db4bb 609 if (IpAddr != IP4_ALLZERO_ADDRESS) {\r
610 Status = NetLibCreateServiceChild (\r
611 Interface->Controller,\r
612 Interface->Image,\r
613 &gEfiArpServiceBindingProtocolGuid,\r
614 &Interface->ArpHandle\r
615 );\r
616\r
617 if (EFI_ERROR (Status)) {\r
1f6729ff 618 return Status;\r
772db4bb 619 }\r
620\r
621 Status = gBS->OpenProtocol (\r
622 Interface->ArpHandle,\r
623 &gEfiArpProtocolGuid,\r
624 (VOID **) &Interface->Arp,\r
625 Interface->Image,\r
626 Interface->Controller,\r
627 EFI_OPEN_PROTOCOL_BY_DRIVER\r
628 );\r
629\r
630 if (EFI_ERROR (Status)) {\r
631 goto ON_ERROR;\r
632 }\r
633\r
634 IpAddr = HTONL (IpAddr);\r
635 ArpConfig.SwAddressType = IP4_ETHER_PROTO;\r
636 ArpConfig.SwAddressLength = 4;\r
637 ArpConfig.StationAddress = &IpAddr;\r
638 ArpConfig.EntryTimeOut = 0;\r
639 ArpConfig.RetryCount = 0;\r
640 ArpConfig.RetryTimeOut = 0;\r
641\r
642 Status = Interface->Arp->Configure (Interface->Arp, &ArpConfig);\r
643\r
644 if (EFI_ERROR (Status)) {\r
645 gBS->CloseProtocol (\r
1f6729ff 646 Interface->ArpHandle,\r
647 &gEfiArpProtocolGuid,\r
648 Interface->Image,\r
649 Interface->Controller\r
650 );\r
772db4bb 651\r
652 goto ON_ERROR;\r
653 }\r
654 }\r
655\r
656 Interface->Configured = TRUE;\r
657 return EFI_SUCCESS;\r
658\r
659ON_ERROR:\r
660 NetLibDestroyServiceChild (\r
661 Interface->Controller,\r
662 Interface->Image,\r
663 &gEfiArpServiceBindingProtocolGuid,\r
2c9abfd5 664 Interface->ArpHandle\r
772db4bb 665 );\r
666\r
667 return Status;\r
668}\r
669\r
670\r
671/**\r
5405e9a6 672 Filter function to cancel all the frame related to an IP instance.\r
772db4bb 673\r
3e8c18da 674 @param[in] Frame The transmit request to test whether to cancel\r
675 @param[in] Context The context which is the Ip instance that issued\r
772db4bb 676 the transmit.\r
677\r
678 @retval TRUE The frame belongs to this instance and is to be\r
679 removed\r
680 @retval FALSE The frame doesn't belong to this instance.\r
681\r
682**/\r
772db4bb 683BOOLEAN\r
684Ip4CancelInstanceFrame (\r
685 IN IP4_LINK_TX_TOKEN *Frame,\r
686 IN VOID *Context\r
687 )\r
688{\r
689 if (Frame->IpInstance == (IP4_PROTOCOL *) Context) {\r
690 return TRUE;\r
691 }\r
692\r
693 return FALSE;\r
694}\r
695\r
696\r
697\r
698/**\r
699 If there is a pending receive request, cancel it. Don't call\r
700 the receive request's callback because this function can be only\r
701 called if the instance or driver is tearing itself down. It\r
702 doesn't make sense to call it back. But it is necessary to call\r
703 the transmit token's callback to give it a chance to free the\r
704 packet and update the upper layer's transmit request status, say\r
705 that from the UDP.\r
706\r
3e8c18da 707 @param[in] Interface The interface used by the IpInstance\r
772db4bb 708\r
709**/\r
710VOID\r
711Ip4CancelReceive (\r
712 IN IP4_INTERFACE *Interface\r
713 )\r
714{\r
715 EFI_TPL OldTpl;\r
716 IP4_LINK_RX_TOKEN *Token;\r
717\r
718 if ((Token = Interface->RecvRequest) != NULL) {\r
e48e37fc 719 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 720\r
721 Interface->RecvRequest = NULL;\r
722 Interface->Mnp->Cancel (Interface->Mnp, &Token->MnpToken);\r
772db4bb 723\r
e48e37fc 724 gBS->RestoreTPL (OldTpl);\r
772db4bb 725 }\r
726}\r
727\r
728\r
729/**\r
730 Free the interface used by IpInstance. All the IP instance with\r
731 the same Ip/Netmask pair share the same interface. It is reference\r
732 counted. All the frames haven't been sent will be cancelled.\r
733 Because the IpInstance is optional, the caller must remove\r
734 IpInstance from the interface's instance list itself.\r
735\r
1f6729ff 736 @param[in] Interface The interface used by the IpInstance.\r
3e8c18da 737 @param[in] IpInstance The Ip instance that free the interface. NULL if\r
5405e9a6 738 the Ip driver is releasing the default interface.\r
772db4bb 739\r
740 @retval EFI_SUCCESS The interface use IpInstance is freed.\r
741\r
742**/\r
743EFI_STATUS\r
744Ip4FreeInterface (\r
745 IN IP4_INTERFACE *Interface,\r
746 IN IP4_PROTOCOL *IpInstance OPTIONAL\r
747 )\r
748{\r
749 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
750 ASSERT (Interface->RefCnt > 0);\r
751\r
752 //\r
753 // Remove all the pending transmit token related to this IP instance.\r
754 //\r
755 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, IpInstance);\r
756\r
d0ccf55e 757 if (--Interface->RefCnt > 0) {\r
758 return EFI_SUCCESS;\r
759 }\r
760\r
772db4bb 761 //\r
d0ccf55e 762 // Destroy the interface if this is the last IP instance that\r
763 // has the address. Remove all the system transmitted packets\r
764 // from this interface, cancel the receive request if there is\r
765 // one, and destroy the ARP requests.\r
772db4bb 766 //\r
d0ccf55e 767 Ip4CancelFrames (Interface, EFI_ABORTED, Ip4CancelInstanceFrame, NULL);\r
768 Ip4CancelReceive (Interface);\r
769\r
770 ASSERT (IsListEmpty (&Interface->IpInstances));\r
771 ASSERT (IsListEmpty (&Interface->ArpQues));\r
772 ASSERT (IsListEmpty (&Interface->SentFrames));\r
773\r
774 if (Interface->Arp != NULL) {\r
772db4bb 775 gBS->CloseProtocol (\r
776 Interface->ArpHandle,\r
777 &gEfiArpProtocolGuid,\r
778 Interface->Image,\r
779 Interface->Controller\r
780 );\r
781\r
782 NetLibDestroyServiceChild (\r
783 Interface->Controller,\r
784 Interface->Image,\r
785 &gEfiArpServiceBindingProtocolGuid,\r
786 Interface->ArpHandle\r
787 );\r
788 }\r
789\r
e48e37fc 790 RemoveEntryList (&Interface->Link);\r
766c7483 791 FreePool (Interface);\r
772db4bb 792\r
793 return EFI_SUCCESS;\r
794}\r
795\r
12ae56cf 796/**\r
4a76d9b9 797 This function tries to send all the queued frames in ArpQue to the default gateway if\r
12ae56cf
FS
798 the ARP resolve for direct destination address is failed when using /32 subnet mask.\r
799\r
800 @param[in] ArpQue The ARP queue of a failed request.\r
4a76d9b9 801\r
12ae56cf
FS
802 @retval EFI_SUCCESS All the queued frames have been send to the default route.\r
803 @retval Others Failed to send the queued frames.\r
4a76d9b9 804\r
12ae56cf
FS
805**/\r
806EFI_STATUS\r
807Ip4SendFrameToDefaultRoute (\r
808 IN IP4_ARP_QUE *ArpQue\r
809 )\r
810{\r
811 LIST_ENTRY *Entry;\r
812 LIST_ENTRY *Next;\r
813 IP4_ROUTE_CACHE_ENTRY *RtCacheEntry;\r
814 IP4_LINK_TX_TOKEN *Token;\r
815 IP4_ADDR Gateway;\r
816 EFI_STATUS Status;\r
817 IP4_ROUTE_ENTRY *DefaultRoute;\r
4a76d9b9 818\r
12ae56cf
FS
819 //\r
820 // ARP resolve failed when using /32 subnet mask.\r
821 //\r
822 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
823 RemoveEntryList (Entry);\r
824 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
825 ASSERT (Token->Interface->SubnetMask == IP4_ALLONE_ADDRESS);\r
826 //\r
827 // Find the default gateway IP address. The default route was saved to the RtCacheEntry->Tag in Ip4Route().\r
828 //\r
829 RtCacheEntry = NULL;\r
830 if (Token->IpInstance != NULL) {\r
831 RtCacheEntry = Ip4FindRouteCache (Token->IpInstance->RouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
832 }\r
833 if (RtCacheEntry == NULL) {\r
834 RtCacheEntry = Ip4FindRouteCache (Token->IpSb->DefaultRouteTable, NTOHL (ArpQue->Ip), Token->Interface->Ip);\r
835 }\r
836 if (RtCacheEntry == NULL) {\r
837 Status= EFI_NO_MAPPING;\r
838 goto ON_ERROR;\r
839 }\r
840 DefaultRoute = (IP4_ROUTE_ENTRY*)RtCacheEntry->Tag;\r
841 if (DefaultRoute == NULL) {\r
842 Status= EFI_NO_MAPPING;\r
843 goto ON_ERROR;\r
844 }\r
845 //\r
846 // Try to send the frame to the default route.\r
847 //\r
848 Gateway = DefaultRoute->NextHop;\r
849 if (ArpQue->Ip == Gateway) {\r
850 //\r
4a76d9b9 851 // ARP resolve for the default route is failed, return error to caller.\r
12ae56cf
FS
852 //\r
853 Status= EFI_NO_MAPPING;\r
854 goto ON_ERROR;\r
855 }\r
856 RtCacheEntry->NextHop = Gateway;\r
857 Status = Ip4SendFrame (Token->Interface,Token->IpInstance,Token->Packet,Gateway,Token->CallBack,Token->Context,Token->IpSb);\r
858 if (EFI_ERROR (Status)) {\r
859 Status= EFI_NO_MAPPING;\r
860 goto ON_ERROR;\r
861 }\r
862 Ip4FreeRouteCacheEntry (RtCacheEntry);\r
863 }\r
864\r
865 return EFI_SUCCESS;\r
4a76d9b9 866\r
12ae56cf
FS
867ON_ERROR:\r
868 if (RtCacheEntry != NULL) {\r
869 Ip4FreeRouteCacheEntry (RtCacheEntry);\r
870 }\r
871 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
872 Ip4FreeLinkTxToken (Token);\r
873 return Status;\r
874}\r
875\r
772db4bb 876\r
877/**\r
12ae56cf 878 Callback function when ARP request are finished. It will cancel\r
772db4bb 879 all the queued frame if the ARP requests failed. Or transmit them\r
880 if the request succeed.\r
881\r
3e8c18da 882 @param[in] Context The context of the callback, a point to the ARP\r
772db4bb 883 queue\r
884\r
772db4bb 885**/\r
772db4bb 886VOID\r
887EFIAPI\r
36ee91ca 888Ip4OnArpResolvedDpc (\r
772db4bb 889 IN VOID *Context\r
890 )\r
891{\r
e48e37fc 892 LIST_ENTRY *Entry;\r
893 LIST_ENTRY *Next;\r
772db4bb 894 IP4_ARP_QUE *ArpQue;\r
895 IP4_INTERFACE *Interface;\r
896 IP4_LINK_TX_TOKEN *Token;\r
897 EFI_STATUS Status;\r
12ae56cf 898 EFI_STATUS IoStatus;\r
772db4bb 899\r
900 ArpQue = (IP4_ARP_QUE *) Context;\r
901 NET_CHECK_SIGNATURE (ArpQue, IP4_FRAME_ARP_SIGNATURE);\r
902\r
e48e37fc 903 RemoveEntryList (&ArpQue->Link);\r
772db4bb 904\r
905 //\r
4a76d9b9 906 // ARP resolve failed for some reason.\r
772db4bb 907 //\r
908 if (NET_MAC_EQUAL (&ArpQue->Mac, &mZeroMacAddress, ArpQue->Interface->HwaddrLen)) {\r
12ae56cf
FS
909 if (ArpQue->Interface->SubnetMask != IP4_ALLONE_ADDRESS) {\r
910 //\r
911 // Release all the frame and ARP queue itself. Ip4FreeArpQue will call the frame's\r
912 // owner back.\r
913 //\r
914 IoStatus = EFI_NO_MAPPING;\r
915 } else {\r
916 //\r
917 // ARP resolve failed when using 32bit subnet mask, try to send the packets to the\r
918 // default route.\r
919 //\r
920 IoStatus = Ip4SendFrameToDefaultRoute (ArpQue);\r
921 }\r
922 goto ON_EXIT;\r
772db4bb 923 }\r
924\r
925 //\r
926 // ARP resolve succeeded, Transmit all the frame. Release the ARP\r
927 // queue. It isn't necessary for us to cache the ARP binding because\r
928 // we always check the ARP cache first before transmit.\r
929 //\r
12ae56cf 930 IoStatus = EFI_SUCCESS;\r
772db4bb 931 Interface = ArpQue->Interface;\r
932\r
933 NET_LIST_FOR_EACH_SAFE (Entry, Next, &ArpQue->Frames) {\r
e48e37fc 934 RemoveEntryList (Entry);\r
772db4bb 935\r
936 Token = NET_LIST_USER_STRUCT (Entry, IP4_LINK_TX_TOKEN, Link);\r
687a2e5f 937 CopyMem (&Token->DstMac, &ArpQue->Mac, sizeof (Token->DstMac));\r
772db4bb 938\r
36ee91ca 939 //\r
940 // Insert the tx token before transmitting it via MNP as the FrameSentDpc\r
941 // may be called before Mnp->Transmit returns which will remove this tx\r
942 // token from the SentFrames list. Remove it from the list if the returned\r
943 // Status of Mnp->Transmit is not EFI_SUCCESS as in this case the\r
944 // FrameSentDpc won't be queued.\r
945 //\r
e48e37fc 946 InsertTailList (&Interface->SentFrames, &Token->Link);\r
772db4bb 947\r
36ee91ca 948 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
772db4bb 949 if (EFI_ERROR (Status)) {\r
ad18ec95 950 RemoveEntryList (&Token->Link);\r
772db4bb 951 Token->CallBack (Token->IpInstance, Token->Packet, Status, 0, Token->Context);\r
952\r
953 Ip4FreeLinkTxToken (Token);\r
954 continue;\r
955 }\r
772db4bb 956 }\r
957\r
12ae56cf
FS
958ON_EXIT:\r
959 Ip4FreeArpQue (ArpQue, IoStatus);\r
772db4bb 960}\r
961\r
5405e9a6 962/**\r
963 Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK.\r
964\r
3e8c18da 965 @param Event The Arp request event.\r
966 @param Context The context of the callback, a point to the ARP\r
967 queue.\r
d1102dba 968\r
5405e9a6 969**/\r
36ee91ca 970VOID\r
971EFIAPI\r
972Ip4OnArpResolved (\r
973 IN EFI_EVENT Event,\r
974 IN VOID *Context\r
975 )\r
36ee91ca 976{\r
977 //\r
978 // Request Ip4OnArpResolvedDpc as a DPC at TPL_CALLBACK\r
979 //\r
d8d26fb2 980 QueueDpc (TPL_CALLBACK, Ip4OnArpResolvedDpc, Context);\r
36ee91ca 981}\r
982\r
983\r
772db4bb 984\r
985/**\r
6c585b52 986 Callback function when frame transmission is finished. It will\r
772db4bb 987 call the frame owner's callback function to tell it the result.\r
988\r
3e8c18da 989 @param[in] Context Context which is point to the token.\r
772db4bb 990\r
991**/\r
772db4bb 992VOID\r
993EFIAPI\r
36ee91ca 994Ip4OnFrameSentDpc (\r
772db4bb 995 IN VOID *Context\r
996 )\r
997{\r
998 IP4_LINK_TX_TOKEN *Token;\r
999\r
1000 Token = (IP4_LINK_TX_TOKEN *) Context;\r
1001 NET_CHECK_SIGNATURE (Token, IP4_FRAME_TX_SIGNATURE);\r
1002\r
e48e37fc 1003 RemoveEntryList (&Token->Link);\r
772db4bb 1004\r
1005 Token->CallBack (\r
1006 Token->IpInstance,\r
1007 Token->Packet,\r
1008 Token->MnpToken.Status,\r
1009 0,\r
1010 Token->Context\r
1011 );\r
1012\r
1013 Ip4FreeLinkTxToken (Token);\r
1014}\r
1015\r
5405e9a6 1016/**\r
1017 Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK.\r
1018\r
3e8c18da 1019 @param[in] Event The transmit token's event.\r
1020 @param[in] Context Context which is point to the token.\r
5405e9a6 1021\r
1022**/\r
36ee91ca 1023VOID\r
1024EFIAPI\r
1025Ip4OnFrameSent (\r
1026 IN EFI_EVENT Event,\r
1027 IN VOID *Context\r
1028 )\r
36ee91ca 1029{\r
1030 //\r
1031 // Request Ip4OnFrameSentDpc as a DPC at TPL_CALLBACK\r
1032 //\r
d8d26fb2 1033 QueueDpc (TPL_CALLBACK, Ip4OnFrameSentDpc, Context);\r
36ee91ca 1034}\r
1035\r
772db4bb 1036\r
1037\r
1038/**\r
1039 Send a frame from the interface. If the next hop is broadcast or\r
1040 multicast address, it is transmitted immediately. If the next hop\r
1041 is a unicast, it will consult ARP to resolve the NextHop's MAC.\r
1042 If some error happened, the CallBack won't be called. So, the caller\r
1043 must test the return value, and take action when there is an error.\r
1044\r
3e8c18da 1045 @param[in] Interface The interface to send the frame from\r
1046 @param[in] IpInstance The IP child that request the transmission. NULL\r
772db4bb 1047 if it is the IP4 driver itself.\r
3e8c18da 1048 @param[in] Packet The packet to transmit.\r
1049 @param[in] NextHop The immediate destination to transmit the packet\r
772db4bb 1050 to.\r
3e8c18da 1051 @param[in] CallBack Function to call back when transmit finished.\r
1052 @param[in] Context Opaque parameter to the call back.\r
12ae56cf 1053 @param[in] IpSb The pointer to the IP4 service binding instance.\r
772db4bb 1054\r
1055 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to send the frame\r
1056 @retval EFI_NO_MAPPING Can't resolve the MAC for the nexthop\r
1057 @retval EFI_SUCCESS The packet is successfully transmitted.\r
5405e9a6 1058 @retval other Other error occurs.\r
772db4bb 1059\r
1060**/\r
1061EFI_STATUS\r
1062Ip4SendFrame (\r
1063 IN IP4_INTERFACE *Interface,\r
24af132f 1064 IN IP4_PROTOCOL *IpInstance OPTIONAL,\r
772db4bb 1065 IN NET_BUF *Packet,\r
1066 IN IP4_ADDR NextHop,\r
1067 IN IP4_FRAME_CALLBACK CallBack,\r
12ae56cf
FS
1068 IN VOID *Context,\r
1069 IN IP4_SERVICE *IpSb\r
772db4bb 1070 )\r
1071{\r
1072 IP4_LINK_TX_TOKEN *Token;\r
e48e37fc 1073 LIST_ENTRY *Entry;\r
772db4bb 1074 IP4_ARP_QUE *ArpQue;\r
1075 EFI_ARP_PROTOCOL *Arp;\r
1076 EFI_STATUS Status;\r
1077\r
1078 ASSERT (Interface->Configured);\r
1079\r
12ae56cf 1080 Token = Ip4WrapLinkTxToken (Interface, IpInstance, Packet, CallBack, Context, IpSb);\r
772db4bb 1081\r
1082 if (Token == NULL) {\r
1083 return EFI_OUT_OF_RESOURCES;\r
1084 }\r
1085\r
1086 //\r
1087 // Get the destination MAC address for multicast and broadcasts.\r
1088 // Don't depend on ARP to solve the address since there maybe no\r
1089 // ARP at all. Ip4Output has set NextHop to 255.255.255.255 for\r
1090 // all the broadcasts.\r
1091 //\r
1092 if (NextHop == IP4_ALLONE_ADDRESS) {\r
687a2e5f 1093 CopyMem (&Token->DstMac, &Interface->BroadcastMac, sizeof (Token->DstMac));\r
772db4bb 1094 goto SEND_NOW;\r
1095\r
1096 } else if (IP4_IS_MULTICAST (NextHop)) {\r
1097\r
1098 Status = Ip4GetMulticastMac (Interface->Mnp, NextHop, &Token->DstMac);\r
1099\r
1100 if (EFI_ERROR (Status)) {\r
1101 goto ON_ERROR;\r
1102 }\r
1103\r
1104 goto SEND_NOW;\r
1105 }\r
1106\r
1107 //\r
1108 // Can only send out multicast/broadcast if the IP address is zero\r
1109 //\r
1110 if ((Arp = Interface->Arp) == NULL) {\r
1111 Status = EFI_NO_MAPPING;\r
1112 goto ON_ERROR;\r
1113 }\r
1114\r
1115 //\r
1116 // First check whether this binding is in the ARP cache.\r
1117 //\r
1118 NextHop = HTONL (NextHop);\r
1119 Status = Arp->Request (Arp, &NextHop, NULL, &Token->DstMac);\r
1120\r
1121 if (Status == EFI_SUCCESS) {\r
1122 goto SEND_NOW;\r
1123\r
1124 } else if (Status != EFI_NOT_READY) {\r
1125 goto ON_ERROR;\r
1126 }\r
1127\r
1128 //\r
1129 // Have to do asynchronous ARP resolution. First check\r
1130 // whether there is already a pending request.\r
1131 //\r
1132 ArpQue = NULL;\r
1133\r
1134 NET_LIST_FOR_EACH (Entry, &Interface->ArpQues) {\r
1135 ArpQue = NET_LIST_USER_STRUCT (Entry, IP4_ARP_QUE, Link);\r
1136\r
1137 if (ArpQue->Ip == NextHop) {\r
1138 break;\r
1139 }\r
1140 }\r
1141\r
1142 //\r
1143 // Found a pending ARP request, enqueue the frame then return\r
1144 //\r
1145 if (Entry != &Interface->ArpQues) {\r
e48e37fc 1146 InsertTailList (&ArpQue->Frames, &Token->Link);\r
772db4bb 1147 return EFI_SUCCESS;\r
1148 }\r
1149\r
1150 //\r
1151 // First frame to NextHop, issue an asynchronous ARP requests\r
1152 //\r
1153 ArpQue = Ip4CreateArpQue (Interface, NextHop);\r
1154\r
1155 if (ArpQue == NULL) {\r
1156 Status = EFI_OUT_OF_RESOURCES;\r
1157 goto ON_ERROR;\r
1158 }\r
1159\r
1160 Status = Arp->Request (Arp, &ArpQue->Ip, ArpQue->OnResolved, ArpQue->Mac.Addr);\r
1161\r
1162 if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {\r
1163 Ip4FreeArpQue (ArpQue, EFI_NO_MAPPING);\r
1164 goto ON_ERROR;\r
1165 }\r
1166\r
e48e37fc 1167 InsertHeadList (&ArpQue->Frames, &Token->Link);\r
1168 InsertHeadList (&Interface->ArpQues, &ArpQue->Link);\r
772db4bb 1169 return EFI_SUCCESS;\r
1170\r
1171SEND_NOW:\r
36ee91ca 1172 //\r
1173 // Insert the tx token into the SentFrames list before calling Mnp->Transmit.\r
1174 // Remove it if the returned status is not EFI_SUCCESS.\r
1175 //\r
e48e37fc 1176 InsertTailList (&Interface->SentFrames, &Token->Link);\r
772db4bb 1177 Status = Interface->Mnp->Transmit (Interface->Mnp, &Token->MnpToken);\r
772db4bb 1178 if (EFI_ERROR (Status)) {\r
ad18ec95 1179 RemoveEntryList (&Token->Link);\r
772db4bb 1180 goto ON_ERROR;\r
1181 }\r
1182\r
772db4bb 1183 return EFI_SUCCESS;\r
1184\r
1185ON_ERROR:\r
1186 Ip4FreeLinkTxToken (Token);\r
1187 return Status;\r
1188}\r
1189\r
1190\r
1191/**\r
1192 Call back function when the received packet is freed.\r
1193 Check Ip4OnFrameReceived for information.\r
1194\r
3e8c18da 1195 @param Context Context, which is the IP4_LINK_RX_TOKEN.\r
772db4bb 1196\r
1197**/\r
772db4bb 1198VOID\r
e798cd87 1199EFIAPI\r
772db4bb 1200Ip4RecycleFrame (\r
1201 IN VOID *Context\r
1202 )\r
1203{\r
1204 IP4_LINK_RX_TOKEN *Frame;\r
1205\r
1206 Frame = (IP4_LINK_RX_TOKEN *) Context;\r
1207 NET_CHECK_SIGNATURE (Frame, IP4_FRAME_RX_SIGNATURE);\r
1208\r
1209 gBS->SignalEvent (Frame->MnpToken.Packet.RxData->RecycleEvent);\r
1210 Ip4FreeFrameRxToken (Frame);\r
1211}\r
1212\r
1213\r
1214/**\r
1215 Received a frame from MNP, wrap it in net buffer then deliver\r
1216 it to IP's input function. The ownship of the packet also\r
1217 transferred to IP. When Ip is finished with this packet, it\r
1218 will call NetbufFree to release the packet, NetbufFree will\r
1219 again call the Ip4RecycleFrame to signal MNP's event and free\r
1220 the token used.\r
1221\r
772db4bb 1222 @param Context Context for the callback.\r
1223\r
772db4bb 1224**/\r
772db4bb 1225VOID\r
1226EFIAPI\r
36ee91ca 1227Ip4OnFrameReceivedDpc (\r
772db4bb 1228 IN VOID *Context\r
1229 )\r
1230{\r
1231 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
1232 EFI_MANAGED_NETWORK_RECEIVE_DATA *MnpRxData;\r
1233 IP4_LINK_RX_TOKEN *Token;\r
1234 NET_FRAGMENT Netfrag;\r
1235 NET_BUF *Packet;\r
1236 UINT32 Flag;\r
1237\r
1238 Token = (IP4_LINK_RX_TOKEN *) Context;\r
1239 NET_CHECK_SIGNATURE (Token, IP4_FRAME_RX_SIGNATURE);\r
1240\r
1241 //\r
1242 // First clear the interface's receive request in case the\r
1243 // caller wants to call Ip4ReceiveFrame in the callback.\r
1244 //\r
1245 Token->Interface->RecvRequest = NULL;\r
1246\r
1247 MnpToken = &Token->MnpToken;\r
1248 MnpRxData = MnpToken->Packet.RxData;\r
1249\r
1250 if (EFI_ERROR (MnpToken->Status) || (MnpRxData == NULL)) {\r
1251 Token->CallBack (Token->IpInstance, NULL, MnpToken->Status, 0, Token->Context);\r
1252 Ip4FreeFrameRxToken (Token);\r
1253\r
1254 return ;\r
1255 }\r
1256\r
1257 //\r
6c585b52 1258 // Wrap the frame in a net buffer then deliver it to IP input.\r
772db4bb 1259 // IP will reassemble the packet, and deliver it to upper layer\r
1260 //\r
1261 Netfrag.Len = MnpRxData->DataLength;\r
1262 Netfrag.Bulk = MnpRxData->PacketData;\r
1263\r
1264 Packet = NetbufFromExt (&Netfrag, 1, 0, IP4_MAX_HEADLEN, Ip4RecycleFrame, Token);\r
1265\r
1266 if (Packet == NULL) {\r
1267 gBS->SignalEvent (MnpRxData->RecycleEvent);\r
1268\r
1269 Token->CallBack (Token->IpInstance, NULL, EFI_OUT_OF_RESOURCES, 0, Token->Context);\r
1270 Ip4FreeFrameRxToken (Token);\r
1271\r
1272 return ;\r
1273 }\r
1274\r
1275 Flag = (MnpRxData->BroadcastFlag ? IP4_LINK_BROADCAST : 0);\r
1276 Flag |= (MnpRxData->MulticastFlag ? IP4_LINK_MULTICAST : 0);\r
1277 Flag |= (MnpRxData->PromiscuousFlag ? IP4_LINK_PROMISC : 0);\r
1278\r
1279 Token->CallBack (Token->IpInstance, Packet, EFI_SUCCESS, Flag, Token->Context);\r
1280}\r
1281\r
2ff29212 1282/**\r
2ff29212 1283 Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK.\r
1284\r
1285 @param Event The receive event delivered to MNP for receive.\r
1286 @param Context Context for the callback.\r
2ff29212 1287\r
1288**/\r
36ee91ca 1289VOID\r
1290EFIAPI\r
1291Ip4OnFrameReceived (\r
1292 IN EFI_EVENT Event,\r
1293 IN VOID *Context\r
1294 )\r
36ee91ca 1295{\r
1296 //\r
1297 // Request Ip4OnFrameReceivedDpc as a DPC at TPL_CALLBACK\r
1298 //\r
d8d26fb2 1299 QueueDpc (TPL_CALLBACK, Ip4OnFrameReceivedDpc, Context);\r
36ee91ca 1300}\r
1301\r
772db4bb 1302\r
1303/**\r
1304 Request to receive the packet from the interface.\r
1305\r
1f6729ff 1306 @param[in] Interface The interface to receive the frames from.\r
3e8c18da 1307 @param[in] IpInstance The instance that requests the receive. NULL for\r
772db4bb 1308 the driver itself.\r
3e8c18da 1309 @param[in] CallBack Function to call when receive finished.\r
1f6729ff 1310 @param[in] Context Opaque parameter to the callback.\r
772db4bb 1311\r
1312 @retval EFI_ALREADY_STARTED There is already a pending receive request.\r
1f6729ff 1313 @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to receive.\r
6c585b52 1314 @retval EFI_SUCCESS The receive request has been started.\r
5405e9a6 1315 @retval other Other error occurs.\r
772db4bb 1316\r
1317**/\r
1318EFI_STATUS\r
1319Ip4ReceiveFrame (\r
1320 IN IP4_INTERFACE *Interface,\r
24af132f 1321 IN IP4_PROTOCOL *IpInstance OPTIONAL,\r
772db4bb 1322 IN IP4_FRAME_CALLBACK CallBack,\r
1323 IN VOID *Context\r
1324 )\r
1325{\r
1326 IP4_LINK_RX_TOKEN *Token;\r
1327 EFI_STATUS Status;\r
1328\r
1329 NET_CHECK_SIGNATURE (Interface, IP4_INTERFACE_SIGNATURE);\r
1330\r
1331 if (Interface->RecvRequest != NULL) {\r
1332 return EFI_ALREADY_STARTED;\r
1333 }\r
1334\r
1335 Token = Ip4CreateLinkRxToken (Interface, IpInstance, CallBack, Context);\r
1336\r
1337 if (Token == NULL) {\r
1338 return EFI_OUT_OF_RESOURCES;\r
1339 }\r
1340\r
36ee91ca 1341 Interface->RecvRequest = Token;\r
772db4bb 1342 Status = Interface->Mnp->Receive (Interface->Mnp, &Token->MnpToken);\r
772db4bb 1343 if (EFI_ERROR (Status)) {\r
36ee91ca 1344 Interface->RecvRequest = NULL;\r
772db4bb 1345 Ip4FreeFrameRxToken (Token);\r
1346 return Status;\r
1347 }\r
772db4bb 1348 return EFI_SUCCESS;\r
1349}\r