/** Create a MTFTP child for the service binding instance, then install the MTFTP protocol to the ChildHandle. @param This The MTFTP service binding instance. @param ChildHandle The Child handle to install the MTFTP protocol. @retval EFI_INVALID_PARAMETER The parameter is invalid. @retval EFI_OUT_OF_RESOURCES Failed to allocate resource for the new child. @retval EFI_SUCCESS The child is successfully create. **/ EFI_STATUS EFIAPI Mtftp4ServiceBindingCreateChild ( IN EFI_SERVICE_BINDING_PROTOCOL *This, IN EFI_HANDLE *ChildHandle ) { MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_STATUS Status; EFI_TPL OldTpl; VOID *Udp4; if ((This == NULL) || (ChildHandle == NULL)) { return EFI_INVALID_PARAMETER; } Instance = AllocatePool (sizeof (*Instance)); if (Instance == NULL) { return EFI_OUT_OF_RESOURCES; } MtftpSb = MTFTP4_SERVICE_FROM_THIS (This); Mtftp4InitProtocol (MtftpSb, Instance); Instance->UnicastPort = UdpIoCreateIo ( MtftpSb->Controller, MtftpSb->Image, Mtftp4ConfigNullUdp, UDP_IO_UDP4_VERSION, Instance ); if (Instance->UnicastPort == NULL) { FreePool (Instance); return EFI_OUT_OF_RESOURCES; } // // Install the MTFTP protocol onto ChildHandle // Status = gBS->InstallMultipleProtocolInterfaces ( ChildHandle, &gEfiMtftp4ProtocolGuid, &Instance->Mtftp4, NULL ); if (EFI_ERROR (Status)) { UdpIoFreeIo (Instance->UnicastPort); FreePool (Instance); return Status; } Instance->Handle = *ChildHandle; // // Open the Udp4 protocol BY_CHILD. // Status = gBS->OpenProtocol ( MtftpSb->ConnectUdp->UdpHandle, &gEfiUdp4ProtocolGuid, (VOID **) &Udp4, gMtftp4DriverBinding.DriverBindingHandle, Instance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Open the Udp4 protocol by child. // Status = gBS->OpenProtocol ( Instance->UnicastPort->UdpHandle, &gEfiUdp4ProtocolGuid, (VOID **) &Udp4, gMtftp4DriverBinding.DriverBindingHandle, Instance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { // // Close the Udp4 protocol. // gBS->CloseProtocol ( MtftpSb->ConnectUdp->UdpHandle, &gEfiUdp4ProtocolGuid, gMtftp4DriverBinding.DriverBindingHandle, ChildHandle ); goto ON_ERROR; } // // Add it to the parent's child list. // OldTpl = gBS->RaiseTPL (TPL_CALLBACK); InsertTailList (&MtftpSb->Children, &Instance->Link); MtftpSb->ChildrenNum++; gBS->RestoreTPL (OldTpl); return EFI_SUCCESS; ON_ERROR: if (Instance->Handle != NULL) { gBS->UninstallMultipleProtocolInterfaces ( Instance->Handle, &gEfiMtftp4ProtocolGuid, &Instance->Mtftp4, NULL ); } UdpIoFreeIo (Instance->UnicastPort); FreePool (Instance); return Status; }
/** 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; }
/** Stop the MTFTP driver on controller. The controller is a UDP child handle. @param This The MTFTP driver binding protocol @param Controller The controller to stop @param NumberOfChildren The number of children @param ChildHandleBuffer The array of the child handle. @retval EFI_SUCCESS The driver is stopped on the controller. @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller. **/ EFI_STATUS EFIAPI Mtftp4DriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; MTFTP4_SERVICE *MtftpSb; EFI_HANDLE NicHandle; EFI_STATUS Status; LIST_ENTRY *List; MTFTP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context; // // MTFTP driver opens UDP child, So, Controller is a UDP // child handle. Locate the Nic handle first. Then get the // MTFTP private data back. // NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid); if (NicHandle == NULL) { return EFI_SUCCESS; } Status = gBS->OpenProtocol ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, (VOID **) &ServiceBinding, This->DriverBindingHandle, NicHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding); if (!IsListEmpty (&MtftpSb->Children)) { // // Destroy the Mtftp4 child instance in ChildHandleBuffer. // List = &MtftpSb->Children; Context.ServiceBinding = ServiceBinding; Context.NumberOfChildren = NumberOfChildren; Context.ChildHandleBuffer = ChildHandleBuffer; Status = NetDestroyLinkList ( List, Mtftp4DestroyChildEntryInHandleBuffer, &Context, NULL ); } if (NumberOfChildren == 0 && IsListEmpty (&MtftpSb->Children)) { gBS->UninstallProtocolInterface ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, ServiceBinding ); Mtftp4CleanService (MtftpSb); if (gMtftp4ControllerNameTable != NULL) { FreeUnicodeStringTable (gMtftp4ControllerNameTable); gMtftp4ControllerNameTable = NULL; } FreePool (MtftpSb); Status = EFI_SUCCESS; } return Status; }
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; }
EFI_STATUS Mtftp4ServiceBindingCreateChild ( IN EFI_SERVICE_BINDING_PROTOCOL *This, IN OUT EFI_HANDLE *ChildHandle ) /*++ Routine Description: Create a MTFTP child for the service binding instance, then install the MTFTP protocol to the ChildHandle. Arguments: This - The MTFTP service binding instance. ChildHandle - The Child handle to install the MTFTP protocol. Returns: EFI_INVALID_PARAMETER - The parameter is invalid. EFI_OUT_OF_RESOURCES - Failed to allocate resource for the new child. EFI_SUCCESS - The child is successfully create. --*/ { MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_STATUS Status; EFI_TPL OldTpl; VOID *Udp4; if ((This == NULL) || (ChildHandle == NULL)) { return EFI_INVALID_PARAMETER; } Instance = NetAllocatePool (sizeof (*Instance)); if (Instance == NULL) { return EFI_OUT_OF_RESOURCES; } MtftpSb = MTFTP4_SERVICE_FROM_THIS (This); Mtftp4InitProtocol (MtftpSb, Instance); Instance->UnicastPort = UdpIoCreatePort ( MtftpSb->Controller, MtftpSb->Image, Mtftp4ConfigNullUdp, Instance ); if (Instance->UnicastPort == NULL) { NetFreePool (Instance); return EFI_OUT_OF_RESOURCES; } // // Install the MTFTP protocol onto ChildHandle // Status = gBS->InstallMultipleProtocolInterfaces ( ChildHandle, &gEfiMtftp4ProtocolGuid, &Instance->Mtftp4, NULL ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Instance->Handle = *ChildHandle; // // Open the Udp4 protocol BY_CHILD. // Status = gBS->OpenProtocol ( MtftpSb->ConnectUdp->UdpHandle, &gEfiUdp4ProtocolGuid, (VOID **) &Udp4, gMtftp4DriverBinding.DriverBindingHandle, Instance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( Instance->Handle, &gEfiMtftp4ProtocolGuid, &Instance->Mtftp4, NULL ); goto ON_ERROR; } // // Add it to the parent's child list. // OldTpl = NET_RAISE_TPL (NET_TPL_LOCK); NetListInsertTail (&MtftpSb->Children, &Instance->Link); MtftpSb->ChildrenNum++; NET_RESTORE_TPL (OldTpl); ON_ERROR: if (EFI_ERROR (Status)) { UdpIoFreePort (Instance->UnicastPort); NetFreePool (Instance); } return Status; }
EFI_STATUS Mtftp4DriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) /*++ Routine Description: Stop the MTFTP driver on controller. The controller is a UDP child handle. Arguments: This - The MTFTP driver binding protocol Controller - The controller to stop NumberOfChildren - The number of children ChildHandleBuffer - The array of the child handle. Returns: EFI_SUCCESS - The driver is stopped on the controller. EFI_DEVICE_ERROR - Failed to stop the driver on the controller. --*/ { EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_HANDLE NicHandle; EFI_STATUS Status; EFI_TPL OldTpl; // // MTFTP driver opens UDP child, So, Controller is a UDP // child handle. Locate the Nic handle first. Then get the // MTFTP private data back. // NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid); if (NicHandle == NULL) { return EFI_DEVICE_ERROR; } Status = gBS->OpenProtocol ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, (VOID **) &ServiceBinding, This->DriverBindingHandle, NicHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding); if (MtftpSb->InDestory) { return EFI_SUCCESS; } OldTpl = NET_RAISE_TPL (NET_TPL_LOCK); if (NumberOfChildren == 0) { MtftpSb->InDestory = TRUE; gBS->UninstallProtocolInterface ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, ServiceBinding ); Mtftp4CleanService (MtftpSb); NetFreePool (MtftpSb); } else { while (!NetListIsEmpty (&MtftpSb->Children)) { Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link); Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle); } if (MtftpSb->ChildrenNum != 0) { Status = EFI_DEVICE_ERROR; } } NET_RESTORE_TPL (OldTpl); return Status; }
/** Stop the MTFTP driver on controller. The controller is a UDP child handle. @param This The MTFTP driver binding protocol @param Controller The controller to stop @param NumberOfChildren The number of children @param ChildHandleBuffer The array of the child handle. @retval EFI_SUCCESS The driver is stopped on the controller. @retval EFI_DEVICE_ERROR Failed to stop the driver on the controller. **/ EFI_STATUS EFIAPI Mtftp4DriverBindingStop ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE Controller, IN UINTN NumberOfChildren, IN EFI_HANDLE *ChildHandleBuffer ) { EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding; MTFTP4_SERVICE *MtftpSb; MTFTP4_PROTOCOL *Instance; EFI_HANDLE NicHandle; EFI_STATUS Status; EFI_TPL OldTpl; // // MTFTP driver opens UDP child, So, Controller is a UDP // child handle. Locate the Nic handle first. Then get the // MTFTP private data back. // NicHandle = NetLibGetNicHandle (Controller, &gEfiUdp4ProtocolGuid); if (NicHandle == NULL) { return EFI_DEVICE_ERROR; } Status = gBS->OpenProtocol ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, (VOID **) &ServiceBinding, This->DriverBindingHandle, NicHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { return EFI_DEVICE_ERROR; } MtftpSb = MTFTP4_SERVICE_FROM_THIS (ServiceBinding); if (MtftpSb->InDestory) { return EFI_SUCCESS; } OldTpl = gBS->RaiseTPL (TPL_CALLBACK); if (NumberOfChildren == 0) { MtftpSb->InDestory = TRUE; gBS->UninstallProtocolInterface ( NicHandle, &gEfiMtftp4ServiceBindingProtocolGuid, ServiceBinding ); Mtftp4CleanService (MtftpSb); FreePool (MtftpSb); } else { while (!IsListEmpty (&MtftpSb->Children)) { Instance = NET_LIST_HEAD (&MtftpSb->Children, MTFTP4_PROTOCOL, Link); Mtftp4ServiceBindingDestroyChild (ServiceBinding, Instance->Handle); } if (MtftpSb->ChildrenNum != 0) { Status = EFI_DEVICE_ERROR; } } gBS->RestoreTPL (OldTpl); return Status; }