BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Driver.c
index 4d78b87..e891b68 100644 (file)
@@ -1,21 +1,7 @@
 /** @file\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. 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
-\r
-\r
-Module Name:\r
-\r
-  Dhcp4Driver.c\r
-\r
-Abstract:\r
-\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -31,35 +17,31 @@ EFI_DRIVER_BINDING_PROTOCOL gDhcp4DriverBinding = {
   NULL\r
 };\r
 \r
-EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplete = {\r
+EFI_SERVICE_BINDING_PROTOCOL mDhcp4ServiceBindingTemplate = {\r
   Dhcp4ServiceBindingCreateChild,\r
   Dhcp4ServiceBindingDestroyChild\r
 };\r
 \r
+/**\r
+  This is the declaration of an EFI image entry point. This entry point is\r
+  the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
+  both device drivers and bus drivers.\r
+\r
+  Entry point of the DHCP driver to install various protocols.\r
+\r
+  @param[in]  ImageHandle           The firmware allocated handle for the UEFI image.\r
+  @param[in]  SystemTable           A pointer to the EFI System Table.\r
+\r
+  @retval EFI_SUCCESS           The operation completed successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  The request could not be completed due to a lack of resources.\r
 \r
+**/\r
 EFI_STATUS\r
 EFIAPI\r
 Dhcp4DriverEntryPoint (\r
   IN EFI_HANDLE             ImageHandle,\r
   IN EFI_SYSTEM_TABLE       *SystemTable\r
   )\r
