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