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