\r
MtftpSb->Signature = MTFTP4_SERVICE_SIGNATURE;\r
MtftpSb->ServiceBinding = gMtftp4ServiceBindingTemplete;\r
- MtftpSb->InDestroy = FALSE;\r
MtftpSb->ChildrenNum = 0;\r
InitializeListHead (&MtftpSb->Children);\r
\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
+Mtftp4DestroyChildEntryInHandleBuffer (\r
+ IN LIST_ENTRY *Entry,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ MTFTP4_PROTOCOL *Instance;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ UINTN NumberOfChildren;\r
+ EFI_HANDLE *ChildHandleBuffer;\r
+\r
+ if (Entry == NULL || Context == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Instance = NET_LIST_USER_STRUCT_S (Entry, MTFTP4_PROTOCOL, Link, MTFTP4_PROTOCOL_SIGNATURE);\r
+ ServiceBinding = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
+ NumberOfChildren = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
+ ChildHandleBuffer = ((MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
+\r
+ if (!NetIsInHandleBuffer (Instance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ return ServiceBinding->DestroyChild (ServiceBinding, Instance->Handle);\r
+}\r
\r
/**\r
Stop the MTFTP driver on controller. The controller is a UDP\r
IN EFI_HANDLE *ChildHandleBuffer\r
)\r
{\r
- EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
- MTFTP4_SERVICE *MtftpSb;\r
- MTFTP4_PROTOCOL *Instance;\r
- EFI_HANDLE NicHandle;\r
- EFI_STATUS Status;\r
- EFI_TPL OldTpl;\r
+ EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
+ MTFTP4_SERVICE *MtftpSb;\r
+ EFI_HANDLE NicHandle;\r
+ EFI_STATUS Status;\r
+ LIST_ENTRY *List;\r
+ MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
\r
//\r
// MTFTP driver opens UDP child, So, Controller is a UDP\r
NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid);\r
\r
if (NicHandle == NULL) {\r
- return EFI_DEVICE_ERROR;\r
+ return EFI_SUCCESS;\r
}\r
\r
Status = gBS->OpenProtocol (\r
\r
MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding);\r
\r
- if (MtftpSb->InDestroy) {\r
- return EFI_SUCCESS;\r
+ if (!IsListEmpty (&MtftpSb->Children)) {\r
+ //\r
+ // Destroy the Mtftp4 child instance in ChildHandleBuffer.\r
+ //\r
+ List = &MtftpSb->Children;\r
+ Context.ServiceBinding = ServiceBinding;\r
+ Context.NumberOfChildren = NumberOfChildren;\r
+ Context.ChildHandleBuffer = ChildHandleBuffer;\r
+ Status = NetDestroyLinkList (\r
+ List,\r
+ Mtftp4DestroyChildEntryInHandleBuffer,\r
+ &Context,\r
+ NULL\r
+ );\r
}\r
\r
- OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
-\r
- if (NumberOfChildren == 0) {\r
-\r
- MtftpSb->InDestroy = TRUE;\r
-\r
+ if (NumberOfChildren == 0 && IsListEmpty (&MtftpSb->Children)) {\r
gBS->UninstallProtocolInterface (\r
NicHandle,\r
&gEfiMtftp4ServiceBindingProtocolGuid,\r
);\r
\r
Mtftp4CleanService (MtftpSb);\r
-\r
- FreePool (MtftpSb);\r
- } else {\r
-\r
- while (!IsListEmpty (&MtftpSb->Children)) {\r
- Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link);\r
- Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle);\r
+ if (gMtftp4ControllerNameTable != NULL) {\r
+ FreeUnicodeStringTable (gMtftp4ControllerNameTable);\r
+ gMtftp4ControllerNameTable = NULL;\r
}\r
+ FreePool (MtftpSb);\r
\r
- if (MtftpSb->ChildrenNum != 0) {\r
- Status = EFI_DEVICE_ERROR;\r
- }\r
+ Status = EFI_SUCCESS;\r
}\r
\r
- gBS->RestoreTPL (OldTpl);\r
return Status;\r
}\r
\r
InitializeListHead (&Instance->Link);\r
CopyMem (&Instance->Mtftp4, &gMtftp4ProtocolTemplate, sizeof (Instance->Mtftp4));\r
Instance->State = MTFTP4_STATE_UNCONFIGED;\r
- Instance->InDestroy = FALSE;\r
Instance->Service = MtftpSb;\r
\r
InitializeListHead (&Instance->Blocks);\r
);\r
\r
if (EFI_ERROR (Status)) {\r
- goto ON_ERROR;\r
+ UdpIoFreeIo (Instance->UnicastPort);\r
+ FreePool (Instance);\r
+ return Status;\r
}\r
\r
Instance->Handle = *ChildHandle;\r
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
);\r
if (EFI_ERROR (Status)) {\r
- gBS->UninstallMultipleProtocolInterfaces (\r
- Instance->Handle,\r
- &gEfiMtftp4ProtocolGuid,\r
- &Instance->Mtftp4,\r
- NULL\r
- );\r
+ goto ON_ERROR;\r
+ }\r
\r
+ //\r
+ // Open the Udp4 protocol by child.\r
+ //\r
+ Status = gBS->OpenProtocol (\r
+ Instance->UnicastPort->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ (VOID **) &Udp4,\r
+ gMtftp4DriverBinding.DriverBindingHandle,\r
+ Instance->Handle,\r
+ EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ //\r
+ // Close the Udp4 protocol.\r
+ //\r
+ gBS->CloseProtocol (\r
+ MtftpSb->ConnectUdp->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ gMtftp4DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
goto ON_ERROR;\r
}\r
\r
\r
gBS->RestoreTPL (OldTpl);\r
\r
-ON_ERROR:\r
+ return EFI_SUCCESS;\r
\r
- if (EFI_ERROR (Status)) {\r
- UdpIoFreeIo (Instance->UnicastPort);\r
- FreePool (Instance);\r
+ON_ERROR:\r
+ if (Instance->Handle != NULL) {\r
+ gBS->UninstallMultipleProtocolInterfaces (\r
+ Instance->Handle,\r
+ &gEfiMtftp4ProtocolGuid,\r
+ &Instance->Mtftp4,\r
+ NULL\r
+ );\r
}\r
\r
+ UdpIoFreeIo (Instance->UnicastPort);\r
+ FreePool (Instance);\r
+\r
return Status;\r
}\r
\r
ChildHandle\r
);\r
\r
+ gBS->CloseProtocol (\r
+ Instance->UnicastPort->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ gMtftp4DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ );\r
+\r
+ if (Instance->McastUdpPort != NULL) {\r
+ gBS->CloseProtocol (\r
+ Instance->McastUdpPort->UdpHandle,\r
+ &gEfiUdp4ProtocolGuid,\r
+ gMtftp4DriverBinding.DriverBindingHandle,\r
+ ChildHandle\r
+ ); \r
+ }\r
+\r
//\r
// Uninstall the MTFTP4 protocol first to enable a top down destruction.\r
//\r