4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/** @file
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Routines to process Wrq (upload).
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
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
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsynchttp://opensource.org/licenses/bsd-license.php<BR>
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
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
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync#include "Mtftp4Impl.h"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Build then send a MTFTP data packet for the MTFTP upload session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Instance The MTFTP upload session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param BlockNum The block number to send.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
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
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMtftp4WrqSendBlock (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT MTFTP4_PROTOCOL *Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT16 BlockNum
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_PACKET *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_TOKEN *Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_BUF *UdpPacket;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 DataLen;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT8 *DataBuf;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 Start;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Allocate a buffer to hold the user data
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UdpPacket = NetbufAlloc (Instance->BlkSize + MTFTP4_DATA_HEAD_LEN);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UdpPacket == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (UdpPacket, MTFTP4_DATA_HEAD_LEN, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Packet != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->Data.OpCode = HTONS (EFI_MTFTP4_OPCODE_DATA);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet->Data.Block = HTONS (BlockNum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Read the block from either the buffer or PacketNeeded callback
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token = Instance->Token;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataLen = Instance->BlkSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Token->Buffer != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Start = MultU64x32 (BlockNum - 1, Instance->BlkSize);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Token->BufferSize < Start + Instance->BlkSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataLen = (UINT16) (Token->BufferSize - Start);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance->LastBlock = BlockNum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataLen > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufAllocSpace (UdpPacket, DataLen, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Packet->Data.Data, (UINT8 *) Token->Buffer + Start, DataLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get data from PacketNeeded
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync DataBuf = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Token->PacketNeeded (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Instance->Mtftp4,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Token,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &DataLen,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (VOID **) &DataBuf
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) || (DataLen > Instance->BlkSize)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataBuf != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (DataBuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SendError (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) "User aborted the transfer"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_ABORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataLen < Instance->BlkSize) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance->LastBlock = BlockNum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SetLastBlockNum (&Instance->Blocks, BlockNum);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (DataLen > 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufAllocSpace (UdpPacket, DataLen, FALSE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync CopyMem (Packet->Data.Data, DataBuf, DataLen);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (DataBuf);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Mtftp4SendPacket (Instance, UdpPacket);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Function to handle received ACK packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
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
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
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
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMtftp4WrqHandleAck (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN MTFTP4_PROTOCOL *Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MTFTP4_PACKET *Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT BOOLEAN *Completed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 AckNum;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Expected;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT64 TotalBlock;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Completed = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync AckNum = NTOHS (Packet->Ack.Block[0]);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Expected >= 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Get an unwanted ACK, return EFI_SUCCESS to let Mtftp4WrqInput
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // restart receive.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Expected != AckNum) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
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 //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4RemoveBlockNum (&Instance->Blocks, AckNum, *Completed,&TotalBlock);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Expected < 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
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 //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Instance->LastBlock == AckNum) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (Instance->LastBlock >= 1);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Completed = TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SendError (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) "Block number rolls back, not supported, try blksize option"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_TFTP_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Mtftp4WrqSendBlock (Instance, (UINT16) Expected);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Check whether the received OACK is valid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
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
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Reply The options included in the OACK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Request The options we requested
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval TRUE The options included in OACK is valid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval FALSE The options included in OACK is invalid.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncBOOLEAN
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMtftp4WrqOackValid (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN MTFTP4_OPTION *Reply,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN MTFTP4_OPTION *Request
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // It is invalid for server to return options we don't request
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Reply->Exist & ~Request->Exist) != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Server can only specify a smaller block size to be used and
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // return the timeout matches that requested.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0) && (Reply->BlkSize > Request->BlkSize)) ||
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return TRUE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Function to handle the MTFTP OACK packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It parses the packet's options, and update the internal states of the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
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
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The OACK process is OK
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_TFTP_ERROR Some error occured, and the session reset.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMtftp4WrqHandleOack (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN OUT MTFTP4_PROTOCOL *Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_MTFTP4_PACKET *Packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT32 Len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync OUT BOOLEAN *Completed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MTFTP4_OPTION Reply;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_PACKET Bogus;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync INTN Expected;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync *Completed = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Ignore the OACK if already started the upload
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Expected != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Parse and validate the options from server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ZeroMem (&Reply, sizeof (MTFTP4_OPTION));
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) || !Mtftp4WrqOackValid (&Reply, &Instance->RequestOption)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Don't send a MTFTP error packet when out of resource, it can
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // only make it worse.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Status != EFI_OUT_OF_RESOURCES) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SendError (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_ERRORCODE_ILLEGAL_OPERATION,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) "Mal-formated OACK packet"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return EFI_TFTP_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Reply.BlkSize != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance->BlkSize = Reply.BlkSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Reply.Timeout != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance->Timeout = Reply.Timeout;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Build a bogus ACK0 packet then pass it to the Mtftp4WrqHandleAck,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // which will start the transmission of the first data block.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Bogus.Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Bogus.Ack.Block[0] = 0;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4WrqHandleAck (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Bogus,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync sizeof (EFI_MTFTP4_ACK_HEADER),
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Completed
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync The input process routine for MTFTP upload.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
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**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncVOID
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFIAPI
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMtftp4WrqInput (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN NET_BUF *UdpPacket,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UDP_END_POINT *EndPoint,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN EFI_STATUS IoStatus,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN VOID *Context
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync MTFTP4_PROTOCOL *Instance;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_PACKET *Packet;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync BOOLEAN Completed;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT32 Len;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync UINT16 Opcode;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance = (MTFTP4_PROTOCOL *) Context;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NET_CHECK_SIGNATURE (Instance, MTFTP4_PROTOCOL_SIGNATURE);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Completed = FALSE;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = NULL;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_SUCCESS;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (IoStatus)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = IoStatus;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ASSERT (UdpPacket != NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UdpPacket->TotalSize < MTFTP4_OPCODE_LEN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Client send initial request to server's listening port. Server
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // will select a UDP port to communicate with the client.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EndPoint->RemotePort != Instance->ConnectedPort) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Instance->ConnectedPort != 0) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance->ConnectedPort = EndPoint->RemotePort;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Copy the MTFTP packet to a continuous buffer if it isn't already so.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Len = UdpPacket->TotalSize;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UdpPacket->BlockOpNum > 1) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = AllocatePool (Len);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Packet == NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_OUT_OF_RESOURCES;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufCopy (UdpPacket, 0, Len, (UINT8 *) Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync } else {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Opcode = NTOHS (Packet->OpCode);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Call the user's CheckPacket if provided. Abort the transmission
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // if CheckPacket returns an EFI_ERROR code.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Instance->Token->CheckPacket != NULL) &&
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync ((Opcode == EFI_MTFTP4_OPCODE_OACK) || (Opcode == EFI_MTFTP4_OPCODE_ERROR))) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Instance->Token->CheckPacket (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync &Instance->Mtftp4,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance->Token,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT16) Len,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Packet
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Send an error message to the server to inform it
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Opcode != EFI_MTFTP4_OPCODE_ERROR) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4SendError (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync (UINT8 *) "User aborted the transfer"
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync );
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_ABORTED;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync switch (Opcode) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_MTFTP4_OPCODE_ACK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Len != MTFTP4_OPCODE_LEN + MTFTP4_BLKNO_LEN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4WrqHandleAck (Instance, Packet, Len, &Completed);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_MTFTP4_OPCODE_OACK:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (Len <= MTFTP4_OPCODE_LEN) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync goto ON_EXIT;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4WrqHandleOack (Instance, Packet, Len, &Completed);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync case EFI_MTFTP4_OPCODE_ERROR:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = EFI_TFTP_ERROR;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync default:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync break;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncON_EXIT:
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Free the resources, then if !EFI_ERROR (Status) and not completed,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // restart the receive, otherwise end the session.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync FreePool (Packet);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (UdpPacket != NULL) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync NetbufFree (UdpPacket);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (!EFI_ERROR (Status) && !Completed) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync // Status may have been updated by UdpIoRecvDatagram
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status) || Completed) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Mtftp4CleanOperation (Instance, Status);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync/**
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Start the MTFTP session for upload.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync It will first init some states, then send the WRQ request packet,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync and start receiving the packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Instance The MTFTP session
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @param Operation Redundant parameter, which is always
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_MTFTP4_OPCODE_WRQ here.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval EFI_SUCCESS The upload process has been started.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync @retval Others Failed to start the upload.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync**/
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncEFI_STATUS
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsyncMtftp4WrqStart (
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN MTFTP4_PROTOCOL *Instance,
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync IN UINT16 Operation
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync )
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync{
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync EFI_STATUS Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
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 // packet.
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync //
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4InitBlockRange (&Instance->Blocks, 0, 0xffff);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync Status = Mtftp4SendRequest (Instance);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync if (EFI_ERROR (Status)) {
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return Status;
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync }
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync}
4fd606d1f5abe38e1f42c38de1d2e895166bd0f4vboxsync