/** @file Functions implementation related with Mtftp for UefiPxeBc Driver. Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.
SPDX-License-Identifier: BSD-2-Clause-Patent **/ #include "PxeBcImpl.h" CHAR8 *mMtftpOptions[PXE_MTFTP_OPTION_MAXIMUM_INDEX] = { "blksize", "timeout", "tsize", "multicast", "windowsize" }; /** This is a callback function when packets are received or transmitted in Mtftp driver. A callback function that is provided by the caller to intercept the EFI_MTFTP6_OPCODE_DATA or EFI_MTFTP6_OPCODE_DATA8 packets processed in the EFI_MTFTP6_PROTOCOL.ReadFile() function, and alternatively to intercept EFI_MTFTP6_OPCODE_OACK or EFI_MTFTP6_OPCODE_ERROR packets during a call to EFI_MTFTP6_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). @param[in] This Pointer to EFI_MTFTP6_PROTOCOL. @param[in] Token Pointer to EFI_MTFTP6_TOKEN. @param[in] PacketLen Length of EFI_MTFTP6_PACKET. @param[in] Packet Pointer to EFI_MTFTP6_PACKET to be checked. @retval EFI_SUCCESS The current operation succeeded. @retval EFI_ABORTED Abort the current transfer process. **/ EFI_STATUS EFIAPI PxeBcMtftp6CheckPacket ( IN EFI_MTFTP6_PROTOCOL *This, IN EFI_MTFTP6_TOKEN *Token, IN UINT16 PacketLen, IN EFI_MTFTP6_PACKET *Packet ) { PXEBC_PRIVATE_DATA *Private; EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; EFI_STATUS Status; Private = (PXEBC_PRIVATE_DATA *) Token->Context; Callback = Private->PxeBcCallback; Status = EFI_SUCCESS; if (Packet->OpCode == EFI_MTFTP6_OPCODE_ERROR) { // // Store the tftp error message into mode data and set the received flag. // Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpyS ( Private->Mode.TftpError.ErrorString, PXE_MTFTP_ERROR_STRING_LENGTH, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH - 1 ); Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; } if (Callback != NULL) { // // Callback to user if has when received any tftp packet. // Status = Callback->Callback ( Callback, Private->Function, TRUE, PacketLen, (EFI_PXE_BASE_CODE_PACKET *) Packet ); if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { // // User wants to abort current process if not EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. // Status = EFI_ABORTED; } else { // // User wants to continue current process if EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. // Status = EFI_SUCCESS; } } return Status; } /** This function is to get the size of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully obtained the size of file. @retval EFI_NOT_FOUND Parse the tftp options failed. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Has not obtained the size of the file. **/ EFI_STATUS PxeBcMtftp6GetFileSize ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP6_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN OUT UINT64 *BufferSize ) { EFI_MTFTP6_PROTOCOL *Mtftp6; EFI_MTFTP6_OPTION ReqOpt[3]; EFI_MTFTP6_PACKET *Packet; EFI_MTFTP6_OPTION *Option; UINT32 PktLen; UINT8 OptBuf[PXE_MTFTP_OPTBUF_MAXNUM_INDEX]; UINTN OptBufSize; UINT32 OptCnt; EFI_STATUS Status; *BufferSize = 0; Status = EFI_DEVICE_ERROR; Mtftp6 = Private->Mtftp6; Packet = NULL; Option = NULL; PktLen = 0; OptBufSize = PXE_MTFTP_OPTBUF_MAXNUM_INDEX; OptCnt = 1; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp6->Configure (Mtftp6, Config); if (EFI_ERROR (Status)) { return Status; } // // Build the required options for get info. // ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; PxeBcUintnToAscDec (0, OptBuf, OptBufSize); ReqOpt[0].ValueStr = OptBuf; if (BlockSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = (UINT8 *) (ReqOpt[OptCnt-1].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); OptBufSize -= (AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); PxeBcUintnToAscDec (*BlockSize, ReqOpt[OptCnt].ValueStr, OptBufSize); OptCnt++; } if (WindowSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_WINDOWSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = (UINT8 *) (ReqOpt[OptCnt-1].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); OptBufSize -= (AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); PxeBcUintnToAscDec (*WindowSize, ReqOpt[OptCnt].ValueStr, OptBufSize); OptCnt++; } Status = Mtftp6->GetInfo ( Mtftp6, NULL, Filename, NULL, (UINT8) OptCnt, ReqOpt, &PktLen, &Packet ); if (EFI_ERROR (Status)) { if (Status == EFI_TFTP_ERROR) { // // Store the tftp error message into mode data and set the received flag. // Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpyS ( Private->Mode.TftpError.ErrorString, PXE_MTFTP_ERROR_STRING_LENGTH, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH - 1 ); Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; } goto ON_ERROR; } // // Parse the options in the reply packet. // OptCnt = 0; Status = Mtftp6->ParseOptions ( Mtftp6, PktLen, Packet, (UINT32 *) &OptCnt, &Option ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Parse out the value of "tsize" option. // Status = EFI_NOT_FOUND; while (OptCnt != 0) { if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr)); Status = EFI_SUCCESS; } OptCnt--; } FreePool (Option); ON_ERROR: if (Packet != NULL) { FreePool (Packet); } Mtftp6->Configure (Mtftp6, NULL); return Status; } /** This function is to get data of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @param[in] DontUseBuffer Indicates whether with a receive buffer. @retval EFI_SUCCESS Successfully read the data from the special file. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Read data from file failed. **/ EFI_STATUS PxeBcMtftp6ReadFile ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP6_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer ) { EFI_MTFTP6_PROTOCOL *Mtftp6; EFI_MTFTP6_TOKEN Token; EFI_MTFTP6_OPTION ReqOpt[2]; UINT32 OptCnt; UINT8 BlksizeBuf[10]; UINT8 WindowsizeBuf[10]; EFI_STATUS Status; Status = EFI_DEVICE_ERROR; Mtftp6 = Private->Mtftp6; OptCnt = 0; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp6->Configure (Mtftp6, Config); if (EFI_ERROR (Status)) { return Status; } if (BlockSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = BlksizeBuf; PxeBcUintnToAscDec (*BlockSize, ReqOpt[OptCnt].ValueStr, sizeof (BlksizeBuf)); OptCnt++; } if (WindowSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_WINDOWSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = WindowsizeBuf; PxeBcUintnToAscDec (*WindowSize, ReqOpt[OptCnt].ValueStr, sizeof (WindowsizeBuf)); OptCnt++; } Token.Event = NULL; Token.OverrideData = NULL; Token.Filename = Filename; Token.ModeStr = NULL; Token.OptionCount = OptCnt; Token.OptionList = ReqOpt; Token.Context = Private; if (DontUseBuffer) { Token.BufferSize = 0; Token.Buffer = NULL; } else { Token.BufferSize = *BufferSize; Token.Buffer = BufferPtr; } Token.CheckPacket = PxeBcMtftp6CheckPacket; Token.TimeoutCallback = NULL; Token.PacketNeeded = NULL; Status = Mtftp6->ReadFile (Mtftp6, &Token); // // Get the real size of received buffer. // *BufferSize = Token.BufferSize; Mtftp6->Configure (Mtftp6, NULL); return Status; } /** This function is used to write the data of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] Overwrite Indicate whether with overwrite attribute. @param[in] BlockSize Pointer to required block size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully wrote the data into a special file. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval other Write data into file failed. **/ EFI_STATUS PxeBcMtftp6WriteFile ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP6_CONFIG_DATA *Config, IN UINT8 *Filename, IN BOOLEAN Overwrite, IN UINTN *BlockSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize ) { EFI_MTFTP6_PROTOCOL *Mtftp6; EFI_MTFTP6_TOKEN Token; EFI_MTFTP6_OPTION ReqOpt[1]; UINT32 OptCnt; UINT8 OptBuf[128]; EFI_STATUS Status; Status = EFI_DEVICE_ERROR; Mtftp6 = Private->Mtftp6; OptCnt = 0; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp6->Configure (Mtftp6, Config); if (EFI_ERROR (Status)) { return Status; } if (BlockSize != NULL) { ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[0].ValueStr = OptBuf; PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); OptCnt++; } Token.Event = NULL; Token.OverrideData = NULL; Token.Filename = Filename; Token.ModeStr = NULL; Token.OptionCount = OptCnt; Token.OptionList = ReqOpt; Token.BufferSize = *BufferSize; Token.Buffer = BufferPtr; Token.CheckPacket = PxeBcMtftp6CheckPacket; Token.TimeoutCallback = NULL; Token.PacketNeeded = NULL; Status = Mtftp6->WriteFile (Mtftp6, &Token); // // Get the real size of transmitted buffer. // *BufferSize = Token.BufferSize; Mtftp6->Configure (Mtftp6, NULL); return Status; } /** This function is to read the data (file) from a directory using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP6_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @param[in] DontUseBuffer Indicates whether to use a receive buffer. @retval EFI_SUCCESS Successfully obtained the data from the file included in directory. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Operation failed. **/ EFI_STATUS PxeBcMtftp6ReadDirectory ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP6_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer ) { EFI_MTFTP6_PROTOCOL *Mtftp6; EFI_MTFTP6_TOKEN Token; EFI_MTFTP6_OPTION ReqOpt[2]; UINT32 OptCnt; UINT8 BlksizeBuf[10]; UINT8 WindowsizeBuf[10]; EFI_STATUS Status; Status = EFI_DEVICE_ERROR; Mtftp6 = Private->Mtftp6; OptCnt = 0; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp6->Configure (Mtftp6, Config); if (EFI_ERROR (Status)) { return Status; } if (BlockSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = BlksizeBuf; PxeBcUintnToAscDec (*BlockSize, ReqOpt[OptCnt].ValueStr, sizeof (BlksizeBuf)); OptCnt++; } if (WindowSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_WINDOWSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = WindowsizeBuf; PxeBcUintnToAscDec (*WindowSize, ReqOpt[OptCnt].ValueStr, sizeof (WindowsizeBuf)); OptCnt++; } Token.Event = NULL; Token.OverrideData = NULL; Token.Filename = Filename; Token.ModeStr = NULL; Token.OptionCount = OptCnt; Token.OptionList = ReqOpt; Token.Context = Private; if (DontUseBuffer) { Token.BufferSize = 0; Token.Buffer = NULL; } else { Token.BufferSize = *BufferSize; Token.Buffer = BufferPtr; } Token.CheckPacket = PxeBcMtftp6CheckPacket; Token.TimeoutCallback = NULL; Token.PacketNeeded = NULL; Status = Mtftp6->ReadDirectory (Mtftp6, &Token); // // Get the real size of received buffer. // *BufferSize = Token.BufferSize; Mtftp6->Configure (Mtftp6, NULL); return Status; } /** This is a callback function when packets are received or transmitted in Mtftp driver. A callback function that is provided by the caller to intercept the EFI_MTFTP6_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory(). @param[in] This Pointer to EFI_MTFTP4_PROTOCOL. @param[in] Token Pointer to EFI_MTFTP4_TOKEN. @param[in] PacketLen Length of EFI_MTFTP4_PACKET. @param[in] Packet Pointer to EFI_MTFTP4_PACKET to be checked. @retval EFI_SUCCESS The current operation succeeded. @retval EFI_ABORTED Abort the current transfer process. **/ EFI_STATUS EFIAPI PxeBcMtftp4CheckPacket ( IN EFI_MTFTP4_PROTOCOL *This, IN EFI_MTFTP4_TOKEN *Token, IN UINT16 PacketLen, IN EFI_MTFTP4_PACKET *Packet ) { PXEBC_PRIVATE_DATA *Private; EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback; EFI_STATUS Status; Private = (PXEBC_PRIVATE_DATA *) Token->Context; Callback = Private->PxeBcCallback; Status = EFI_SUCCESS; if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) { // // Store the tftp error message into mode data and set the received flag. // Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpyS ( Private->Mode.TftpError.ErrorString, PXE_MTFTP_ERROR_STRING_LENGTH, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH - 1 ); Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; } if (Callback != NULL) { // // Callback to user if has when received any tftp packet. // Status = Callback->Callback ( Callback, Private->Function, TRUE, PacketLen, (EFI_PXE_BASE_CODE_PACKET *) Packet ); if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) { // // User wants to abort current process if not EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. // Status = EFI_ABORTED; } else { // // User wants to continue current process if EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE. // Status = EFI_SUCCESS; } } return Status; } /** This function is to get size of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully obtained the size of file. @retval EFI_NOT_FOUND Parse the tftp options failed. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Did not obtain the size of the file. **/ EFI_STATUS PxeBcMtftp4GetFileSize ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN OUT UINT64 *BufferSize ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_OPTION ReqOpt[3]; EFI_MTFTP4_PACKET *Packet; EFI_MTFTP4_OPTION *Option; UINT32 PktLen; UINT8 OptBuf[PXE_MTFTP_OPTBUF_MAXNUM_INDEX]; UINTN OptBufSize; UINT32 OptCnt; EFI_STATUS Status; *BufferSize = 0; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; Packet = NULL; Option = NULL; PktLen = 0; OptBufSize = PXE_MTFTP_OPTBUF_MAXNUM_INDEX; OptCnt = 1; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } // // Build the required options for get info. // ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX]; PxeBcUintnToAscDec (0, OptBuf, OptBufSize); ReqOpt[0].ValueStr = OptBuf; if (BlockSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = (UINT8 *) (ReqOpt[OptCnt-1].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); OptBufSize -= (AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); PxeBcUintnToAscDec (*BlockSize, ReqOpt[OptCnt].ValueStr, OptBufSize); OptCnt++; } if (WindowSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_WINDOWSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = (UINT8 *) (ReqOpt[OptCnt-1].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); OptBufSize -= (AsciiStrLen ((CHAR8 *) ReqOpt[OptCnt-1].ValueStr) + 1); PxeBcUintnToAscDec (*WindowSize, ReqOpt[OptCnt].ValueStr, OptBufSize); OptCnt++; } Status = Mtftp4->GetInfo ( Mtftp4, NULL, Filename, NULL, (UINT8) OptCnt, ReqOpt, &PktLen, &Packet ); if (EFI_ERROR (Status)) { if (Status == EFI_TFTP_ERROR) { // // Store the tftp error message into mode data and set the received flag. // Private->Mode.TftpErrorReceived = TRUE; Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode; AsciiStrnCpyS ( Private->Mode.TftpError.ErrorString, PXE_MTFTP_ERROR_STRING_LENGTH, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH - 1 ); Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0'; } goto ON_ERROR; } // // Parse the options in the reply packet. // OptCnt = 0; Status = Mtftp4->ParseOptions ( Mtftp4, PktLen, Packet, (UINT32 *) &OptCnt, &Option ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Parse out the value of "tsize" option. // Status = EFI_NOT_FOUND; while (OptCnt != 0) { if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) { *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr)); Status = EFI_SUCCESS; } OptCnt--; } FreePool (Option); ON_ERROR: if (Packet != NULL) { FreePool (Packet); } Mtftp4->Configure (Mtftp4, NULL); return Status; } /** This function is to read the data of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @param[in] DontUseBuffer Indicates whether to use a receive buffer. @retval EFI_SUCCESS Successfully read the data from the special file. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Read data from file failed. **/ EFI_STATUS PxeBcMtftp4ReadFile ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_TOKEN Token; EFI_MTFTP4_OPTION ReqOpt[2]; UINT32 OptCnt; UINT8 BlksizeBuf[10]; UINT8 WindowsizeBuf[10]; EFI_STATUS Status; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; OptCnt = 0; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } if (BlockSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = BlksizeBuf; PxeBcUintnToAscDec (*BlockSize, ReqOpt[OptCnt].ValueStr, sizeof (BlksizeBuf)); OptCnt++; } if (WindowSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_WINDOWSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = WindowsizeBuf; PxeBcUintnToAscDec (*WindowSize, ReqOpt[OptCnt].ValueStr, sizeof (WindowsizeBuf)); OptCnt++; } Token.Event = NULL; Token.OverrideData = NULL; Token.Filename = Filename; Token.ModeStr = NULL; Token.OptionCount = OptCnt; Token.OptionList = ReqOpt; Token.Context = Private; if (DontUseBuffer) { Token.BufferSize = 0; Token.Buffer = NULL; } else { Token.BufferSize = *BufferSize; Token.Buffer = BufferPtr; } Token.CheckPacket = PxeBcMtftp4CheckPacket; Token.TimeoutCallback = NULL; Token.PacketNeeded = NULL; Status = Mtftp4->ReadFile (Mtftp4, &Token); // // Get the real size of received buffer. // *BufferSize = Token.BufferSize; Mtftp4->Configure (Mtftp4, NULL); return Status; } /** This function is to write the data of a file using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] Overwrite Indicates whether to use the overwrite attribute. @param[in] BlockSize Pointer to required block size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully write the data into the special file. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval other Write data into file failed. **/ EFI_STATUS PxeBcMtftp4WriteFile ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN BOOLEAN Overwrite, IN UINTN *BlockSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_TOKEN Token; EFI_MTFTP4_OPTION ReqOpt[1]; UINT32 OptCnt; UINT8 OptBuf[128]; EFI_STATUS Status; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; OptCnt = 0; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } if (BlockSize != NULL) { ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[0].ValueStr = OptBuf; PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX); OptCnt++; } Token.Event = NULL; Token.OverrideData = NULL; Token.Filename = Filename; Token.ModeStr = NULL; Token.OptionCount = OptCnt; Token.OptionList = ReqOpt; Token.BufferSize = *BufferSize; Token.Buffer = BufferPtr; Token.CheckPacket = PxeBcMtftp4CheckPacket; Token.TimeoutCallback = NULL; Token.PacketNeeded = NULL; Status = Mtftp4->WriteFile (Mtftp4, &Token); // // Get the real size of transmitted buffer. // *BufferSize = Token.BufferSize; Mtftp4->Configure (Mtftp4, NULL); return Status; } /** This function is to get data (file) from a directory using Tftp. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to EFI_MTFTP4_CONFIG_DATA. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @param[in] DontUseBuffer Indicates whether to use a receive buffer. @retval EFI_SUCCESS Successfully obtained the data from the file included in the directory. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Operation failed. **/ EFI_STATUS PxeBcMtftp4ReadDirectory ( IN PXEBC_PRIVATE_DATA *Private, IN EFI_MTFTP4_CONFIG_DATA *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer ) { EFI_MTFTP4_PROTOCOL *Mtftp4; EFI_MTFTP4_TOKEN Token; EFI_MTFTP4_OPTION ReqOpt[2]; UINT32 OptCnt; UINT8 BlksizeBuf[10]; UINT8 WindowsizeBuf[10]; EFI_STATUS Status; Status = EFI_DEVICE_ERROR; Mtftp4 = Private->Mtftp4; OptCnt = 0; Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT; Status = Mtftp4->Configure (Mtftp4, Config); if (EFI_ERROR (Status)) { return Status; } if (BlockSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = BlksizeBuf; PxeBcUintnToAscDec (*BlockSize, ReqOpt[OptCnt].ValueStr, sizeof (BlksizeBuf)); OptCnt++; } if (WindowSize != NULL) { ReqOpt[OptCnt].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_WINDOWSIZE_INDEX]; ReqOpt[OptCnt].ValueStr = WindowsizeBuf; PxeBcUintnToAscDec (*WindowSize, ReqOpt[OptCnt].ValueStr, sizeof (WindowsizeBuf)); OptCnt++; } Token.Event = NULL; Token.OverrideData = NULL; Token.Filename = Filename; Token.ModeStr = NULL; Token.OptionCount = OptCnt; Token.OptionList = ReqOpt; Token.Context = Private; if (DontUseBuffer) { Token.BufferSize = 0; Token.Buffer = NULL; } else { Token.BufferSize = *BufferSize; Token.Buffer = BufferPtr; } Token.CheckPacket = PxeBcMtftp4CheckPacket; Token.TimeoutCallback = NULL; Token.PacketNeeded = NULL; Status = Mtftp4->ReadDirectory (Mtftp4, &Token); // // Get the real size of received buffer. // *BufferSize = Token.BufferSize; Mtftp4->Configure (Mtftp4, NULL); return Status; } /** This function is wrapper to get the file size using TFTP. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to configure data. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully obtained the size of file. @retval EFI_NOT_FOUND Parse the tftp options failed. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Did not obtain the size of the file. **/ EFI_STATUS PxeBcTftpGetFileSize ( IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN OUT UINT64 *BufferSize ) { if (Private->PxeBc.Mode->UsingIpv6) { return PxeBcMtftp6GetFileSize ( Private, (EFI_MTFTP6_CONFIG_DATA *) Config, Filename, BlockSize, WindowSize, BufferSize ); } else { return PxeBcMtftp4GetFileSize ( Private, (EFI_MTFTP4_CONFIG_DATA *) Config, Filename, BlockSize, WindowSize, BufferSize ); } } /** This function is a wrapper to get file using TFTP. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to config data. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @param[in] DontUseBuffer Indicates whether to use a receive buffer. @retval EFI_SUCCESS Successfully read the data from the special file. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Read data from file failed. **/ EFI_STATUS PxeBcTftpReadFile ( IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer ) { if (Private->PxeBc.Mode->UsingIpv6) { return PxeBcMtftp6ReadFile ( Private, (EFI_MTFTP6_CONFIG_DATA *) Config, Filename, BlockSize, WindowSize, BufferPtr, BufferSize, DontUseBuffer ); } else { return PxeBcMtftp4ReadFile ( Private, (EFI_MTFTP4_CONFIG_DATA *) Config, Filename, BlockSize, WindowSize, BufferPtr, BufferSize, DontUseBuffer ); } } /** This function is a wrapper to write file using TFTP. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to config data. @param[in] Filename Pointer to boot file name. @param[in] Overwrite Indicate whether with overwrite attribute. @param[in] BlockSize Pointer to required block size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @retval EFI_SUCCESS Successfully wrote the data into a special file. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval other Write data into file failed. **/ EFI_STATUS PxeBcTftpWriteFile ( IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN BOOLEAN Overwrite, IN UINTN *BlockSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize ) { if (Private->PxeBc.Mode->UsingIpv6) { return PxeBcMtftp6WriteFile ( Private, (EFI_MTFTP6_CONFIG_DATA *) Config, Filename, Overwrite, BlockSize, BufferPtr, BufferSize ); } else { return PxeBcMtftp4WriteFile ( Private, (EFI_MTFTP4_CONFIG_DATA *) Config, Filename, Overwrite, BlockSize, BufferPtr, BufferSize ); } } /** This function is a wrapper to get the data (file) from a directory using TFTP. @param[in] Private Pointer to PxeBc private data. @param[in] Config Pointer to config data. @param[in] Filename Pointer to boot file name. @param[in] BlockSize Pointer to required block size. @param[in] WindowSize Pointer to required window size. @param[in] BufferPtr Pointer to buffer. @param[in, out] BufferSize Pointer to buffer size. @param[in] DontUseBuffer Indicatse whether to use a receive buffer. @retval EFI_SUCCESS Successfully obtained the data from the file included in the directory. @retval EFI_DEVICE_ERROR The network device encountered an error during this operation. @retval Others Operation failed. **/ EFI_STATUS PxeBcTftpReadDirectory ( IN PXEBC_PRIVATE_DATA *Private, IN VOID *Config, IN UINT8 *Filename, IN UINTN *BlockSize, IN UINTN *WindowSize, IN UINT8 *BufferPtr, IN OUT UINT64 *BufferSize, IN BOOLEAN DontUseBuffer ) { if (Private->PxeBc.Mode->UsingIpv6) { return PxeBcMtftp6ReadDirectory ( Private, (EFI_MTFTP6_CONFIG_DATA *) Config, Filename, BlockSize, WindowSize, BufferPtr, BufferSize, DontUseBuffer ); } else { return PxeBcMtftp4ReadDirectory ( Private, (EFI_MTFTP4_CONFIG_DATA *) Config, Filename, BlockSize, WindowSize, BufferPtr, BufferSize, DontUseBuffer ); } }