2 The driver binding and service binding protocol for IP6 driver.
4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
5 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>
7 This program and the accompanying materials
8 are licensed and made available under the terms and conditions of the BSD License
9 which accompanies this distribution. The full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php.
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding
= {
20 Ip6DriverBindingSupported
,
21 Ip6DriverBindingStart
,
28 BOOLEAN mIpSec2Installed
= FALSE
;
31 Callback function for IpSec2 Protocol install.
33 @param[in] Event Event whose notification function is being invoked
34 @param[in] Context Pointer to the notification function's context
39 IpSec2InstalledCallback (
45 // Close the event so it does not get called again.
47 gBS
->CloseEvent (Event
);
49 mIpSec2Installed
= TRUE
;
55 This is the declaration of an EFI image entry point. This entry point is
56 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
57 both device drivers and bus drivers.
59 The entry point for IP6 driver which installs the driver
60 binding and component name protocol on its image.
62 @param[in] ImageHandle The firmware allocated handle for the UEFI image.
63 @param[in] SystemTable A pointer to the EFI System Table.
65 @retval EFI_SUCCESS The operation completed successfully.
66 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
72 IN EFI_HANDLE ImageHandle
,
73 IN EFI_SYSTEM_TABLE
*SystemTable
78 EfiCreateProtocolNotifyEvent (
79 &gEfiIpSec2ProtocolGuid
,
81 IpSec2InstalledCallback
,
86 return EfiLibInstallDriverBindingComponentName2 (
97 Test to see if this driver supports ControllerHandle.
99 @param[in] This Protocol instance pointer.
100 @param[in] ControllerHandle Handle of device to test.
101 @param[in] RemainingDevicePath Optional parameter use to pick a specific child
104 @retval EFI_SUCCESS This driver supports this device.
105 @retval EFI_ALREADY_STARTED This driver is already running on this device.
106 @retval other This driver does not support this device.
111 Ip6DriverBindingSupported (
112 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
113 IN EFI_HANDLE ControllerHandle
,
114 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
118 // Test for the MNP service binding Protocol
120 return gBS
->OpenProtocol (
122 &gEfiManagedNetworkServiceBindingProtocolGuid
,
124 This
->DriverBindingHandle
,
126 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
131 Clean up an IP6 service binding instance. It releases all
132 the resource allocated by the instance. The instance may be
133 partly initialized, or partly destroyed. If a resource is
134 destroyed, it is marked as that in case the destroy failed and
135 being called again later.
137 @param[in] IpSb The IP6 service binding instance to clean up.
139 @retval EFI_SUCCESS The resource used by the instance are cleaned up.
140 @retval Others Failed to clean up some of the resources.
149 EFI_IPv6_ADDRESS AllNodes
;
150 IP6_NEIGHBOR_ENTRY
*NeighborCache
;
152 Ip6ConfigCleanInstance (&IpSb
->Ip6ConfigInstance
);
154 if (!IpSb
->LinkLocalDadFail
) {
156 // Leave link-scope all-nodes multicast address (FF02::1)
158 Ip6SetToAllNodeMulticast (FALSE
, IP6_LINK_LOCAL_SCOPE
, &AllNodes
);
160 Status
= Ip6LeaveGroup (IpSb
, &AllNodes
);
161 if (EFI_ERROR (Status
)) {
166 if (IpSb
->DefaultInterface
!= NULL
) {
167 Ip6CleanInterface (IpSb
->DefaultInterface
, NULL
);
168 IpSb
->DefaultInterface
= NULL
;
171 Ip6CleanDefaultRouterList (IpSb
);
173 Ip6CleanPrefixListTable (IpSb
, &IpSb
->OnlinkPrefix
);
174 Ip6CleanPrefixListTable (IpSb
, &IpSb
->AutonomousPrefix
);
176 if (IpSb
->RouteTable
!= NULL
) {
177 Ip6CleanRouteTable (IpSb
->RouteTable
);
178 IpSb
->RouteTable
= NULL
;
181 if (IpSb
->InterfaceId
!= NULL
) {
182 FreePool (IpSb
->InterfaceId
);
185 IpSb
->InterfaceId
= NULL
;
187 Ip6CleanAssembleTable (&IpSb
->Assemble
);
189 if (IpSb
->MnpChildHandle
!= NULL
) {
190 if (IpSb
->Mnp
!= NULL
) {
191 IpSb
->Mnp
->Cancel (IpSb
->Mnp
, NULL
);
192 IpSb
->Mnp
->Configure (IpSb
->Mnp
, NULL
);
194 IpSb
->MnpChildHandle
,
195 &gEfiManagedNetworkProtocolGuid
,
203 NetLibDestroyServiceChild (
206 &gEfiManagedNetworkServiceBindingProtocolGuid
,
210 IpSb
->MnpChildHandle
= NULL
;
213 if (IpSb
->RecvRequest
.MnpToken
.Event
!= NULL
) {
214 gBS
->CloseEvent (IpSb
->RecvRequest
.MnpToken
.Event
);
217 if (IpSb
->Timer
!= NULL
) {
218 gBS
->SetTimer (IpSb
->Timer
, TimerCancel
, 0);
219 gBS
->CloseEvent (IpSb
->Timer
);
224 if (IpSb
->FasterTimer
!= NULL
) {
225 gBS
->SetTimer (IpSb
->FasterTimer
, TimerCancel
, 0);
226 gBS
->CloseEvent (IpSb
->FasterTimer
);
228 IpSb
->FasterTimer
= NULL
;
231 // Free the Neighbor Discovery resources
233 while (!IsListEmpty (&IpSb
->NeighborTable
)) {
234 NeighborCache
= NET_LIST_HEAD (&IpSb
->NeighborTable
, IP6_NEIGHBOR_ENTRY
, Link
);
235 Ip6FreeNeighborEntry (IpSb
, NeighborCache
, FALSE
, TRUE
, EFI_SUCCESS
, NULL
, NULL
);
242 Create a new IP6 driver service binding protocol.
244 @param[in] Controller The controller that has MNP service binding
246 @param[in] ImageHandle The IP6 driver's image handle.
247 @param[out] Service The variable to receive the newly created IP6
250 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.
251 @retval EFI_SUCCESS A new IP6 service binding private is created.
256 IN EFI_HANDLE Controller
,
257 IN EFI_HANDLE ImageHandle
,
258 OUT IP6_SERVICE
**Service
263 EFI_MANAGED_NETWORK_COMPLETION_TOKEN
*MnpToken
;
264 EFI_MANAGED_NETWORK_CONFIG_DATA
*Config
;
266 ASSERT (Service
!= NULL
);
271 // allocate a service private data then initialize all the filed to
272 // empty resources, so if any thing goes wrong when allocating
273 // resources, Ip6CleanService can be called to clean it up.
275 IpSb
= AllocateZeroPool (sizeof (IP6_SERVICE
));
278 return EFI_OUT_OF_RESOURCES
;
281 IpSb
->Signature
= IP6_SERVICE_SIGNATURE
;
282 IpSb
->ServiceBinding
.CreateChild
= Ip6ServiceBindingCreateChild
;
283 IpSb
->ServiceBinding
.DestroyChild
= Ip6ServiceBindingDestroyChild
;
284 IpSb
->State
= IP6_SERVICE_UNSTARTED
;
286 IpSb
->NumChildren
= 0;
287 InitializeListHead (&IpSb
->Children
);
289 InitializeListHead (&IpSb
->Interfaces
);
290 IpSb
->DefaultInterface
= NULL
;
291 IpSb
->RouteTable
= NULL
;
293 IpSb
->RecvRequest
.Signature
= IP6_LINK_RX_SIGNATURE
;
294 IpSb
->RecvRequest
.CallBack
= NULL
;
295 IpSb
->RecvRequest
.Context
= NULL
;
296 MnpToken
= &IpSb
->RecvRequest
.MnpToken
;
297 MnpToken
->Event
= NULL
;
298 MnpToken
->Status
= EFI_NOT_READY
;
299 MnpToken
->Packet
.RxData
= NULL
;
301 Ip6CreateAssembleTable (&IpSb
->Assemble
);
303 IpSb
->MldCtrl
.Mldv1QuerySeen
= 0;
304 InitializeListHead (&IpSb
->MldCtrl
.Groups
);
306 ZeroMem (&IpSb
->LinkLocalAddr
, sizeof (EFI_IPv6_ADDRESS
));
307 IpSb
->LinkLocalOk
= FALSE
;
308 IpSb
->LinkLocalDadFail
= FALSE
;
309 IpSb
->Dhcp6NeedStart
= FALSE
;
310 IpSb
->Dhcp6NeedInfoRequest
= FALSE
;
312 IpSb
->CurHopLimit
= IP6_HOP_LIMIT
;
313 IpSb
->LinkMTU
= IP6_MIN_LINK_MTU
;
314 IpSb
->BaseReachableTime
= IP6_REACHABLE_TIME
;
315 Ip6UpdateReachableTime (IpSb
);
317 // RFC4861 RETRANS_TIMER: 1,000 milliseconds
319 IpSb
->RetransTimer
= IP6_RETRANS_TIMER
;
321 IpSb
->RoundRobin
= 0;
323 InitializeListHead (&IpSb
->NeighborTable
);
324 InitializeListHead (&IpSb
->DefaultRouterList
);
325 InitializeListHead (&IpSb
->OnlinkPrefix
);
326 InitializeListHead (&IpSb
->AutonomousPrefix
);
328 IpSb
->InterfaceIdLen
= IP6_IF_ID_LEN
;
329 IpSb
->InterfaceId
= NULL
;
331 IpSb
->RouterAdvertiseReceived
= FALSE
;
332 IpSb
->SolicitTimer
= IP6_MAX_RTR_SOLICITATIONS
;
335 IpSb
->Image
= ImageHandle
;
336 IpSb
->Controller
= Controller
;
338 IpSb
->MnpChildHandle
= NULL
;
341 Config
= &IpSb
->MnpConfigData
;
342 Config
->ReceivedQueueTimeoutValue
= 0;
343 Config
->TransmitQueueTimeoutValue
= 0;
344 Config
->ProtocolTypeFilter
= IP6_ETHER_PROTO
;
345 Config
->EnableUnicastReceive
= TRUE
;
346 Config
->EnableMulticastReceive
= TRUE
;
347 Config
->EnableBroadcastReceive
= TRUE
;
348 Config
->EnablePromiscuousReceive
= FALSE
;
349 Config
->FlushQueuesOnReset
= TRUE
;
350 Config
->EnableReceiveTimestamps
= FALSE
;
351 Config
->DisableBackgroundPolling
= FALSE
;
353 ZeroMem (&IpSb
->SnpMode
, sizeof (EFI_SIMPLE_NETWORK_MODE
));
356 IpSb
->FasterTimer
= NULL
;
358 ZeroMem (&IpSb
->Ip6ConfigInstance
, sizeof (IP6_CONFIG_INSTANCE
));
360 IpSb
->MacString
= NULL
;
363 // Create various resources. First create the route table, timer
364 // event, MNP token event and MNP child.
367 IpSb
->RouteTable
= Ip6CreateRouteTable ();
368 if (IpSb
->RouteTable
== NULL
) {
369 Status
= EFI_OUT_OF_RESOURCES
;
373 Status
= gBS
->CreateEvent (
374 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
380 if (EFI_ERROR (Status
)) {
384 Status
= gBS
->CreateEvent (
385 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
387 Ip6NdFasterTimerTicking
,
391 if (EFI_ERROR (Status
)) {
395 Status
= NetLibCreateServiceChild (
398 &gEfiManagedNetworkServiceBindingProtocolGuid
,
399 &IpSb
->MnpChildHandle
401 if (EFI_ERROR (Status
)) {
405 Status
= gBS
->OpenProtocol (
406 IpSb
->MnpChildHandle
,
407 &gEfiManagedNetworkProtocolGuid
,
408 (VOID
**) (&IpSb
->Mnp
),
411 EFI_OPEN_PROTOCOL_BY_DRIVER
413 if (EFI_ERROR (Status
)) {
417 Status
= Ip6ServiceConfigMnp (IpSb
, TRUE
);
418 if (EFI_ERROR (Status
)) {
422 Status
= IpSb
->Mnp
->GetModeData (IpSb
->Mnp
, NULL
, &IpSb
->SnpMode
);
423 if (EFI_ERROR (Status
)) {
427 IpSb
->MaxPacketSize
= IP6_MIN_LINK_MTU
- sizeof (EFI_IP6_HEADER
);
428 if (NetLibGetVlanId (IpSb
->Controller
) != 0) {
430 // This is a VLAN device, reduce MTU by VLAN tag length
432 IpSb
->MaxPacketSize
-= NET_VLAN_TAG_LEN
;
434 IpSb
->OldMaxPacketSize
= IpSb
->MaxPacketSize
;
437 // Currently only ETHERNET is supported in IPv6 stack, since
438 // link local address requires an IEEE 802 48-bit MACs for
439 // EUI-64 format interface identifier mapping.
441 if (IpSb
->SnpMode
.IfType
!= NET_IFTYPE_ETHERNET
) {
442 Status
= EFI_UNSUPPORTED
;
446 Status
= Ip6InitMld (IpSb
);
447 if (EFI_ERROR (Status
)) {
451 Status
= NetLibGetMacString (IpSb
->Controller
, IpSb
->Image
, &IpSb
->MacString
);
452 if (EFI_ERROR (Status
)) {
456 Status
= Ip6ConfigInitInstance (&IpSb
->Ip6ConfigInstance
);
457 if (EFI_ERROR (Status
)) {
461 IpSb
->DefaultInterface
= Ip6CreateInterface (IpSb
, TRUE
);
462 if (IpSb
->DefaultInterface
== NULL
) {
463 Status
= EFI_DEVICE_ERROR
;
467 Status
= gBS
->CreateEvent (
474 if (EFI_ERROR (Status
)) {
478 InsertHeadList (&IpSb
->Interfaces
, &IpSb
->DefaultInterface
->Link
);
484 Ip6CleanService (IpSb
);
491 Start this driver on ControllerHandle.
493 @param[in] This Protocol instance pointer.
494 @param[in] ControllerHandle Handle of device to bind driver to.
495 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
498 @retval EFI_SUCCES This driver is added to ControllerHandle.
499 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
500 @retval other This driver does not support this device.
505 Ip6DriverBindingStart (
506 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
507 IN EFI_HANDLE ControllerHandle
,
508 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
513 EFI_IP6_CONFIG_PROTOCOL
*Ip6Cfg
;
514 IP6_CONFIG_DATA_ITEM
*DataItem
;
521 // Test for the Ip6 service binding protocol
523 Status
= gBS
->OpenProtocol (
525 &gEfiIp6ServiceBindingProtocolGuid
,
527 This
->DriverBindingHandle
,
529 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
532 if (Status
== EFI_SUCCESS
) {
533 return EFI_ALREADY_STARTED
;
536 Status
= Ip6CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
538 if (EFI_ERROR (Status
)) {
542 ASSERT (IpSb
!= NULL
);
544 Ip6Cfg
= &IpSb
->Ip6ConfigInstance
.Ip6Config
;
547 // Install the Ip6ServiceBinding Protocol onto ControlerHandle
549 Status
= gBS
->InstallMultipleProtocolInterfaces (
551 &gEfiIp6ServiceBindingProtocolGuid
,
552 &IpSb
->ServiceBinding
,
553 &gEfiIp6ConfigProtocolGuid
,
557 if (EFI_ERROR (Status
)) {
562 // Read the config data from NV variable again.
563 // The default data can be changed by other drivers.
565 Status
= Ip6ConfigReadConfigData (IpSb
->MacString
, &IpSb
->Ip6ConfigInstance
);
566 if (EFI_ERROR (Status
)) {
571 // If there is any default manual address, set it.
573 DataItem
= &IpSb
->Ip6ConfigInstance
.DataItem
[Ip6ConfigDataTypeManualAddress
];
574 if (DataItem
->Data
.Ptr
!= NULL
) {
575 Status
= Ip6Cfg
->SetData (
577 Ip6ConfigDataTypeManualAddress
,
581 if (EFI_ERROR(Status
)) {
587 // If there is any default gateway address, set it.
589 DataItem
= &IpSb
->Ip6ConfigInstance
.DataItem
[Ip6ConfigDataTypeGateway
];
590 if (DataItem
->Data
.Ptr
!= NULL
) {
591 Status
= Ip6Cfg
->SetData (
593 Ip6ConfigDataTypeGateway
,
597 if (EFI_ERROR(Status
)) {
602 if (!EFI_ERROR (Status
)) {
604 // ready to go: start the receiving and timer
606 Status
= Ip6ReceiveFrame (Ip6AcceptFrame
, IpSb
);
607 if (EFI_ERROR (Status
)) {
612 // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.
614 Status
= gBS
->SetTimer (
617 TICKS_PER_MS
* IP6_TIMER_INTERVAL_IN_MS
619 if (EFI_ERROR (Status
)) {
624 // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.
626 Status
= gBS
->SetTimer (
629 TICKS_PER_MS
* IP6_ONE_SECOND_IN_MS
631 if (EFI_ERROR (Status
)) {
636 // Initialize the IP6 ID
638 mIp6Id
= NET_RANDOM (NetRandomInitSeed ());
644 Ip6CleanService (IpSb
);
650 Callback function which provided by user to remove one node in NetDestroyLinkList process.
652 @param[in] Entry The entry to be removed.
653 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
655 @retval EFI_SUCCESS The entry has been removed successfully.
656 @retval Others Fail to remove the entry.
661 Ip6DestroyChildEntryInHandleBuffer (
662 IN LIST_ENTRY
*Entry
,
666 IP6_PROTOCOL
*IpInstance
;
667 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
668 UINTN NumberOfChildren
;
669 EFI_HANDLE
*ChildHandleBuffer
;
671 if (Entry
== NULL
|| Context
== NULL
) {
672 return EFI_INVALID_PARAMETER
;
675 IpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP6_PROTOCOL
, Link
, IP6_PROTOCOL_SIGNATURE
);
676 ServiceBinding
= ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
677 NumberOfChildren
= ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
678 ChildHandleBuffer
= ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
680 if (!NetIsInHandleBuffer (IpInstance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
684 return ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
688 Stop this driver on ControllerHandle.
690 @param[in] This Protocol instance pointer.
691 @param[in] ControllerHandle Handle of device to stop driver on.
692 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
693 of children is zero, stop the entire bus driver.
694 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
695 if NumberOfChildren is 0.
697 @retval EFI_SUCCESS The device was stopped.
698 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
703 Ip6DriverBindingStop (
704 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
705 IN EFI_HANDLE ControllerHandle
,
706 IN UINTN NumberOfChildren
,
707 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
710 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
712 EFI_HANDLE NicHandle
;
717 IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
720 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
721 if (NicHandle
== NULL
) {
722 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp6ProtocolGuid
);
723 if (NicHandle
!= NULL
) {
730 Status
= gBS
->OpenProtocol (
732 &gEfiIp6ServiceBindingProtocolGuid
,
733 (VOID
**) &ServiceBinding
,
734 This
->DriverBindingHandle
,
736 EFI_OPEN_PROTOCOL_GET_PROTOCOL
738 if (EFI_ERROR (Status
)) {
739 return EFI_DEVICE_ERROR
;
742 IpSb
= IP6_SERVICE_FROM_PROTOCOL (ServiceBinding
);
745 Status
= Ip6ConfigDestroyDhcp6 (&IpSb
->Ip6ConfigInstance
);
746 gBS
->CloseEvent (IpSb
->Ip6ConfigInstance
.Dhcp6Event
);
747 IpSb
->Ip6ConfigInstance
.Dhcp6Event
= NULL
;
748 } else if (NumberOfChildren
!= 0) {
750 // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer.
752 List
= &IpSb
->Children
;
753 Context
.ServiceBinding
= ServiceBinding
;
754 Context
.NumberOfChildren
= NumberOfChildren
;
755 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
756 Status
= NetDestroyLinkList (
758 Ip6DestroyChildEntryInHandleBuffer
,
762 } else if (IsListEmpty (&IpSb
->Children
)) {
764 IpSb
->State
= IP6_SERVICE_DESTROY
;
766 Status
= Ip6CleanService (IpSb
);
767 if (EFI_ERROR (Status
)) {
772 Status
= gBS
->UninstallMultipleProtocolInterfaces (
774 &gEfiIp6ServiceBindingProtocolGuid
,
776 &gEfiIp6ConfigProtocolGuid
,
777 &IpSb
->Ip6ConfigInstance
.Ip6Config
,
780 ASSERT_EFI_ERROR (Status
);
782 Status
= EFI_SUCCESS
;
791 Creates a child handle with a set of I/O services.
793 @param[in] This Protocol instance pointer.
794 @param[in] ChildHandle Pointer to the handle of the child to create. If
795 it is NULL, then a new handle is created. If it
796 is not NULL, then the I/O services are added to
797 the existing child handle.
799 @retval EFI_SUCCES The child handle was created with the I/O services.
800 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
802 @retval other The child handle was not created.
807 Ip6ServiceBindingCreateChild (
808 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
809 IN EFI_HANDLE
*ChildHandle
813 IP6_PROTOCOL
*IpInstance
;
818 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
819 return EFI_INVALID_PARAMETER
;
822 IpSb
= IP6_SERVICE_FROM_PROTOCOL (This
);
824 if (IpSb
->LinkLocalDadFail
) {
825 return EFI_DEVICE_ERROR
;
828 IpInstance
= AllocatePool (sizeof (IP6_PROTOCOL
));
830 if (IpInstance
== NULL
) {
831 return EFI_OUT_OF_RESOURCES
;
834 Ip6InitProtocol (IpSb
, IpInstance
);
837 // Install Ip6 onto ChildHandle
839 Status
= gBS
->InstallMultipleProtocolInterfaces (
841 &gEfiIp6ProtocolGuid
,
842 &IpInstance
->Ip6Proto
,
845 if (EFI_ERROR (Status
)) {
849 IpInstance
->Handle
= *ChildHandle
;
852 // Open the Managed Network protocol BY_CHILD.
854 Status
= gBS
->OpenProtocol (
855 IpSb
->MnpChildHandle
,
856 &gEfiManagedNetworkProtocolGuid
,
858 gIp6DriverBinding
.DriverBindingHandle
,
860 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
862 if (EFI_ERROR (Status
)) {
863 gBS
->UninstallMultipleProtocolInterfaces (
865 &gEfiIp6ProtocolGuid
,
866 &IpInstance
->Ip6Proto
,
874 // Insert it into the service binding instance.
876 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
878 InsertTailList (&IpSb
->Children
, &IpInstance
->Link
);
881 gBS
->RestoreTPL (OldTpl
);
885 if (EFI_ERROR (Status
)) {
887 Ip6CleanProtocol (IpInstance
);
889 FreePool (IpInstance
);
896 Destroys a child handle with a set of I/O services.
898 @param[in] This Protocol instance pointer.
899 @param[in] ChildHandle Handle of the child to destroy.
901 @retval EFI_SUCCES The I/O services were removed from the child
903 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
904 that are being removed.
905 @retval EFI_INVALID_PARAMETER Child handle is NULL.
906 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
907 its I/O services are being used.
908 @retval other The child handle was not destroyed.
913 Ip6ServiceBindingDestroyChild (
914 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
915 IN EFI_HANDLE ChildHandle
920 IP6_PROTOCOL
*IpInstance
;
921 EFI_IP6_PROTOCOL
*Ip6
;
924 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
925 return EFI_INVALID_PARAMETER
;
929 // Retrieve the private context data structures
931 IpSb
= IP6_SERVICE_FROM_PROTOCOL (This
);
933 Status
= gBS
->OpenProtocol (
935 &gEfiIp6ProtocolGuid
,
937 gIp6DriverBinding
.DriverBindingHandle
,
939 EFI_OPEN_PROTOCOL_GET_PROTOCOL
942 if (EFI_ERROR (Status
)) {
943 return EFI_UNSUPPORTED
;
946 IpInstance
= IP6_INSTANCE_FROM_PROTOCOL (Ip6
);
948 if (IpInstance
->Service
!= IpSb
) {
949 return EFI_INVALID_PARAMETER
;
952 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
955 // A child can be destroyed more than once. For example,
956 // Ip6DriverBindingStop will destroy all of its children.
957 // when UDP driver is being stopped, it will destroy all
958 // the IP child it opens.
960 if (IpInstance
->InDestroy
) {
961 gBS
->RestoreTPL (OldTpl
);
965 IpInstance
->InDestroy
= TRUE
;
968 // Close the Managed Network protocol.
971 IpSb
->MnpChildHandle
,
972 &gEfiManagedNetworkProtocolGuid
,
973 gIp6DriverBinding
.DriverBindingHandle
,
978 // Uninstall the IP6 protocol first. Many thing happens during
980 // 1. The consumer of the IP6 protocol will be stopped if it
981 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
982 // stopped, IP driver's stop function will be called, and uninstall
983 // EFI_IP6_PROTOCOL will trigger the UDP's stop function. This
984 // makes it possible to create the network stack bottom up, and
986 // 2. the upper layer will recycle the received packet. The recycle
987 // event's TPL is higher than this function. The recycle events
988 // will be called back before preceeding. If any packets not recycled,
989 // that means there is a resource leak.
991 gBS
->RestoreTPL (OldTpl
);
992 Status
= gBS
->UninstallProtocolInterface (
994 &gEfiIp6ProtocolGuid
,
995 &IpInstance
->Ip6Proto
997 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
998 if (EFI_ERROR (Status
)) {
1002 Status
= Ip6CleanProtocol (IpInstance
);
1003 if (EFI_ERROR (Status
)) {
1004 gBS
->InstallMultipleProtocolInterfaces (
1006 &gEfiIp6ProtocolGuid
,
1014 RemoveEntryList (&IpInstance
->Link
);
1015 ASSERT (IpSb
->NumChildren
> 0);
1016 IpSb
->NumChildren
--;
1018 gBS
->RestoreTPL (OldTpl
);
1020 FreePool (IpInstance
);
1024 gBS
->RestoreTPL (OldTpl
);