]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/Dhcp6Dxe/Dhcp6Driver.c
OvmfPkg: raise DXEFV size to 13 MB in the traditional platform FDFs
[mirror_edk2.git] / NetworkPkg / Dhcp6Dxe / Dhcp6Driver.c
index d14f169f07807b78664a698fdd5f23c628a2fa25..b591a4605bc9cd991d50ac578f9cc8bd1f4a712a 100644 (file)
@@ -1,23 +1,16 @@
 /** @file\r
   Driver Binding functions and Service Binding functions\r
-  implementationfor for Dhcp6 Driver.\r
+  implementation for Dhcp6 Driver.\r
 \r
-  Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2018, 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
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php.\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "Dhcp6Impl.h"\r
 \r
-\r
-EFI_DRIVER_BINDING_PROTOCOL gDhcp6DriverBinding = {\r
+EFI_DRIVER_BINDING_PROTOCOL  gDhcp6DriverBinding = {\r
   Dhcp6DriverBindingSupported,\r
   Dhcp6DriverBindingStart,\r
   Dhcp6DriverBindingStop,\r
@@ -26,12 +19,11 @@ EFI_DRIVER_BINDING_PROTOCOL gDhcp6DriverBinding = {
   NULL\r
 };\r
 \r
-EFI_SERVICE_BINDING_PROTOCOL gDhcp6ServiceBindingTemplate = {\r
+EFI_SERVICE_BINDING_PROTOCOL  gDhcp6ServiceBindingTemplate = {\r
   Dhcp6ServiceBindingCreateChild,\r
   Dhcp6ServiceBindingDestroyChild\r
 };\r
 \r
-\r
 /**\r
   Configure the default Udp6Io to receive all the DHCP6 traffic\r
   on this network interface.\r
@@ -46,12 +38,12 @@ EFI_SERVICE_BINDING_PROTOCOL gDhcp6ServiceBindingTemplate = {
 EFI_STATUS\r
 EFIAPI\r
 Dhcp6ConfigureUdpIo (\r
-  IN UDP_IO                 *UdpIo,\r
-  IN VOID                   *Context\r
+  IN UDP_IO  *UdpIo,\r
+  IN VOID    *Context\r
   )\r
 {\r
-  EFI_UDP6_PROTOCOL         *Udp6;\r
-  EFI_UDP6_CONFIG_DATA      *Config;\r
+  EFI_UDP6_PROTOCOL     *Udp6;\r
+  EFI_UDP6_CONFIG_DATA  *Config;\r
 \r
   Udp6   = UdpIo->Protocol.Udp6;\r
   Config = &(UdpIo->Config.Udp6);\r
@@ -74,15 +66,14 @@ Dhcp6ConfigureUdpIo (
   // will be overridden later. Note that we MUST not limit RemotePort.\r
   // More details, refer to RFC 3315 section 5.2.\r
   //\r
-  Config->StationPort        = DHCP6_PORT_CLIENT;\r
-  Config->RemotePort         = 0;\r
+  Config->StationPort = DHCP6_PORT_CLIENT;\r
+  Config->RemotePort  = 0;\r
 \r
-  return Udp6->Configure (Udp6, Config);;\r
+  return Udp6->Configure (Udp6, Config);\r
 }\r
 \r
-\r
 /**\r
-  Destory the Dhcp6 service. The Dhcp6 service may be partly initialized,\r
+  Destroy the Dhcp6 service. The Dhcp6 service may be partly initialized,\r
   or partly destroyed. If a resource is destroyed, it is marked as such in\r
   case the destroy failed and being called again later.\r
 \r
@@ -91,11 +82,11 @@ Dhcp6ConfigureUdpIo (
 **/\r
 VOID\r
 Dhcp6DestroyService (\r
-  IN OUT DHCP6_SERVICE          *Service\r
+  IN OUT DHCP6_SERVICE  *Service\r
   )\r
 {\r
   //\r
-  // All children instances should have been already destoryed here.\r
+  // All children instances should have been already destroyed here.\r
   //\r
   ASSERT (Service->NumOfChild == 0);\r
 \r
@@ -110,7 +101,6 @@ Dhcp6DestroyService (
   FreePool (Service);\r
 }\r
 \r
-\r
 /**\r
   Create a new Dhcp6 service for the Nic controller.\r
 \r
@@ -126,12 +116,13 @@ Dhcp6DestroyService (
 **/\r
 EFI_STATUS\r
 Dhcp6CreateService (\r
-  IN  EFI_HANDLE            Controller,\r
-  IN  EFI_HANDLE            ImageHandle,\r
-  OUT DHCP6_SERVICE         **Service\r
+  IN  EFI_HANDLE     Controller,\r
+  IN  EFI_HANDLE     ImageHandle,\r
+  OUT DHCP6_SERVICE  **Service\r
   )\r
 {\r
-  DHCP6_SERVICE             *Dhcp6Srv;\r
+  DHCP6_SERVICE  *Dhcp6Srv;\r
+  EFI_STATUS     Status;\r
 \r
   *Service = NULL;\r
   Dhcp6Srv = AllocateZeroPool (sizeof (DHCP6_SERVICE));\r
@@ -153,11 +144,10 @@ Dhcp6CreateService (
   //\r
   // Initialize the fields of the new Dhcp6 service.\r
   //\r
-  Dhcp6Srv->Signature       = DHCP6_SERVICE_SIGNATURE;\r
-  Dhcp6Srv->InDestory       = FALSE;\r
-  Dhcp6Srv->Controller      = Controller;\r
-  Dhcp6Srv->Image           = ImageHandle;\r
-  Dhcp6Srv->Xid             = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));\r
+  Dhcp6Srv->Signature  = DHCP6_SERVICE_SIGNATURE;\r
+  Dhcp6Srv->Controller = Controller;\r
+  Dhcp6Srv->Image      = ImageHandle;\r
+  Dhcp6Srv->Xid        = (0xffffff & NET_RANDOM (NetRandomInitSeed ()));\r
 \r
   CopyMem (\r
     &Dhcp6Srv->ServiceBinding,\r
@@ -166,9 +156,23 @@ Dhcp6CreateService (
     );\r
 \r
   //\r
-  // Generate client Duid in the format of Duid-llt.\r
+  // Locate Ip6->Ip6Config and store it for get IP6 Duplicate Address Detection transmits.\r
+  //\r
+  Status = gBS->HandleProtocol (\r
+                  Controller,\r
+                  &gEfiIp6ConfigProtocolGuid,\r
+                  (VOID **)&Dhcp6Srv->Ip6Cfg\r
+                  );\r
+  if (EFI_ERROR (Status)) {\r
+    FreePool (Dhcp6Srv);\r
+    return Status;\r
+  }\r
+\r
+  //\r
+  // Generate client Duid: If SMBIOS system UUID is located, generate DUID in DUID-UUID format.\r
+  // Otherwise, in DUID-LLT format.\r
   //\r
-  Dhcp6Srv->ClientId        = Dhcp6GenerateClientId (Dhcp6Srv->Snp->Mode);\r
+  Dhcp6Srv->ClientId = Dhcp6GenerateClientId (Dhcp6Srv->Snp->Mode);\r
 \r
   if (Dhcp6Srv->ClientId == NULL) {\r
     FreePool (Dhcp6Srv);\r
@@ -199,7 +203,6 @@ Dhcp6CreateService (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Destroy the Dhcp6 instance and recycle the resources.\r
 \r
@@ -208,7 +211,7 @@ Dhcp6CreateService (
 **/\r
 VOID\r
 Dhcp6DestroyInstance (\r
-  IN OUT DHCP6_INSTANCE         *Instance\r
+  IN OUT DHCP6_INSTANCE  *Instance\r
   )\r
 {\r
   //\r
@@ -232,6 +235,7 @@ Dhcp6DestroyInstance (
     if (Instance->IaCb.Ia->ReplyPacket != NULL) {\r
       FreePool (Instance->IaCb.Ia->ReplyPacket);\r
     }\r
+\r
     FreePool (Instance->IaCb.Ia);\r
   }\r
 \r
@@ -246,7 +250,6 @@ Dhcp6DestroyInstance (
   FreePool (Instance);\r
 }\r
 \r
-\r
 /**\r
   Create the Dhcp6 instance and initialize it.\r
 \r
@@ -259,12 +262,12 @@ Dhcp6DestroyInstance (
 **/\r
 EFI_STATUS\r
 Dhcp6CreateInstance (\r
-  IN  DHCP6_SERVICE         *Service,\r
-  OUT DHCP6_INSTANCE        **Instance\r
+  IN  DHCP6_SERVICE   *Service,\r
+  OUT DHCP6_INSTANCE  **Instance\r
   )\r
 {\r
-  EFI_STATUS                Status;\r
-  DHCP6_INSTANCE            *Dhcp6Ins;\r
+  EFI_STATUS      Status;\r
+  DHCP6_INSTANCE  *Dhcp6Ins;\r
 \r
   *Instance = NULL;\r
   Dhcp6Ins  = AllocateZeroPool (sizeof (DHCP6_INSTANCE));\r
@@ -276,11 +279,11 @@ Dhcp6CreateInstance (
   //\r
   // Initialize the fields of the new Dhcp6 instance.\r
   //\r
-  Dhcp6Ins->Signature       = DHCP6_INSTANCE_SIGNATURE;\r
-  Dhcp6Ins->UdpSts          = EFI_ALREADY_STARTED;\r
-  Dhcp6Ins->Service         = Service;\r
-  Dhcp6Ins->InDestory       = FALSE;\r
-  Dhcp6Ins->MediaPresent    = TRUE;\r
+  Dhcp6Ins->Signature    = DHCP6_INSTANCE_SIGNATURE;\r
+  Dhcp6Ins->UdpSts       = EFI_ALREADY_STARTED;\r
+  Dhcp6Ins->Service      = Service;\r
+  Dhcp6Ins->InDestroy    = FALSE;\r
+  Dhcp6Ins->MediaPresent = TRUE;\r
 \r
   CopyMem (\r
     &Dhcp6Ins->Dhcp6,\r
@@ -293,7 +296,7 @@ Dhcp6CreateInstance (
 \r
   //\r
   // There is a timer for each Dhcp6 instance, which is used to track the\r
-  // lease time of Ia and the retransmisson time of all sent packets.\r
+  // lease time of Ia and the retransmission time of all sent packets.\r
   //\r
   Status = gBS->CreateEvent (\r
                   EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
@@ -313,6 +316,35 @@ Dhcp6CreateInstance (
   return EFI_SUCCESS;\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
+EFIAPI\r
+Dhcp6DestroyChildEntry (\r
+  IN LIST_ENTRY  *Entry,\r
+  IN VOID        *Context\r
+  )\r
+{\r
+  DHCP6_INSTANCE                *Instance;\r
+  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
+\r
+  if ((Entry == NULL) || (Context == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance       = NET_LIST_USER_STRUCT_S (Entry, DHCP6_INSTANCE, Link, DHCP6_INSTANCE_SIGNATURE);\r
+  ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *)Context;\r
+\r
+  return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
+}\r
 \r
 /**\r
   Entry point of the DHCP6 driver to install various protocols.\r
@@ -327,8 +359,8 @@ Dhcp6CreateInstance (
 EFI_STATUS\r
 EFIAPI\r
 Dhcp6DriverEntryPoint (\r
-  IN EFI_HANDLE                   ImageHandle,\r
-  IN EFI_SYSTEM_TABLE             *SystemTable\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
   )\r
 {\r
   return EfiLibInstallDriverBindingComponentName2 (\r
@@ -341,7 +373,6 @@ Dhcp6DriverEntryPoint (
            );\r
 }\r
 \r
-\r
 /**\r
   Test to see if this driver supports ControllerHandle. This service\r
   is called by the EFI boot service ConnectController(). In\r
@@ -377,7 +408,6 @@ Dhcp6DriverBindingSupported (
                 );\r
 }\r
 \r
-\r
 /**\r
   Start this driver on ControllerHandle. This service is called by the\r
   EFI boot service ConnectController(). In order to make\r
@@ -404,11 +434,11 @@ Dhcp6DriverBindingStart (
   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS                      Status;\r
-  DHCP6_SERVICE                   *Service;\r
+  EFI_STATUS     Status;\r
+  DHCP6_SERVICE  *Service;\r
 \r
   //\r
-  // Check the Dhcp6 serivce whether already started.\r
+  // Check the Dhcp6 service whether already started.\r
   //\r
   Status = gBS->OpenProtocol (\r
                   ControllerHandle,\r
@@ -453,7 +483,6 @@ Dhcp6DriverBindingStart (
   return EFI_SUCCESS;\r
 }\r
 \r
-\r
 /**\r
   Stop this driver on ControllerHandle. This service is called by the\r
   EFI boot service DisconnectController(). In order to\r
@@ -482,12 +511,12 @@ Dhcp6DriverBindingStop (
   IN  EFI_HANDLE                   *ChildHandleBuffer   OPTIONAL\r
   )\r
 {\r
-  EFI_STATUS                       Status;\r
-  EFI_TPL                          OldTpl;\r
-  EFI_HANDLE                       NicHandle;\r
-  EFI_SERVICE_BINDING_PROTOCOL     *ServiceBinding;\r
-  DHCP6_SERVICE                    *Service;\r
-  DHCP6_INSTANCE                   *Instance;\r
+  EFI_STATUS                    Status;\r
+  EFI_HANDLE                    NicHandle;\r
+  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
+  DHCP6_SERVICE                 *Service;\r
+  LIST_ENTRY                    *List;\r
+  UINTN                         ListLength;\r
 \r
   //\r
   // Find and check the Nic handle by the controller handle.\r
@@ -495,13 +524,13 @@ Dhcp6DriverBindingStop (
   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);\r
 \r
   if (NicHandle == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
   Status = gBS->OpenProtocol (\r
                   NicHandle,\r
                   &gEfiDhcp6ServiceBindingProtocolGuid,\r
-                  (VOID **) &ServiceBinding,\r
+                  (VOID **)&ServiceBinding,\r
                   This->DriverBindingHandle,\r
                   NicHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
@@ -512,54 +541,47 @@ Dhcp6DriverBindingStop (
   }\r
 \r
   Service = DHCP6_SERVICE_FROM_THIS (ServiceBinding);\r
-\r
-  if (Service->InDestory) {\r
-    return EFI_SUCCESS;\r
+  if (!IsListEmpty (&Service->Child)) {\r
+    //\r
+    // Destroy all the children instances before destroy the service.\r
+    //\r
+    List   = &Service->Child;\r
+    Status = NetDestroyLinkList (\r
+               List,\r
+               Dhcp6DestroyChildEntry,\r
+               ServiceBinding,\r
+               &ListLength\r
+               );\r
+    if (EFI_ERROR (Status) || (ListLength != 0)) {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
   }\r
 \r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  if ((NumberOfChildren == 0) && !IsListEmpty (&Service->Child)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
 \r
-  if (NumberOfChildren == 0) {\r
+  if ((NumberOfChildren == 0) && IsListEmpty (&Service->Child)) {\r
     //\r
-    // Destory the service itself if no child instance left.\r
+    // Destroy the service itself if no child instance left.\r
     //\r
-    Service->InDestory = TRUE;\r
-\r
     Status = gBS->UninstallProtocolInterface (\r
                     NicHandle,\r
                     &gEfiDhcp6ServiceBindingProtocolGuid,\r
                     ServiceBinding\r
                     );\r
-\r
     if (EFI_ERROR (Status)) {\r
-      Service->InDestory = FALSE;\r
       goto ON_EXIT;\r
     }\r
 \r
     Dhcp6DestroyService (Service);\r
-\r
-  } else {\r
-    //\r
-    // Destory all the children instances before destory the service.\r
-    //\r
-    while (!IsListEmpty (&Service->Child)) {\r
-      Instance = NET_LIST_HEAD (&Service->Child, DHCP6_INSTANCE, Link);\r
-      ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
-    }\r
-    //\r
-    // Any of child failed to be destroyed.\r
-    //\r
-    if (Service->NumOfChild != 0) {\r
-      Status = EFI_DEVICE_ERROR;\r
-    }\r
+    Status = EFI_SUCCESS;\r
   }\r
 \r
 ON_EXIT:\r
-  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Creates a child handle and installs a protocol.\r
 \r
@@ -572,7 +594,7 @@ ON_EXIT:
                               then a new handle is created. If it is a pointer to an existing\r
                               UEFI handle, then the protocol is added to the existing UEFI handle.\r
 \r
-  @retval EFI_SUCCES            The protocol was added to ChildHandle.\r
+  @retval EFI_SUCCESS           The protocol was added to ChildHandle.\r
   @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
   @retval other                 The child handle was not created.\r
 \r
@@ -584,19 +606,19 @@ Dhcp6ServiceBindingCreateChild (
   IN OUT EFI_HANDLE                    *ChildHandle\r
   )\r
 {\r
-  EFI_STATUS                       Status;\r
-  EFI_TPL                          OldTpl;\r
-  DHCP6_SERVICE                    *Service;\r
-  DHCP6_INSTANCE                   *Instance;\r
-  VOID                             *Udp6;\r
+  EFI_STATUS      Status;\r
+  EFI_TPL         OldTpl;\r
+  DHCP6_SERVICE   *Service;\r
+  DHCP6_INSTANCE  *Instance;\r
+  VOID            *Udp6;\r
 \r
-  if (This == NULL || ChildHandle == NULL) {\r
+  if ((This == NULL) || (ChildHandle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
   Service = DHCP6_SERVICE_FROM_THIS (This);\r
 \r
-  Status  = Dhcp6CreateInstance (Service, &Instance);\r
+  Status = Dhcp6CreateInstance (Service, &Instance);\r
 \r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
@@ -639,14 +661,13 @@ Dhcp6ServiceBindingCreateChild (
   Status = gBS->OpenProtocol (\r
                   Service->UdpIo->UdpHandle,\r
                   &gEfiUdp6ProtocolGuid,\r
-                  (VOID **) &Udp6,\r
+                  (VOID **)&Udp6,\r
                   gDhcp6DriverBinding.DriverBindingHandle,\r
                   Instance->Handle,\r
                   EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-\r
     gBS->UninstallMultipleProtocolInterfaces (\r
            Instance->Handle,\r
            &gEfiDhcp6ProtocolGuid,\r
@@ -673,7 +694,6 @@ ON_ERROR:
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Destroys a child handle with a protocol installed on it.\r
 \r
@@ -684,9 +704,9 @@ ON_ERROR:
   @param[in]  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
   @param[in]  ChildHandle Handle of the child to destroy\r
 \r
-  @retval EFI_SUCCES            The protocol was removed from ChildHandle.\r
+  @retval EFI_SUCCESS           The protocol was removed from ChildHandle.\r
   @retval EFI_UNSUPPORTED       ChildHandle does not support the protocol that is being removed.\r
-  @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.\r
+  @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
   @retval EFI_ACCESS_DENIED     The protocol could not be removed from the ChildHandle\r
                                 because its services are being used.\r
   @retval other                 The child handle was not destroyed\r
@@ -699,13 +719,13 @@ Dhcp6ServiceBindingDestroyChild (
   IN EFI_HANDLE                    ChildHandle\r
   )\r
 {\r
-  EFI_STATUS                       Status;\r
-  EFI_TPL                          OldTpl;\r
-  EFI_DHCP6_PROTOCOL               *Dhcp6;\r
-  DHCP6_SERVICE                    *Service;\r
-  DHCP6_INSTANCE                   *Instance;\r
+  EFI_STATUS          Status;\r
+  EFI_TPL             OldTpl;\r
+  EFI_DHCP6_PROTOCOL  *Dhcp6;\r
+  DHCP6_SERVICE       *Service;\r
+  DHCP6_INSTANCE      *Instance;\r
 \r
-  if (This == NULL || ChildHandle == NULL) {\r
+  if ((This == NULL) || (ChildHandle == NULL)) {\r
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
@@ -715,7 +735,7 @@ Dhcp6ServiceBindingDestroyChild (
   Status = gBS->OpenProtocol (\r
                   ChildHandle,\r
                   &gEfiDhcp6ProtocolGuid,\r
-                  (VOID **) &Dhcp6,\r
+                  (VOID **)&Dhcp6,\r
                   gDhcp6DriverBinding.DriverBindingHandle,\r
                   ChildHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
@@ -732,13 +752,13 @@ Dhcp6ServiceBindingDestroyChild (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  if (Instance->InDestory) {\r
+  if (Instance->InDestroy) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
 \r
-  Instance->InDestory = TRUE;\r
+  Instance->InDestroy = TRUE;\r
 \r
   Status = gBS->CloseProtocol (\r
                   Service->UdpIo->UdpHandle,\r
@@ -748,7 +768,7 @@ Dhcp6ServiceBindingDestroyChild (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    Instance->InDestory = FALSE;\r
+    Instance->InDestroy = FALSE;\r
     gBS->RestoreTPL (OldTpl);\r
     return Status;\r
   }\r
@@ -756,14 +776,15 @@ Dhcp6ServiceBindingDestroyChild (
   //\r
   // Uninstall the MTFTP6 protocol first to enable a top down destruction.\r
   //\r
+  gBS->RestoreTPL (OldTpl);\r
   Status = gBS->UninstallProtocolInterface (\r
                   ChildHandle,\r
                   &gEfiDhcp6ProtocolGuid,\r
                   Dhcp6\r
                   );\r
-\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
   if (EFI_ERROR (Status)) {\r
-    Instance->InDestory = FALSE;\r
+    Instance->InDestroy = FALSE;\r
     gBS->RestoreTPL (OldTpl);\r
     return Status;\r
   }\r
@@ -774,9 +795,8 @@ Dhcp6ServiceBindingDestroyChild (
   RemoveEntryList (&Instance->Link);\r
   Service->NumOfChild--;\r
 \r
-  Dhcp6DestroyInstance (Instance);\r
-\r
   gBS->RestoreTPL (OldTpl);\r
 \r
+  Dhcp6DestroyInstance (Instance);\r
   return EFI_SUCCESS;\r
 }\r