]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Ip6Dxe/Ip6Driver.c
NetworkPkg: remove redundant words in function comment.
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6Driver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 The driver binding and service binding protocol for IP6 driver.\r
3\r
d551cc64 4 Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
c79de074 5 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
a3bcde70
HT
6\r
7 This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php.\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "Ip6Impl.h"\r
18\r
19EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding = {\r
20 Ip6DriverBindingSupported,\r
21 Ip6DriverBindingStart,\r
22 Ip6DriverBindingStop,\r
23 0xa,\r
24 NULL,\r
25 NULL\r
26};\r
27\r
c79de074
SEHM
28BOOLEAN mIpSec2Installed = FALSE;\r
29\r
30/**\r
31 Callback function for IpSec2 Protocol install.\r
32\r
33 @param[in] Event Event whose notification function is being invoked\r
34 @param[in] Context Pointer to the notification function's context\r
35\r
c79de074
SEHM
36**/\r
37VOID\r
38EFIAPI\r
39IpSec2InstalledCallback (\r
40 IN EFI_EVENT Event,\r
41 IN VOID *Context\r
42 )\r
43{\r
44 //\r
45 // Close the event so it does not get called again.\r
46 //\r
47 gBS->CloseEvent (Event);\r
48\r
49 mIpSec2Installed = TRUE;\r
50\r
51 return;\r
52}\r
53\r
a3bcde70
HT
54/**\r
55 This is the declaration of an EFI image entry point. This entry point is\r
56 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
57 both device drivers and bus drivers.\r
58\r
59 The entry point for IP6 driver which installs the driver\r
60 binding and component name protocol on its image.\r
61\r
62 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
63 @param[in] SystemTable A pointer to the EFI System Table.\r
64\r
65 @retval EFI_SUCCESS The operation completed successfully.\r
66 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
67\r
68**/\r
69EFI_STATUS\r
70EFIAPI\r
71Ip6DriverEntryPoint (\r
72 IN EFI_HANDLE ImageHandle,\r
73 IN EFI_SYSTEM_TABLE *SystemTable\r
74 )\r
75{\r
c79de074
SEHM
76 VOID *Registration;\r
77\r
78 EfiCreateProtocolNotifyEvent (\r
79 &gEfiIpSec2ProtocolGuid,\r
80 TPL_CALLBACK,\r
81 IpSec2InstalledCallback,\r
82 NULL,\r
83 &Registration\r
84 );\r
85\r
a3bcde70
HT
86 return EfiLibInstallDriverBindingComponentName2 (\r
87 ImageHandle,\r
88 SystemTable,\r
89 &gIp6DriverBinding,\r
90 ImageHandle,\r
91 &gIp6ComponentName,\r
92 &gIp6ComponentName2\r
93 );\r
94}\r
95\r
96/**\r
97 Test to see if this driver supports ControllerHandle.\r
98\r
99 @param[in] This Protocol instance pointer.\r
100 @param[in] ControllerHandle Handle of device to test.\r
101 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
102 device to start.\r
103\r
104 @retval EFI_SUCCESS This driver supports this device.\r
105 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
106 @retval other This driver does not support this device.\r
107\r
108**/\r
109EFI_STATUS\r
110EFIAPI\r
111Ip6DriverBindingSupported (\r
112 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
113 IN EFI_HANDLE ControllerHandle,\r
114 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
115 )\r
116{\r
117 //\r
118 // Test for the MNP service binding Protocol\r
119 //\r
120 return gBS->OpenProtocol (\r
121 ControllerHandle,\r
122 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
123 NULL,\r
124 This->DriverBindingHandle,\r
125 ControllerHandle,\r
126 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
127 );\r
128}\r
129\r
130/**\r
131 Clean up an IP6 service binding instance. It releases all\r
132 the resource allocated by the instance. The instance may be\r
133 partly initialized, or partly destroyed. If a resource is\r
75dce340 134 destroyed, it is marked as that in case the destroy failed and\r
a3bcde70
HT
135 being called again later.\r
136\r
137 @param[in] IpSb The IP6 service binding instance to clean up.\r
138\r
139 @retval EFI_SUCCESS The resource used by the instance are cleaned up.\r
140 @retval Others Failed to clean up some of the resources.\r
141\r
142**/\r
143EFI_STATUS\r
144Ip6CleanService (\r
145 IN IP6_SERVICE *IpSb\r
146 )\r
147{\r
148 EFI_STATUS Status;\r
149 EFI_IPv6_ADDRESS AllNodes;\r
150 IP6_NEIGHBOR_ENTRY *NeighborCache;\r
151\r
152 Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);\r
153\r
216f7970 154 if (!IpSb->LinkLocalDadFail) {\r
155 //\r
156 // Leave link-scope all-nodes multicast address (FF02::1)\r
157 //\r
158 Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);\r
a3bcde70 159\r
216f7970 160 Status = Ip6LeaveGroup (IpSb, &AllNodes);\r
161 if (EFI_ERROR (Status)) {\r
162 return Status;\r
163 } \r
a3bcde70
HT
164 }\r
165\r
166 if (IpSb->DefaultInterface != NULL) {\r
167 Ip6CleanInterface (IpSb->DefaultInterface, NULL);\r
168 IpSb->DefaultInterface = NULL;\r
169 }\r
170\r
171 Ip6CleanDefaultRouterList (IpSb);\r
172\r
173 Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);\r
174 Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);\r
175\r
176 if (IpSb->RouteTable != NULL) {\r
177 Ip6CleanRouteTable (IpSb->RouteTable);\r
178 IpSb->RouteTable = NULL;\r
179 }\r
180\r
181 if (IpSb->InterfaceId != NULL) {\r
182 FreePool (IpSb->InterfaceId);\r
183 }\r
184\r
185 IpSb->InterfaceId = NULL;\r
186\r
187 Ip6CleanAssembleTable (&IpSb->Assemble);\r
188\r
189 if (IpSb->MnpChildHandle != NULL) {\r
190 if (IpSb->Mnp != NULL) {\r
191 IpSb->Mnp->Cancel (IpSb->Mnp, NULL);\r
192 IpSb->Mnp->Configure (IpSb->Mnp, NULL);\r
193 gBS->CloseProtocol (\r
194 IpSb->MnpChildHandle,\r
195 &gEfiManagedNetworkProtocolGuid,\r
196 IpSb->Image,\r
197 IpSb->Controller\r
198 );\r
199\r
200 IpSb->Mnp = NULL;\r
201 }\r
202\r
203 NetLibDestroyServiceChild (\r
204 IpSb->Controller,\r
205 IpSb->Image,\r
206 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
207 IpSb->MnpChildHandle\r
208 );\r
209\r
210 IpSb->MnpChildHandle = NULL;\r
211 }\r
212\r
213 if (IpSb->RecvRequest.MnpToken.Event != NULL) {\r
214 gBS->CloseEvent (IpSb->RecvRequest.MnpToken.Event);\r
215 }\r
216\r
217 if (IpSb->Timer != NULL) {\r
218 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
219 gBS->CloseEvent (IpSb->Timer);\r
220\r
221 IpSb->Timer = NULL;\r
222 }\r
223\r
224 if (IpSb->FasterTimer != NULL) {\r
225 gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);\r
226 gBS->CloseEvent (IpSb->FasterTimer);\r
227\r
228 IpSb->FasterTimer = NULL;\r
229 }\r
230 //\r
231 // Free the Neighbor Discovery resources\r
232 //\r
233 while (!IsListEmpty (&IpSb->NeighborTable)) {\r
234 NeighborCache = NET_LIST_HEAD (&IpSb->NeighborTable, IP6_NEIGHBOR_ENTRY, Link);\r
235 Ip6FreeNeighborEntry (IpSb, NeighborCache, FALSE, TRUE, EFI_SUCCESS, NULL, NULL);\r
236 }\r
237\r
238 return EFI_SUCCESS;\r
239}\r
240\r
241/**\r
242 Create a new IP6 driver service binding protocol.\r
243\r
244 @param[in] Controller The controller that has MNP service binding\r
245 installed.\r
246 @param[in] ImageHandle The IP6 driver's image handle.\r
247 @param[out] Service The variable to receive the newly created IP6\r
248 service.\r
249\r
250 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.\r
251 @retval EFI_SUCCESS A new IP6 service binding private is created.\r
252\r
253**/\r
254EFI_STATUS\r
255Ip6CreateService (\r
256 IN EFI_HANDLE Controller,\r
257 IN EFI_HANDLE ImageHandle,\r
258 OUT IP6_SERVICE **Service\r
259 )\r
260{\r
261 IP6_SERVICE *IpSb;\r
262 EFI_STATUS Status;\r
263 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
264 EFI_MANAGED_NETWORK_CONFIG_DATA *Config;\r
265 IP6_CONFIG_DATA_ITEM *DataItem;\r
266\r
267 ASSERT (Service != NULL);\r
268\r
269 *Service = NULL;\r
270\r
271 //\r
272 // allocate a service private data then initialize all the filed to\r
273 // empty resources, so if any thing goes wrong when allocating\r
274 // resources, Ip6CleanService can be called to clean it up.\r
275 //\r
276 IpSb = AllocateZeroPool (sizeof (IP6_SERVICE));\r
277\r
278 if (IpSb == NULL) {\r
279 return EFI_OUT_OF_RESOURCES;\r
280 }\r
281\r
282 IpSb->Signature = IP6_SERVICE_SIGNATURE;\r
283 IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild;\r
284 IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;\r
285 IpSb->State = IP6_SERVICE_UNSTARTED;\r
a3bcde70
HT
286\r
287 IpSb->NumChildren = 0;\r
288 InitializeListHead (&IpSb->Children);\r
289\r
290 InitializeListHead (&IpSb->Interfaces);\r
291 IpSb->DefaultInterface = NULL;\r
292 IpSb->RouteTable = NULL;\r
293\r
294 IpSb->RecvRequest.Signature = IP6_LINK_RX_SIGNATURE;\r
295 IpSb->RecvRequest.CallBack = NULL;\r
296 IpSb->RecvRequest.Context = NULL;\r
297 MnpToken = &IpSb->RecvRequest.MnpToken;\r
298 MnpToken->Event = NULL;\r
299 MnpToken->Status = EFI_NOT_READY;\r
300 MnpToken->Packet.RxData = NULL;\r
301\r
302 Ip6CreateAssembleTable (&IpSb->Assemble);\r
303\r
304 IpSb->MldCtrl.Mldv1QuerySeen = 0;\r
305 InitializeListHead (&IpSb->MldCtrl.Groups);\r
306\r
307 ZeroMem (&IpSb->LinkLocalAddr, sizeof (EFI_IPv6_ADDRESS));\r
308 IpSb->LinkLocalOk = FALSE;\r
309 IpSb->LinkLocalDadFail = FALSE;\r
310 IpSb->Dhcp6NeedStart = FALSE;\r
311 IpSb->Dhcp6NeedInfoRequest = FALSE;\r
312\r
313 IpSb->CurHopLimit = IP6_HOP_LIMIT;\r
314 IpSb->LinkMTU = IP6_MIN_LINK_MTU;\r
315 IpSb->BaseReachableTime = IP6_REACHABLE_TIME;\r
316 Ip6UpdateReachableTime (IpSb);\r
317 //\r
318 // RFC4861 RETRANS_TIMER: 1,000 milliseconds\r
319 //\r
320 IpSb->RetransTimer = IP6_RETRANS_TIMER;\r
321\r
322 IpSb->RoundRobin = 0;\r
323\r
324 InitializeListHead (&IpSb->NeighborTable);\r
325 InitializeListHead (&IpSb->DefaultRouterList);\r
326 InitializeListHead (&IpSb->OnlinkPrefix);\r
327 InitializeListHead (&IpSb->AutonomousPrefix);\r
328\r
329 IpSb->InterfaceIdLen = IP6_IF_ID_LEN;\r
330 IpSb->InterfaceId = NULL;\r
331\r
332 IpSb->RouterAdvertiseReceived = FALSE;\r
333 IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS;\r
334 IpSb->Ticks = 0;\r
335\r
336 IpSb->Image = ImageHandle;\r
337 IpSb->Controller = Controller;\r
338\r
339 IpSb->MnpChildHandle = NULL;\r
340 IpSb->Mnp = NULL;\r
341\r
342 Config = &IpSb->MnpConfigData;\r
343 Config->ReceivedQueueTimeoutValue = 0;\r
344 Config->TransmitQueueTimeoutValue = 0;\r
345 Config->ProtocolTypeFilter = IP6_ETHER_PROTO;\r
346 Config->EnableUnicastReceive = TRUE;\r
347 Config->EnableMulticastReceive = TRUE;\r
348 Config->EnableBroadcastReceive = TRUE;\r
349 Config->EnablePromiscuousReceive = FALSE;\r
350 Config->FlushQueuesOnReset = TRUE;\r
351 Config->EnableReceiveTimestamps = FALSE;\r
352 Config->DisableBackgroundPolling = FALSE;\r
353\r
354 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
355\r
356 IpSb->Timer = NULL;\r
357 IpSb->FasterTimer = NULL;\r
358\r
359 ZeroMem (&IpSb->Ip6ConfigInstance, sizeof (IP6_CONFIG_INSTANCE));\r
360\r
361 IpSb->MacString = NULL;\r
362\r
363 //\r
364 // Create various resources. First create the route table, timer\r
365 // event, MNP token event and MNP child.\r
366 //\r
367\r
368 IpSb->RouteTable = Ip6CreateRouteTable ();\r
369 if (IpSb->RouteTable == NULL) {\r
370 Status = EFI_OUT_OF_RESOURCES;\r
371 goto ON_ERROR;\r
372 }\r
373\r
374 Status = gBS->CreateEvent (\r
375 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
376 TPL_CALLBACK,\r
377 Ip6TimerTicking,\r
378 IpSb,\r
379 &IpSb->Timer\r
380 );\r
381 if (EFI_ERROR (Status)) {\r
382 goto ON_ERROR;\r
383 }\r
384\r
385 Status = gBS->CreateEvent (\r
386 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
387 TPL_CALLBACK,\r
388 Ip6NdFasterTimerTicking,\r
389 IpSb,\r
390 &IpSb->FasterTimer\r
391 );\r
392 if (EFI_ERROR (Status)) {\r
393 goto ON_ERROR;\r
394 }\r
395\r
396 Status = NetLibCreateServiceChild (\r
397 Controller,\r
398 ImageHandle,\r
399 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
400 &IpSb->MnpChildHandle\r
401 );\r
402 if (EFI_ERROR (Status)) {\r
403 goto ON_ERROR;\r
404 }\r
405\r
406 Status = gBS->OpenProtocol (\r
407 IpSb->MnpChildHandle,\r
408 &gEfiManagedNetworkProtocolGuid,\r
409 (VOID **) (&IpSb->Mnp),\r
410 ImageHandle,\r
411 Controller,\r
412 EFI_OPEN_PROTOCOL_BY_DRIVER\r
413 );\r
414 if (EFI_ERROR (Status)) {\r
415 goto ON_ERROR;\r
416 }\r
417\r
418 Status = Ip6ServiceConfigMnp (IpSb, TRUE);\r
419 if (EFI_ERROR (Status)) {\r
420 goto ON_ERROR;\r
421 }\r
422\r
423 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);\r
424 if (EFI_ERROR (Status)) {\r
425 goto ON_ERROR;\r
426 }\r
427\r
428 IpSb->MaxPacketSize = IP6_MIN_LINK_MTU - sizeof (EFI_IP6_HEADER);\r
429 if (NetLibGetVlanId (IpSb->Controller) != 0) {\r
430 //\r
431 // This is a VLAN device, reduce MTU by VLAN tag length\r
432 //\r
433 IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;\r
434 }\r
435 IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
436\r
437 //\r
438 // Currently only ETHERNET is supported in IPv6 stack, since\r
439 // link local address requires an IEEE 802 48-bit MACs for\r
440 // EUI-64 format interface identifier mapping.\r
441 //\r
442 if (IpSb->SnpMode.IfType != NET_IFTYPE_ETHERNET) {\r
443 Status = EFI_UNSUPPORTED;\r
444 goto ON_ERROR;\r
445 }\r
446\r
447 Status = Ip6InitMld (IpSb);\r
448 if (EFI_ERROR (Status)) {\r
449 goto ON_ERROR;\r
450 }\r
451\r
8fedfc04 452 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
a3bcde70
HT
453 if (EFI_ERROR (Status)) {\r
454 goto ON_ERROR;\r
455 }\r
456\r
8fedfc04 457 Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance);\r
a3bcde70
HT
458 if (EFI_ERROR (Status)) {\r
459 goto ON_ERROR;\r
460 }\r
461\r
8fedfc04
YT
462 IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE);\r
463 if (IpSb->DefaultInterface == NULL) {\r
464 Status = EFI_DEVICE_ERROR;\r
465 goto ON_ERROR;\r
466 }\r
a3bcde70
HT
467\r
468 Status = gBS->CreateEvent (\r
469 EVT_NOTIFY_SIGNAL,\r
470 TPL_NOTIFY,\r
471 Ip6OnFrameReceived,\r
472 &IpSb->RecvRequest,\r
473 &MnpToken->Event\r
474 );\r
475 if (EFI_ERROR (Status)) {\r
476 goto ON_ERROR;\r
477 }\r
478\r
a3bcde70
HT
479 //\r
480 // If there is any manual address, set it.\r
481 //\r
482 DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress];\r
483 if (DataItem->Data.Ptr != NULL) {\r
484 DataItem->SetData (\r
485 &IpSb->Ip6ConfigInstance,\r
486 DataItem->DataSize,\r
487 DataItem->Data.Ptr\r
488 );\r
489 }\r
490\r
f269f2af 491 //\r
492 // If there is any gateway address, set it.\r
493 //\r
494 DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeGateway];\r
495 if (DataItem->Data.Ptr != NULL) {\r
496 DataItem->SetData (\r
497 &IpSb->Ip6ConfigInstance,\r
498 DataItem->DataSize,\r
499 DataItem->Data.Ptr\r
500 );\r
501 }\r
502\r
a3bcde70
HT
503 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
504\r
505 *Service = IpSb;\r
506 return EFI_SUCCESS;\r
507\r
508ON_ERROR:\r
509 Ip6CleanService (IpSb);\r
510 FreePool (IpSb);\r
511 return Status;\r
512}\r
513\r
514\r
515/**\r
516 Start this driver on ControllerHandle.\r
517\r
518 @param[in] This Protocol instance pointer.\r
519 @param[in] ControllerHandle Handle of device to bind driver to.\r
520 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
521 device to start.\r
522\r
523 @retval EFI_SUCCES This driver is added to ControllerHandle.\r
524 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
525 @retval other This driver does not support this device.\r
526\r
527**/\r
528EFI_STATUS\r
529EFIAPI\r
530Ip6DriverBindingStart (\r
531 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
532 IN EFI_HANDLE ControllerHandle,\r
533 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
534 )\r
535{\r
536 IP6_SERVICE *IpSb;\r
537 EFI_STATUS Status;\r
538\r
539 //\r
540 // Test for the Ip6 service binding protocol\r
541 //\r
542 Status = gBS->OpenProtocol (\r
543 ControllerHandle,\r
544 &gEfiIp6ServiceBindingProtocolGuid,\r
545 NULL,\r
546 This->DriverBindingHandle,\r
547 ControllerHandle,\r
548 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
549 );\r
550\r
551 if (Status == EFI_SUCCESS) {\r
552 return EFI_ALREADY_STARTED;\r
553 }\r
554\r
555 Status = Ip6CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
556\r
557 if (EFI_ERROR (Status)) {\r
558 return Status;\r
559 }\r
560\r
561 ASSERT (IpSb != NULL);\r
562\r
563 //\r
564 // Install the Ip6ServiceBinding Protocol onto ControlerHandle\r
565 //\r
566 Status = gBS->InstallMultipleProtocolInterfaces (\r
567 &ControllerHandle,\r
568 &gEfiIp6ServiceBindingProtocolGuid,\r
569 &IpSb->ServiceBinding,\r
570 &gEfiIp6ConfigProtocolGuid,\r
571 &IpSb->Ip6ConfigInstance.Ip6Config,\r
572 NULL\r
573 );\r
574\r
8fedfc04
YT
575 if (!EFI_ERROR (Status)) {\r
576 //\r
577 // ready to go: start the receiving and timer\r
578 //\r
579 Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);\r
580 if (EFI_ERROR (Status)) {\r
581 goto ON_ERROR;\r
582 }\r
583\r
584 //\r
585 // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.\r
586 //\r
587 Status = gBS->SetTimer (\r
588 IpSb->FasterTimer,\r
589 TimerPeriodic,\r
590 TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS\r
591 );\r
592 if (EFI_ERROR (Status)) {\r
593 goto ON_ERROR;\r
594 }\r
595\r
596 //\r
597 // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.\r
598 //\r
599 Status = gBS->SetTimer (\r
600 IpSb->Timer,\r
601 TimerPeriodic,\r
602 TICKS_PER_MS * IP6_ONE_SECOND_IN_MS\r
603 );\r
604 if (EFI_ERROR (Status)) {\r
605 goto ON_ERROR;\r
606 } \r
a3bcde70 607\r
a3bcde70
HT
608 //\r
609 // Initialize the IP6 ID\r
610 //\r
611 mIp6Id = NET_RANDOM (NetRandomInitSeed ());\r
612\r
8fedfc04 613 return EFI_SUCCESS;\r
a3bcde70
HT
614 }\r
615\r
8fedfc04
YT
616ON_ERROR:\r
617 Ip6CleanService (IpSb);\r
618 FreePool (IpSb);\r
a3bcde70
HT
619 return Status;\r
620}\r
621\r
216f7970 622/**\r
623 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
624 \r
625 @param[in] Entry The entry to be removed.\r
626 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
627\r
628 @retval EFI_SUCCESS The entry has been removed successfully.\r
629 @retval Others Fail to remove the entry.\r
630\r
631**/\r
632EFI_STATUS\r
1f7eb561 633EFIAPI\r
216f7970 634Ip6DestroyChildEntryInHandleBuffer (\r
635 IN LIST_ENTRY *Entry,\r
636 IN VOID *Context\r
1f7eb561 637 )\r
216f7970 638{\r
639 IP6_PROTOCOL *IpInstance;\r
640 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
641 UINTN NumberOfChildren;\r
642 EFI_HANDLE *ChildHandleBuffer;\r
643\r
644 if (Entry == NULL || Context == NULL) {\r
645 return EFI_INVALID_PARAMETER;\r
646 }\r
647\r
648 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);\r
649 ServiceBinding = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
650 NumberOfChildren = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
651 ChildHandleBuffer = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
652\r
653 if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
654 return EFI_SUCCESS;\r
655 }\r
656\r
657 return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
658}\r
659\r
a3bcde70
HT
660/**\r
661 Stop this driver on ControllerHandle.\r
662\r
663 @param[in] This Protocol instance pointer.\r
664 @param[in] ControllerHandle Handle of device to stop driver on.\r
665 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
666 of children is zero, stop the entire bus driver.\r
667 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
668 if NumberOfChildren is 0.\r
669\r
670 @retval EFI_SUCCESS The device was stopped.\r
671 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
672\r
673**/\r
674EFI_STATUS\r
675EFIAPI\r
676Ip6DriverBindingStop (\r
677 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
678 IN EFI_HANDLE ControllerHandle,\r
679 IN UINTN NumberOfChildren,\r
680 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
681 )\r
682{\r
216f7970 683 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
684 IP6_SERVICE *IpSb;\r
685 EFI_HANDLE NicHandle;\r
686 EFI_STATUS Status;\r
687 LIST_ENTRY *List;\r
688 INTN State;\r
689 BOOLEAN IsDhcp6;\r
690 IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
a3bcde70
HT
691\r
692 IsDhcp6 = FALSE;\r
216f7970 693 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
694 if (NicHandle == NULL) {\r
695 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
696 if (NicHandle != NULL) {\r
697 IsDhcp6 = TRUE;\r
698 } else {\r
699 return EFI_SUCCESS;\r
a3bcde70
HT
700 }\r
701 }\r
702\r
703 Status = gBS->OpenProtocol (\r
704 NicHandle,\r
705 &gEfiIp6ServiceBindingProtocolGuid,\r
706 (VOID **) &ServiceBinding,\r
707 This->DriverBindingHandle,\r
708 NicHandle,\r
709 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
710 );\r
711 if (EFI_ERROR (Status)) {\r
712 return EFI_DEVICE_ERROR;\r
713 }\r
714\r
715 IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
716\r
a3bcde70 717 if (IsDhcp6) {\r
a3bcde70
HT
718 Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);\r
719 gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);\r
720 IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;\r
216f7970 721 } else if (NumberOfChildren != 0) {\r
722 //\r
723 // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer.\r
724 //\r
725 List = &IpSb->Children;\r
726 Context.ServiceBinding = ServiceBinding;\r
727 Context.NumberOfChildren = NumberOfChildren;\r
728 Context.ChildHandleBuffer = ChildHandleBuffer;\r
729 Status = NetDestroyLinkList (\r
730 List,\r
731 Ip6DestroyChildEntryInHandleBuffer,\r
732 &Context,\r
733 NULL\r
734 );\r
735 } else if (IsListEmpty (&IpSb->Children)) {\r
a3bcde70
HT
736 State = IpSb->State;\r
737 IpSb->State = IP6_SERVICE_DESTROY;\r
738\r
a3bcde70
HT
739 Status = Ip6CleanService (IpSb);\r
740 if (EFI_ERROR (Status)) {\r
741 IpSb->State = State;\r
742 goto Exit;\r
743 }\r
744\r
745 Status = gBS->UninstallMultipleProtocolInterfaces (\r
746 NicHandle,\r
747 &gEfiIp6ServiceBindingProtocolGuid,\r
748 ServiceBinding,\r
749 &gEfiIp6ConfigProtocolGuid,\r
750 &IpSb->Ip6ConfigInstance.Ip6Config,\r
751 NULL\r
752 );\r
753 ASSERT_EFI_ERROR (Status);\r
754 FreePool (IpSb);\r
216f7970 755 Status = EFI_SUCCESS;\r
a3bcde70 756 }\r
216f7970 757 \r
a3bcde70 758Exit:\r
a3bcde70
HT
759 return Status;\r
760}\r
761\r
762\r
763/**\r
764 Creates a child handle with a set of I/O services.\r
765\r
766 @param[in] This Protocol instance pointer.\r
767 @param[in] ChildHandle Pointer to the handle of the child to create. If\r
768 it is NULL, then a new handle is created. If it\r
769 is not NULL, then the I/O services are added to\r
770 the existing child handle.\r
771\r
772 @retval EFI_SUCCES The child handle was created with the I/O services.\r
773 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
774 the child.\r
775 @retval other The child handle was not created.\r
776\r
777**/\r
778EFI_STATUS\r
779EFIAPI\r
780Ip6ServiceBindingCreateChild (\r
781 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
782 IN EFI_HANDLE *ChildHandle\r
783 )\r
784{\r
785 IP6_SERVICE *IpSb;\r
786 IP6_PROTOCOL *IpInstance;\r
787 EFI_TPL OldTpl;\r
788 EFI_STATUS Status;\r
789 VOID *Mnp;\r
790\r
791 if ((This == NULL) || (ChildHandle == NULL)) {\r
792 return EFI_INVALID_PARAMETER;\r
793 }\r
794\r
795 IpSb = IP6_SERVICE_FROM_PROTOCOL (This);\r
796\r
797 if (IpSb->LinkLocalDadFail) {\r
798 return EFI_DEVICE_ERROR;\r
799 }\r
800\r
801 IpInstance = AllocatePool (sizeof (IP6_PROTOCOL));\r
802\r
803 if (IpInstance == NULL) {\r
804 return EFI_OUT_OF_RESOURCES;\r
805 }\r
806\r
807 Ip6InitProtocol (IpSb, IpInstance);\r
808\r
809 //\r
810 // Install Ip6 onto ChildHandle\r
811 //\r
812 Status = gBS->InstallMultipleProtocolInterfaces (\r
813 ChildHandle,\r
814 &gEfiIp6ProtocolGuid,\r
815 &IpInstance->Ip6Proto,\r
816 NULL\r
817 );\r
818 if (EFI_ERROR (Status)) {\r
819 goto ON_ERROR;\r
820 }\r
821\r
822 IpInstance->Handle = *ChildHandle;\r
823\r
824 //\r
825 // Open the Managed Network protocol BY_CHILD.\r
826 //\r
827 Status = gBS->OpenProtocol (\r
828 IpSb->MnpChildHandle,\r
829 &gEfiManagedNetworkProtocolGuid,\r
830 (VOID **) &Mnp,\r
831 gIp6DriverBinding.DriverBindingHandle,\r
832 IpInstance->Handle,\r
833 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
834 );\r
835 if (EFI_ERROR (Status)) {\r
836 gBS->UninstallMultipleProtocolInterfaces (\r
837 ChildHandle,\r
838 &gEfiIp6ProtocolGuid,\r
839 &IpInstance->Ip6Proto,\r
840 NULL\r
841 );\r
842\r
843 goto ON_ERROR;\r
844 }\r
845\r
846 //\r
847 // Insert it into the service binding instance.\r
848 //\r
849 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
850\r
851 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
852 IpSb->NumChildren++;\r
853\r
854 gBS->RestoreTPL (OldTpl);\r
855\r
856ON_ERROR:\r
857\r
858 if (EFI_ERROR (Status)) {\r
859\r
860 Ip6CleanProtocol (IpInstance);\r
861\r
862 FreePool (IpInstance);\r
863 }\r
864\r
865 return Status;\r
866}\r
867\r
868/**\r
869 Destroys a child handle with a set of I/O services.\r
870\r
871 @param[in] This Protocol instance pointer.\r
872 @param[in] ChildHandle Handle of the child to destroy.\r
873\r
874 @retval EFI_SUCCES The I/O services were removed from the child\r
875 handle.\r
876 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
877 that are being removed.\r
15ee13fc 878 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
a3bcde70
HT
879 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
880 its I/O services are being used.\r
881 @retval other The child handle was not destroyed.\r
882\r
883**/\r
884EFI_STATUS\r
885EFIAPI\r
886Ip6ServiceBindingDestroyChild (\r
887 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
888 IN EFI_HANDLE ChildHandle\r
889 )\r
890{\r
891 EFI_STATUS Status;\r
892 IP6_SERVICE *IpSb;\r
893 IP6_PROTOCOL *IpInstance;\r
894 EFI_IP6_PROTOCOL *Ip6;\r
895 EFI_TPL OldTpl;\r
a3bcde70
HT
896\r
897 if ((This == NULL) || (ChildHandle == NULL)) {\r
898 return EFI_INVALID_PARAMETER;\r
899 }\r
900\r
901 //\r
902 // Retrieve the private context data structures\r
903 //\r
904 IpSb = IP6_SERVICE_FROM_PROTOCOL (This);\r
905\r
906 Status = gBS->OpenProtocol (\r
907 ChildHandle,\r
908 &gEfiIp6ProtocolGuid,\r
909 (VOID **) &Ip6,\r
910 gIp6DriverBinding.DriverBindingHandle,\r
911 ChildHandle,\r
912 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
913 );\r
914\r
915 if (EFI_ERROR (Status)) {\r
916 return EFI_UNSUPPORTED;\r
917 }\r
918\r
919 IpInstance = IP6_INSTANCE_FROM_PROTOCOL (Ip6);\r
920\r
921 if (IpInstance->Service != IpSb) {\r
922 return EFI_INVALID_PARAMETER;\r
923 }\r
924\r
925 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
926\r
927 //\r
928 // A child can be destroyed more than once. For example,\r
75dce340 929 // Ip6DriverBindingStop will destroy all of its children.\r
930 // when UDP driver is being stopped, it will destroy all\r
a3bcde70
HT
931 // the IP child it opens.\r
932 //\r
216f7970 933 if (IpInstance->InDestroy) {\r
a3bcde70
HT
934 gBS->RestoreTPL (OldTpl);\r
935 return EFI_SUCCESS;\r
936 }\r
937\r
216f7970 938 IpInstance->InDestroy = TRUE;\r
a3bcde70
HT
939\r
940 //\r
941 // Close the Managed Network protocol.\r
942 //\r
943 gBS->CloseProtocol (\r
944 IpSb->MnpChildHandle,\r
945 &gEfiManagedNetworkProtocolGuid,\r
946 gIp6DriverBinding.DriverBindingHandle,\r
947 ChildHandle\r
948 );\r
949\r
950 //\r
951 // Uninstall the IP6 protocol first. Many thing happens during\r
952 // this:\r
953 // 1. The consumer of the IP6 protocol will be stopped if it\r
954 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
955 // stopped, IP driver's stop function will be called, and uninstall\r
956 // EFI_IP6_PROTOCOL will trigger the UDP's stop function. This\r
957 // makes it possible to create the network stack bottom up, and\r
958 // stop it top down.\r
959 // 2. the upper layer will recycle the received packet. The recycle\r
960 // event's TPL is higher than this function. The recycle events\r
961 // will be called back before preceeding. If any packets not recycled,\r
962 // that means there is a resource leak.\r
963 //\r
216f7970 964 gBS->RestoreTPL (OldTpl);\r
a3bcde70
HT
965 Status = gBS->UninstallProtocolInterface (\r
966 ChildHandle,\r
967 &gEfiIp6ProtocolGuid,\r
968 &IpInstance->Ip6Proto\r
969 );\r
216f7970 970 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
a3bcde70
HT
971 if (EFI_ERROR (Status)) {\r
972 goto ON_ERROR;\r
973 }\r
974\r
975 Status = Ip6CleanProtocol (IpInstance);\r
a3bcde70
HT
976 if (EFI_ERROR (Status)) {\r
977 gBS->InstallMultipleProtocolInterfaces (\r
978 &ChildHandle,\r
979 &gEfiIp6ProtocolGuid,\r
980 Ip6,\r
981 NULL\r
982 );\r
983\r
984 goto ON_ERROR;\r
985 }\r
986\r
987 RemoveEntryList (&IpInstance->Link);\r
988 ASSERT (IpSb->NumChildren > 0);\r
989 IpSb->NumChildren--;\r
990\r
991 gBS->RestoreTPL (OldTpl);\r
992\r
993 FreePool (IpInstance);\r
994 return EFI_SUCCESS;\r
995\r
996ON_ERROR:\r
a3bcde70
HT
997 gBS->RestoreTPL (OldTpl);\r
998\r
999 return Status;\r
1000}\r