2 The driver binding and service binding protocol for IP6 driver.
4 Copyright (c) 2009 - 2014, 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
;
265 IP6_CONFIG_DATA_ITEM
*DataItem
;
267 ASSERT (Service
!= NULL
);
272 // allocate a service private data then initialize all the filed to
273 // empty resources, so if any thing goes wrong when allocating
274 // resources, Ip6CleanService can be called to clean it up.
276 IpSb
= AllocateZeroPool (sizeof (IP6_SERVICE
));
279 return EFI_OUT_OF_RESOURCES
;
282 IpSb
->Signature
= IP6_SERVICE_SIGNATURE
;
283 IpSb
->ServiceBinding
.CreateChild
= Ip6ServiceBindingCreateChild
;
284 IpSb
->ServiceBinding
.DestroyChild
= Ip6ServiceBindingDestroyChild
;
285 IpSb
->State
= IP6_SERVICE_UNSTARTED
;
287 IpSb
->NumChildren
= 0;
288 InitializeListHead (&IpSb
->Children
);
290 InitializeListHead (&IpSb
->Interfaces
);
291 IpSb
->DefaultInterface
= NULL
;
292 IpSb
->RouteTable
= NULL
;
294 IpSb
->RecvRequest
.Signature
= IP6_LINK_RX_SIGNATURE
;
295 IpSb
->RecvRequest
.CallBack
= NULL
;
296 IpSb
->RecvRequest
.Context
= NULL
;
297 MnpToken
= &IpSb
->RecvRequest
.MnpToken
;
298 MnpToken
->Event
= NULL
;
299 MnpToken
->Status
= EFI_NOT_READY
;
300 MnpToken
->Packet
.RxData
= NULL
;
302 Ip6CreateAssembleTable (&IpSb
->Assemble
);
304 IpSb
->MldCtrl
.Mldv1QuerySeen
= 0;
305 InitializeListHead (&IpSb
->MldCtrl
.Groups
);
307 ZeroMem (&IpSb
->LinkLocalAddr
, sizeof (EFI_IPv6_ADDRESS
));
308 IpSb
->LinkLocalOk
= FALSE
;
309 IpSb
->LinkLocalDadFail
= FALSE
;
310 IpSb
->Dhcp6NeedStart
= FALSE
;
311 IpSb
->Dhcp6NeedInfoRequest
= FALSE
;
313 IpSb
->CurHopLimit
= IP6_HOP_LIMIT
;
314 IpSb
->LinkMTU
= IP6_MIN_LINK_MTU
;
315 IpSb
->BaseReachableTime
= IP6_REACHABLE_TIME
;
316 Ip6UpdateReachableTime (IpSb
);
318 // RFC4861 RETRANS_TIMER: 1,000 milliseconds
320 IpSb
->RetransTimer
= IP6_RETRANS_TIMER
;
322 IpSb
->RoundRobin
= 0;
324 InitializeListHead (&IpSb
->NeighborTable
);
325 InitializeListHead (&IpSb
->DefaultRouterList
);
326 InitializeListHead (&IpSb
->OnlinkPrefix
);
327 InitializeListHead (&IpSb
->AutonomousPrefix
);
329 IpSb
->InterfaceIdLen
= IP6_IF_ID_LEN
;
330 IpSb
->InterfaceId
= NULL
;
332 IpSb
->RouterAdvertiseReceived
= FALSE
;
333 IpSb
->SolicitTimer
= IP6_MAX_RTR_SOLICITATIONS
;
336 IpSb
->Image
= ImageHandle
;
337 IpSb
->Controller
= Controller
;
339 IpSb
->MnpChildHandle
= NULL
;
342 Config
= &IpSb
->MnpConfigData
;
343 Config
->ReceivedQueueTimeoutValue
= 0;
344 Config
->TransmitQueueTimeoutValue
= 0;
345 Config
->ProtocolTypeFilter
= IP6_ETHER_PROTO
;
346 Config
->EnableUnicastReceive
= TRUE
;
347 Config
->EnableMulticastReceive
= TRUE
;
348 Config
->EnableBroadcastReceive
= TRUE
;
349 Config
->EnablePromiscuousReceive
= FALSE
;
350 Config
->FlushQueuesOnReset
= TRUE
;
351 Config
->EnableReceiveTimestamps
= FALSE
;
352 Config
->DisableBackgroundPolling
= FALSE
;
354 ZeroMem (&IpSb
->SnpMode
, sizeof (EFI_SIMPLE_NETWORK_MODE
));
357 IpSb
->FasterTimer
= NULL
;
359 ZeroMem (&IpSb
->Ip6ConfigInstance
, sizeof (IP6_CONFIG_INSTANCE
));
361 IpSb
->MacString
= NULL
;
364 // Create various resources. First create the route table, timer
365 // event, MNP token event and MNP child.
368 IpSb
->RouteTable
= Ip6CreateRouteTable ();
369 if (IpSb
->RouteTable
== NULL
) {
370 Status
= EFI_OUT_OF_RESOURCES
;
374 Status
= gBS
->CreateEvent (
375 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
381 if (EFI_ERROR (Status
)) {
385 Status
= gBS
->CreateEvent (
386 EVT_NOTIFY_SIGNAL
| EVT_TIMER
,
388 Ip6NdFasterTimerTicking
,
392 if (EFI_ERROR (Status
)) {
396 Status
= NetLibCreateServiceChild (
399 &gEfiManagedNetworkServiceBindingProtocolGuid
,
400 &IpSb
->MnpChildHandle
402 if (EFI_ERROR (Status
)) {
406 Status
= gBS
->OpenProtocol (
407 IpSb
->MnpChildHandle
,
408 &gEfiManagedNetworkProtocolGuid
,
409 (VOID
**) (&IpSb
->Mnp
),
412 EFI_OPEN_PROTOCOL_BY_DRIVER
414 if (EFI_ERROR (Status
)) {
418 Status
= Ip6ServiceConfigMnp (IpSb
, TRUE
);
419 if (EFI_ERROR (Status
)) {
423 Status
= IpSb
->Mnp
->GetModeData (IpSb
->Mnp
, NULL
, &IpSb
->SnpMode
);
424 if (EFI_ERROR (Status
)) {
428 IpSb
->MaxPacketSize
= IP6_MIN_LINK_MTU
- sizeof (EFI_IP6_HEADER
);
429 if (NetLibGetVlanId (IpSb
->Controller
) != 0) {
431 // This is a VLAN device, reduce MTU by VLAN tag length
433 IpSb
->MaxPacketSize
-= NET_VLAN_TAG_LEN
;
435 IpSb
->OldMaxPacketSize
= IpSb
->MaxPacketSize
;
438 // Currently only ETHERNET is supported in IPv6 stack, since
439 // link local address requires an IEEE 802 48-bit MACs for
440 // EUI-64 format interface identifier mapping.
442 if (IpSb
->SnpMode
.IfType
!= NET_IFTYPE_ETHERNET
) {
443 Status
= EFI_UNSUPPORTED
;
447 Status
= Ip6InitMld (IpSb
);
448 if (EFI_ERROR (Status
)) {
452 Status
= NetLibGetMacString (IpSb
->Controller
, IpSb
->Image
, &IpSb
->MacString
);
453 if (EFI_ERROR (Status
)) {
457 Status
= Ip6ConfigInitInstance (&IpSb
->Ip6ConfigInstance
);
458 if (EFI_ERROR (Status
)) {
462 IpSb
->DefaultInterface
= Ip6CreateInterface (IpSb
, TRUE
);
463 if (IpSb
->DefaultInterface
== NULL
) {
464 Status
= EFI_DEVICE_ERROR
;
468 Status
= gBS
->CreateEvent (
475 if (EFI_ERROR (Status
)) {
480 // If there is any manual address, set it.
482 DataItem
= &IpSb
->Ip6ConfigInstance
.DataItem
[Ip6ConfigDataTypeManualAddress
];
483 if (DataItem
->Data
.Ptr
!= NULL
) {
485 &IpSb
->Ip6ConfigInstance
,
492 // If there is any gateway address, set it.
494 DataItem
= &IpSb
->Ip6ConfigInstance
.DataItem
[Ip6ConfigDataTypeGateway
];
495 if (DataItem
->Data
.Ptr
!= NULL
) {
497 &IpSb
->Ip6ConfigInstance
,
503 InsertHeadList (&IpSb
->Interfaces
, &IpSb
->DefaultInterface
->Link
);
509 Ip6CleanService (IpSb
);
516 Start this driver on ControllerHandle.
518 @param[in] This Protocol instance pointer.
519 @param[in] ControllerHandle Handle of device to bind driver to.
520 @param[in] RemainingDevicePath Optional parameter used to pick a specific child
523 @retval EFI_SUCCES This driver is added to ControllerHandle.
524 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.
525 @retval other This driver does not support this device.
530 Ip6DriverBindingStart (
531 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
532 IN EFI_HANDLE ControllerHandle
,
533 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath OPTIONAL
540 // Test for the Ip6 service binding protocol
542 Status
= gBS
->OpenProtocol (
544 &gEfiIp6ServiceBindingProtocolGuid
,
546 This
->DriverBindingHandle
,
548 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
551 if (Status
== EFI_SUCCESS
) {
552 return EFI_ALREADY_STARTED
;
555 Status
= Ip6CreateService (ControllerHandle
, This
->DriverBindingHandle
, &IpSb
);
557 if (EFI_ERROR (Status
)) {
561 ASSERT (IpSb
!= NULL
);
564 // Install the Ip6ServiceBinding Protocol onto ControlerHandle
566 Status
= gBS
->InstallMultipleProtocolInterfaces (
568 &gEfiIp6ServiceBindingProtocolGuid
,
569 &IpSb
->ServiceBinding
,
570 &gEfiIp6ConfigProtocolGuid
,
571 &IpSb
->Ip6ConfigInstance
.Ip6Config
,
575 if (!EFI_ERROR (Status
)) {
577 // ready to go: start the receiving and timer
579 Status
= Ip6ReceiveFrame (Ip6AcceptFrame
, IpSb
);
580 if (EFI_ERROR (Status
)) {
585 // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.
587 Status
= gBS
->SetTimer (
590 TICKS_PER_MS
* IP6_TIMER_INTERVAL_IN_MS
592 if (EFI_ERROR (Status
)) {
597 // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.
599 Status
= gBS
->SetTimer (
602 TICKS_PER_MS
* IP6_ONE_SECOND_IN_MS
604 if (EFI_ERROR (Status
)) {
609 // Initialize the IP6 ID
611 mIp6Id
= NET_RANDOM (NetRandomInitSeed ());
617 Ip6CleanService (IpSb
);
623 Callback function which provided by user to remove one node in NetDestroyLinkList process.
625 @param[in] Entry The entry to be removed.
626 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
628 @retval EFI_SUCCESS The entry has been removed successfully.
629 @retval Others Fail to remove the entry.
634 Ip6DestroyChildEntryInHandleBuffer (
635 IN LIST_ENTRY
*Entry
,
639 IP6_PROTOCOL
*IpInstance
;
640 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
641 UINTN NumberOfChildren
;
642 EFI_HANDLE
*ChildHandleBuffer
;
644 if (Entry
== NULL
|| Context
== NULL
) {
645 return EFI_INVALID_PARAMETER
;
648 IpInstance
= NET_LIST_USER_STRUCT_S (Entry
, IP6_PROTOCOL
, Link
, IP6_PROTOCOL_SIGNATURE
);
649 ServiceBinding
= ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ServiceBinding
;
650 NumberOfChildren
= ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->NumberOfChildren
;
651 ChildHandleBuffer
= ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT
*) Context
)->ChildHandleBuffer
;
653 if (!NetIsInHandleBuffer (IpInstance
->Handle
, NumberOfChildren
, ChildHandleBuffer
)) {
657 return ServiceBinding
->DestroyChild (ServiceBinding
, IpInstance
->Handle
);
661 Stop this driver on ControllerHandle.
663 @param[in] This Protocol instance pointer.
664 @param[in] ControllerHandle Handle of device to stop driver on.
665 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number
666 of children is zero, stop the entire bus driver.
667 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
668 if NumberOfChildren is 0.
670 @retval EFI_SUCCESS The device was stopped.
671 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
676 Ip6DriverBindingStop (
677 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
678 IN EFI_HANDLE ControllerHandle
,
679 IN UINTN NumberOfChildren
,
680 IN EFI_HANDLE
*ChildHandleBuffer OPTIONAL
683 EFI_SERVICE_BINDING_PROTOCOL
*ServiceBinding
;
685 EFI_HANDLE NicHandle
;
690 IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context
;
693 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiManagedNetworkProtocolGuid
);
694 if (NicHandle
== NULL
) {
695 NicHandle
= NetLibGetNicHandle (ControllerHandle
, &gEfiDhcp6ProtocolGuid
);
696 if (NicHandle
!= NULL
) {
703 Status
= gBS
->OpenProtocol (
705 &gEfiIp6ServiceBindingProtocolGuid
,
706 (VOID
**) &ServiceBinding
,
707 This
->DriverBindingHandle
,
709 EFI_OPEN_PROTOCOL_GET_PROTOCOL
711 if (EFI_ERROR (Status
)) {
712 return EFI_DEVICE_ERROR
;
715 IpSb
= IP6_SERVICE_FROM_PROTOCOL (ServiceBinding
);
718 Status
= Ip6ConfigDestroyDhcp6 (&IpSb
->Ip6ConfigInstance
);
719 gBS
->CloseEvent (IpSb
->Ip6ConfigInstance
.Dhcp6Event
);
720 IpSb
->Ip6ConfigInstance
.Dhcp6Event
= NULL
;
721 } else if (NumberOfChildren
!= 0) {
723 // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer.
725 List
= &IpSb
->Children
;
726 Context
.ServiceBinding
= ServiceBinding
;
727 Context
.NumberOfChildren
= NumberOfChildren
;
728 Context
.ChildHandleBuffer
= ChildHandleBuffer
;
729 Status
= NetDestroyLinkList (
731 Ip6DestroyChildEntryInHandleBuffer
,
735 } else if (IsListEmpty (&IpSb
->Children
)) {
737 IpSb
->State
= IP6_SERVICE_DESTROY
;
739 Status
= Ip6CleanService (IpSb
);
740 if (EFI_ERROR (Status
)) {
745 Status
= gBS
->UninstallMultipleProtocolInterfaces (
747 &gEfiIp6ServiceBindingProtocolGuid
,
749 &gEfiIp6ConfigProtocolGuid
,
750 &IpSb
->Ip6ConfigInstance
.Ip6Config
,
753 ASSERT_EFI_ERROR (Status
);
755 Status
= EFI_SUCCESS
;
764 Creates a child handle with a set of I/O services.
766 @param[in] This Protocol instance pointer.
767 @param[in] ChildHandle Pointer to the handle of the child to create. If
768 it is NULL, then a new handle is created. If it
769 is not NULL, then the I/O services are added to
770 the existing child handle.
772 @retval EFI_SUCCES The child handle was created with the I/O services.
773 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create
775 @retval other The child handle was not created.
780 Ip6ServiceBindingCreateChild (
781 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
782 IN EFI_HANDLE
*ChildHandle
786 IP6_PROTOCOL
*IpInstance
;
791 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
792 return EFI_INVALID_PARAMETER
;
795 IpSb
= IP6_SERVICE_FROM_PROTOCOL (This
);
797 if (IpSb
->LinkLocalDadFail
) {
798 return EFI_DEVICE_ERROR
;
801 IpInstance
= AllocatePool (sizeof (IP6_PROTOCOL
));
803 if (IpInstance
== NULL
) {
804 return EFI_OUT_OF_RESOURCES
;
807 Ip6InitProtocol (IpSb
, IpInstance
);
810 // Install Ip6 onto ChildHandle
812 Status
= gBS
->InstallMultipleProtocolInterfaces (
814 &gEfiIp6ProtocolGuid
,
815 &IpInstance
->Ip6Proto
,
818 if (EFI_ERROR (Status
)) {
822 IpInstance
->Handle
= *ChildHandle
;
825 // Open the Managed Network protocol BY_CHILD.
827 Status
= gBS
->OpenProtocol (
828 IpSb
->MnpChildHandle
,
829 &gEfiManagedNetworkProtocolGuid
,
831 gIp6DriverBinding
.DriverBindingHandle
,
833 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
835 if (EFI_ERROR (Status
)) {
836 gBS
->UninstallMultipleProtocolInterfaces (
838 &gEfiIp6ProtocolGuid
,
839 &IpInstance
->Ip6Proto
,
847 // Insert it into the service binding instance.
849 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
851 InsertTailList (&IpSb
->Children
, &IpInstance
->Link
);
854 gBS
->RestoreTPL (OldTpl
);
858 if (EFI_ERROR (Status
)) {
860 Ip6CleanProtocol (IpInstance
);
862 FreePool (IpInstance
);
869 Destroys a child handle with a set of I/O services.
871 @param[in] This Protocol instance pointer.
872 @param[in] ChildHandle Handle of the child to destroy.
874 @retval EFI_SUCCES The I/O services were removed from the child
876 @retval EFI_UNSUPPORTED The child handle does not support the I/O services
877 that are being removed.
878 @retval EFI_INVALID_PARAMETER Child handle is NULL.
879 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because
880 its I/O services are being used.
881 @retval other The child handle was not destroyed.
886 Ip6ServiceBindingDestroyChild (
887 IN EFI_SERVICE_BINDING_PROTOCOL
*This
,
888 IN EFI_HANDLE ChildHandle
893 IP6_PROTOCOL
*IpInstance
;
894 EFI_IP6_PROTOCOL
*Ip6
;
897 if ((This
== NULL
) || (ChildHandle
== NULL
)) {
898 return EFI_INVALID_PARAMETER
;
902 // Retrieve the private context data structures
904 IpSb
= IP6_SERVICE_FROM_PROTOCOL (This
);
906 Status
= gBS
->OpenProtocol (
908 &gEfiIp6ProtocolGuid
,
910 gIp6DriverBinding
.DriverBindingHandle
,
912 EFI_OPEN_PROTOCOL_GET_PROTOCOL
915 if (EFI_ERROR (Status
)) {
916 return EFI_UNSUPPORTED
;
919 IpInstance
= IP6_INSTANCE_FROM_PROTOCOL (Ip6
);
921 if (IpInstance
->Service
!= IpSb
) {
922 return EFI_INVALID_PARAMETER
;
925 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
928 // A child can be destroyed more than once. For example,
929 // Ip6DriverBindingStop will destroy all of its children.
930 // when UDP driver is being stopped, it will destroy all
931 // the IP child it opens.
933 if (IpInstance
->InDestroy
) {
934 gBS
->RestoreTPL (OldTpl
);
938 IpInstance
->InDestroy
= TRUE
;
941 // Close the Managed Network protocol.
944 IpSb
->MnpChildHandle
,
945 &gEfiManagedNetworkProtocolGuid
,
946 gIp6DriverBinding
.DriverBindingHandle
,
951 // Uninstall the IP6 protocol first. Many thing happens during
953 // 1. The consumer of the IP6 protocol will be stopped if it
954 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is
955 // stopped, IP driver's stop function will be called, and uninstall
956 // EFI_IP6_PROTOCOL will trigger the UDP's stop function. This
957 // makes it possible to create the network stack bottom up, and
959 // 2. the upper layer will recycle the received packet. The recycle
960 // event's TPL is higher than this function. The recycle events
961 // will be called back before preceeding. If any packets not recycled,
962 // that means there is a resource leak.
964 gBS
->RestoreTPL (OldTpl
);
965 Status
= gBS
->UninstallProtocolInterface (
967 &gEfiIp6ProtocolGuid
,
968 &IpInstance
->Ip6Proto
970 OldTpl
= gBS
->RaiseTPL (TPL_CALLBACK
);
971 if (EFI_ERROR (Status
)) {
975 Status
= Ip6CleanProtocol (IpInstance
);
976 if (EFI_ERROR (Status
)) {
977 gBS
->InstallMultipleProtocolInterfaces (
979 &gEfiIp6ProtocolGuid
,
987 RemoveEntryList (&IpInstance
->Link
);
988 ASSERT (IpSb
->NumChildren
> 0);
991 gBS
->RestoreTPL (OldTpl
);
993 FreePool (IpInstance
);
997 gBS
->RestoreTPL (OldTpl
);