/** @file\r
Support routines for Mtftp.\r
- \r
-Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR>\r
-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<BR>\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
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
\r
**/\r
\r
\r
\r
/**\r
- Initialize the block range for either RRQ or WRQ. \r
- \r
- RRQ and WRQ have different requirements for Start and End. \r
- For example, during start up, WRQ initializes its whole valid block range \r
- to [0, 0xffff]. This is bacause the server will send us a ACK0 to inform us \r
- to start the upload. When the client received ACK0, it will remove 0 from the \r
+ Initialize the block range for either RRQ or WRQ.\r
+\r
+ RRQ and WRQ have different requirements for Start and End.\r
+ For example, during start up, WRQ initializes its whole valid block range\r
+ to [0, 0xffff]. This is bacause the server will send us a ACK0 to inform us\r
+ to start the upload. When the client received ACK0, it will remove 0 from the\r
range, get the next block number, which is 1, then upload the BLOCK1. For RRQ\r
- without option negotiation, the server will directly send us the BLOCK1 in \r
- response to the client's RRQ. When received BLOCK1, the client will remove \r
- it from the block range and send an ACK. It also works if there is option \r
+ without option negotiation, the server will directly send us the BLOCK1 in\r
+ response to the client's RRQ. When received BLOCK1, the client will remove\r
+ it from the block range and send an ACK. It also works if there is option\r
negotiation.\r
\r
@param Head The block range head to initialize\r
\r
@param Head The block range head\r
\r
- @return The first valid block number, -1 if the block range is empty. \r
+ @return The first valid block number, -1 if the block range is empty.\r
\r
**/\r
INTN\r
\r
\r
/**\r
- Set the last block number of the block range list. \r
- \r
+ Set the last block number of the block range list.\r
+\r
It will remove all the blocks after the Last. MTFTP initialize the block range\r
- to the maximum possible range, such as [0, 0xffff] for WRQ. When it gets the \r
+ to the maximum possible range, such as [0, 0xffff] for WRQ. When it gets the\r
last block number, it will call this function to set the last block number.\r
\r
@param Head The block range list\r
\r
@param Head The block range list to remove from\r
@param Num The block number to remove\r
- @param Completed Whether Num is the last block number\r
- @param TotalBlock The continuous block number in all \r
+ @param Completed Whether Num is the last block number.\r
+ @param BlockCounter The continuous block counter instead of the value after roll-over.\r
\r
@retval EFI_NOT_FOUND The block number isn't in the block range list\r
@retval EFI_SUCCESS The block number has been removed from the list\r
IN LIST_ENTRY *Head,\r
IN UINT16 Num,\r
IN BOOLEAN Completed,\r
- OUT UINT64 *TotalBlock\r
+ OUT UINT64 *BlockCounter\r
)\r
{\r
MTFTP4_BLOCK_RANGE *Range;\r
Range->Start++;\r
\r
//\r
- // Note that: RFC 1350 does not mention block counter roll-over, \r
- // but several TFTP hosts implement the roll-over be able to accept \r
- // transfers of unlimited size. There is no consensus, however, whether \r
- // the counter should wrap around to zero or to one. Many implementations \r
- // wrap to zero, because this is the simplest to implement. Here we choose \r
+ // Note that: RFC 1350 does not mention block counter roll-over,\r
+ // but several TFTP hosts implement the roll-over be able to accept\r
+ // transfers of unlimited size. There is no consensus, however, whether\r
+ // the counter should wrap around to zero or to one. Many implementations\r
+ // wrap to zero, because this is the simplest to implement. Here we choose\r
// this solution.\r
//\r
- *TotalBlock = Num;\r
- \r
+ *BlockCounter = Num;\r
+\r
if (Range->Round > 0) {\r
- *TotalBlock += Range->Bound + MultU64x32 ((UINTN) (Range->Round -1), (UINT32) (Range->Bound + 1)) + 1;\r
- }\r
+ *BlockCounter += Range->Bound + MultU64x32 ((UINTN) (Range->Round -1), (UINT32) (Range->Bound + 1)) + 1;\r
+ }\r
\r
if (Range->Start > Range->Bound) {\r
- Range->Start = 0;\r
- Range->Round ++;\r
+ Range->Start = 0;\r
+ Range->Round ++;\r
}\r
\r
if ((Range->Start > Range->End) || Completed) {\r
EFI_MTFTP4_PACKET *Packet;\r
EFI_MTFTP4_OPTION *Options;\r
EFI_MTFTP4_TOKEN *Token;\r
+ RETURN_STATUS Status;\r
NET_BUF *Nbuf;\r
UINT8 *Mode;\r
UINT8 *Cur;\r
- UINT32 Len;\r
UINTN Index;\r
- UINT32 Len1;\r
- UINT32 Len2;\r
+ UINT32 BufferLength;\r
+ UINTN FileNameLength;\r
+ UINTN ModeLength;\r
+ UINTN OptionStrLength;\r
+ UINTN ValueStrLength;\r
\r
Token = Instance->Token;\r
Options = Token->OptionList;\r
//\r
// Compute the packet length\r
//\r
- Len1 = (UINT32) AsciiStrLen ((CHAR8 *) Token->Filename);\r
- Len2 = (UINT32) AsciiStrLen ((CHAR8 *) Mode);\r
- Len = (Len1 + Len2 + 4);\r
+ FileNameLength = AsciiStrLen ((CHAR8 *) Token->Filename);\r
+ ModeLength = AsciiStrLen ((CHAR8 *) Mode);\r
+ BufferLength = (UINT32) FileNameLength + (UINT32) ModeLength + 4;\r
\r
for (Index = 0; Index < Token->OptionCount; Index++) {\r
- Len1 = (UINT32) AsciiStrLen ((CHAR8 *) Options[Index].OptionStr);\r
- Len2 = (UINT32) AsciiStrLen ((CHAR8 *) Options[Index].ValueStr);\r
- Len += Len1 + Len2 + 2;\r
+ OptionStrLength = AsciiStrLen ((CHAR8 *) Options[Index].OptionStr);\r
+ ValueStrLength = AsciiStrLen ((CHAR8 *) Options[Index].ValueStr);\r
+ BufferLength += (UINT32) OptionStrLength + (UINT32) ValueStrLength + 2;\r
}\r
-\r
//\r
// Allocate a packet then copy the data over\r
//\r
- if ((Nbuf = NetbufAlloc (Len)) == NULL) {\r
+ if ((Nbuf = NetbufAlloc (BufferLength)) == NULL) {\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
- Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (Nbuf, Len, FALSE);\r
+ Packet = (EFI_MTFTP4_PACKET *) NetbufAllocSpace (Nbuf, BufferLength, FALSE);\r
ASSERT (Packet != NULL);\r
\r
Packet->OpCode = HTONS (Instance->Operation);\r
+ BufferLength -= sizeof (Packet->OpCode);\r
+\r
Cur = Packet->Rrq.Filename;\r
- Cur = (UINT8 *) AsciiStrCpy ((CHAR8 *) Cur, (CHAR8 *) Token->Filename);\r
- Cur += AsciiStrLen ((CHAR8 *) Token->Filename) + 1;\r
- Cur = (UINT8 *) AsciiStrCpy ((CHAR8 *) Cur, (CHAR8 *) Mode);\r
- Cur += AsciiStrLen ((CHAR8 *) Mode) + 1;\r
+ Status = AsciiStrCpyS ((CHAR8 *) Cur, BufferLength, (CHAR8 *) Token->Filename);\r
+ ASSERT_EFI_ERROR (Status);\r
+ BufferLength -= (UINT32) (FileNameLength + 1);\r
+ Cur += FileNameLength + 1;\r
+ Status = AsciiStrCpyS ((CHAR8 *) Cur, BufferLength, (CHAR8 *) Mode);\r
+ ASSERT_EFI_ERROR (Status);\r
+ BufferLength -= (UINT32) (ModeLength + 1);\r
+ Cur += ModeLength + 1;\r
\r
for (Index = 0; Index < Token->OptionCount; ++Index) {\r
- Cur = (UINT8 *) AsciiStrCpy ((CHAR8 *) Cur, (CHAR8 *) Options[Index].OptionStr);\r
- Cur += AsciiStrLen ((CHAR8 *) Options[Index].OptionStr) + 1;\r
+ OptionStrLength = AsciiStrLen ((CHAR8 *) Options[Index].OptionStr);\r
+ ValueStrLength = AsciiStrLen ((CHAR8 *) Options[Index].ValueStr);\r
+\r
+ Status = AsciiStrCpyS ((CHAR8 *) Cur, BufferLength, (CHAR8 *) Options[Index].OptionStr);\r
+ ASSERT_EFI_ERROR (Status);\r
+ BufferLength -= (UINT32) (OptionStrLength + 1);\r
+ Cur += OptionStrLength + 1;\r
+\r
+ Status = AsciiStrCpyS ((CHAR8 *) Cur, BufferLength, (CHAR8 *) Options[Index].ValueStr);\r
+ ASSERT_EFI_ERROR (Status);\r
+ BufferLength -= (UINT32) (ValueStrLength + 1);\r
+ Cur += ValueStrLength + 1;\r
\r
- Cur = (UINT8 *) AsciiStrCpy ((CHAR8 *) Cur, (CHAR8 *) Options[Index].ValueStr);\r
- Cur += AsciiStrLen ((CHAR8 *) (CHAR8 *) Options[Index].ValueStr) + 1;\r
}\r
\r
return Mtftp4SendPacket (Instance, Nbuf);\r
Build then send an error message.\r
\r
@param Instance The MTFTP session\r
- @param ErrCode The error code \r
+ @param ErrCode The error code\r
@param ErrInfo The error message\r
\r
@retval EFI_OUT_OF_RESOURCES Failed to allocate memory for the error packet\r
TftpError->OpCode = HTONS (EFI_MTFTP4_OPCODE_ERROR);\r
TftpError->Error.ErrorCode = HTONS (ErrCode);\r
\r
- AsciiStrCpy ((CHAR8 *) TftpError->Error.ErrorMessage, (CHAR8 *) ErrInfo);\r
+ AsciiStrCpyS ((CHAR8 *) TftpError->Error.ErrorMessage, Len, (CHAR8 *) ErrInfo);\r
\r
return Mtftp4SendPacket (Instance, Packet);\r
}\r
\r
/**\r
The callback function called when the packet is transmitted.\r
- \r
+\r
It simply frees the packet.\r
\r
@param Packet The transmitted (or failed to) packet\r
\r
\r
/**\r
- Send the packet for the instance. \r
- \r
- It will first save a reference to the packet for later retransmission. \r
- Then determine the destination port, listen port for requests, and connected \r
+ Send the packet for the instance.\r
+\r
+ It will first save a reference to the packet for later retransmission.\r
+ Then determine the destination port, listen port for requests, and connected\r
port for others. At last, send the packet out.\r
\r
@param Instance The Mtftp instance\r
ASSERT (Buffer != NULL);\r
OpCode = NTOHS (*(UINT16 *)Buffer);\r
\r
- if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) || \r
+ if ((OpCode == EFI_MTFTP4_OPCODE_RRQ) ||\r
(OpCode == EFI_MTFTP4_OPCODE_DIR) ||\r
(OpCode == EFI_MTFTP4_OPCODE_WRQ)) {\r
UdpPoint.RemotePort = Instance->ListeningPort;\r
}\r
\r
\r
+/**\r
+ The timer ticking function in TPL_NOTIFY level for the Mtftp service instance.\r
+\r
+ @param Event The ticking event\r
+ @param Context The Mtftp service instance\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+Mtftp4OnTimerTickNotifyLevel (\r
+ IN EFI_EVENT Event,\r
+ IN VOID *Context\r
+ )\r
+{\r
+ MTFTP4_SERVICE *MtftpSb;\r
+ LIST_ENTRY *Entry;\r
+ LIST_ENTRY *Next;\r
+ MTFTP4_PROTOCOL *Instance;\r
+\r
+ MtftpSb = (MTFTP4_SERVICE *) Context;\r
+\r
+ //\r
+ // Iterate through all the children of the Mtftp service instance. Time\r
+ // out the current packet transmit.\r
+ //\r
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {\r
+ Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);\r
+ if ((Instance->PacketToLive == 0) || (--Instance->PacketToLive > 0)) {\r
+ Instance->HasTimeout = FALSE;\r
+ } else {\r
+ Instance->HasTimeout = TRUE;\r
+ }\r
+ }\r
+}\r
+\r
+\r
/**\r
The timer ticking function for the Mtftp service instance.\r
\r
MtftpSb = (MTFTP4_SERVICE *) Context;\r
\r
//\r
- // Iterate through all the children of the Mtftp service instance. Time\r
- // out the packet. If maximum retries reached, clean the session up.\r
+ // Iterate through all the children of the Mtftp service instance.\r
//\r
NET_LIST_FOR_EACH_SAFE (Entry, Next, &MtftpSb->Children) {\r
Instance = NET_LIST_USER_STRUCT (Entry, MTFTP4_PROTOCOL, Link);\r
-\r
- if ((Instance->PacketToLive == 0) || (--Instance->PacketToLive > 0)) {\r
+ if (!Instance->HasTimeout) {\r
continue;\r
}\r
\r
+ Instance->HasTimeout = FALSE;\r
+\r
//\r
// Call the user's time out handler\r
//\r
Token = Instance->Token;\r
\r
- if ((Token->TimeoutCallback != NULL) &&\r
+ if (Token != NULL && Token->TimeoutCallback != NULL &&\r
EFI_ERROR (Token->TimeoutCallback (&Instance->Mtftp4, Token))) {\r
-\r
Mtftp4SendError (\r
- Instance,\r
- EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,\r
- (UINT8 *) "User aborted the transfer in time out"\r
- );\r
+ Instance,\r
+ EFI_MTFTP4_ERRORCODE_REQUEST_DENIED,\r
+ (UINT8 *) "User aborted the transfer in time out"\r
+ );\r
\r
Mtftp4CleanOperation (Instance, EFI_ABORTED);\r
continue;\r