audk/NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c

1194 lines
40 KiB
C

/** @file
Functions implementation related with Mtftp for UefiPxeBc Driver.
Copyright (c) 2007 - 2018, Intel Corporation. All rights reserved.<BR>
This program and the accompanying materials
are licensed and made available under the terms and conditions of the BSD License
which accompanies this distribution. The full text of the license may be found at
http://opensource.org/licenses/bsd-license.php.
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
**/
#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 Sucessfully obtained the size of file.
@retval EFI_NOT_FOUND Parse the tftp ptions 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 succeeeded.
@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_SUCCES 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 Sucessfully 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_SUCCES 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
);
}
}