/** Destroy one of the service binding's child. @param This The service binding instance @param ChildHandle The child handle to destroy @retval EFI_INVALID_PARAMETER The parameter is invaid. @retval EFI_UNSUPPORTED The child may have already been destroyed. @retval EFI_SUCCESS The child is destroyed and removed from the parent's child list. **/ EFI_STATUS EFIAPI Mtftp4ServiceBindingDestroyChild ( IN EFI_SERVICE_BINDING_PROTOCOL *This, IN EFI_HANDLE ChildHandle ) { MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_STATUS Status; EFI_TPL OldTpl; if ((This == NULL) || (ChildHandle == NULL)) { return EFI_INVALID_PARAMETER; } // // Retrieve the private context data structures // Status = gBS->OpenProtocol ( ChildHandle, &gEfiMtftp4ProtocolGuid, (VOID **) &Mtftp4, gMtftp4DriverBinding.DriverBindingHandle, ChildHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4); MtftpSb = MTFTP4_SERVICE_FROM_THIS (This); if (Instance->Service != MtftpSb) { return EFI_INVALID_PARAMETER; } if (Instance->InDestroy) { return EFI_SUCCESS; } Instance->InDestroy = TRUE; // // Close the Udp4 protocol. // gBS->CloseProtocol ( MtftpSb->ConnectUdp->UdpHandle, &gEfiUdp4ProtocolGuid, gMtftp4DriverBinding.DriverBindingHandle, ChildHandle ); gBS->CloseProtocol ( Instance->UnicastPort->UdpHandle, &gEfiUdp4ProtocolGuid, gMtftp4DriverBinding.DriverBindingHandle, ChildHandle ); if (Instance->McastUdpPort != NULL) { gBS->CloseProtocol ( Instance->McastUdpPort->UdpHandle, &gEfiUdp4ProtocolGuid, gMtftp4DriverBinding.DriverBindingHandle, ChildHandle ); } // // Uninstall the MTFTP4 protocol first to enable a top down destruction. // Status = gBS->UninstallProtocolInterface ( ChildHandle, &gEfiMtftp4ProtocolGuid, Mtftp4 ); if (EFI_ERROR (Status)) { Instance->InDestroy = FALSE; return Status; } OldTpl = gBS->RaiseTPL (TPL_CALLBACK); Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR); UdpIoFreeIo (Instance->UnicastPort); RemoveEntryList (&Instance->Link); MtftpSb->ChildrenNum--; gBS->RestoreTPL (OldTpl); FreePool (Instance); return EFI_SUCCESS; }
EFI_STATUS Mtftp4ServiceBindingDestroyChild ( IN EFI_SERVICE_BINDING_PROTOCOL *This, IN EFI_HANDLE ChildHandle ) /*++ Routine Description: Destory one of the service binding's child. Arguments: This - The service binding instance ChildHandle - The child handle to destory Returns: EFI_INVALID_PARAMETER - The parameter is invaid. EFI_UNSUPPORTED - The child may have already been destoried. EFI_SUCCESS - The child is destoried and removed from the parent's child list. --*/ { MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_STATUS Status; EFI_TPL OldTpl; if ((This == NULL) || (ChildHandle == NULL)) { return EFI_INVALID_PARAMETER; } // // Retrieve the private context data structures // Status = gBS->OpenProtocol ( ChildHandle, &gEfiMtftp4ProtocolGuid, (VOID **) &Mtftp4, gMtftp4DriverBinding.DriverBindingHandle, ChildHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_UNSUPPORTED; } Instance = MTFTP4_PROTOCOL_FROM_THIS (Mtftp4); MtftpSb = MTFTP4_SERVICE_FROM_THIS (This); if (Instance->Service != MtftpSb) { return EFI_INVALID_PARAMETER; } if (Instance->Indestory) { return EFI_SUCCESS; } Instance->Indestory = TRUE; // // Close the Udp4 protocol. // gBS->CloseProtocol ( MtftpSb->ConnectUdp->UdpHandle, &gEfiUdp4ProtocolGuid, gMtftp4DriverBinding.DriverBindingHandle, ChildHandle ); // // Uninstall the MTFTP4 protocol first to enable a top down destruction. // Status = gBS->UninstallProtocolInterface ( ChildHandle, &gEfiMtftp4ProtocolGuid, Mtftp4 ); if (EFI_ERROR (Status)) { Instance->Indestory = FALSE; return Status; } OldTpl = NET_RAISE_TPL (NET_TPL_LOCK); Mtftp4CleanOperation (Instance, EFI_DEVICE_ERROR); UdpIoFreePort (Instance->UnicastPort); NetListRemoveEntry (&Instance->Link); MtftpSb->ChildrenNum--; NET_RESTORE_TPL (OldTpl); NetFreePool (Instance); return EFI_SUCCESS; }