]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Sync the latest version from R8.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Driver.c
index bf43677e8a8dbbeb5bdb7868244455c674a67205..589eca520801c1506ebd09d742c33dc28a8766e3 100644 (file)
@@ -512,6 +512,7 @@ Ip4DriverBindingStop (
   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
@@ -549,7 +550,7 @@ Ip4DriverBindingStop (
                     );\r
 \r
     if (EFI_ERROR (Status)) {\r
-      return EFI_SUCCESS;\r
+      return EFI_DEVICE_ERROR;\r
     }\r
 \r
     IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
@@ -594,14 +595,16 @@ Ip4DriverBindingStop (
   // 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
   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_SUCCESS;\r
+    return EFI_DEVICE_ERROR;\r
   }\r
 \r
   //\r
@@ -629,62 +632,88 @@ Ip4DriverBindingStop (
     return EFI_SUCCESS;\r
   }\r
 \r
-  IpSb->InDestory = TRUE;\r
+  if (IsArp) {\r
+    while (!NetListIsEmpty (&IpSb->Children)) {\r
+      IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
 \r
-  State           = IpSb->State;\r
-  IpSb->State     = IP4_SERVICE_DESTORY;\r
+      ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
+    }\r
 \r
-  //\r
-  // Destory all the children first. If not all children are destoried,\r
-  // the IP driver can operate correctly, so restore it state. Don't\r
-  // use NET_LIST_FOR_EACH_SAFE here, because it will cache the next\r
-  // pointer, which may point to the child that has already been destoried.\r
-  // For example, if there are two child in the list, the first is UDP\r
-  // listen child, the send is the MTFTP's child. When Udp child is\r
-  // destoried, it will destory the MTFTP's child. Then Next point to\r
-  // a invalid child.\r
-  //\r
-  while (!NetListIsEmpty (&IpSb->Children)) {\r
-    IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
-    Ip4ServiceBindingDestroyChild (ServiceBinding, IpInstance->Handle);\r
-  }\r
+    if (IpSb->NumChildren != 0) {\r
+      Status = EFI_DEVICE_ERROR;\r
+      goto ON_ERROR;\r
+    }\r
 \r
-  if (IpSb->NumChildren != 0) {\r
-    IpSb->State = State;\r
-    Status      = EFI_DEVICE_ERROR;\r
-    goto ON_ERROR;\r
-  }\r
+    IpSb->InDestory = TRUE;\r
 \r
-  //\r
-  // Clear the variable data.\r
-  //\r
-  Ip4ClearVariableData (IpSb);\r
+    State           = IpSb->State;\r
+    IpSb->State     = IP4_SERVICE_DESTORY;\r
 \r
-  //\r
-  // OK, clean other resources then uninstall the service binding protocol.\r
-  //\r
-  Status = Ip4CleanService (IpSb);\r
+    //\r
+    // Clear the variable data.\r
+    //\r
+    Ip4ClearVariableData (IpSb);\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
+    //\r
+    // OK, clean other resources then uninstall the service binding protocol.\r
+    //\r
+    Status = Ip4CleanService (IpSb);\r
 \r
-  Status = gBS->UninstallProtocolInterface (\r
-                  NicHandle,\r
-                  &gEfiIp4ServiceBindingProtocolGuid,\r
-                  ServiceBinding\r
-                  );\r
+    if (EFI_ERROR (Status)) {\r
+      IpSb->State = State;\r
+      goto ON_ERROR;\r
+    }\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_ERROR;\r
-  }\r
+    gBS->UninstallProtocolInterface (\r
+           NicHandle,\r
+           &gEfiIp4ServiceBindingProtocolGuid,\r
+           ServiceBinding\r
+           );\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
-  NetFreePool (IpSb);\r
-  return EFI_SUCCESS;\r
+    NetFreePool (IpSb);\r
+  } else if (NumberOfChildren == 0) {\r
+    IpSb->InDestory = TRUE;\r
+\r
+    State           = IpSb->State;\r
+    IpSb->State     = IP4_SERVICE_DESTORY;\r
+\r
+    //\r
+    // Clear the variable data.\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
+      goto ON_ERROR;\r
+    }\r
+\r
+    gBS->UninstallProtocolInterface (\r
+           NicHandle,\r
+           &gEfiIp4ServiceBindingProtocolGuid,\r
+           ServiceBinding\r
+           );\r
+\r
+    NetFreePool (IpSb);\r
+  } else {\r
+\r
+    while (!NetListIsEmpty (&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
+  }\r
 \r
 ON_ERROR:\r
-  IpSb->InDestory = FALSE;\r
+\r
   NET_RESTORE_TPL (OldTpl);\r
   return Status;\r
 }\r