]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
MdeModulePkg: Update Ip4Dxe driver to support Ip4Config2 protocol,
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Driver.c
index cccaab6dee285b09bebba21c4ed830ed1ef8c4df..101390cdf85270d5d733f34ca819ac8e83458e81 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   The driver binding and service binding protocol for IP4 driver.\r
 \r
-Copyright (c) 2005 - 2010, Intel Corporation.<BR>\r
-All rights reserved. This program and the accompanying materials\r
+Copyright (c) 2005 - 2015, Intel Corporation. All rights reserved.<BR>\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
@@ -118,10 +118,10 @@ Ip4DriverBindingSupported (
   Clean up a IP4 service binding instance. It will release 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 IP4 serviceing binding instance to clean up\r
+  @param[in]  IpSb               The IP4 service binding instance to clean up\r
 \r
   @retval EFI_SUCCESS            The resource used by the instance are cleaned up\r
   @retval other                  Failed to clean up some of the resources.\r
@@ -166,7 +166,7 @@ Ip4CreateService (
   // empty resources, so if any thing goes wrong when allocating\r
   // resources, Ip4CleanService can be called to clean it up.\r
   //\r
-  IpSb = AllocatePool (sizeof (IP4_SERVICE));\r
+  IpSb = AllocateZeroPool (sizeof (IP4_SERVICE));\r
 \r
   if (IpSb == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -176,7 +176,6 @@ Ip4CreateService (
   IpSb->ServiceBinding.CreateChild  = Ip4ServiceBindingCreateChild;\r
   IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;\r
   IpSb->State                       = IP4_SERVICE_UNSTARTED;\r
-  IpSb->InDestory                   = FALSE;\r
 \r
   IpSb->NumChildren                 = 0;\r
   InitializeListHead (&IpSb->Children);\r
@@ -209,11 +208,7 @@ Ip4CreateService (
 \r
   ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
 \r
-  IpSb->Timer                       = NULL;\r
-  IpSb->Ip4Config                   = NULL;\r
-  IpSb->DoneEvent                   = NULL;\r
-  IpSb->ReconfigEvent               = NULL;\r
-  IpSb->ActiveEvent                 = NULL;\r
+  IpSb->Timer = NULL;\r
 \r
   //\r
   // Create various resources. First create the route table, timer\r
@@ -281,6 +276,13 @@ Ip4CreateService (
     goto ON_ERROR;\r
   }\r
 \r
+  IpSb->MacString = NULL;\r
+  Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
+  \r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);\r
 \r
   if (IpSb->DefaultInterface == NULL) {\r
@@ -290,6 +292,14 @@ Ip4CreateService (
 \r
   InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
 \r
+  ZeroMem (&IpSb->Ip4Config2Instance, sizeof (IP4_CONFIG2_INSTANCE));\r
+  \r
+  Status = Ip4Config2InitInstance (&IpSb->Ip4Config2Instance);\r
+\r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
+\r
   IpSb->MaxPacketSize = IpSb->SnpMode.MaxPacketSize - sizeof (IP4_HEAD);\r
   if (NetLibGetVlanId (IpSb->Controller) != 0) {\r
     //\r
@@ -297,9 +307,9 @@ Ip4CreateService (
     //\r
     IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;\r
   }\r
-  IpSb->MacString = NULL;\r
-\r
+  IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
   *Service = IpSb;\r
+\r
   return EFI_SUCCESS;\r
 \r
 ON_ERROR:\r
@@ -314,10 +324,10 @@ ON_ERROR:
   Clean up a IP4 service binding instance. It will release 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 IP4 serviceing binding instance to clean up\r
+  @param[in]  IpSb               The IP4 service binding instance to clean up\r
 \r
   @retval EFI_SUCCESS            The resource used by the instance are cleaned up\r
   @retval other                  Failed to clean up some of the resources.\r
@@ -376,25 +386,52 @@ Ip4CleanService (
     IpSb->Timer = NULL;\r
   }\r
 \r
-  if (IpSb->Ip4Config != NULL) {\r
-    IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-\r
-    gBS->CloseProtocol (\r
-          IpSb->Controller,\r
-          &gEfiIp4ConfigProtocolGuid,\r
-          IpSb->Image,\r
-          IpSb->Controller\r
-          );\r
-\r
-    gBS->CloseEvent (IpSb->DoneEvent);\r
-    gBS->CloseEvent (IpSb->ReconfigEvent);\r
-    IpSb->ActiveEvent = NULL;\r
-    IpSb->Ip4Config = NULL;\r
+  if (IpSb->MacString != NULL) {\r
+    FreePool (IpSb->MacString);\r
   }\r
 \r
+  Ip4Config2CleanInstance (&IpSb->Ip4Config2Instance);\r
+\r
   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
+Ip4DestroyChildEntryInHandleBuffer (\r
+  IN LIST_ENTRY         *Entry,\r
+  IN VOID               *Context\r
+  )\r
+{\r
+  IP4_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, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);\r
+  ServiceBinding    = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
+  NumberOfChildren  = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
+  ChildHandleBuffer = ((IP4_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
   Start this driver on ControllerHandle. This service is called by the\r
@@ -417,13 +454,13 @@ Ip4CleanService (
 EFI_STATUS\r
 EFIAPI\r
 Ip4DriverBindingStart (\r
-  IN EFI_DRIVER_BINDING_PROTOCOL  * This,\r
+  IN EFI_DRIVER_BINDING_PROTOCOL  *This,\r
   IN EFI_HANDLE                   ControllerHandle,\r
-  IN EFI_DEVICE_PATH_PROTOCOL     * RemainingDevicePath OPTIONAL\r
+  IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath OPTIONAL\r
   )\r
-{\r
-  IP4_SERVICE               *IpSb;\r
-  EFI_STATUS                Status;\r
+{ \r
+  EFI_STATUS                    Status;\r
+  IP4_SERVICE                   *IpSb;\r
 \r
   //\r
   // Test for the Ip4 service binding protocol\r
@@ -440,12 +477,13 @@ Ip4DriverBindingStart (
   if (Status == EFI_SUCCESS) {\r
     return EFI_ALREADY_STARTED;\r
   }\r
-\r
+  \r
   Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
-\r
+  \r
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  \r
   ASSERT (IpSb != NULL);\r
 \r
   //\r
@@ -455,19 +493,23 @@ Ip4DriverBindingStart (
                   &ControllerHandle,\r
                   &gEfiIp4ServiceBindingProtocolGuid,\r
                   &IpSb->ServiceBinding,\r
+                  &gEfiIp4Config2ProtocolGuid,\r
+                  &IpSb->Ip4Config2Instance.Ip4Config2,\r
                   NULL\r
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
     goto FREE_SERVICE;\r
   }\r
-\r
\r
   //\r
-  // ready to go: start the receiving and timer\r
+  // Ready to go: start the receiving and timer.\r
+  // Ip4Config2SetPolicy maybe call Ip4ReceiveFrame() to set the default interface's RecvRequest first after\r
+  // Ip4Config2 instance is initialized. So, EFI_ALREADY_STARTED is the allowed return status.\r
   //\r
   Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
 \r
-  if (EFI_ERROR (Status)) {\r
+  if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
     goto UNINSTALL_PROTOCOL;\r
   }\r
 \r
@@ -482,8 +524,6 @@ Ip4DriverBindingStart (
   //\r
   mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
 \r
-  Ip4SetVariableData (IpSb);\r
-\r
   return Status;\r
 \r
 UNINSTALL_PROTOCOL:\r
@@ -496,7 +536,6 @@ UNINSTALL_PROTOCOL:
 FREE_SERVICE:\r
   Ip4CleanService (IpSb);\r
   FreePool (IpSb);\r
-\r
   return Status;\r
 }\r
 \r
@@ -528,111 +567,33 @@ Ip4DriverBindingStop (
   IN  EFI_HANDLE                   *ChildHandleBuffer\r
   )\r
 {\r
-  EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
-  IP4_SERVICE                   *IpSb;\r
-  IP4_PROTOCOL                  *IpInstance;\r
-  EFI_HANDLE                    NicHandle;\r
-  EFI_STATUS                    Status;\r
-  EFI_TPL                       OldTpl;\r
-  INTN                          State;\r
-  BOOLEAN                       IsArp;\r
-\r
-  //\r
-  // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol\r
-  // by driver. So the ControllerHandle may be the MNP child handle, ARP child\r
-  // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed\r
-  // in the NIC handle.\r
-  //\r
-  //\r
-  // First, check whether it is the IP4_CONFIG protocol being uninstalled.\r
-  // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary\r
-  // to clean up the default configuration if IP4_CONFIG is being stopped.\r
-  //\r
-  Status = gBS->OpenProtocol (\r
-                  ControllerHandle,\r
-                  &gEfiIp4ConfigProtocolGuid,\r
-                  NULL,\r
-                  This->DriverBindingHandle,\r
-                  ControllerHandle,\r
-                  EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
-                  );\r
-\r
-  if (Status == EFI_SUCCESS) {\r
-    //\r
-    // Retrieve the IP4 service binding protocol. If failed, it is\r
-    // likely that Ip4 ServiceBinding is uninstalled already. In this\r
-    // case, return immediately.\r
-    //\r
-    Status = gBS->OpenProtocol (\r
-                    ControllerHandle,\r
-                    &gEfiIp4ServiceBindingProtocolGuid,\r
-                    (VOID **) &ServiceBinding,\r
-                    This->DriverBindingHandle,\r
-                    ControllerHandle,\r
-                    EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
-                    );\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      return EFI_DEVICE_ERROR;\r
-    }\r
-\r
-    IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
-\r
-    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-    if (IpSb->Ip4Config != NULL && (IpSb->State != IP4_SERVICE_DESTORY)) {\r
-\r
-      IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
-\r
-      Status = gBS->CloseProtocol (\r
-                      ControllerHandle,\r
-                      &gEfiIp4ConfigProtocolGuid,\r
-                      IpSb->Image,\r
-                      ControllerHandle\r
-                      );\r
-\r
-      if (EFI_ERROR (Status)) {\r
-        gBS->RestoreTPL (OldTpl);\r
-        return Status;\r
-      }\r
-\r
-      //\r
-      // If the auto configure hasn't complete, mark it as not started.\r
-      //\r
-      if (IpSb->State == IP4_SERVICE_STARTED) {\r
-        IpSb->State = IP4_SERVICE_UNSTARTED;\r
-      }\r
-\r
-      IpSb->Ip4Config = NULL;\r
-      gBS->CloseEvent (IpSb->DoneEvent);\r
-      gBS->CloseEvent (IpSb->ReconfigEvent);\r
-    }\r
-\r
-    gBS->RestoreTPL (OldTpl);\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  //\r
-  // Either MNP or ARP protocol is being uninstalled. The controller\r
-  // handle is either the MNP child or ARP child. But, the IP4's\r
-  // service binding is installed on the NIC handle. So, need to open\r
-  // the protocol info to find the NIC handle.\r
-  //\r
-  IsArp     = FALSE;\r
+  EFI_SERVICE_BINDING_PROTOCOL             *ServiceBinding;\r
+  IP4_SERVICE                              *IpSb; \r
+  EFI_HANDLE                               NicHandle;\r
+  EFI_STATUS                               Status; \r
+  INTN                                     State;\r
+  LIST_ENTRY                               *List;\r
+  IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT  Context;\r
+  IP4_INTERFACE                            *IpIf;\r
+  IP4_ROUTE_TABLE                          *RouteTable;\r
+\r
+  BOOLEAN                                  IsDhcp4;\r
+\r
+  IsDhcp4   = FALSE;\r
+   \r
   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
-\r
   if (NicHandle == NULL) {\r
     NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
-    IsArp     = TRUE;\r
-  }\r
-\r
-  if (NicHandle == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
+    if (NicHandle == NULL) {\r
+      NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
+      if (NicHandle != NULL) {\r
+        IsDhcp4 = TRUE;  \r
+      } else {\r
+        return EFI_SUCCESS;\r
+      }\r
+    }\r
   }\r
-\r
-  //\r
-  // Retrieve the IP4 service binding protocol\r
-  //\r
+   \r
   Status = gBS->OpenProtocol (\r
                   NicHandle,\r
                   &gEfiIp4ServiceBindingProtocolGuid,\r
@@ -641,103 +602,85 @@ Ip4DriverBindingStop (
                   NicHandle,\r
                   EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
                   );\r
-\r
   if (EFI_ERROR (Status)) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
-\r
-  IpSb   = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
-\r
-  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
-  if (IpSb->InDestory) {\r
-    gBS->RestoreTPL (OldTpl);\r
-    return EFI_SUCCESS;\r
-  }\r
-\r
-  if (IsArp) {\r
-    while (!IsListEmpty (&IpSb->Children)) {\r
-      IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
-\r
-      ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
-    }\r
-\r
-    if (IpSb->NumChildren != 0) {\r
-      Status = EFI_DEVICE_ERROR;\r
-      goto ON_ERROR;\r
-    }\r
-\r
-    IpSb->InDestory = TRUE;\r
-\r
-    State           = IpSb->State;\r
-    IpSb->State     = IP4_SERVICE_DESTORY;\r
-\r
+  \r
+  IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
+\r
+  if (IsDhcp4) {\r
+    Status = Ip4Config2DestroyDhcp4 (&IpSb->Ip4Config2Instance);\r
+    gBS->CloseEvent (IpSb->Ip4Config2Instance.Dhcp4Event);\r
+    IpSb->Ip4Config2Instance.Dhcp4Event = NULL;\r
+  } else if (NumberOfChildren != 0) {\r
+    List = &IpSb->Children;\r
+    Context.ServiceBinding    = ServiceBinding;\r
+    Context.NumberOfChildren  = NumberOfChildren;\r
+    Context.ChildHandleBuffer = ChildHandleBuffer;\r
+    Status = NetDestroyLinkList (\r
+               List,\r
+               Ip4DestroyChildEntryInHandleBuffer,\r
+               &Context,\r
+               NULL\r
+               );\r
+  } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {\r
+  \r
     //\r
-    // Clear the variable data.\r
+    // The ARP protocol for the default interface is being uninstalled and all\r
+    // its IP child handles should have been destroyed before. So, release the\r
+    // default interface and route table, create a new one and mark it as not started.\r
     //\r
-    Ip4ClearVariableData (IpSb);\r
-\r
-    //\r
-    // OK, clean other resources then uninstall the service binding protocol.\r
-    //\r
-    Status = Ip4CleanService (IpSb);\r
-\r
-    if (EFI_ERROR (Status)) {\r
-      IpSb->State = State;\r
+    Ip4CancelReceive (IpSb->DefaultInterface);\r
+    Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
+    Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
+    \r
+    IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
+    if (IpIf == NULL) {\r
       goto ON_ERROR;\r
     }\r
+    RouteTable = Ip4CreateRouteTable ();\r
+    if (RouteTable == NULL) {\r
+      Ip4FreeInterface (IpIf, NULL);\r
+      goto ON_ERROR;;\r
+    }\r
+    \r
+    IpSb->DefaultInterface  = IpIf;\r
+    InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
+    IpSb->DefaultRouteTable = RouteTable;\r
+    Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
 \r
-    gBS->UninstallProtocolInterface (\r
-           NicHandle,\r
-           &gEfiIp4ServiceBindingProtocolGuid,\r
-           ServiceBinding\r
-           );\r
-\r
-    FreePool (IpSb);\r
-  } else if (NumberOfChildren == 0) {\r
-    IpSb->InDestory = TRUE;\r
+    IpSb->State = IP4_SERVICE_UNSTARTED;\r
 \r
+  } else if (IsListEmpty (&IpSb->Children)) {\r
     State           = IpSb->State;\r
-    IpSb->State     = IP4_SERVICE_DESTORY;\r
-\r
-    //\r
-    // Clear the variable data.\r
-    //\r
-    Ip4ClearVariableData (IpSb);\r
+    IpSb->State     = IP4_SERVICE_DESTROY;\r
 \r
     //\r
     // OK, clean other resources then uninstall the service binding protocol.\r
     //\r
     Status = Ip4CleanService (IpSb);\r
-\r
     if (EFI_ERROR (Status)) {\r
       IpSb->State = State;\r
       goto ON_ERROR;\r
     }\r
 \r
-    gBS->UninstallProtocolInterface (\r
+    gBS->UninstallMultipleProtocolInterfaces (\r
            NicHandle,\r
            &gEfiIp4ServiceBindingProtocolGuid,\r
-           ServiceBinding\r
+           ServiceBinding,\r
+           &gEfiIp4Config2ProtocolGuid,\r
+           &IpSb->Ip4Config2Instance.Ip4Config2,\r
+           NULL\r
            );\r
-\r
-    FreePool (IpSb);\r
-  } else {\r
-\r
-    while (!IsListEmpty (&IpSb->Children)) {\r
-      IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
-\r
-      ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
-    }\r
-\r
-    if (IpSb->NumChildren != 0) {\r
-      Status = EFI_DEVICE_ERROR;\r
+    \r
+    if (gIp4ControllerNameTable != NULL) {\r
+      FreeUnicodeStringTable (gIp4ControllerNameTable);\r
+      gIp4ControllerNameTable = NULL;\r
     }\r
+    FreePool (IpSb);\r
   }\r
 \r
 ON_ERROR:\r
-\r
-  gBS->RestoreTPL (OldTpl);\r
   return Status;\r
 }\r
 \r
@@ -860,7 +803,7 @@ ON_ERROR:
 \r
   @retval EFI_SUCCES            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
@@ -911,18 +854,18 @@ Ip4ServiceBindingDestroyChild (
   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
 \r
   //\r
-  // A child can be destoried more than once. For example,\r
-  // Ip4DriverBindingStop will destory all of its children.\r
-  // when UDP driver is being stopped, it will destory all\r
+  // A child can be destroyed more than once. For example,\r
+  // Ip4DriverBindingStop 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 == IP4_STATE_DESTORY) {\r
+  if (IpInstance->State == IP4_STATE_DESTROY) {\r
     gBS->RestoreTPL (OldTpl);\r
     return EFI_SUCCESS;\r
   }\r
 \r
   State             = IpInstance->State;\r
-  IpInstance->State = IP4_STATE_DESTORY;\r
+  IpInstance->State = IP4_STATE_DESTROY;\r
 \r
   //\r
   // Close the Managed Network protocol.\r
@@ -934,6 +877,15 @@ Ip4ServiceBindingDestroyChild (
          ChildHandle\r
          );\r
 \r
+  if (IpInstance->Interface != NULL && IpInstance->Interface->Arp != NULL) {\r
+    gBS->CloseProtocol (\r
+           IpInstance->Interface->ArpHandle,\r
+           &gEfiArpProtocolGuid,\r
+           gIp4DriverBinding.DriverBindingHandle,\r
+           ChildHandle\r
+           );\r
+  }\r
+\r
   //\r
   // Uninstall the IP4 protocol first. Many thing happens during\r
   // this:\r
@@ -948,20 +900,18 @@ Ip4ServiceBindingDestroyChild (
   // 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
                   &gEfiIp4ProtocolGuid,\r
                   &IpInstance->Ip4Proto\r
                   );\r
-\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
   if (EFI_ERROR (Status)) {\r
     goto ON_ERROR;\r
   }\r
 \r
   Status = Ip4CleanProtocol (IpInstance);\r
-\r
-  Ip4SetVariableData (IpSb);\r
-\r
   if (EFI_ERROR (Status)) {\r
     gBS->InstallMultipleProtocolInterfaces (\r
            &ChildHandle,\r