-/*++\r
-\r
-Routine Description:\r
-\r
-  Entry point of the DHCP driver to install various protocols.\r
-\r
-Arguments:\r
-\r
-  ImageHandle - The driver's image handle\r
-  SystemTable - The system table\r
-\r
-Returns:\r
-\r
-  EFI_SUCCESS - All the related protocols are installed.\r
-  Others      - Failed to install the protocols.\r
-\r
---*/\r
 {\r
   return EfiLibInstallDriverBindingComponentName2 (\r
            ImageHandle,\r
@@ -73,15 +55,21 @@ Returns:
 \r
 \r
 /**\r
-  Test to see if DHCP driver supports the ControllerHandle.\r
-\r
-  @param  This                   Protocol instance pointer.\r
-  @param  ControllerHandle       Handle of device to test\r
-  @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
-                                 device to start.\r
-\r
-  @retval EFI_SUCCES             This driver supports this device\r
-  @retval other                  This driver does not support this device\r
+  Test to see if this driver supports ControllerHandle. This service\r
+  is called by the EFI boot service ConnectController(). In\r
+  order to make drivers as small as possible, there are a few calling\r
+  restrictions for this service. ConnectController() must\r
+  follow these calling restrictions. If any other agent wishes to call\r
+  Supported() it must also follow these calling restrictions.\r
+\r
+  @param[in]  This                Protocol instance pointer.\r
+  @param[in]  ControllerHandle    Handle of device to test\r
+  @param[in]  RemainingDevicePath Optional parameter use to pick a specific child\r
+                                  device to start.\r
+\r
+  @retval EFI_SUCCESS         This driver supports this device\r
+  @retval EFI_ALREADY_STARTED This driver is already running on this device\r
+  @retval other               This driver does not support this device\r
 \r
 **/\r
 EFI_STATUS\r
@@ -112,16 +100,17 @@ Dhcp4DriverBindingSupported (
   Configure the default UDP child to receive all the DHCP traffics\r
   on this network interface.\r
 \r
-  @param  UdpIo                  The UDP IO port to configure\r
-  @param  Context                The context to the function\r
+  @param[in]  UdpIo                  The UDP IO to configure\r
+  @param[in]  Context                The context to the function\r
 \r
-  @retval EFI_SUCCESS            The UDP IO port is successfully configured.\r
+  @retval EFI_SUCCESS            The UDP IO is successfully configured.\r
   @retval Others                 Failed to configure the UDP child.\r
 \r
 **/\r
 EFI_STATUS\r
+EFIAPI\r
 DhcpConfigUdpIo (\r
-  IN UDP_IO_PORT            *UdpIo,\r
+  IN UDP_IO                 *UdpIo,\r
   IN VOID                   *Context\r
   )\r
 {\r
@@ -141,23 +130,23 @@ DhcpConfigUdpIo (
   UdpConfigData.StationPort               = DHCP_CLIENT_PORT;\r
   UdpConfigData.RemotePort                = DHCP_SERVER_PORT;\r
 \r
-  NetZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
-  NetZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
-  NetZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
+  ZeroMem (&UdpConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS));\r
+  ZeroMem (&UdpConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS));\r
+  ZeroMem (&UdpConfigData.RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
 \r
-  return UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);;\r
+  return UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfigData);;\r
 }\r
 \r
 \r
 \r
 /**\r
-  Destory the DHCP service. The Dhcp4 service may be partly initialized,\r
-  or partly destoried. If a resource is destoried, it is marked as so in\r
-  case the destory failed and being called again later.\r
+  Destroy the DHCP service. The Dhcp4 service may be partly initialized,\r
+  or partly destroyed. If a resource is destroyed, it is marked as so in\r
+  case the destroy failed and being called again later.\r
 \r
-  @param  DhcpSb                 The DHCP service instance to destory.\r
+  @param[in]  DhcpSb                 The DHCP service instance to destroy.\r
 \r
-  @retval EFI_SUCCESS            The DHCP service is successfully closed.\r
+  @retval EFI_SUCCESS            Always return success.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -168,7 +157,7 @@ Dhcp4CloseService (
   DhcpCleanLease (DhcpSb);\r
 \r
   if (DhcpSb->UdpIo != NULL) {\r
-    UdpIoFreePort (DhcpSb->UdpIo);\r
+    UdpIoFreeIo (DhcpSb->UdpIo);\r
     DhcpSb->UdpIo = NULL;\r
   }\r
 \r
@@ -187,14 +176,15 @@ Dhcp4CloseService (
 /**\r
   Create a new DHCP service binding instance for the controller.\r
 \r
-  @param  Controller             The controller to install DHCP service binding\r
-                                 protocol onto\r
-  @param  ImageHandle            The driver's image handle\r
-  @param  Service                The variable to receive the created DHCP service\r
-                                 instance.\r
+  @param[in]  Controller             The controller to install DHCP service binding\r
+                                     protocol onto\r
+  @param[in]  ImageHandle            The driver's image handle\r
+  @param[out] Service                The variable to receive the created DHCP service\r
+                                     instance.\r
 \r
   @retval EFI_OUT_OF_RESOURCES   Failed to allocate resource .\r
   @retval EFI_SUCCESS            The DHCP service instance is created.\r
+  @retval other                  Other error occurs.\r
 \r
 **/\r
 EFI_STATUS\r
@@ -208,28 +198,30 @@ Dhcp4CreateService (
   EFI_STATUS                Status;\r
 \r
   *Service  = NULL;\r
-  DhcpSb    = NetAllocateZeroPool (sizeof (DHCP_SERVICE));\r
+  DhcpSb    = AllocateZeroPool (sizeof (DHCP_SERVICE));\r
 \r
   if (DhcpSb == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   DhcpSb->Signature       = DHCP_SERVICE_SIGNATURE;\r
-  DhcpSb->ServiceBinding  = mDhcp4ServiceBindingTemplete;\r
   DhcpSb->ServiceState    = DHCP_UNCONFIGED;\r
-  DhcpSb->InDestory       = FALSE;\r
   DhcpSb->Controller      = Controller;\r
   DhcpSb->Image           = ImageHandle;\r
-  NetListInit (&DhcpSb->Children);\r
+  InitializeListHead (&DhcpSb->Children);\r
   DhcpSb->DhcpState       = Dhcp4Stopped;\r
   DhcpSb->Xid             = NET_RANDOM (NetRandomInitSeed ());\r
-\r
+  CopyMem (\r
+    &DhcpSb->ServiceBinding,\r
+    &mDhcp4ServiceBindingTemplate,\r
+    sizeof (EFI_SERVICE_BINDING_PROTOCOL)\r
+    );\r
   //\r
   // Create various resources, UdpIo, Timer, and get Mac address\r
   //\r
   Status = gBS->CreateEvent (\r
                   EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
-                  NET_TPL_TIMER,\r
+                  TPL_CALLBACK,\r
                   DhcpOnTimerTick,\r
                   DhcpSb,\r
                   &DhcpSb->Timer\r
@@ -239,7 +231,13 @@ Dhcp4CreateService (
     goto ON_ERROR;\r
   }\r
 \r
-  DhcpSb->UdpIo = UdpIoCreatePort (Controller, ImageHandle, DhcpConfigUdpIo, NULL);\r
+  DhcpSb->UdpIo = UdpIoCreateIo (\r
+                    Controller,\r
+                    ImageHandle,\r
+                    DhcpConfigUdpIo,\r
+                    UDP_IO_UDP4_VERSION,\r
+                    NULL\r
+                    );\r
 \r
   if (DhcpSb->UdpIo == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
@@ -255,23 +253,28 @@ Dhcp4CreateService (
 \r
 ON_ERROR:\r
   Dhcp4CloseService (DhcpSb);\r
-  NetFreePool (DhcpSb);\r
+  FreePool (DhcpSb);\r
 \r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Start this driver on ControllerHandle.\r
-\r
-  @param  This                   Protocol instance pointer.\r
-  @param  ControllerHandle       Handle of device to bind driver to\r
-  @param  RemainingDevicePath    Optional parameter use to pick a specific child\r
-                                 device to start.\r
-\r
-  @retval EFI_SUCCES             This driver is added to ControllerHandle\r
-  @retval EFI_ALREADY_STARTED    This driver is already running on ControllerHandle\r
-  @retval other                  This driver does not support this device\r
+  Start this driver on ControllerHandle. This service is called by the\r
+  EFI boot service ConnectController(). In order to make\r
+  drivers as small as possible, there are a few calling restrictions for\r
+  this service. ConnectController() must follow these\r
+  calling restrictions. If any other agent wishes to call Start() it\r
+  must also follow these calling restrictions.\r
+\r
+  @param[in]  This                 Protocol instance pointer.\r
+  @param[in]  ControllerHandle     Handle of device to bind driver to\r
+  @param[in]  RemainingDevicePath  Optional parameter use to pick a specific child\r
+                                   device to start.\r
+\r
+  @retval EFI_SUCCESS          This driver is added to ControllerHandle\r
+  @retval EFI_ALREADY_STARTED  This driver is already running on ControllerHandle\r
+  @retval other                This driver does not support this device\r
 \r
 **/\r
 EFI_STATUS\r
@@ -306,7 +309,16 @@ Dhcp4DriverBindingStart (
   if (EFI_ERROR (Status)) {\r
     return Status;\r
   }\r
+  ASSERT (DhcpSb != NULL);\r
+\r
+  //\r
+  // Start the receiving\r
+  //\r
+  Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
 \r
+  if (EFI_ERROR (Status)) {\r
+    goto ON_ERROR;\r
+  }\r
   Status = gBS->SetTimer (DhcpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
 \r
   if (EFI_ERROR (Status)) {\r
@@ -331,22 +343,57 @@ Dhcp4DriverBindingStart (
 \r
 ON_ERROR:\r
   Dhcp4CloseService (DhcpSb);\r
-  NetFreePool (DhcpSb);\r
+  FreePool (DhcpSb);\r
   return Status;\r
 }\r
 \r
-\r
 /**\r
-  Stop this driver on ControllerHandle.\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
+Dhcp4DestroyChildEntry (\r
+  IN LIST_ENTRY         *Entry,\r
+  IN VOID               *Context\r
+  )\r
+{\r
+  DHCP_PROTOCOL                    *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, DHCP_PROTOCOL, Link, DHCP_PROTOCOL_SIGNATURE);\r
+  ServiceBinding = (EFI_SERVICE_BINDING_PROTOCOL *) Context;\r
+\r
+  return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
+}\r
 \r
-  @param  This                   Protocol instance pointer.\r
-  @param  ControllerHandle       Handle of device to stop driver on\r
-  @param  NumberOfChildren       Number of Handles in ChildHandleBuffer. If number\r
-                                 of  children is zero stop the entire bus driver.\r
-  @param  ChildHandleBuffer      List of Child Handles to Stop.\r
 \r
-  @retval EFI_SUCCES             This driver is removed ControllerHandle\r
-  @retval other                  This driver was not removed from this device\r
+/**\r
+  Stop this driver on ControllerHandle. This service is called by the\r
+  EFI boot service DisconnectController(). In order to\r
+  make drivers as small as possible, there are a few calling\r
+  restrictions for this service. DisconnectController()\r
+  must follow these calling restrictions. If any other agent wishes\r
+  to call Stop() it must also follow these calling restrictions.\r
+\r
+  @param[in]  This              Protocol instance pointer.\r
+  @param[in]  ControllerHandle  Handle of device to stop driver on\r
+  @param[in]  NumberOfChildren  Number of Handles in ChildHandleBuffer. If number of\r
+                                children is zero stop the entire bus driver.\r
+  @param[in]  ChildHandleBuffer List of Child Handles to Stop.\r
+\r
+  @retval EFI_SUCCESS       This driver is removed ControllerHandle\r
+  @retval other             This driver was not removed from this device\r
 \r
 **/\r
 EFI_STATUS\r
@@ -360,10 +407,10 @@ Dhcp4DriverBindingStop (
 {\r
   EFI_SERVICE_BINDING_PROTOCOL  *ServiceBinding;\r
   DHCP_SERVICE                  *DhcpSb;\r
-  DHCP_PROTOCOL                 *Instance;\r
   EFI_HANDLE                    NicHandle;\r
   EFI_STATUS                    Status;\r
-  EFI_TPL                       OldTpl;\r
+  LIST_ENTRY                    *List;\r
+  UINTN                         ListLength;\r
 \r
   //\r
   // DHCP driver opens UDP child, So, the ControllerHandle is the\r
@@ -372,7 +419,7 @@ Dhcp4DriverBindingStop (
   NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);\r
 \r
   if (NicHandle == NULL) {\r
-    return EFI_DEVICE_ERROR;\r
+    return EFI_SUCCESS;\r
   }\r
 \r
    Status = gBS->OpenProtocol (\r
@@ -389,17 +436,31 @@ Dhcp4DriverBindingStop (
   }\r
 \r
   DhcpSb = DHCP_SERVICE_FROM_THIS (ServiceBinding);\r
-\r
-  if (DhcpSb->InDestory) {\r
-    return EFI_SUCCESS;\r
+  if (!IsListEmpty (&DhcpSb->Children)) {\r
+    //\r
+    // Destroy all the children instances before destory the service.\r
+    //\r
+    List = &DhcpSb->Children;\r
+    Status = NetDestroyLinkList (\r
+               List,\r
+               Dhcp4DestroyChildEntry,\r
+               ServiceBinding,\r
+               &ListLength\r
+               );\r
+    if (EFI_ERROR (Status) || ListLength != 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+    }\r
   }\r
 \r
-  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
-\r
-  if (NumberOfChildren == 0) {\r
+  if (NumberOfChildren == 0 && !IsListEmpty (&DhcpSb->Children)) {\r
+    Status = EFI_DEVICE_ERROR;\r
+  }\r
 \r
-    DhcpSb->InDestory    = TRUE;\r
-    DhcpSb->ServiceState = DHCP_DESTORY;\r
+  if (NumberOfChildren == 0 && IsListEmpty (&DhcpSb->Children)) {\r
+    //\r
+    // Destroy the service itself if no child instance left.\r
+    //\r
+    DhcpSb->ServiceState = DHCP_DESTROY;\r
 \r
     gBS->UninstallProtocolInterface (\r
            NicHandle,\r
@@ -409,70 +470,64 @@ Dhcp4DriverBindingStop (
 \r
     Dhcp4CloseService (DhcpSb);\r
 \r
-    NetFreePool (DhcpSb);\r
-  } else {\r
-    //\r
-    // Don't use NET_LIST_FOR_EACH_SAFE here, Dhcp4ServiceBindingDestoryChild\r
-    // may cause other child to be deleted.\r
-    //\r
-    while (!NetListIsEmpty (&DhcpSb->Children)) {\r
-      Instance = NET_LIST_HEAD (&DhcpSb->Children, DHCP_PROTOCOL, Link);\r
-      ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
+    if (gDhcpControllerNameTable != NULL) {\r
+      FreeUnicodeStringTable (gDhcpControllerNameTable);\r
+      gDhcpControllerNameTable = NULL;\r
     }\r
+    FreePool (DhcpSb);\r
 \r
-    if (DhcpSb->NumChildren != 0) {\r
-      Status = EFI_DEVICE_ERROR;\r
-    }\r
+    Status = EFI_SUCCESS;\r
   }\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
-\r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Initialize a new DHCP child\r
+  Initialize a new DHCP instance.\r
 \r
   @param  DhcpSb                 The dhcp service instance\r
   @param  Instance               The dhcp instance to initialize\r
 \r
-  @return None\r
-\r
 **/\r
 VOID\r
 DhcpInitProtocol (\r
-  IN DHCP_SERVICE           *DhcpSb,\r
-  IN DHCP_PROTOCOL          *Instance\r
+  IN     DHCP_SERVICE           *DhcpSb,\r
+  IN OUT DHCP_PROTOCOL          *Instance\r
   )\r
 {\r
   Instance->Signature         = DHCP_PROTOCOL_SIGNATURE;\r
   CopyMem (&Instance->Dhcp4Protocol, &mDhcp4ProtocolTemplate, sizeof (Instance->Dhcp4Protocol));\r
-  NetListInit (&Instance->Link);\r
+  InitializeListHead (&Instance->Link);\r
   Instance->Handle            = NULL;\r
   Instance->Service           = DhcpSb;\r
-  Instance->InDestory         = FALSE;\r
+  Instance->InDestroy         = FALSE;\r
   Instance->CompletionEvent   = NULL;\r
   Instance->RenewRebindEvent  = NULL;\r
   Instance->Token             = NULL;\r
   Instance->UdpIo             = NULL;\r
+  Instance->ElaspedTime       = 0;\r
   NetbufQueInit (&Instance->ResponseQueue);\r
 }\r
 \r
 \r
 /**\r
-  Creates a child handle with a set of DHCP4 services.\r
+  Creates a child handle and installs a protocol.\r
 \r
-  @param  This                   Protocol instance pointer.\r
-  @param  ChildHandle            Pointer to the handle of the child to create.  If\r
-                                 it  is NULL, then a new handle is created.  If it\r
-                                 is not  NULL, then the DHCP4 services are added to\r
-                                 the existing  child handle.\r
+  The CreateChild() function installs a protocol on ChildHandle.\r
+  If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
+  If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
 \r
-  @retval EFI_SUCCES             The child handle was created with the DHCP4\r
-                                 services\r
-  @retval EFI_OUT_OF_RESOURCES   There are not enough resources to create the child\r
-  @retval other                  The child handle was not created\r
+  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+  @param  ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
+                      then a new handle is created. If it is a pointer to an existing UEFI handle,\r
+                      then the protocol is added to the existing UEFI handle.\r
+\r
+  @retval EFI_SUCCES            The protocol was added to ChildHandle.\r
+  @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
+  @retval EFI_OUT_OF_RESOURCES  There are not enough resources available to create\r
+                                the child\r
+  @retval other                 The child handle was not created\r
 \r
 **/\r
 EFI_STATUS\r
@@ -492,7 +547,7 @@ Dhcp4ServiceBindingCreateChild (
     return EFI_INVALID_PARAMETER;\r
   }\r
 \r
-  Instance = NetAllocatePool (sizeof (*Instance));\r
+  Instance = AllocatePool (sizeof (*Instance));\r
 \r
   if (Instance == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
@@ -512,7 +567,7 @@ Dhcp4ServiceBindingCreateChild (
                   );\r
 \r
   if (EFI_ERROR (Status)) {\r
-    NetFreePool (Instance);\r
+    FreePool (Instance);\r
     return Status;\r
   }\r
 \r
@@ -537,34 +592,37 @@ Dhcp4ServiceBindingCreateChild (
            NULL\r
            );\r
 \r
-    NetFreePool (Instance);\r
+    FreePool (Instance);\r
     return Status;\r
   }\r
 \r
-  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
 \r
-  NetListInsertTail (&DhcpSb->Children, &Instance->Link);\r
+  InsertTailList (&DhcpSb->Children, &Instance->Link);\r
   DhcpSb->NumChildren++;\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
+  gBS->RestoreTPL (OldTpl);\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
 \r
 /**\r
-  Destroys a child handle with a set of DHCP4 services.\r
+  Destroys a child handle with a protocol installed on it.\r
+\r
+  The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
+  that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
+  last protocol on ChildHandle, then ChildHandle is destroyed.\r
 \r
-  @param  This                   Protocol instance pointer.\r
-  @param  ChildHandle            Handle of the child to destroy\r
+  @param  This        Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
+  @param  ChildHandle Handle of the child to destroy\r
 \r
-  @retval EFI_SUCCES             The DHCP4 service is removed from the child handle\r
-  @retval EFI_UNSUPPORTED        The child handle does not support the DHCP4\r
-                                 service\r
-  @retval EFI_INVALID_PARAMETER  Child handle is not a valid EFI Handle.\r
-  @retval EFI_ACCESS_DENIED      The child handle could not be destroyed because\r
-                                 its  DHCP4 services are being used.\r
-  @retval other                  The child handle was not destroyed\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 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
 \r
 **/\r
 EFI_STATUS\r
@@ -608,17 +666,17 @@ Dhcp4ServiceBindingDestroyChild (
   }\r
 \r
   //\r
-  // A child can be destoried more than once. For example,\r
-  // Dhcp4DriverBindingStop will destory all of its children.\r
-  // when caller driver is being stopped, it will destory the\r
+  // A child can be destroyed more than once. For example,\r
+  // Dhcp4DriverBindingStop will destroy all of its children.\r
+  // when caller driver is being stopped, it will destroy the\r
   // dhcp child it opens.\r
   //\r
-  if (Instance->InDestory) {\r
+  if (Instance->InDestroy) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
-  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
-  Instance->InDestory = TRUE;\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+  Instance->InDestroy = TRUE;\r
 \r
   //\r
   // Close the Udp4 protocol.\r
@@ -633,16 +691,17 @@ Dhcp4ServiceBindingDestroyChild (
   //\r
   // Uninstall the DHCP4 protocol first to enable a top down destruction.\r
   //\r
+  gBS->RestoreTPL (OldTpl);\r
   Status = gBS->UninstallProtocolInterface (\r
                   ChildHandle,\r
                   &gEfiDhcp4ProtocolGuid,\r
                   Dhcp\r
                   );\r
-\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
   if (EFI_ERROR (Status)) {\r
-    Instance->InDestory = FALSE;\r
+    Instance->InDestroy = FALSE;\r
 \r
-    NET_RESTORE_TPL (OldTpl);\r
+    gBS->RestoreTPL (OldTpl);\r
     return Status;\r
   }\r
 \r
@@ -650,11 +709,24 @@ Dhcp4ServiceBindingDestroyChild (
     DhcpYieldControl (DhcpSb);\r
   }\r
 \r
-  NetListRemoveEntry (&Instance->Link);\r
+  RemoveEntryList (&Instance->Link);\r
   DhcpSb->NumChildren--;\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
+  if (Instance->UdpIo != NULL) {\r
+    UdpIoCleanIo (Instance->UdpIo);\r
+    gBS->CloseProtocol (\r
+           Instance->UdpIo->UdpHandle,\r
+           &gEfiUdp4ProtocolGuid,\r
+           Instance->Service->Image,\r
+           Instance->Handle\r
+           );\r
+    UdpIoFreeIo (Instance->UdpIo);\r
+    Instance->UdpIo = NULL;\r
+    Instance->Token = NULL;\r
+  }\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
 \r
-  NetFreePool (Instance);\r
+  FreePool (Instance);\r
   return EFI_SUCCESS;\r
 }\r