4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Routines to process Wrq (upload).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncCopyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncThis program and the accompanying materials
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncare licensed and made available under the terms and conditions of the BSD License
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncwhich accompanies this distribution. The full text of the license may be found at
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncTHE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncWITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build then send a MTFTP data packet for the MTFTP upload session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Instance The MTFTP upload session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BlockNum The block number to send.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_OUT_OF_RESOURCES Failed to build the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_ABORTED The consumer of this child directs to abort the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync transmission by return an error through PacketNeeded.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The data is sent.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate a buffer to hold the user data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UdpPacket = NetbufAlloc (Instance->BlkSize + MTFTP4_DATA_HEAD_LEN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (UdpPacket, MTFTP4_DATA_HEAD_LEN, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->Data.OpCode = HTONS (EFI_MTFTP4_OPCODE_DATA);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the block from either the buffer or PacketNeeded callback
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Start = MultU64x32 (BlockNum - 1, Instance->BlkSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Token->BufferSize < Start + Instance->BlkSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Packet->Data.Data, (UINT8 *) Token->Buffer + Start, DataLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get data from PacketNeeded
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) || (DataLen > Instance->BlkSize)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Function to handle received ACK packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync If the ACK number matches the expected block number, and there are more
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync data pending, send the next block. Otherwise tell the caller that we are done.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Instance The MTFTP upload session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Packet The MTFTP packet received
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Len The packet length
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Completed Return whether the upload has finished.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The ACK is successfully processed.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_TFTP_ERROR The block number loops back.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to transmit the next data packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get an unwanted ACK, return EFI_SUCCESS to let Mtftp4WrqInput
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // restart receive.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Remove the acked block number, if this is the last block number,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // tell the Mtftp4WrqInput to finish the transfer. This is the last
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // block number if the block range are empty..
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4RemoveBlockNum (&Instance->Blocks, AckNum, *Completed,&TotalBlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The block range is empty. It may either because the the last
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // block has been ACKed, or the sequence number just looped back,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // that is, there is more than 0xffff blocks.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) "Block number rolls back, not supported, try blksize option"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Mtftp4WrqSendBlock (Instance, (UINT16) Expected);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check whether the received OACK is valid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The OACK is valid only if:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 1. It only include options requested by us
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 2. It can only include a smaller block size
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 3. It can't change the proposed time out value.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync 4. Other requirements of the individal MTFTP options as required.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Reply The options included in the OACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Request The options we requested
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval TRUE The options included in OACK is valid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval FALSE The options included in OACK is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It is invalid for server to return options we don't request
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Server can only specify a smaller block size to be used and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // return the timeout matches that requested.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0) && (Reply->BlkSize > Request->BlkSize)) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Function to handle the MTFTP OACK packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It parses the packet's options, and update the internal states of the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Instance The MTFTP session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Packet The received OACK packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Len The length of the packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Completed Whether the transmisson has completed. NOT used by
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync this function.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The OACK process is OK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_TFTP_ERROR Some error occured, and the session reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Ignore the OACK if already started the upload
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Parse and validate the options from server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) || !Mtftp4WrqOackValid (&Reply, &Instance->RequestOption)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Don't send a MTFTP error packet when out of resource, it can
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // only make it worse.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Build a bogus ACK0 packet then pass it to the Mtftp4WrqHandleAck,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // which will start the transmission of the first data block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The input process routine for MTFTP upload.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param UdpPacket The received MTFTP packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param EndPoint The local/remote access point
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param IoStatus The result of the packet receiving
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Context Opaque parameter for the callback, which is the
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MTFTP session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Client send initial request to server's listening port. Server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // will select a UDP port to communicate with the client.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EndPoint->RemotePort != Instance->ConnectedPort) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy the MTFTP packet to a continuous buffer if it isn't already so.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Call the user's CheckPacket if provided. Abort the transmission
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if CheckPacket returns an EFI_ERROR code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send an error message to the server to inform it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4WrqHandleAck (Instance, Packet, Len, &Completed);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4WrqHandleOack (Instance, Packet, Len, &Completed);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Free the resources, then if !EFI_ERROR (Status) and not completed,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // restart the receive, otherwise end the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Status may have been updated by UdpIoRecvDatagram
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Start the MTFTP session for upload.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It will first init some states, then send the WRQ request packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and start receiving the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Instance The MTFTP session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Operation Redundant parameter, which is always
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_OPCODE_WRQ here.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The upload process has been started.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to start the upload.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // The valid block number range are [0, 0xffff]. For example:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // the client sends an WRQ request to the server, the server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // ACK with an ACK0 to let client start transfer the first
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4InitBlockRange (&Instance->Blocks, 0, 0xffff);