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
);\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
// 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
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