/** @file\r
The driver binding and service binding protocol for IP6 driver.\r
\r
- Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
Clean up an IP6 service binding instance. It releases all\r
the resource allocated by the instance. The instance may be\r
partly initialized, or partly destroyed. If a resource is\r
- destroyed, it is marked as that in case the destory failed and\r
+ destroyed, it is marked as that in case the destroy failed and\r
being called again later.\r
\r
@param[in] IpSb The IP6 service binding instance to clean up.\r
\r
Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);\r
\r
- //\r
- // Leave link-scope all-nodes multicast address (FF02::1)\r
- //\r
- Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);\r
+ if (!IpSb->LinkLocalDadFail) {\r
+ //\r
+ // Leave link-scope all-nodes multicast address (FF02::1)\r
+ //\r
+ Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);\r
\r
- Status = Ip6LeaveGroup (IpSb, &AllNodes);\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
+ Status = Ip6LeaveGroup (IpSb, &AllNodes);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ } \r
}\r
\r
if (IpSb->DefaultInterface != NULL) {\r
IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild;\r
IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;\r
IpSb->State = IP6_SERVICE_UNSTARTED;\r
- IpSb->InDestroy = FALSE;\r
\r
IpSb->NumChildren = 0;\r
InitializeListHead (&IpSb->Children);\r
);\r
}\r
\r
+ //\r
+ // If there is any gateway address, set it.\r
+ //\r
+ DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeGateway];\r
+ if (DataItem->Data.Ptr != NULL) {\r
+ DataItem->SetData (\r
+ &IpSb->Ip6ConfigInstance,\r
+ DataItem->DataSize,\r
+ DataItem->Data.Ptr\r
+ );\r
+ }\r
+\r
InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
\r
*Service = IpSb;\r
return Status;\r
}\r
\r
+/**\r
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
+ \r
+ @param[in] Entry The entry to be removed.\r
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
+\r
+ @retval EFI_SUCCESS The entry has been removed successfully.\r
+ @retval Others Fail to remove the entry.\r
+\r
+**/\r
+EFI_STATUS\r
+Ip6DestroyChildEntryInHandleBuffer (\r
+ IN LIST_ENTRY *Entry,\r
+ IN VOID *Context\r
+)\r
+{\r
+ IP6_PROTOCOL *IpInstance;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ UINTN NumberOfChildren;\r
+ EFI_HANDLE *ChildHandleBuffer;\r
+\r
+ if (Entry == NULL || Context == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);\r
+ ServiceBinding = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
+ NumberOfChildren = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
+ ChildHandleBuffer = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
+\r
+ if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
+}\r
+\r
/**\r
Stop this driver on ControllerHandle.\r
\r
IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
)\r
{\r
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
- IP6_SERVICE *IpSb;\r
- IP6_PROTOCOL *IpInstance;\r
- EFI_HANDLE NicHandle;\r
- EFI_STATUS Status;\r
- BOOLEAN IsDhcp6;\r
- EFI_TPL OldTpl;\r
- INTN State;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ IP6_SERVICE *IpSb;\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *List;\r
+ INTN State;\r
+ BOOLEAN IsDhcp6;\r
+ IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
\r
IsDhcp6 = FALSE;\r
- NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
-\r
- if (NicHandle != NULL) {\r
- //\r
- // DriverBindingStop is triggered by the uninstallation of the EFI DHCPv6\r
- // Protocol used by Ip6Config.\r
- //\r
- IsDhcp6 = TRUE;\r
- } else {\r
-\r
- NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
-\r
- if (NicHandle == NULL) {\r
- return EFI_DEVICE_ERROR;\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
+ if (NicHandle == NULL) {\r
+ NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
+ if (NicHandle != NULL) {\r
+ IsDhcp6 = TRUE;\r
+ } else {\r
+ return EFI_SUCCESS;\r
}\r
}\r
\r
\r
IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- if (IpSb->InDestroy) {\r
- Status = EFI_SUCCESS;\r
- goto Exit;\r
- }\r
-\r
if (IsDhcp6) {\r
-\r
Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);\r
gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);\r
IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;\r
- } else if (NumberOfChildren == 0) {\r
-\r
- IpSb->InDestroy = TRUE;\r
+ } else if (NumberOfChildren != 0) {\r
+ //\r
+ // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer.\r
+ //\r
+ List = &IpSb->Children;\r
+ Context.ServiceBinding = ServiceBinding;\r
+ Context.NumberOfChildren = NumberOfChildren;\r
+ Context.ChildHandleBuffer = ChildHandleBuffer;\r
+ Status = NetDestroyLinkList (\r
+ List,\r
+ Ip6DestroyChildEntryInHandleBuffer,\r
+ &Context,\r
+ NULL\r
+ );\r
+ } else if (IsListEmpty (&IpSb->Children)) {\r
State = IpSb->State;\r
IpSb->State = IP6_SERVICE_DESTROY;\r
\r
);\r
ASSERT_EFI_ERROR (Status);\r
FreePool (IpSb);\r
- } else {\r
- //\r
- // NumberOfChildren is not zero, destroy all IP6 children instances.\r
- //\r
- while (!IsListEmpty (&IpSb->Children)) {\r
- IpInstance = NET_LIST_HEAD (&IpSb->Children, IP6_PROTOCOL, Link);\r
- ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
- }\r
-\r
- if (IpSb->NumChildren != 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
+ Status = EFI_SUCCESS;\r
}\r
-\r
+ \r
Exit:\r
-\r
- gBS->RestoreTPL (OldTpl);\r
-\r
return Status;\r
}\r
\r
IP6_PROTOCOL *IpInstance;\r
EFI_IP6_PROTOCOL *Ip6;\r
EFI_TPL OldTpl;\r
- INTN State;\r
\r
if ((This == NULL) || (ChildHandle == NULL)) {\r
return EFI_INVALID_PARAMETER;\r
\r
//\r
// A child can be destroyed more than once. For example,\r
- // Ip6DriverBindingStop will destory all of its children.\r
- // when UDP driver is being stopped, it will destory all\r
+ // Ip6DriverBindingStop will destroy all of its children.\r
+ // when UDP driver is being stopped, it will destroy all\r
// the IP child it opens.\r
//\r
- if (IpInstance->State == IP6_STATE_DESTROY) {\r
+ if (IpInstance->InDestroy) {\r
gBS->RestoreTPL (OldTpl);\r
return EFI_SUCCESS;\r
}\r
\r
- State = IpInstance->State;\r
- IpInstance->State = IP6_STATE_DESTROY;\r
+ IpInstance->InDestroy = TRUE;\r
\r
//\r
// Close the Managed Network protocol.\r
// will be called back before preceeding. If any packets not recycled,\r
// that means there is a resource leak.\r
//\r
+ gBS->RestoreTPL (OldTpl);\r
Status = gBS->UninstallProtocolInterface (\r
ChildHandle,\r
&gEfiIp6ProtocolGuid,\r
&IpInstance->Ip6Proto\r
);\r
-\r
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
if (EFI_ERROR (Status)) {\r
goto ON_ERROR;\r
}\r
return EFI_SUCCESS;\r
\r
ON_ERROR:\r
- IpInstance->State = State;\r
gBS->RestoreTPL (OldTpl);\r
\r
return Status;\r