]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/Ip6Dxe/Ip6Driver.c
1. Add EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName() support.
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6Driver.c
index 502c32bd0d844f5721beadb3dd05f212e89cb607..27550a5b3ed8bbf785e611ccf97f4719963361ac 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The driver binding and service binding protocol for IP6 driver.\r
 \r
 /** @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
 \r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
@@ -94,7 +94,7 @@ Ip6DriverBindingSupported (
   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
   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
   being called again later.\r
 \r
   @param[in]  IpSb               The IP6 service binding instance to clean up.\r
@@ -114,14 +114,16 @@ Ip6CleanService (
 \r
   Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);\r
 \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
 \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
   }\r
 \r
   if (IpSb->DefaultInterface != NULL) {\r
@@ -244,7 +246,6 @@ Ip6CreateService (
   IpSb->ServiceBinding.CreateChild  = Ip6ServiceBindingCreateChild;\r
   IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;\r
   IpSb->State                       = IP6_SERVICE_UNSTARTED;\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
   IpSb->NumChildren                 = 0;\r
   InitializeListHead (&IpSb->Children);\r
@@ -472,6 +473,18 @@ Ip6CreateService (
                 );\r
   }\r
 \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
   InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
 \r
   *Service = IpSb;\r
@@ -560,6 +573,43 @@ Ip6DriverBindingStart (
   return Status;\r
 }\r
 \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
 /**\r
   Stop this driver on ControllerHandle.\r
 \r
@@ -583,30 +633,23 @@ Ip6DriverBindingStop (
   IN  EFI_HANDLE                   *ChildHandleBuffer OPTIONAL\r
   )\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
 \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
   }\r
 \r
@@ -624,21 +667,25 @@ Ip6DriverBindingStop (
 \r
   IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);\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
   if (IsDhcp6) {\r
-\r
     Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);\r
     gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);\r
     IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;\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
     State           = IpSb->State;\r
     IpSb->State     = IP6_SERVICE_DESTROY;\r
 \r
@@ -663,24 +710,10 @@ Ip6DriverBindingStop (
                     );\r
     ASSERT_EFI_ERROR (Status);\r
     FreePool (IpSb);\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
+  \r
 Exit:\r
 Exit:\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
-\r
   return Status;\r
 }\r
 \r
   return Status;\r
 }\r
 \r
@@ -818,7 +851,6 @@ Ip6ServiceBindingDestroyChild (
   IP6_PROTOCOL              *IpInstance;\r
   EFI_IP6_PROTOCOL          *Ip6;\r
   EFI_TPL                   OldTpl;\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
   if ((This == NULL) || (ChildHandle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -852,17 +884,16 @@ Ip6ServiceBindingDestroyChild (
 \r
   //\r
   // A child can be destroyed more than once. For example,\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
   // 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
     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
 \r
   //\r
   // Close the Managed Network protocol.\r
@@ -888,12 +919,13 @@ Ip6ServiceBindingDestroyChild (
   // will be called back before preceeding. If any packets not recycled,\r
   // that means there is a resource leak.\r
   //\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
   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
   if (EFI_ERROR (Status)) {\r
     goto ON_ERROR;\r
   }\r
@@ -923,7 +955,6 @@ Ip6ServiceBindingDestroyChild (
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
-  IpInstance->State = State;\r
   gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r
   gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r