summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c')
-rw-r--r--MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c163
1 files changed, 73 insertions, 90 deletions
diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
index 4ce85a3f51..5a84837a44 100644
--- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
+++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
@@ -176,7 +176,6 @@ Ip4CreateService (
IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;
IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;
IpSb->State = IP4_SERVICE_UNSTARTED;
- IpSb->InDestroy = FALSE;
IpSb->NumChildren = 0;
InitializeListHead (&IpSb->Children);
@@ -396,6 +395,42 @@ Ip4CleanService (
return EFI_SUCCESS;
}
+/**
+ Callback function which provided by user to remove one node in NetDestroyLinkList process.
+
+ @param[in] Entry The entry to be removed.
+ @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
+
+ @retval EFI_SUCCESS The entry has been removed successfully.
+ @retval Others Fail to remove the entry.
+
+**/
+EFI_STATUS
+Ip4DestroyChildEntryInHandleBuffer (
+ IN LIST_ENTRY *Entry,
+ IN VOID *Context
+)
+{
+ IP4_PROTOCOL *IpInstance;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ UINTN NumberOfChildren;
+ EFI_HANDLE *ChildHandleBuffer;
+
+ if (Entry == NULL || Context == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);
+ ServiceBinding = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;
+ NumberOfChildren = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;
+ ChildHandleBuffer = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;
+
+ if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {
+ return EFI_SUCCESS;
+ }
+
+ return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);
+}
/**
Start this driver on ControllerHandle. This service is called by the
@@ -529,14 +564,13 @@ Ip4DriverBindingStop (
IN EFI_HANDLE *ChildHandleBuffer
)
{
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
- IP4_SERVICE *IpSb;
- IP4_PROTOCOL *IpInstance;
- EFI_HANDLE NicHandle;
- EFI_STATUS Status;
- EFI_TPL OldTpl;
- INTN State;
- BOOLEAN IsArp;
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
+ IP4_SERVICE *IpSb;
+ EFI_HANDLE NicHandle;
+ EFI_STATUS Status;
+ INTN State;
+ LIST_ENTRY *List;
+ IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
//
// IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol
@@ -557,7 +591,6 @@ Ip4DriverBindingStop (
ControllerHandle,
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
);
-
if (Status == EFI_SUCCESS) {
//
// Retrieve the IP4 service binding protocol. If failed, it is
@@ -572,15 +605,11 @@ Ip4DriverBindingStop (
ControllerHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
-
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
if (IpSb->Ip4Config != NULL && (IpSb->State != IP4_SERVICE_DESTROY)) {
IpSb->Ip4Config->Stop (IpSb->Ip4Config);
@@ -591,9 +620,7 @@ Ip4DriverBindingStop (
IpSb->Image,
ControllerHandle
);
-
if (EFI_ERROR (Status)) {
- gBS->RestoreTPL (OldTpl);
return Status;
}
@@ -609,7 +636,6 @@ Ip4DriverBindingStop (
gBS->CloseEvent (IpSb->ReconfigEvent);
}
- gBS->RestoreTPL (OldTpl);
return EFI_SUCCESS;
}
@@ -619,16 +645,12 @@ Ip4DriverBindingStop (
// service binding is installed on the NIC handle. So, need to open
// the protocol info to find the NIC handle.
//
- IsArp = FALSE;
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);
-
if (NicHandle == NULL) {
NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);
- IsArp = TRUE;
- }
-
- if (NicHandle == NULL) {
- return EFI_DEVICE_ERROR;
+ if (NicHandle == NULL) {
+ return EFI_SUCCESS;
+ }
}
//
@@ -642,34 +664,23 @@ Ip4DriverBindingStop (
NicHandle,
EFI_OPEN_PROTOCOL_GET_PROTOCOL
);
-
if (EFI_ERROR (Status)) {
return EFI_DEVICE_ERROR;
}
IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);
-
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
-
- if (IpSb->InDestroy) {
- gBS->RestoreTPL (OldTpl);
- return EFI_SUCCESS;
- }
-
- if (IsArp) {
- while (!IsListEmpty (&IpSb->Children)) {
- IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);
-
- ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);
- }
-
- if (IpSb->NumChildren != 0) {
- Status = EFI_DEVICE_ERROR;
- goto ON_ERROR;
- }
-
- IpSb->InDestroy = TRUE;
-
+ if (NumberOfChildren != 0) {
+ List = &IpSb->Children;
+ Context.ServiceBinding = ServiceBinding;
+ Context.NumberOfChildren = NumberOfChildren;
+ Context.ChildHandleBuffer = ChildHandleBuffer;
+ Status = NetDestroyLinkList (
+ List,
+ Ip4DestroyChildEntryInHandleBuffer,
+ &Context,
+ NULL
+ );
+ } else if (IsListEmpty (&IpSb->Children)) {
State = IpSb->State;
IpSb->State = IP4_SERVICE_DESTROY;
@@ -682,7 +693,6 @@ Ip4DriverBindingStop (
// OK, clean other resources then uninstall the service binding protocol.
//
Status = Ip4CleanService (IpSb);
-
if (EFI_ERROR (Status)) {
IpSb->State = State;
goto ON_ERROR;
@@ -693,52 +703,15 @@ Ip4DriverBindingStop (
&gEfiIp4ServiceBindingProtocolGuid,
ServiceBinding
);
-
- FreePool (IpSb);
- } else if (NumberOfChildren == 0) {
- IpSb->InDestroy = TRUE;
-
- State = IpSb->State;
- IpSb->State = IP4_SERVICE_DESTROY;
-
- //
- // Clear the variable data.
- //
- Ip4ClearVariableData (IpSb);
-
- //
- // OK, clean other resources then uninstall the service binding protocol.
- //
- Status = Ip4CleanService (IpSb);
-
- if (EFI_ERROR (Status)) {
- IpSb->State = State;
- goto ON_ERROR;
+
+ if (gIp4ControllerNameTable != NULL) {
+ FreeUnicodeStringTable (gIp4ControllerNameTable);
+ gIp4ControllerNameTable = NULL;
}
-
- gBS->UninstallProtocolInterface (
- NicHandle,
- &gEfiIp4ServiceBindingProtocolGuid,
- ServiceBinding
- );
-
FreePool (IpSb);
- } else {
-
- while (!IsListEmpty (&IpSb->Children)) {
- IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);
-
- ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);
- }
-
- if (IpSb->NumChildren != 0) {
- Status = EFI_DEVICE_ERROR;
- }
}
ON_ERROR:
-
- gBS->RestoreTPL (OldTpl);
return Status;
}
@@ -935,6 +908,15 @@ Ip4ServiceBindingDestroyChild (
ChildHandle
);
+ if (IpInstance->Interface != NULL && IpInstance->Interface->Arp != NULL) {
+ gBS->CloseProtocol (
+ IpInstance->Interface->ArpHandle,
+ &gEfiArpProtocolGuid,
+ gIp4DriverBinding.DriverBindingHandle,
+ ChildHandle
+ );
+ }
+
//
// Uninstall the IP4 protocol first. Many thing happens during
// this:
@@ -949,12 +931,13 @@ Ip4ServiceBindingDestroyChild (
// will be called back before preceeding. If any packets not recycled,
// that means there is a resource leak.
//
+ gBS->RestoreTPL (OldTpl);
Status = gBS->UninstallProtocolInterface (
ChildHandle,
&gEfiIp4ProtocolGuid,
&IpInstance->Ip4Proto
);
-
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
if (EFI_ERROR (Status)) {
goto ON_ERROR;
}