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