/** @file\r
\r
-Copyright (c) 2006 - 2011, 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
-\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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
\r
/**\r
- Destory the DHCP service. The Dhcp4 service may be partly initialized,\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[in] DhcpSb The DHCP service instance to destory.\r
+ @param[in] DhcpSb The DHCP service instance to destroy.\r
\r
@retval EFI_SUCCESS Always return success.\r
\r
\r
DhcpSb->Signature = DHCP_SERVICE_SIGNATURE;\r
DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
- DhcpSb->InDestory = FALSE;\r
DhcpSb->Controller = Controller;\r
DhcpSb->Image = ImageHandle;\r
InitializeListHead (&DhcpSb->Children);\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
+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
\r
/**\r
Stop this driver on ControllerHandle. This service is called by the\r
{\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
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
}\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 = gBS->RaiseTPL (TPL_CALLBACK);\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
\r
Dhcp4CloseService (DhcpSb);\r
\r
- FreePool (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 (!IsListEmpty (&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
- gBS->RestoreTPL (OldTpl);\r
-\r
return Status;\r
}\r
\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
\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 availabe to create\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
// 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 destory the\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 = gBS->RaiseTPL (TPL_CALLBACK);\r
- Instance->InDestory = TRUE;\r
+ Instance->InDestroy = TRUE;\r
\r
//\r
// Close the Udp4 protocol.\r
//\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
gBS->RestoreTPL (OldTpl);\r
return Status;\r
RemoveEntryList (&Instance->Link);\r
DhcpSb->NumChildren--;\r
\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
FreePool (Instance);\r