aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/NetworkPkg/Mtftp4Dxe/Mtftp4Impl.c
diff options
context:
space:
mode:
authorAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
committerAngelos Mouzakitis <a.mouzakitis@virtualopensystems.com>2023-10-10 14:33:42 +0000
commitaf1a266670d040d2f4083ff309d732d648afba2a (patch)
tree2fc46203448ddcc6f81546d379abfaeb323575e9 /roms/edk2/NetworkPkg/Mtftp4Dxe/Mtftp4Impl.c
parente02cda008591317b1625707ff8e115a4841aa889 (diff)
Add submodule dependency filesHEADmaster
Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
Diffstat (limited to 'roms/edk2/NetworkPkg/Mtftp4Dxe/Mtftp4Impl.c')
-rw-r--r--roms/edk2/NetworkPkg/Mtftp4Dxe/Mtftp4Impl.c1113
1 files changed, 1113 insertions, 0 deletions
diff --git a/roms/edk2/NetworkPkg/Mtftp4Dxe/Mtftp4Impl.c b/roms/edk2/NetworkPkg/Mtftp4Dxe/Mtftp4Impl.c
new file mode 100644
index 000000000..990a9ef03
--- /dev/null
+++ b/roms/edk2/NetworkPkg/Mtftp4Dxe/Mtftp4Impl.c
@@ -0,0 +1,1113 @@
+/** @file
+ Interface routine for Mtftp4.
+
+(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
+SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+
+#include "Mtftp4Impl.h"
+
+
+/**
+ Clean up the MTFTP session to get ready for new operation.
+
+ @param Instance The MTFTP session to clean up
+ @param Result The result to return to the caller who initiated
+ the operation.
+**/
+VOID
+Mtftp4CleanOperation (
+ IN OUT MTFTP4_PROTOCOL *Instance,
+ IN EFI_STATUS Result
+ )
+{
+ LIST_ENTRY *Entry;
+ LIST_ENTRY *Next;
+ MTFTP4_BLOCK_RANGE *Block;
+ EFI_MTFTP4_TOKEN *Token;
+
+ //
+ // Free various resources.
+ //
+ Token = Instance->Token;
+
+ if (Token != NULL) {
+ Token->Status = Result;
+
+ if (Token->Event != NULL) {
+ gBS->SignalEvent (Token->Event);
+ }
+
+ Instance->Token = NULL;
+ }
+
+ ASSERT (Instance->UnicastPort != NULL);
+ UdpIoCleanIo (Instance->UnicastPort);
+
+ if (Instance->LastPacket != NULL) {
+ NetbufFree (Instance->LastPacket);
+ Instance->LastPacket = NULL;
+ }
+
+ if (Instance->McastUdpPort != NULL) {
+ gBS->CloseProtocol (
+ Instance->McastUdpPort->UdpHandle,
+ &gEfiUdp4ProtocolGuid,
+ gMtftp4DriverBinding.DriverBindingHandle,
+ Instance->Handle
+ );
+ UdpIoFreeIo (Instance->McastUdpPort);
+ Instance->McastUdpPort = NULL;
+ }
+
+ NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->Blocks) {
+ Block = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);
+ RemoveEntryList (Entry);
+ FreePool (Block);
+ }
+
+ ZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));
+
+ Instance->Operation = 0;
+
+ Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;
+ Instance->WindowSize = 1;
+ Instance->TotalBlock = 0;
+ Instance->AckedBlock = 0;
+ Instance->LastBlock = 0;
+ Instance->ServerIp = 0;
+ Instance->ListeningPort = 0;
+ Instance->ConnectedPort = 0;
+ Instance->Gateway = 0;
+ Instance->PacketToLive = 0;
+ Instance->MaxRetry = 0;
+ Instance->CurRetry = 0;
+ Instance->Timeout = 0;
+ Instance->McastIp = 0;
+ Instance->McastPort = 0;
+ Instance->Master = TRUE;
+}
+
+
+/**
+ Check packet for GetInfo.
+
+ GetInfo is implemented with EfiMtftp4ReadFile. It use Mtftp4GetInfoCheckPacket
+ to inspect the first packet from server, then abort the session.
+
+ @param This The MTFTP4 protocol instance
+ @param Token The user's token
+ @param PacketLen The length of the packet
+ @param Packet The received packet.
+
+ @retval EFI_ABORTED Abort the ReadFile operation and return.
+
+**/
+EFI_STATUS
+EFIAPI
+Mtftp4GetInfoCheckPacket (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_TOKEN *Token,
+ IN UINT16 PacketLen,
+ IN EFI_MTFTP4_PACKET *Packet
+ )
+{
+ MTFTP4_GETINFO_STATE *State;
+ EFI_STATUS Status;
+ UINT16 OpCode;
+ EFI_MTFTP4_ERROR_HEADER *ErrorHeader;
+
+ State = (MTFTP4_GETINFO_STATE *) Token->Context;
+ OpCode = NTOHS (Packet->OpCode);
+
+ //
+ // Set the GetInfo's return status according to the OpCode.
+ //
+ switch (OpCode) {
+ case EFI_MTFTP4_OPCODE_ERROR:
+ ErrorHeader = (EFI_MTFTP4_ERROR_HEADER *) Packet;
+ if (ErrorHeader->ErrorCode == EFI_MTFTP4_ERRORCODE_FILE_NOT_FOUND) {
+ DEBUG ((EFI_D_ERROR, "TFTP error code 1 (File Not Found)\n"));
+ } else {
+ DEBUG ((EFI_D_ERROR, "TFTP error code %d\n", ErrorHeader->ErrorCode));
+ }
+ State->Status = EFI_TFTP_ERROR;
+ break;
+
+ case EFI_MTFTP4_OPCODE_OACK:
+ State->Status = EFI_SUCCESS;
+ break;
+
+ default:
+ State->Status = EFI_PROTOCOL_ERROR;
+ }
+
+ //
+ // Allocate buffer then copy the packet over. Use gBS->AllocatePool
+ // in case AllocatePool will implements something tricky.
+ //
+ Status = gBS->AllocatePool (EfiBootServicesData, PacketLen, (VOID **) State->Packet);
+
+ if (EFI_ERROR (Status)) {
+ State->Status = EFI_OUT_OF_RESOURCES;
+ return EFI_ABORTED;
+ }
+
+ *(State->PacketLen) = PacketLen;
+ CopyMem (*(State->Packet), Packet, PacketLen);
+
+ return EFI_ABORTED;
+}
+
+
+/**
+ Check whether the override data is valid.
+
+ It will first validate whether the server is a valid unicast. If a gateway
+ is provided in the Override, it also check that it is a unicast on the
+ connected network.
+
+ @param Instance The MTFTP instance
+ @param Override The override data to validate.
+
+ @retval TRUE The override data is valid
+ @retval FALSE The override data is invalid
+
+**/
+BOOLEAN
+Mtftp4OverrideValid (
+ IN MTFTP4_PROTOCOL *Instance,
+ IN EFI_MTFTP4_OVERRIDE_DATA *Override
+ )
+{
+ EFI_MTFTP4_CONFIG_DATA *Config;
+ IP4_ADDR Ip;
+ IP4_ADDR Netmask;
+ IP4_ADDR Gateway;
+
+ CopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));
+ if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
+ return FALSE;
+ }
+
+ Config = &Instance->Config;
+
+ CopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
+ Gateway = NTOHL (Gateway);
+
+ if (!Config->UseDefaultSetting && (Gateway != 0)) {
+ CopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));
+ CopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));
+
+ Netmask = NTOHL (Netmask);
+ Ip = NTOHL (Ip);
+
+ if ((Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {
+ return FALSE;
+ }
+ }
+
+ return TRUE;
+}
+
+
+/**
+ Poll the UDP to get the IP4 default address, which may be retrieved
+ by DHCP.
+
+ The default time out value is 5 seconds. If IP has retrieved the default address,
+ the UDP is reconfigured.
+
+ @param Instance The Mtftp instance
+ @param UdpIo The UDP_IO to poll
+ @param UdpCfgData The UDP configure data to reconfigure the UDP_IO
+
+ @retval TRUE The default address is retrieved and UDP is reconfigured.
+ @retval FALSE Some error occurred.
+
+**/
+BOOLEAN
+Mtftp4GetMapping (
+ IN MTFTP4_PROTOCOL *Instance,
+ IN UDP_IO *UdpIo,
+ IN EFI_UDP4_CONFIG_DATA *UdpCfgData
+ )
+{
+ MTFTP4_SERVICE *Service;
+ EFI_IP4_MODE_DATA Ip4Mode;
+ EFI_UDP4_PROTOCOL *Udp;
+ EFI_STATUS Status;
+
+ ASSERT (Instance->Config.UseDefaultSetting);
+
+ Service = Instance->Service;
+ Udp = UdpIo->Protocol.Udp4;
+
+ Status = gBS->SetTimer (
+ Service->TimerToGetMap,
+ TimerRelative,
+ MTFTP4_TIME_TO_GETMAP * TICKS_PER_SECOND
+ );
+ if (EFI_ERROR (Status)) {
+ return FALSE;
+ }
+
+ while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {
+ Udp->Poll (Udp);
+
+ if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&
+ Ip4Mode.IsConfigured) {
+
+ Udp->Configure (Udp, NULL);
+ return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
+ }
+ }
+
+ return FALSE;
+}
+
+
+/**
+ Configure the UDP port for unicast receiving.
+
+ @param UdpIo The UDP_IO instance
+ @param Instance The MTFTP session
+
+ @retval EFI_SUCCESS The UDP port is successfully configured for the
+ session to unicast receive.
+
+**/
+EFI_STATUS
+Mtftp4ConfigUnicastPort (
+ IN UDP_IO *UdpIo,
+ IN MTFTP4_PROTOCOL *Instance
+ )
+{
+ EFI_MTFTP4_CONFIG_DATA *Config;
+ EFI_UDP4_CONFIG_DATA UdpConfig;
+ EFI_STATUS Status;
+ IP4_ADDR Ip;
+
+ Config = &Instance->Config;
+
+ UdpConfig.AcceptBroadcast = FALSE;
+ UdpConfig.AcceptPromiscuous = FALSE;
+ UdpConfig.AcceptAnyPort = FALSE;
+ UdpConfig.AllowDuplicatePort = FALSE;
+ UdpConfig.TypeOfService = 0;
+ UdpConfig.TimeToLive = 64;
+ UdpConfig.DoNotFragment = FALSE;
+ UdpConfig.ReceiveTimeout = 0;
+ UdpConfig.TransmitTimeout = 0;
+ UdpConfig.UseDefaultAddress = Config->UseDefaultSetting;
+ IP4_COPY_ADDRESS (&UdpConfig.StationAddress, &Config->StationIp);
+ IP4_COPY_ADDRESS (&UdpConfig.SubnetMask, &Config->SubnetMask);
+ UdpConfig.StationPort = Config->LocalPort;
+ UdpConfig.RemotePort = 0;
+
+ Ip = HTONL (Instance->ServerIp);
+ IP4_COPY_ADDRESS (&UdpConfig.RemoteAddress, &Ip);
+
+ Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);
+
+ if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {
+ return EFI_SUCCESS;
+ }
+
+ if (!Config->UseDefaultSetting && !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp)) {
+ //
+ // The station IP address is manually configured and the Gateway IP is not 0.
+ // Add the default route for this UDP instance.
+ //
+ Status = UdpIo->Protocol.Udp4->Routes (
+ UdpIo->Protocol.Udp4,
+ FALSE,
+ &mZeroIp4Addr,
+ &mZeroIp4Addr,
+ &Config->GatewayIp
+ );
+ if (EFI_ERROR (Status)) {
+ UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, NULL);
+ }
+ }
+ return Status;
+}
+
+
+/**
+ Start the MTFTP session to do the operation, such as read file,
+ write file, and read directory.
+
+ @param This The MTFTP session
+ @param Token The token than encapsules the user's request.
+ @param Operation The operation to do
+
+ @retval EFI_INVALID_PARAMETER Some of the parameters are invalid.
+ @retval EFI_NOT_STARTED The MTFTP session hasn't been configured.
+ @retval EFI_ALREADY_STARTED There is pending operation for the session.
+ @retval EFI_SUCCESS The operation is successfully started.
+
+**/
+EFI_STATUS
+Mtftp4Start (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_TOKEN *Token,
+ IN UINT16 Operation
+ )
+{
+ MTFTP4_PROTOCOL *Instance;
+ EFI_MTFTP4_OVERRIDE_DATA *Override;
+ EFI_MTFTP4_CONFIG_DATA *Config;
+ EFI_TPL OldTpl;
+ EFI_STATUS Status;
+ EFI_STATUS TokenStatus;
+
+ //
+ // Validate the parameters
+ //
+ if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||
+ ((Token->OptionCount != 0) && (Token->OptionList == NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // User must provide at least one method to collect the data for download.
+ //
+ if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&
+ ((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ //
+ // User must provide at least one method to provide the data for upload.
+ //
+ if ((Operation == EFI_MTFTP4_OPCODE_WRQ) &&
+ ((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
+
+ Status = EFI_SUCCESS;
+ TokenStatus = EFI_SUCCESS;
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if (Instance->State != MTFTP4_STATE_CONFIGED) {
+ Status = EFI_NOT_STARTED;
+ }
+
+ if (Instance->Operation != 0) {
+ Status = EFI_ACCESS_DENIED;
+ }
+
+ if ((Token->OverrideData != NULL) && !Mtftp4OverrideValid (Instance, Token->OverrideData)) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+
+ if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL (OldTpl);
+ return Status;
+ }
+
+ //
+ // Set the Operation now to prevent the application start other
+ // operations.
+ //
+ Instance->Operation = Operation;
+ Override = Token->OverrideData;
+
+ if (Token->OptionCount != 0) {
+ Status = Mtftp4ParseOption (
+ Token->OptionList,
+ Token->OptionCount,
+ TRUE,
+ Instance->Operation,
+ &Instance->RequestOption
+ );
+
+ if (EFI_ERROR (Status)) {
+ TokenStatus = EFI_DEVICE_ERROR;
+ goto ON_ERROR;
+ }
+ }
+
+ //
+ // Set the operation parameters from the configuration or override data.
+ //
+ Config = &Instance->Config;
+ Instance->Token = Token;
+ Instance->BlkSize = MTFTP4_DEFAULT_BLKSIZE;
+ Instance->WindowSize = MTFTP4_DEFAULT_WINDOWSIZE;
+
+ CopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));
+ Instance->ServerIp = NTOHL (Instance->ServerIp);
+
+ Instance->ListeningPort = Config->InitialServerPort;
+ Instance->ConnectedPort = 0;
+
+ CopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));
+ Instance->Gateway = NTOHL (Instance->Gateway);
+
+ Instance->MaxRetry = Config->TryCount;
+ Instance->Timeout = Config->TimeoutValue;
+ Instance->Master = TRUE;
+
+ if (Override != NULL) {
+ CopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));
+ CopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
+
+ Instance->ServerIp = NTOHL (Instance->ServerIp);
+ Instance->Gateway = NTOHL (Instance->Gateway);
+
+ Instance->ListeningPort = Override->ServerPort;
+ Instance->MaxRetry = Override->TryCount;
+ Instance->Timeout = Override->TimeoutValue;
+ }
+
+ if (Instance->ListeningPort == 0) {
+ Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;
+ }
+
+ if (Instance->MaxRetry == 0) {
+ Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;
+ }
+
+ if (Instance->Timeout == 0) {
+ Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;
+ }
+
+ //
+ // Config the unicast UDP child to send initial request
+ //
+ Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);
+ if (EFI_ERROR (Status)) {
+ TokenStatus = EFI_DEVICE_ERROR;
+ goto ON_ERROR;
+ }
+
+ //
+ // Set initial status.
+ //
+ Token->Status = EFI_NOT_READY;
+
+ //
+ // Build and send an initial requests
+ //
+ if (Operation == EFI_MTFTP4_OPCODE_WRQ) {
+ Status = Mtftp4WrqStart (Instance, Operation);
+ } else {
+ Status = Mtftp4RrqStart (Instance, Operation);
+ }
+
+ if (EFI_ERROR (Status)) {
+ TokenStatus = EFI_DEVICE_ERROR;
+ goto ON_ERROR;
+ }
+
+ gBS->RestoreTPL(OldTpl);
+
+ if (Token->Event != NULL) {
+ return EFI_SUCCESS;
+ }
+
+ //
+ // Return immediately for asynchronous operation or poll the
+ // instance for synchronous operation.
+ //
+ while (Token->Status == EFI_NOT_READY) {
+ This->Poll (This);
+ }
+
+ return Token->Status;
+
+ON_ERROR:
+ Mtftp4CleanOperation (Instance, TokenStatus);
+ gBS->RestoreTPL (OldTpl);
+
+ return Status;
+}
+
+
+/**
+ Reads the current operational settings.
+
+ The GetModeData()function reads the current operational settings of this
+ EFI MTFTPv4 Protocol driver instance.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance.
+ @param ModeData Pointer to storage for the EFI MTFTPv4 Protocol
+ driver mode data.
+
+ @retval EFI_SUCCESS The configuration data was successfully returned.
+ @retval EFI_OUT_OF_RESOURCES The required mode data could not be allocated.
+ @retval EFI_INVALID_PARAMETER This is NULL or ModeData is NULL.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4GetModeData (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ OUT EFI_MTFTP4_MODE_DATA *ModeData
+ )
+{
+ MTFTP4_PROTOCOL *Instance;
+ EFI_TPL OldTpl;
+
+ if ((This == NULL) || (ModeData == NULL)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
+ CopyMem(&ModeData->ConfigData, &Instance->Config, sizeof (Instance->Config));
+ ModeData->SupportedOptionCount = MTFTP4_SUPPORTED_OPTIONS;
+ ModeData->SupportedOptoins = (UINT8 **) mMtftp4SupportedOptions;
+ ModeData->UnsupportedOptionCount = 0;
+ ModeData->UnsupportedOptoins = NULL;
+
+ gBS->RestoreTPL (OldTpl);
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Initializes, changes, or resets the default operational setting for this
+ EFI MTFTPv4 Protocol driver instance.
+
+ The Configure() function is used to set and change the configuration data for
+ this EFI MTFTPv4 Protocol driver instance. The configuration data can be reset
+ to startup defaults by calling Configure() with MtftpConfigData set to NULL.
+ Whenever the instance is reset, any pending operation is aborted. By changing
+ the EFI MTFTPv4 Protocol driver instance configuration data, the client can
+ connect to different MTFTPv4 servers. The configuration parameters in
+ MtftpConfigData are used as the default parameters in later MTFTPv4 operations
+ and can be overridden in later operations.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance
+ @param ConfigData MtftpConfigDataPointer to the configuration data
+ structure
+
+ @retval EFI_SUCCESS The EFI MTFTPv4 Protocol driver was configured
+ successfully.
+ @retval EFI_INVALID_PARAMETER One or more following conditions are TRUE:
+ 1.This is NULL.
+ 2.MtftpConfigData.UseDefaultSetting is FALSE and
+ MtftpConfigData.StationIp is not a valid IPv4
+ unicast address.
+ 3.MtftpConfigData.UseDefaultSetting is FALSE and
+ MtftpConfigData.SubnetMask is invalid.
+ 4.MtftpConfigData.ServerIp is not a valid IPv4
+ unicast address.
+ 5.MtftpConfigData.UseDefaultSetting is FALSE and
+ MtftpConfigData.GatewayIp is not a valid IPv4
+ unicast address or is not in the same subnet
+ with station address.
+ @retval EFI_ACCESS_DENIED The EFI configuration could not be changed at this
+ time because there is one MTFTP background operation
+ in progress.
+ @retval EFI_NO_MAPPING When using a default address, configuration
+ (DHCP, BOOTP, RARP, etc.) has not finished yet.
+ @retval EFI_UNSUPPORTED A configuration protocol (DHCP, BOOTP, RARP, etc.)
+ could not be located when clients choose to use
+ the default address settings.
+ @retval EFI_OUT_OF_RESOURCES The EFI MTFTPv4 Protocol driver instance data could
+ not be allocated.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ The EFI MTFTPv4 Protocol driver instance is not
+ configured.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4Configure (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_CONFIG_DATA *ConfigData
+ )
+{
+ MTFTP4_PROTOCOL *Instance;
+ EFI_TPL OldTpl;
+ IP4_ADDR Ip;
+ IP4_ADDR Netmask;
+ IP4_ADDR Gateway;
+ IP4_ADDR ServerIp;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
+
+ if (ConfigData == NULL) {
+ //
+ // Reset the operation if ConfigData is NULL
+ //
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ Mtftp4CleanOperation (Instance, EFI_ABORTED);
+ ZeroMem (&Instance->Config, sizeof (EFI_MTFTP4_CONFIG_DATA));
+ Instance->State = MTFTP4_STATE_UNCONFIGED;
+
+ gBS->RestoreTPL (OldTpl);
+
+ } else {
+ //
+ // Configure the parameters for new operation.
+ //
+ CopyMem (&Ip, &ConfigData->StationIp, sizeof (IP4_ADDR));
+ CopyMem (&Netmask, &ConfigData->SubnetMask, sizeof (IP4_ADDR));
+ CopyMem (&Gateway, &ConfigData->GatewayIp, sizeof (IP4_ADDR));
+ CopyMem (&ServerIp, &ConfigData->ServerIp, sizeof (IP4_ADDR));
+
+ Ip = NTOHL (Ip);
+ Netmask = NTOHL (Netmask);
+ Gateway = NTOHL (Gateway);
+ ServerIp = NTOHL (ServerIp);
+
+ if (ServerIp == 0 || IP4_IS_LOCAL_BROADCAST (ServerIp)) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (!ConfigData->UseDefaultSetting &&
+ ((!IP4_IS_VALID_NETMASK (Netmask) || (Netmask != 0 && !NetIp4IsUnicast (Ip, Netmask))))) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Gateway != 0) &&
+ ((Netmask != 0xFFFFFFFF && !IP4_NET_EQUAL (Gateway, Ip, Netmask)) || (Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)))) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
+
+ if ((Instance->State == MTFTP4_STATE_CONFIGED) && (Instance->Operation != 0)) {
+ gBS->RestoreTPL (OldTpl);
+ return EFI_ACCESS_DENIED;
+ }
+
+ CopyMem(&Instance->Config, ConfigData, sizeof (*ConfigData));;
+ Instance->State = MTFTP4_STATE_CONFIGED;
+
+ gBS->RestoreTPL (OldTpl);
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+
+/**
+ Parses the options in an MTFTPv4 OACK packet.
+
+ The ParseOptions() function parses the option fields in an MTFTPv4 OACK packet
+ and returns the number of options that were found and optionally a list of
+ pointers to the options in the packet.
+ If one or more of the option fields are not valid, then EFI_PROTOCOL_ERROR is
+ returned and *OptionCount and *OptionList stop at the last valid option.
+ The OptionList is allocated by this function, and caller should free it when used.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance.
+ @param PacketLen Length of the OACK packet to be parsed.
+ @param Packet Pointer to the OACK packet to be parsed.
+ @param OptionCount Pointer to the number of options in following OptionList.
+ @param OptionList Pointer to EFI_MTFTP4_OPTION storage. Call the
+ EFI Boot Service FreePool() to release theOptionList
+ if the options in this OptionList are not needed
+ any more
+
+ @retval EFI_SUCCESS The OACK packet was valid and the OptionCount and
+ OptionList parameters have been updated.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ 1.PacketLen is 0.
+ 2.Packet is NULL or Packet is not a valid MTFTPv4 packet.
+ 3.OptionCount is NULL.
+ @retval EFI_NOT_FOUND No options were found in the OACK packet.
+ @retval EFI_OUT_OF_RESOURCES Storage for the OptionList array cannot be allocated.
+ @retval EFI_PROTOCOL_ERROR One or more of the option fields is invalid.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4ParseOptions (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN UINT32 PacketLen,
+ IN EFI_MTFTP4_PACKET *Packet,
+ OUT UINT32 *OptionCount,
+ OUT EFI_MTFTP4_OPTION **OptionList OPTIONAL
+ )
+{
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||
+ (Packet == NULL) || (OptionCount == NULL)) {
+
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);
+
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ if (*OptionCount == 0) {
+ return EFI_NOT_FOUND;
+ }
+
+ return EFI_SUCCESS;
+}
+
+
+/**
+ Downloads a file from an MTFTPv4 server.
+
+ The ReadFile() function is used to initialize and start an MTFTPv4 download
+ process and optionally wait for completion. When the download operation completes,
+ whether successfully or not, the Token.Status field is updated by the EFI MTFTPv4
+ Protocol driver and then Token.Event is signaled (if it is not NULL).
+ Data can be downloaded from the MTFTPv4 server into either of the following locations:
+ 1.A fixed buffer that is pointed to by Token.Buffer
+ 2.A download service function that is pointed to by Token.CheckPacket
+ If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
+ will be called first. If the call is successful, the packet will be stored in
+ Token.Buffer.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance
+ @param Token Pointer to the token structure to provide the
+ parameters that are used in this operation.
+
+ @retval EFI_SUCCESS The data file has been transferred successfully.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_BUFFER_TOO_SMALL BufferSize is not large enough to hold the downloaded
+ data in downloading process.
+ @retval EFI_ABORTED Current operation is aborted by user.
+ @retval EFI_ICMP_ERROR An ICMP ERROR packet was received.
+ @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server.
+ @retval EFI_TFTP_ERROR An MTFTPv4 ERROR packet was received.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+ @retval EFI_NO_MEDIA There was a media error.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4ReadFile (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_TOKEN *Token
+ )
+{
+ return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);
+}
+
+
+/**
+ Sends a data file to an MTFTPv4 server. May be unsupported in some EFI implementations
+
+ The WriteFile() function is used to initialize an uploading operation with the
+ given option list and optionally wait for completion. If one or more of the
+ options is not supported by the server, the unsupported options are ignored and
+ a standard TFTP process starts instead. When the upload process completes,
+ whether successfully or not, Token.Event is signaled, and the EFI MTFTPv4 Protocol
+ driver updates Token.Status.
+ The caller can supply the data to be uploaded in the following two modes:
+ 1.Through the user-provided buffer
+ 2.Through a callback function
+ With the user-provided buffer, the Token.BufferSize field indicates the length
+ of the buffer, and the driver will upload the data in the buffer. With an
+ EFI_MTFTP4_PACKET_NEEDED callback function, the driver will call this callback
+ function to get more data from the user to upload. See the definition of
+ EFI_MTFTP4_PACKET_NEEDED for more information. These two modes cannot be used at
+ the same time. The callback function will be ignored if the user provides the buffer.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance.
+ @param Token Pointer to the token structure to provide the
+ parameters that are used in this function
+
+ @retval EFI_SUCCESS The upload session has started.
+ @retval EFI_UNSUPPORTED The operation is not supported by this implementation.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ 1. This is NULL.
+ 2. Token is NULL.
+ 3. Token.Filename is NULL.
+ 4. Token.OptionCount is not zero and
+ Token.OptionList is NULL.
+ 5. One or more options in Token.OptionList have wrong
+ format.
+ 6. Token.Buffer and Token.PacketNeeded are both
+ NULL.
+ 7. One or more IPv4 addresses in Token.OverrideData
+ are not valid unicast IPv4 addresses if
+ Token.OverrideData is not NULL.
+ @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are in the
+ unsupported list of structure EFI_MTFTP4_MODE_DATA.
+ @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started.
+ @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
+ BOOTP, RARP, etc.) is not finished yet.
+ @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv4
+ session.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ACCESS_DENIED The previous operation has not completed yet.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4WriteFile (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_TOKEN *Token
+ )
+{
+ return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);
+}
+
+
+/**
+ Downloads a data file "directory" from an MTFTPv4 server.
+ May be unsupported in some EFI implementations
+
+ The ReadDirectory() function is used to return a list of files on the MTFTPv4
+ server that are logically (or operationally) related to Token.Filename. The
+ directory request packet that is sent to the server is built with the option
+ list that was provided by caller, if present.
+ The file information that the server returns is put into either of the following
+ locations:
+ 1.A fixed buffer that is pointed to by Token.Buffer
+ 2.A download service function that is pointed to by Token.CheckPacket
+ If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket will
+ be called first. If the call is successful, the packet will be stored in Token.Buffer.
+ The returned directory listing in the Token.Buffer or EFI_MTFTP4_PACKET consists
+ of a list of two or three variable-length ASCII strings, each terminated by a
+ null character, for each file in the directory. If the multicast option is involved,
+ the first field of each directory entry is the static multicast IP address and
+ UDP port number that is associated with the file name. The format of the field
+ is ip:ip:ip:ip:port. If the multicast option is not involved, this field and its
+ terminating null character are not present.
+ The next field of each directory entry is the file name and the last field is
+ the file information string. The information string contains the file size and
+ the create/modify timestamp. The format of the information string is filesize
+ yyyy-mm-dd hh:mm:ss:ffff. The timestamp is Coordinated Universal Time
+ (UTC; also known as Greenwich Mean Time [GMT]).
+ The only difference between ReadFile and ReadDirectory is the opcode used.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance
+ @param Token Pointer to the token structure to provide the
+ parameters that are used in this function
+
+ @retval EFI_SUCCESS The MTFTPv4 related file "directory" has been downloaded.
+ @retval EFI_UNSUPPORTED The operation is not supported by this implementation.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ 1. This is NULL.
+ 2. Token is NULL.
+ 3. Token.Filename is NULL.
+ 4. Token.OptionCount is not zero and
+ Token.OptionList is NULL.
+ 5. One or more options in Token.OptionList have wrong
+ format.
+ 6. Token.Buffer and Token.PacketNeeded are both
+ NULL.
+ 7. One or more IPv4 addresses in Token.OverrideData
+ are not valid unicast IPv4 addresses if
+ Token.OverrideData is not NULL.
+ @retval EFI_UNSUPPORTED One or more options in the Token.OptionList are in the
+ unsupported list of structure EFI_MTFTP4_MODE_DATA.
+ @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started.
+ @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
+ BOOTP, RARP, etc.) is not finished yet.
+ @retval EFI_ALREADY_STARTED This Token is already being used in another MTFTPv4
+ session.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_ACCESS_DENIED The previous operation has not completed yet.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4ReadDirectory (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_TOKEN *Token
+ )
+{
+ return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);
+}
+
+
+/**
+ Gets information about a file from an MTFTPv4 server.
+
+ The GetInfo() function assembles an MTFTPv4 request packet with options;
+ sends it to the MTFTPv4 server; and may return an MTFTPv4 OACK, MTFTPv4 ERROR,
+ or ICMP ERROR packet. Retries occur only if no response packets are received
+ from the MTFTPv4 server before the timeout expires.
+ It is implemented with EfiMtftp4ReadFile: build a token, then pass it to
+ EfiMtftp4ReadFile. In its check packet callback abort the operations.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance
+ @param OverrideData Data that is used to override the existing
+ parameters. If NULL, the default parameters that
+ were set in the EFI_MTFTP4_PROTOCOL.Configure()
+ function are used
+ @param Filename Pointer to null-terminated ASCII file name string
+ @param ModeStr Pointer to null-terminated ASCII mode string. If NULL, "octet"
+ will be used
+ @param OptionCount Number of option/value string pairs in OptionList
+ @param OptionList Pointer to array of option/value string pairs.
+ Ignored if OptionCount is zero
+ @param PacketLength The number of bytes in the returned packet
+ @param Packet PacketThe pointer to the received packet. This
+ buffer must be freed by the caller.
+
+ @retval EFI_SUCCESS An MTFTPv4 OACK packet was received and is in
+ the Buffer.
+ @retval EFI_INVALID_PARAMETER One or more of the following conditions is TRUE:
+ 1.This is NULL.
+ 2.Filename is NULL.
+ 3.OptionCount is not zero and OptionList is NULL.
+ 4.One or more options in OptionList have wrong format.
+ 5.PacketLength is NULL.
+ 6.One or more IPv4 addresses in OverrideData are
+ not valid unicast IPv4 addresses if OverrideData
+ is not NULL.
+ @retval EFI_UNSUPPORTED One or more options in the OptionList are in the
+ unsupported list of structure EFI_MTFTP4_MODE_DATA
+ @retval EFI_NOT_STARTED The EFI MTFTPv4 Protocol driver has not been started.
+ @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
+ BOOTP, RARP, etc.) has not finished yet.
+ @retval EFI_ACCESS_DENIED The previous operation has not completed yet.
+ @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
+ @retval EFI_TFTP_ERROR An MTFTPv4 ERROR packet was received and is in
+ the Buffer.
+ @retval EFI_ICMP_ERROR An ICMP ERROR packet was received and the Packet
+ is set to NULL.
+ @retval EFI_PROTOCOL_ERROR An unexpected MTFTPv4 packet was received and is
+ in the Buffer.
+ @retval EFI_TIMEOUT No responses were received from the MTFTPv4 server.
+ @retval EFI_DEVICE_ERROR An unexpected network error or system error occurred.
+ @retval EFI_NO_MEDIA There was a media error.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4GetInfo (
+ IN EFI_MTFTP4_PROTOCOL *This,
+ IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData OPTIONAL,
+ IN UINT8 *Filename,
+ IN UINT8 *ModeStr OPTIONAL,
+ IN UINT8 OptionCount,
+ IN EFI_MTFTP4_OPTION *OptionList OPTIONAL,
+ OUT UINT32 *PacketLength,
+ OUT EFI_MTFTP4_PACKET **Packet OPTIONAL
+ )
+{
+ EFI_MTFTP4_TOKEN Token;
+ MTFTP4_GETINFO_STATE State;
+ EFI_STATUS Status;
+
+ if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||
+ ((OptionCount != 0) && (OptionList == NULL))) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if (Packet != NULL) {
+ *Packet = NULL;
+ }
+
+ *PacketLength = 0;
+ State.Packet = Packet;
+ State.PacketLen = PacketLength;
+ State.Status = EFI_SUCCESS;
+
+ //
+ // Fill in the Token to issue an synchronous ReadFile operation
+ //
+ Token.Status = EFI_SUCCESS;
+ Token.Event = NULL;
+ Token.OverrideData = OverrideData;
+ Token.Filename = Filename;
+ Token.ModeStr = ModeStr;
+ Token.OptionCount = OptionCount;
+ Token.OptionList = OptionList;
+ Token.BufferSize = 0;
+ Token.Buffer = NULL;
+ Token.Context = &State;
+ Token.CheckPacket = Mtftp4GetInfoCheckPacket;
+ Token.TimeoutCallback = NULL;
+ Token.PacketNeeded = NULL;
+
+ Status = EfiMtftp4ReadFile (This, &Token);
+
+ if (EFI_ABORTED == Status) {
+ return State.Status;
+ }
+
+ return Status;
+}
+
+/**
+ Polls for incoming data packets and processes outgoing data packets.
+
+ The Poll() function can be used by network drivers and applications to increase
+ the rate that data packets are moved between the communications device and the
+ transmit and receive queues.
+ In some systems, the periodic timer event in the managed network driver may not
+ poll the underlying communications device fast enough to transmit and/or receive
+ all data packets without missing incoming packets or dropping outgoing packets.
+ Drivers and applications that are experiencing packet loss should try calling
+ the Poll() function more often.
+
+ @param This Pointer to the EFI_MTFTP4_PROTOCOL instance
+
+ @retval EFI_SUCCESS Incoming or outgoing data was processed.
+ @retval EFI_NOT_STARTED This EFI MTFTPv4 Protocol instance has not been started.
+ @retval EFI_NO_MAPPING When using a default address, configuration (DHCP,
+ BOOTP, RARP, etc.) is not finished yet.
+ @retval EFI_INVALID_PARAMETER This is NULL.
+ @retval EFI_DEVICE_ERROR An unexpected system or network error occurred.
+ @retval EFI_TIMEOUT Data was dropped out of the transmit and/or receive
+ queue. Consider increasing the polling rate.
+
+**/
+EFI_STATUS
+EFIAPI
+EfiMtftp4Poll (
+ IN EFI_MTFTP4_PROTOCOL *This
+ )
+{
+ MTFTP4_PROTOCOL *Instance;
+ EFI_UDP4_PROTOCOL *Udp;
+ EFI_STATUS Status;
+
+ if (This == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
+
+ if (Instance->State == MTFTP4_STATE_UNCONFIGED) {
+ return EFI_NOT_STARTED;
+ } else if (Instance->State == MTFTP4_STATE_DESTROY) {
+ return EFI_DEVICE_ERROR;
+ }
+
+ Udp = Instance->UnicastPort->Protocol.Udp4;
+ Status = Udp->Poll (Udp);
+ Mtftp4OnTimerTick (NULL, Instance->Service);
+ return Status;
+}
+
+EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {
+ EfiMtftp4GetModeData,
+ EfiMtftp4Configure,
+ EfiMtftp4GetInfo,
+ EfiMtftp4ParseOptions,
+ EfiMtftp4ReadFile,
+ EfiMtftp4WriteFile,
+ EfiMtftp4ReadDirectory,
+ EfiMtftp4Poll
+};