/** 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; }
/** The input process routine for MTFTP upload. @param UdpPacket The received MTFTP packet. @param EndPoint The local/remote access point @param IoStatus The result of the packet receiving @param Context Opaque parameter for the callback, which is the MTFTP session. **/ VOID EFIAPI Mtftp4WrqInput ( IN NET_BUF *UdpPacket, IN UDP_END_POINT *EndPoint, IN EFI_STATUS IoStatus, IN VOID *Context ) { MTFTP4_PROTOCOL *Instance; EFI_MTFTP4_PACKET *Packet; BOOLEAN Completed; EFI_STATUS Status; UINT32 Len; UINT16 Opcode; Instance = (MTFTP4_PROTOCOL *) Context; NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE); Completed = FALSE; Packet = NULL; Status = EFI_SUCCESS; if (EFI_ERROR (IoStatus)) { Status = IoStatus; goto ON_EXIT; } ASSERT (UdpPacket != NULL); if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) { goto ON_EXIT; } // // Client send initial request to server's listening port. Server // will select a UDP port to communicate with the client. // if (EndPoint->RemotePort != Instance->ConnectedPort) { if (Instance->ConnectedPort != 0) { goto ON_EXIT; } else { Instance->ConnectedPort = EndPoint->RemotePort; } } // // Copy the MTFTP packet to a continuous buffer if it isn't already so. // Len = UdpPacket->TotalSize; if (UdpPacket->BlockOpNum > 1) { Packet = AllocatePool (Len); if (Packet == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet); } else { Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL); ASSERT (Packet != NULL); } Opcode = NTOHS (Packet->OpCode); // // Call the user's CheckPacket if provided. Abort the transmission // if CheckPacket returns an EFI_ERROR code. // if ((Instance->Token->CheckPacket != NULL) && ((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) { Status = Instance->Token->CheckPacket ( &Instance->Mtftp4, Instance->Token, (UINT16) Len, Packet ); if (EFI_ERROR (Status)) { // // Send an error message to the server to inform it // if (Opcode != EFI_MTFTP4_OPCODE_ERROR) { Mtftp4SendError ( Instance, EFI_MTFTP4_ERRORCODE_REQUEST_DENIED, (UINT8 *) "User aborted the transfer" ); } Status = EFI_ABORTED; goto ON_EXIT; } } switch (Opcode) { case EFI_MTFTP4_OPCODE_ACK: if (Len != MTFTP4_OPCODE_LEN + MTFTP4_BLKNO_LEN) { goto ON_EXIT; } Status = Mtftp4WrqHandleAck (Instance, Packet, Len, &Completed); break; case EFI_MTFTP4_OPCODE_OACK: if (Len <= MTFTP4_OPCODE_LEN) { goto ON_EXIT; } Status = Mtftp4WrqHandleOack (Instance, Packet, Len, &Completed); break; case EFI_MTFTP4_OPCODE_ERROR: Status = EFI_TFTP_ERROR; break; default: break; } ON_EXIT: // // Free the resources, then if !EFI_ERROR (Status) and not completed, // restart the receive, otherwise end the session. // if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) { FreePool (Packet); } if (UdpPacket != NULL) { NetbufFree (UdpPacket); } if (!EFI_ERROR (Status) && !Completed) { Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0); } // // Status may have been updated by UdpIoRecvDatagram // if (EFI_ERROR (Status) || Completed) { Mtftp4CleanOperation (Instance, 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; }