/** @file\r
+ Routines to process Wrq (upload).\r
\r
-Copyright (c) 2006, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution. The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
- Mtftp4Wrq.c\r
-\r
-Abstract:\r
-\r
- Routines to process Wrq (upload)\r
-\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
#include "Mtftp4Impl.h"\r
\r
-VOID\r
-Mtftp4WrqInput (\r
- IN NET_BUF *UdpPacket,\r
- IN UDP_POINTS *Points,\r
- IN EFI_STATUS IoStatus,\r
- IN VOID *Context\r
- );\r
-\r
-\r
-/**\r
- Start the MTFTP session for pload. It will first init some states,\r
- then send the WRQ request packet, and start receiving the packet.\r
-\r
- @param Instance The MTFTP session\r
- @param Operation Redundant parameter, which is always\r
- EFI_MTFTP4_OPCODE_WRQ here.\r
-\r
- @retval EFI_SUCCESS The upload process has been started.\r
- @retval Others Failed to start the upload.\r
-\r
-**/\r
-EFI_STATUS\r
-Mtftp4WrqStart (\r
- IN MTFTP4_PROTOCOL *Instance,\r
- IN UINT16 Operation\r
- )\r
-{\r
- EFI_STATUS Status;\r
-\r
- //\r
- // The valid block number range are [0, 0xffff]. For example:\r
- // the client sends an WRQ request to the server, the server\r
- // ACK with an ACK0 to let client start transfer the first\r
- // packet.\r
- //\r
- Status = Mtftp4InitBlockRange (&Instance->Blocks, 0, 0xffff);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- Status = Mtftp4SendRequest (Instance);\r
-\r
- if (EFI_ERROR (Status)) {\r
- return Status;\r
- }\r
-\r
- return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);\r
-}\r
\r
\r
/**\r
Build then send a MTFTP data packet for the MTFTP upload session.\r
\r
- @param Instance The MTFTP upload session\r
- @param BlockNum The block number to send\r
+ @param Instance The MTFTP upload session.\r
+ @param BlockNum The block number to send.\r
\r
- @retval EFI_OUT_OF_RESOURCES Failed to build the packet\r
+ @retval EFI_OUT_OF_RESOURCES Failed to build the packet.\r
@retval EFI_ABORTED The consumer of this child directs to abort the\r
- transmission by return an error through\r
- PacketNeeded\r
+ transmission by return an error through PacketNeeded.\r
@retval EFI_SUCCESS The data is sent.\r
\r
**/\r
EFI_STATUS\r
Mtftp4WrqSendBlock (\r
- IN MTFTP4_PROTOCOL *Instance,\r
- IN UINT16 BlockNum\r
+ IN OUT MTFTP4_PROTOCOL *Instance,\r
+ IN UINT16 BlockNum\r
)\r
{\r
EFI_MTFTP4_PACKET *Packet;\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Packet = (EFI_MTFTP4_PACKET *)NetbufAllocSpace (UdpPacket, MTFTP4_DATA_HEAD_LEN, FALSE);\r
+ Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (UdpPacket, MTFTP4_DATA_HEAD_LEN, FALSE);\r
+ ASSERT (Packet != NULL);\r
\r
Packet->Data.OpCode = HTONS (EFI_MTFTP4_OPCODE_DATA);\r
Packet->Data.Block = HTONS (BlockNum);\r
// Get data from PacketNeeded\r
//\r
DataBuf = NULL;\r
- Status = Token->PacketNeeded (&Instance->Mtftp4, Token, &DataLen, (VOID **) &DataBuf);\r
+ Status = Token->PacketNeeded (\r
+ &Instance->Mtftp4,\r
+ Token,\r
+ &DataLen,\r
+ (VOID **) &DataBuf\r
+ );\r
\r
if (EFI_ERROR (Status) || (DataLen > Instance->BlkSize)) {\r
if (DataBuf != NULL) {\r
- gBS->FreePool (DataBuf);\r
+ FreePool (DataBuf);\r
+ }\r
+\r
+ if (UdpPacket != NULL) {\r
+ NetbufFree (UdpPacket);\r
}\r
\r
Mtftp4SendError (\r
if (DataLen > 0) {\r
NetbufAllocSpace (UdpPacket, DataLen, FALSE);\r
CopyMem (Packet->Data.Data, DataBuf, DataLen);\r
- gBS->FreePool (DataBuf);\r
+ FreePool (DataBuf);\r
}\r
}\r
\r
\r
\r
/**\r
- Function to handle received ACK packet. If the ACK number matches the\r
- expected block number, and there are more data pending, send the next\r
- block. Otherwise tell the caller that we are done.\r
+ Function to handle received ACK packet.\r
+\r
+ If the ACK number matches the expected block number, and there are more\r
+ data pending, send the next block. Otherwise tell the caller that we are done.\r
\r
@param Instance The MTFTP upload session\r
@param Packet The MTFTP packet received\r
**/\r
EFI_STATUS\r
Mtftp4WrqHandleAck (\r
- IN MTFTP4_PROTOCOL *Instance,\r
- IN EFI_MTFTP4_PACKET *Packet,\r
- IN UINT32 Len,\r
- OUT BOOLEAN *Completed\r
+ IN MTFTP4_PROTOCOL *Instance,\r
+ IN EFI_MTFTP4_PACKET *Packet,\r
+ IN UINT32 Len,\r
+ OUT BOOLEAN *Completed\r
)\r
{\r
UINT16 AckNum;\r
INTN Expected;\r
+ UINT64 BlockCounter;\r
\r
*Completed = FALSE;\r
AckNum = NTOHS (Packet->Ack.Block[0]);\r
//\r
// Remove the acked block number, if this is the last block number,\r
// tell the Mtftp4WrqInput to finish the transfer. This is the last\r
- // block number if the block range are empty..\r
+ // block number if the block range are empty.\r
//\r
- Mtftp4RemoveBlockNum (&Instance->Blocks, AckNum);\r
+ Mtftp4RemoveBlockNum (&Instance->Blocks, AckNum, *Completed, &BlockCounter);\r
\r
Expected = Mtftp4GetNextBlockNum (&Instance->Blocks);\r
\r
if (Expected < 0) {\r
+\r
//\r
// The block range is empty. It may either because the the last\r
// block has been ACKed, or the sequence number just looped back,\r
\r
\r
/**\r
- Check whether the received OACK is valid. The OACK is valid\r
- only if:\r
+ Check whether the received OACK is valid.\r
+\r
+ The OACK is valid only if:\r
1. It only include options requested by us\r
2. It can only include a smaller block size\r
3. It can't change the proposed time out value.\r
- 4. Other requirements of the individal MTFTP options as required.s\r
+ 4. Other requirements of the individal MTFTP options as required.\r
\r
@param Reply The options included in the OACK\r
@param Request The options we requested\r
\r
- @return TRUE if the options included in OACK is valid, otherwise FALSE.\r
+ @retval TRUE The options included in OACK is valid.\r
+ @retval FALSE The options included in OACK is invalid.\r
\r
**/\r
BOOLEAN\r
//\r
// It is invalid for server to return options we don't request\r
//\r
- if ((Reply->Exist &~Request->Exist) != 0) {\r
+ if ((Reply->Exist & ~Request->Exist) != 0) {\r
return FALSE;\r
}\r
\r
// Server can only specify a smaller block size to be used and\r
// return the timeout matches that requested.\r
//\r
- if (((Reply->Exist & MTFTP4_BLKSIZE_EXIST) && (Reply->BlkSize > Request->BlkSize)) ||\r
- ((Reply->Exist & MTFTP4_TIMEOUT_EXIST) && (Reply->Timeout != Request->Timeout))) {\r
+ if ((((Reply->Exist & MTFTP4_BLKSIZE_EXIST) != 0) && (Reply->BlkSize > Request->BlkSize)) ||\r
+ (((Reply->Exist & MTFTP4_TIMEOUT_EXIST) != 0) && (Reply->Timeout != Request->Timeout))) {\r
return FALSE;\r
}\r
\r
\r
\r
/**\r
- Function to handle the MTFTP OACK packet. It parses the packet's\r
- options, and update the internal states of the session\r
+ Function to handle the MTFTP OACK packet.\r
+\r
+ It parses the packet's options, and update the internal states of the session.\r
\r
@param Instance The MTFTP session\r
@param Packet The received OACK packet\r
**/\r
EFI_STATUS\r
Mtftp4WrqHandleOack (\r
- IN MTFTP4_PROTOCOL *Instance,\r
- IN EFI_MTFTP4_PACKET *Packet,\r
- IN UINT32 Len,\r
- OUT BOOLEAN *Completed\r
+ IN OUT MTFTP4_PROTOCOL *Instance,\r
+ IN EFI_MTFTP4_PACKET *Packet,\r
+ IN UINT32 Len,\r
+ OUT BOOLEAN *Completed\r
)\r
{\r
MTFTP4_OPTION Reply;\r
// Parse and validate the options from server\r
//\r
ZeroMem (&Reply, sizeof (MTFTP4_OPTION));\r
- Status = Mtftp4ParseOptionOack (Packet, Len, &Reply);\r
+ Status = Mtftp4ParseOptionOack (Packet, Len, Instance->Operation, &Reply);\r
\r
if (EFI_ERROR (Status) || !Mtftp4WrqOackValid (&Reply, &Instance->RequestOption)) {\r
//\r
Bogus.Ack.OpCode = HTONS (EFI_MTFTP4_OPCODE_ACK);\r
Bogus.Ack.Block[0] = 0;\r
\r
- return Mtftp4WrqHandleAck (Instance, &Bogus, sizeof (EFI_MTFTP4_ACK_HEADER), Completed);\r
+ Status = Mtftp4WrqHandleAck (\r
+ Instance,\r
+ &Bogus,\r
+ sizeof (EFI_MTFTP4_ACK_HEADER),\r
+ Completed\r
+ );\r
+\r
+ return Status;\r
}\r
\r
\r
The input process routine for MTFTP upload.\r
\r
@param UdpPacket The received MTFTP packet.\r
- @param Points The local/remote access point\r
+ @param EndPoint The local/remote access point\r
@param IoStatus The result of the packet receiving\r
@param Context Opaque parameter for the callback, which is the\r
MTFTP session.\r
-\r
- @return None\r
-\r
**/\r
VOID\r
+EFIAPI\r
Mtftp4WrqInput (\r
IN NET_BUF *UdpPacket,\r
- IN UDP_POINTS *Points,\r
+ IN UDP_END_POINT *EndPoint,\r
IN EFI_STATUS IoStatus,\r
IN VOID *Context\r
)\r
// Client send initial request to server's listening port. Server\r
// will select a UDP port to communicate with the client.\r
//\r
- if (Points->RemotePort != Instance->ConnectedPort) {\r
+ if (EndPoint->RemotePort != Instance->ConnectedPort) {\r
if (Instance->ConnectedPort != 0) {\r
goto ON_EXIT;\r
} else {\r
- Instance->ConnectedPort = Points->RemotePort;\r
+ Instance->ConnectedPort = EndPoint->RemotePort;\r
}\r
}\r
\r
\r
} else {\r
Packet = (EFI_MTFTP4_PACKET *) NetbufGetByte (UdpPacket, 0, NULL);\r
+ ASSERT (Packet != NULL);\r
}\r
\r
Opcode = NTOHS (Packet->OpCode);\r
case EFI_MTFTP4_OPCODE_ERROR:\r
Status = EFI_TFTP_ERROR;\r
break;\r
+\r
+ default:\r
+ break;\r
}\r
\r
ON_EXIT:\r
// restart the receive, otherwise end the session.\r
//\r
if ((Packet != NULL) && (UdpPacket->BlockOpNum > 1)) {\r
- gBS->FreePool (Packet);\r
+ FreePool (Packet);\r
}\r
\r
if (UdpPacket != NULL) {\r
Mtftp4CleanOperation (Instance, Status);\r
}\r
}\r
+\r
+\r
+\r
+/**\r
+ Start the MTFTP session for upload.\r
+\r
+ It will first init some states, then send the WRQ request packet,\r
+ and start receiving the packet.\r
+\r
+ @param Instance The MTFTP session\r
+ @param Operation Redundant parameter, which is always\r
+ EFI_MTFTP4_OPCODE_WRQ here.\r
+\r
+ @retval EFI_SUCCESS The upload process has been started.\r
+ @retval Others Failed to start the upload.\r
+\r
+**/\r
+EFI_STATUS\r
+Mtftp4WrqStart (\r
+ IN MTFTP4_PROTOCOL *Instance,\r
+ IN UINT16 Operation\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+\r
+ //\r
+ // The valid block number range are [0, 0xffff]. For example:\r
+ // the client sends an WRQ request to the server, the server\r
+ // ACK with an ACK0 to let client start transfer the first\r
+ // packet.\r
+ //\r
+ Status = Mtftp4InitBlockRange (&Instance->Blocks, 0, 0xffff);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ Status = Mtftp4SendRequest (Instance);\r
+\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ return UdpIoRecvDatagram (Instance->UnicastPort, Mtftp4WrqInput, Instance, 0);\r
+}\r
+\r