aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c')
-rw-r--r--roms/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c1187
1 files changed, 1187 insertions, 0 deletions
diff --git a/roms/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c b/roms/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c
new file mode 100644
index 000000000..addcafc0c
--- /dev/null
+++ b/roms/edk2/NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c
@@ -0,0 +1,1187 @@
+/** @file
+ Functions implementation related with Mtftp for UefiPxeBc Driver.
+
+ Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
+
+ 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
+ );
+ }
+}
+