]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/Network/Mtftp4Dxe/Mtftp4Impl.c
BaseTools:Change the path of the file that Binary Cache
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Mtftp4Dxe / Mtftp4Impl.c
index 3ce879253751426fc25531595a08e076c33112f5..70bd693e4e3a6f172a543421a850e10cf5bebd1d 100644 (file)
@@ -1,74 +1,14 @@
 /** @file\r
+  Interface routine for Mtftp4.\r
 \r
-Copyright (c) 2006 - 2007, Intel Corporation\r
-All rights reserved. This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
-\r
-Module Name:\r
-\r
-  Mtftp4Impl.c\r
-\r
-Abstract:\r
-\r
-  Interface routine for Mtftp4\r
-\r
-\r
-**/\r
-\r
-#include "Mtftp4Impl.h"\r
-\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-EfiMtftp4ReadFile (\r
-  IN EFI_MTFTP4_PROTOCOL    *This,\r
-  IN EFI_MTFTP4_TOKEN       *Token\r
-  );\r
-\r
-\r
-/**\r
-  Get the current operation parameter for the MTFTP session\r
-\r
-  @param  This                   The MTFTP protocol instance\r
-  @param  ModeData               The MTFTP mode data\r
-\r
-  @retval EFI_INVALID_PARAMETER  This or ModeData is NULL\r
-  @retval EFI_SUCCESS            The operation parameter is saved in ModeData\r
+(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>\r
+Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-EfiMtftp4GetModeData (\r
-  IN EFI_MTFTP4_PROTOCOL    *This,\r
-  OUT EFI_MTFTP4_MODE_DATA  *ModeData\r
-  )\r
-{\r
-  MTFTP4_PROTOCOL  *Instance;\r
-  EFI_TPL          OldTpl;\r
-\r
-  if ((This == NULL) || (ModeData == NULL)) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
-\r
-  Instance                         = MTFTP4_PROTOCOL_FROM_THIS (This);\r
-  CopyMem(&ModeData->ConfigData, &Instance->Config, sizeof (Instance->Config));\r
-  ModeData->SupportedOptionCount   = MTFTP4_SUPPORTED_OPTIONS;\r
-  ModeData->SupportedOptoins       = (UINT8 **) mMtftp4SupportedOptions;\r
-  ModeData->UnsupportedOptionCount = 0;\r
-  ModeData->UnsupportedOptoins     = NULL;\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
 \r
-  return EFI_SUCCESS;\r
-}\r
+#include "Mtftp4Impl.h"\r
 \r
 \r
 /**\r
@@ -77,18 +17,15 @@ EfiMtftp4GetModeData (
   @param  Instance               The MTFTP session to clean up\r
   @param  Result                 The result to return to the caller who initiated\r
                                  the operation.\r
-\r
-  @return None\r
-\r
 **/\r
 VOID\r
 Mtftp4CleanOperation (\r
-  IN MTFTP4_PROTOCOL        *Instance,\r
-  IN EFI_STATUS             Result\r
+  IN OUT MTFTP4_PROTOCOL        *Instance,\r
+  IN     EFI_STATUS             Result\r
   )\r
 {\r
-  NET_LIST_ENTRY            *Entry;\r
-  NET_LIST_ENTRY            *Next;\r
+  LIST_ENTRY                *Entry;\r
+  LIST_ENTRY                *Next;\r
   MTFTP4_BLOCK_RANGE        *Block;\r
   EFI_MTFTP4_TOKEN          *Token;\r
 \r
@@ -108,7 +45,7 @@ Mtftp4CleanOperation (
   }\r
 \r
   ASSERT (Instance->UnicastPort != NULL);\r
-  UdpIoCleanPort (Instance->UnicastPort);\r
+  UdpIoCleanIo (Instance->UnicastPort);\r
 \r
   if (Instance->LastPacket != NULL) {\r
     NetbufFree (Instance->LastPacket);\r
@@ -116,21 +53,30 @@ Mtftp4CleanOperation (
   }\r
 \r
   if (Instance->McastUdpPort != NULL) {\r
-    UdpIoFreePort (Instance->McastUdpPort);\r
+    gBS->CloseProtocol (\r
+           Instance->McastUdpPort->UdpHandle,\r
+           &gEfiUdp4ProtocolGuid,\r
+           gMtftp4DriverBinding.DriverBindingHandle,\r
+           Instance->Handle\r
+           );\r
+    UdpIoFreeIo (Instance->McastUdpPort);\r
     Instance->McastUdpPort = NULL;\r
   }\r
 \r
   NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->Blocks) {\r
     Block = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);\r
-    NetListRemoveEntry (Entry);\r
-    NetFreePool (Block);\r
+    RemoveEntryList (Entry);\r
+    FreePool (Block);\r
   }\r
 \r
-  NetZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));\r
+  ZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));\r
 \r
   Instance->Operation     = 0;\r
 \r
   Instance->BlkSize       = MTFTP4_DEFAULT_BLKSIZE;\r
+  Instance->WindowSize    = 1;\r
+  Instance->TotalBlock    = 0;\r
+  Instance->AckedBlock    = 0;\r
   Instance->LastBlock     = 0;\r
   Instance->ServerIp      = 0;\r
   Instance->ListeningPort = 0;\r
@@ -147,101 +93,10 @@ Mtftp4CleanOperation (
 \r
 \r
 /**\r
-  Configure the MTFTP session for new operation or reset the current\r
-  operation if ConfigData is NULL.\r
-\r
-  @param  This                   The MTFTP session to configure\r
-  @param  ConfigData             The configure parameters\r
-\r
-  @retval EFI_INVALID_PARAMETER  Some of the parameter is invalid.\r
-  @retval EFI_ACCESS_DENIED      There is pending operation\r
-  @retval EFI_SUCCESS            The instance is configured for operation.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-EfiMtftp4Configure (\r
-  IN EFI_MTFTP4_PROTOCOL    *This,\r
-  IN EFI_MTFTP4_CONFIG_DATA *ConfigData\r
-  )\r
-{\r
-  MTFTP4_PROTOCOL           *Instance;\r
-  EFI_TPL                   OldTpl;\r
-  IP4_ADDR                  Ip;\r
-  IP4_ADDR                  Netmask;\r
-  IP4_ADDR                  Gateway;\r
-  IP4_ADDR                  ServerIp;\r
-\r
-  if (This == NULL) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
-\r
-  if (ConfigData == NULL) {\r
-    //\r
-    // Reset the operation if ConfigData is NULL\r
-    //\r
-    OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
-\r
-    Mtftp4CleanOperation (Instance, EFI_ABORTED);\r
-    NetZeroMem (&Instance->Config, sizeof (EFI_MTFTP4_CONFIG_DATA));\r
-    Instance->State = MTFTP4_STATE_UNCONFIGED;\r
-\r
-    NET_RESTORE_TPL (OldTpl);\r
-\r
-  } else {\r
-    //\r
-    // Configure the parameters for new operation.\r
-    //\r
-    NetCopyMem (&Ip, &ConfigData->StationIp, sizeof (IP4_ADDR));\r
-    NetCopyMem (&Netmask, &ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
-    NetCopyMem (&Gateway, &ConfigData->GatewayIp, sizeof (IP4_ADDR));\r
-    NetCopyMem (&ServerIp, &ConfigData->ServerIp, sizeof (IP4_ADDR));\r
-\r
-    Ip       = NTOHL (Ip);\r
-    Netmask  = NTOHL (Netmask);\r
-    Gateway  = NTOHL (Gateway);\r
-    ServerIp = NTOHL (ServerIp);\r
-\r
-    if (!Ip4IsUnicast (ServerIp, 0)) {\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    if (!ConfigData->UseDefaultSetting &&\r
-       ((!IP4_IS_VALID_NETMASK (Netmask) || !Ip4IsUnicast (Ip, Netmask)))) {\r
-\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    if ((Gateway != 0) &&\r
-       (!IP4_NET_EQUAL (Gateway, Ip, Netmask) || !Ip4IsUnicast (Gateway, Netmask))) {\r
-\r
-      return EFI_INVALID_PARAMETER;\r
-    }\r
-\r
-    OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  Check packet for GetInfo.\r
 \r
-    if ((Instance->State == MTFTP4_STATE_CONFIGED) && (Instance->Operation != 0)) {\r
-      NET_RESTORE_TPL (OldTpl);\r
-      return EFI_ACCESS_DENIED;\r
-    }\r
-\r
-    CopyMem(&Instance->Config, ConfigData, sizeof (*ConfigData));;\r
-    Instance->State = MTFTP4_STATE_CONFIGED;\r
-\r
-    NET_RESTORE_TPL (OldTpl);\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Check packet for GetInfo. GetInfo is implemented with EfiMtftp4ReadFile.\r
-  It use Mtftp4GetInfoCheckPacket to inspect the first packet from server,\r
-  then abort the session.\r
+  GetInfo is implemented with EfiMtftp4ReadFile. It use Mtftp4GetInfoCheckPacket\r
+  to inspect the first packet from server, then abort the session.\r
 \r
   @param  This                   The MTFTP4 protocol instance\r
   @param  Token                  The user's token\r
@@ -251,8 +106,8 @@ EfiMtftp4Configure (
   @retval EFI_ABORTED            Abort the ReadFile operation and return.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
+EFIAPI\r
 Mtftp4GetInfoCheckPacket (\r
   IN EFI_MTFTP4_PROTOCOL    *This,\r
   IN EFI_MTFTP4_TOKEN       *Token,\r
@@ -260,13 +115,12 @@ Mtftp4GetInfoCheckPacket (
   IN EFI_MTFTP4_PACKET      *Packet\r
   )\r
 {\r
-  MTFTP4_PROTOCOL           *Instance;\r
   MTFTP4_GETINFO_STATE      *State;\r
   EFI_STATUS                Status;\r
   UINT16                    OpCode;\r
+  EFI_MTFTP4_ERROR_HEADER  *ErrorHeader;\r
 \r
-  Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
-  State    = &Instance->GetInfoState;\r
+  State   = (MTFTP4_GETINFO_STATE *) Token->Context;\r
   OpCode   = NTOHS (Packet->OpCode);\r
 \r
   //\r
@@ -274,6 +128,12 @@ Mtftp4GetInfoCheckPacket (
   //\r
   switch (OpCode) {\r
   case EFI_MTFTP4_OPCODE_ERROR:\r
+    ErrorHeader = (EFI_MTFTP4_ERROR_HEADER *) Packet;\r
+    if (ErrorHeader->ErrorCode == EFI_MTFTP4_ERRORCODE_FILE_NOT_FOUND) {\r
+      DEBUG ((EFI_D_ERROR, "TFTP error code 1 (File Not Found)\n"));\r
+    } else {\r
+      DEBUG ((EFI_D_ERROR, "TFTP error code %d\n", ErrorHeader->ErrorCode));\r
+    }\r
     State->Status = EFI_TFTP_ERROR;\r
     break;\r
 \r
@@ -287,7 +147,7 @@ Mtftp4GetInfoCheckPacket (
 \r
   //\r
   // Allocate buffer then copy the packet over. Use gBS->AllocatePool\r
-  // in case NetAllocatePool will implements something tricky.\r
+  // in case AllocatePool will implements something tricky.\r
   //\r
   Status = gBS->AllocatePool (EfiBootServicesData, PacketLen, (VOID **) State->Packet);\r
 \r
@@ -297,154 +157,26 @@ Mtftp4GetInfoCheckPacket (
   }\r
 \r
   *(State->PacketLen) = PacketLen;\r
-  NetCopyMem (*(State->Packet), Packet, PacketLen);\r
+  CopyMem (*(State->Packet), Packet, PacketLen);\r
 \r
   return EFI_ABORTED;\r
 }\r
 \r
 \r
 /**\r
-  Get the information of the download from the server. It is implemented\r
-  with EfiMtftp4ReadFile: build a token, then pass it to EfiMtftp4ReadFile.\r
-  In its check packet callback abort the opertions.\r
-\r
-  @param  This                   The MTFTP protocol instance\r
-  @param  OverrideData           The MTFTP override data\r
-  @param  Filename               The file to get information\r
-  @param  ModeStr                The mode to use\r
-  @param  OptionCount            The number of options to append\r
-  @param  OptionList             The options to append\r
-  @param  PacketLength           The variable to receive the packet length\r
-  @param  Packet                 The variable to receive the packet.\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameter is invaid\r
-  @retval EFI_SUCCESS            The information is got\r
-  @retval Others                 Failed to get the information.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-EfiMtftp4GetInfo (\r
-  IN EFI_MTFTP4_PROTOCOL      *This,\r
-  IN EFI_MTFTP4_OVERRIDE_DATA *OverrideData,        OPTIONAL\r
-  IN UINT8                    *Filename,\r
-  IN UINT8                    *ModeStr,             OPTIONAL\r
-  IN UINT8                    OptionCount,\r
-  IN EFI_MTFTP4_OPTION        *OptionList,\r
-  OUT UINT32                  *PacketLength,\r
-  OUT EFI_MTFTP4_PACKET       **Packet OPTIONAL\r
-  )\r
-{\r
-  EFI_MTFTP4_TOKEN          Token;\r
-  MTFTP4_PROTOCOL           *Instance;\r
-  MTFTP4_GETINFO_STATE      *State;\r
-  EFI_STATUS                Status;\r
+  Check whether the override data is valid.\r
 \r
-  if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||\r
-      (OptionCount && (OptionList == NULL))) {\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  if (Packet != NULL) {\r
-    *Packet = NULL;\r
-  }\r
-\r
-  *PacketLength         = 0;\r
-  Instance              = MTFTP4_PROTOCOL_FROM_THIS (This);\r
-  State                 = &Instance->GetInfoState;\r
-  State->Packet          = Packet;\r
-  State->PacketLen       = PacketLength;\r
-  State->Status          = EFI_SUCCESS;\r
-\r
-  //\r
-  // Fill in the Token to issue an synchronous ReadFile operation\r
-  //\r
-  Token.Status          = EFI_SUCCESS;\r
-  Token.Event           = NULL;\r
-  Token.OverrideData    = OverrideData;\r
-  Token.Filename        = Filename;\r
-  Token.ModeStr         = ModeStr;\r
-  Token.OptionCount     = OptionCount;\r
-  Token.OptionList      = OptionList;\r
-  Token.BufferSize      = 0;\r
-  Token.Buffer          = NULL;\r
-  Token.CheckPacket     = Mtftp4GetInfoCheckPacket;\r
-  Token.TimeoutCallback = NULL;\r
-  Token.PacketNeeded    = NULL;\r
-\r
-  Status                = EfiMtftp4ReadFile (This, &Token);\r
-\r
-  if (EFI_ABORTED == Status) {\r
-    return State->Status;\r
-  }\r
-\r
-  return Status;\r
-}\r
-\r
-\r
-/**\r
-  Parse the packet into an array of options. The OptionList is allocated\r
-  by this function, and caller should free it when used.\r
-\r
-  @param  This                   The MTFTP protocol instance\r
-  @param  PacketLen              The length of the packet\r
-  @param  Packet                 The packet to parse\r
-  @param  OptionCount            The size of the OptionList array allocated.\r
-  @param  OptionList             The allocated option array to save the option\r
-                                 addresses.\r
-\r
-  @retval EFI_INVALID_PARAMETER  The parameters are invalid.\r
-  @retval EFI_NOT_FOUND          There is no valid option in the packet\r
-  @retval EFI_SUCCESS            The packet is parsed.\r
-\r
-**/\r
-STATIC\r
-EFI_STATUS\r
-EFIAPI\r
-EfiMtftp4ParseOptions (\r
-  IN EFI_MTFTP4_PROTOCOL    *This,\r
-  IN UINT32                 PacketLen,\r
-  IN EFI_MTFTP4_PACKET      *Packet,\r
-  IN OUT UINT32             *OptionCount,\r
-  OUT EFI_MTFTP4_OPTION     **OptionList          OPTIONAL\r
-  )\r
-{\r
-  EFI_STATUS                Status;\r
-\r
-  if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||\r
-      (Packet == NULL) || (OptionCount == NULL)) {\r
-\r
-    return EFI_INVALID_PARAMETER;\r
-  }\r
-\r
-  Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);\r
-\r
-  if (EFI_ERROR (Status)) {\r
-    return Status;\r
-  }\r
-\r
-  if (*OptionCount == 0) {\r
-    return EFI_NOT_FOUND;\r
-  }\r
-\r
-  return EFI_SUCCESS;\r
-}\r
-\r
-\r
-/**\r
-  Check whether the override data is valid. It will first\r
-  validate whether the server is a valid unicast. If a gateway\r
-  is provided in the Override, it also check that it is a\r
-  unicast on the connected network.\r
+  It will first validate whether the server is a valid unicast. If a gateway\r
+  is provided in the Override, it also check that it is a unicast on the\r
+  connected network.\r
 \r
   @param  Instance               The MTFTP instance\r
   @param  Override               The override data to validate.\r
 \r
-  @return TRUE if the override data is valid, otherwise FALSE.\r
+  @retval TRUE                   The override data is valid\r
+  @retval FALSE                  The override data is invalid\r
 \r
 **/\r
-STATIC\r
 BOOLEAN\r
 Mtftp4OverrideValid (\r
   IN MTFTP4_PROTOCOL          *Instance,\r
@@ -456,24 +188,24 @@ Mtftp4OverrideValid (
   IP4_ADDR                  Netmask;\r
   IP4_ADDR                  Gateway;\r
 \r
-  NetCopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));\r
-  if (!Ip4IsUnicast (NTOHL (Ip), 0)) {\r
+  CopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));\r
+  if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {\r
     return FALSE;\r
   }\r
 \r
   Config = &Instance->Config;\r
 \r
-  NetCopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
+  CopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
   Gateway = NTOHL (Gateway);\r
 \r
   if (!Config->UseDefaultSetting && (Gateway != 0)) {\r
-    NetCopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));\r
-    NetCopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));\r
+    CopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));\r
+    CopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));\r
 \r
     Netmask = NTOHL (Netmask);\r
     Ip      = NTOHL (Ip);\r
 \r
-    if (!Ip4IsUnicast (Gateway, Netmask) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {\r
+    if ((Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {\r
       return FALSE;\r
     }\r
   }\r
@@ -484,22 +216,23 @@ Mtftp4OverrideValid (
 \r
 /**\r
   Poll the UDP to get the IP4 default address, which may be retrieved\r
-  by DHCP. The default time out value is 5 seconds. If IP has retrieved\r
-  the default address, the UDP is reconfigured.\r
+  by DHCP.\r
+\r
+  The default time out value is 5 seconds. If IP has retrieved the default address,\r
+  the UDP is reconfigured.\r
 \r
   @param  Instance               The Mtftp instance\r
-  @param  UdpPort                The UDP port to poll\r
-  @param  UdpCfgData             The UDP configure data to reconfigure the UDP\r
-                                 port.\r
+  @param  UdpIo                  The UDP_IO to poll\r
+  @param  UdpCfgData             The UDP configure data to reconfigure the UDP_IO\r
 \r
-  @return TRUE if the default address is retrieved and UDP is reconfigured.\r
-  @return Otherwise FALSE.\r
+  @retval TRUE                   The default address is retrieved and UDP is reconfigured.\r
+  @retval FALSE                  Some error occured.\r
 \r
 **/\r
 BOOLEAN\r
 Mtftp4GetMapping (\r
   IN MTFTP4_PROTOCOL        *Instance,\r
-  IN UDP_IO_PORT            *UdpPort,\r
+  IN UDP_IO                 *UdpIo,\r
   IN EFI_UDP4_CONFIG_DATA   *UdpCfgData\r
   )\r
 {\r
@@ -511,7 +244,7 @@ Mtftp4GetMapping (
   ASSERT (Instance->Config.UseDefaultSetting);\r
 \r
   Service = Instance->Service;\r
-  Udp     = UdpPort->Udp;\r
+  Udp     = UdpIo->Protocol.Udp4;\r
 \r
   Status = gBS->SetTimer (\r
                   Service->TimerToGetMap,\r
@@ -522,7 +255,7 @@ Mtftp4GetMapping (
     return FALSE;\r
   }\r
 \r
-  while (!EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
+  while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {\r
     Udp->Poll (Udp);\r
 \r
     if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&\r
@@ -540,17 +273,16 @@ Mtftp4GetMapping (
 /**\r
   Configure the UDP port for unicast receiving.\r
 \r
-  @param  UdpIo                  The UDP port\r
+  @param  UdpIo                  The UDP_IO instance\r
   @param  Instance               The MTFTP session\r
 \r
   @retval EFI_SUCCESS            The UDP port is successfully configured for the\r
                                  session to unicast receive.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 Mtftp4ConfigUnicastPort (\r
-  IN UDP_IO_PORT            *UdpIo,\r
+  IN UDP_IO                 *UdpIo,\r
   IN MTFTP4_PROTOCOL        *Instance\r
   )\r
 {\r
@@ -571,20 +303,36 @@ Mtftp4ConfigUnicastPort (
   UdpConfig.ReceiveTimeout     = 0;\r
   UdpConfig.TransmitTimeout    = 0;\r
   UdpConfig.UseDefaultAddress  = Config->UseDefaultSetting;\r
-  UdpConfig.StationAddress     = Config->StationIp;\r
-  UdpConfig.SubnetMask         = Config->SubnetMask;\r
-  UdpConfig.StationPort        = 0;\r
+  IP4_COPY_ADDRESS (&UdpConfig.StationAddress, &Config->StationIp);\r
+  IP4_COPY_ADDRESS (&UdpConfig.SubnetMask, &Config->SubnetMask);\r
+  UdpConfig.StationPort        = Config->LocalPort;\r
   UdpConfig.RemotePort         = 0;\r
 \r
   Ip = HTONL (Instance->ServerIp);\r
-  NetCopyMem (&UdpConfig.RemoteAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
+  IP4_COPY_ADDRESS (&UdpConfig.RemoteAddress, &Ip);\r
 \r
-  Status = UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfig);\r
+  Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);\r
 \r
   if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
+  if (!Config->UseDefaultSetting && !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp)) {\r
+    //\r
+    // The station IP address is manually configured and the Gateway IP is not 0.\r
+    // Add the default route for this UDP instance.\r
+    //\r
+    Status = UdpIo->Protocol.Udp4->Routes (\r
+                                     UdpIo->Protocol.Udp4,\r
+                                     FALSE,\r
+                                     &mZeroIp4Addr,\r
+                                     &mZeroIp4Addr,\r
+                                     &Config->GatewayIp\r
+                                     );\r
+    if (EFI_ERROR (Status)) {\r
+      UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, NULL);\r
+    }\r
+  }\r
   return Status;\r
 }\r
 \r
@@ -603,7 +351,6 @@ Mtftp4ConfigUnicastPort (
   @retval EFI_SUCCESS            The operation is successfully started.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 Mtftp4Start (\r
   IN EFI_MTFTP4_PROTOCOL    *This,\r
@@ -616,6 +363,7 @@ Mtftp4Start (
   EFI_MTFTP4_CONFIG_DATA    *Config;\r
   EFI_TPL                   OldTpl;\r
   EFI_STATUS                Status;\r
+  EFI_STATUS                TokenStatus;\r
 \r
   //\r
   // Validate the parameters\r
@@ -643,8 +391,10 @@ Mtftp4Start (
 \r
   Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
 \r
-  Status = EFI_SUCCESS;\r
-  OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
+  Status      = EFI_SUCCESS;\r
+  TokenStatus = EFI_SUCCESS;\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
 \r
   if (Instance->State != MTFTP4_STATE_CONFIGED) {\r
     Status = EFI_NOT_STARTED;\r
@@ -654,8 +404,12 @@ Mtftp4Start (
     Status = EFI_ACCESS_DENIED;\r
   }\r
 \r
+  if ((Token->OverrideData != NULL) && !Mtftp4OverrideValid (Instance, Token->OverrideData)) {\r
+    Status = EFI_INVALID_PARAMETER;\r
+  }\r
+\r
   if (EFI_ERROR (Status)) {\r
-    NET_RESTORE_TPL (OldTpl);\r
+    gBS->RestoreTPL (OldTpl);\r
     return Status;\r
   }\r
 \r
@@ -666,20 +420,17 @@ Mtftp4Start (
   Instance->Operation = Operation;\r
   Override            = Token->OverrideData;\r
 \r
-  if ((Override != NULL) && !Mtftp4OverrideValid (Instance, Override)) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_ERROR;\r
-  }\r
-\r
   if (Token->OptionCount != 0) {\r
     Status = Mtftp4ParseOption (\r
                Token->OptionList,\r
                Token->OptionCount,\r
                TRUE,\r
+               Instance->Operation,\r
                &Instance->RequestOption\r
                );\r
 \r
     if (EFI_ERROR (Status)) {\r
+      TokenStatus = EFI_DEVICE_ERROR;\r
       goto ON_ERROR;\r
     }\r
   }\r
@@ -690,14 +441,15 @@ Mtftp4Start (
   Config                  = &Instance->Config;\r
   Instance->Token         = Token;\r
   Instance->BlkSize       = MTFTP4_DEFAULT_BLKSIZE;\r
+  Instance->WindowSize    = MTFTP4_DEFAULT_WINDOWSIZE;\r
 \r
-  NetCopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));\r
+  CopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));\r
   Instance->ServerIp      = NTOHL (Instance->ServerIp);\r
 \r
   Instance->ListeningPort = Config->InitialServerPort;\r
   Instance->ConnectedPort = 0;\r
 \r
-  NetCopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));\r
+  CopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));\r
   Instance->Gateway       = NTOHL (Instance->Gateway);\r
 \r
   Instance->MaxRetry      = Config->TryCount;\r
@@ -705,8 +457,8 @@ Mtftp4Start (
   Instance->Master        = TRUE;\r
 \r
   if (Override != NULL) {\r
-    NetCopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));\r
-    NetCopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
+    CopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));\r
+    CopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));\r
 \r
     Instance->ServerIp      = NTOHL (Instance->ServerIp);\r
     Instance->Gateway       = NTOHL (Instance->Gateway);\r
@@ -732,11 +484,16 @@ Mtftp4Start (
   // Config the unicast UDP child to send initial request\r
   //\r
   Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);\r
-\r
   if (EFI_ERROR (Status)) {\r
+    TokenStatus = EFI_DEVICE_ERROR;\r
     goto ON_ERROR;\r
   }\r
 \r
+  //\r
+  // Set initial status.\r
+  //\r
+  Token->Status = EFI_NOT_READY;\r
+\r
   //\r
   // Build and send an initial requests\r
   //\r
@@ -746,21 +503,21 @@ Mtftp4Start (
     Status = Mtftp4RrqStart (Instance, Operation);\r
   }\r
 \r
-  NET_RESTORE_TPL (OldTpl);\r
-\r
   if (EFI_ERROR (Status)) {\r
+    TokenStatus = EFI_DEVICE_ERROR;\r
     goto ON_ERROR;\r
   }\r
-  //\r
-  // Return immediately for asynchronous operation or poll the\r
-  // instance for synchronous operation.\r
-  //\r
-  Token->Status = EFI_NOT_READY;\r
+\r
+  gBS->RestoreTPL(OldTpl);\r
 \r
   if (Token->Event != NULL) {\r
     return EFI_SUCCESS;\r
   }\r
 \r
+  //\r
+  // Return immediately for asynchronous operation or poll the\r
+  // instance for synchronous operation.\r
+  //\r
   while (Token->Status == EFI_NOT_READY) {\r
     This->Poll (This);\r
   }\r
@@ -768,26 +525,277 @@ Mtftp4Start (
   return Token->Status;\r
 \r
 ON_ERROR:\r
-  Mtftp4CleanOperation (Instance, Status);\r
-  NET_RESTORE_TPL (OldTpl);\r
+  Mtftp4CleanOperation (Instance, TokenStatus);\r
+  gBS->RestoreTPL (OldTpl);\r
 \r
   return Status;\r
 }\r
 \r
 \r
 /**\r
-  Read a file from the server.\r
+  Reads the current operational settings.\r
+\r
+  The GetModeData()function reads the current operational settings of this\r
+  EFI MTFTPv4 Protocol driver instance.\r
+\r
+  @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.\r
+  @param  ModeData               Pointer to storage for the EFI MTFTPv4 Protocol\r
+                                 driver mode data.\r
+\r
+  @retval EFI_SUCCESS            The configuration data was successfully returned.\r
+  @retval EFI_OUT_OF_RESOURCES   The required mode data could not be allocated.\r
+  @retval EFI_INVALID_PARAMETER  This is NULL or ModeData is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiMtftp4GetModeData (\r
+  IN     EFI_MTFTP4_PROTOCOL    *This,\r
+     OUT EFI_MTFTP4_MODE_DATA  *ModeData\r
+  )\r
+{\r
+  MTFTP4_PROTOCOL  *Instance;\r
+  EFI_TPL          OldTpl;\r
+\r
+  if ((This == NULL) || (ModeData == NULL)) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+  Instance                         = MTFTP4_PROTOCOL_FROM_THIS (This);\r
+  CopyMem(&ModeData->ConfigData, &Instance->Config, sizeof (Instance->Config));\r
+  ModeData->SupportedOptionCount   = MTFTP4_SUPPORTED_OPTIONS;\r
+  ModeData->SupportedOptoins       = (UINT8 **) mMtftp4SupportedOptions;\r
+  ModeData->UnsupportedOptionCount = 0;\r
+  ModeData->UnsupportedOptoins     = NULL;\r
+\r
+  gBS->RestoreTPL (OldTpl);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Initializes, changes, or resets the default operational setting for this\r
+  EFI MTFTPv4 Protocol driver instance.\r
+\r
+  The Configure() function is used to set and change the configuration data for\r
+  this EFI MTFTPv4 Protocol driver instance. The configuration data can be reset\r
+  to startup defaults by calling Configure() with MtftpConfigData set to NULL.\r
+  Whenever the instance is reset, any pending operation is aborted. By changing\r
+  the EFI MTFTPv4 Protocol driver instance configuration data, the client can\r
+  connect to different MTFTPv4 servers. The configuration parameters in\r
+  MtftpConfigData are used as the default parameters in later MTFTPv4 operations\r
+  and can be overridden in later operations.\r
+\r
+  @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
+  @param  ConfigData             MtftpConfigDataPointer to the configuration data\r
+                                 structure\r
+\r
+  @retval EFI_SUCCESS            The EFI MTFTPv4 Protocol driver was configured\r
+                                 successfully.\r
+  @retval EFI_INVALID_PARAMETER  One or more following conditions are TRUE:\r
+                                 1.This is NULL.\r
+                                 2.MtftpConfigData.UseDefaultSetting is FALSE and\r
+                                   MtftpConfigData.StationIp is not a valid IPv4\r
+                                   unicast address.\r
+                                 3.MtftpCofigData.UseDefaultSetting is FALSE and\r
+                                   MtftpConfigData.SubnetMask is invalid.\r
+                                 4.MtftpCofigData.ServerIp is not a valid IPv4\r
+                                   unicast address.\r
+                                 5.MtftpConfigData.UseDefaultSetting is FALSE and\r
+                                   MtftpConfigData.GatewayIp is not a valid IPv4\r
+                                   unicast address or is not in the same subnet\r
+                                   with station address.\r
+  @retval EFI_ACCESS_DENIED      The EFI configuration could not be changed at this\r
+                                 time because there is one MTFTP background operation\r
+                                 in progress.\r
+  @retval EFI_NO_MAPPING         When using a default address, configuration\r
+                                 (DHCP, BOOTP, RARP, etc.) has not finished yet.\r
+  @retval EFI_UNSUPPORTED        A configuration protocol (DHCP, BOOTP, RARP, etc.)\r
+                                 could not be located when clients choose to use\r
+                                 the default address settings.\r
+  @retval EFI_OUT_OF_RESOURCES   The EFI MTFTPv4 Protocol driver instance data could\r
+                                 not be allocated.\r
+  @retval EFI_DEVICE_ERROR       An unexpected system or network error occurred.\r
+                                 The EFI MTFTPv4 Protocol driver instance is not\r
+                                 configured.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiMtftp4Configure (\r
+  IN EFI_MTFTP4_PROTOCOL    *This,\r
+  IN EFI_MTFTP4_CONFIG_DATA *ConfigData\r
+  )\r
+{\r
+  MTFTP4_PROTOCOL           *Instance;\r
+  EFI_TPL                   OldTpl;\r
+  IP4_ADDR                  Ip;\r
+  IP4_ADDR                  Netmask;\r
+  IP4_ADDR                  Gateway;\r
+  IP4_ADDR                  ServerIp;\r
+\r
+  if (This == NULL) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
+\r
+  Instance = MTFTP4_PROTOCOL_FROM_THIS (This);\r
+\r
+  if (ConfigData == NULL) {\r
+    //\r
+    // Reset the operation if ConfigData is NULL\r
+    //\r
+    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+    Mtftp4CleanOperation (Instance, EFI_ABORTED);\r
+    ZeroMem (&Instance->Config, sizeof (EFI_MTFTP4_CONFIG_DATA));\r
+    Instance->State = MTFTP4_STATE_UNCONFIGED;\r
+\r
+    gBS->RestoreTPL (OldTpl);\r
+\r
+  } else {\r
+    //\r
+    // Configure the parameters for new operation.\r
+    //\r
+    CopyMem (&Ip, &ConfigData->StationIp, sizeof (IP4_ADDR));\r
+    CopyMem (&Netmask, &ConfigData->SubnetMask, sizeof (IP4_ADDR));\r
+    CopyMem (&Gateway, &ConfigData->GatewayIp, sizeof (IP4_ADDR));\r
+    CopyMem (&ServerIp, &ConfigData->ServerIp, sizeof (IP4_ADDR));\r
+\r
+    Ip       = NTOHL (Ip);\r
+    Netmask  = NTOHL (Netmask);\r
+    Gateway  = NTOHL (Gateway);\r
+    ServerIp = NTOHL (ServerIp);\r
+\r
+    if (ServerIp == 0 || IP4_IS_LOCAL_BROADCAST (ServerIp)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if (!ConfigData->UseDefaultSetting &&\r
+        ((!IP4_IS_VALID_NETMASK (Netmask) || (Netmask != 0 && !NetIp4IsUnicast (Ip, Netmask))))) {\r
+\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    if ((Gateway != 0) &&\r
+        ((Netmask != 0xFFFFFFFF && !IP4_NET_EQUAL (Gateway, Ip, Netmask)) || (Netmask != 0 && !NetIp4IsUnicast (Gateway, Netmask)))) {\r
+\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
+\r
+    OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
+\r
+    if ((Instance->State == MTFTP4_STATE_CONFIGED) && (Instance->Operation != 0)) {\r
+      gBS->RestoreTPL (OldTpl);\r
+      return EFI_ACCESS_DENIED;\r
+    }\r
+\r
+    CopyMem(&Instance->Config, ConfigData, sizeof (*ConfigData));;\r
+    Instance->State = MTFTP4_STATE_CONFIGED;\r
+\r
+    gBS->RestoreTPL (OldTpl);\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+\r
+/**\r
+  Parses the options in an MTFTPv4 OACK packet.\r
+\r
+  The ParseOptions() function parses the option fields in an MTFTPv4 OACK packet\r
+  and returns the number of options that were found and optionally a list of\r
+  pointers to the options in the packet.\r
+  If one or more of the option fields are not valid, then EFI_PROTOCOL_ERROR is\r
+  returned and *OptionCount and *OptionList stop at the last valid option.\r
+  The OptionList is allocated by this function, and caller should free it when used.\r
+\r
+  @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.\r
+  @param  PacketLen              Length of the OACK packet to be parsed.\r
+  @param  Packet                 Pointer to the OACK packet to be parsed.\r
+  @param  OptionCount            Pointer to the number of options in following OptionList.\r
+  @param  OptionList             Pointer to EFI_MTFTP4_OPTION storage. Call the\r
+                                 EFI Boot Service FreePool() to release theOptionList\r
+                                 if the options in this OptionList are not needed\r
+                                 any more\r
+\r
+  @retval EFI_SUCCESS            The OACK packet was valid and the OptionCount and\r
+                                 OptionList parameters have been updated.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
+                                 1.PacketLen is 0.\r
+                                 2.Packet is NULL or Packet is not a valid MTFTPv4 packet.\r
+                                 3.OptionCount is NULL.\r
+  @retval EFI_NOT_FOUND          No options were found in the OACK packet.\r
+  @retval EFI_OUT_OF_RESOURCES   Storage for the OptionList array cannot be allocated.\r
+  @retval EFI_PROTOCOL_ERROR     One or more of the option fields is invalid.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiMtftp4ParseOptions (\r
+  IN     EFI_MTFTP4_PROTOCOL    *This,\r
+  IN     UINT32                 PacketLen,\r
+  IN     EFI_MTFTP4_PACKET      *Packet,\r
+     OUT UINT32                 *OptionCount,\r
+     OUT EFI_MTFTP4_OPTION      **OptionList          OPTIONAL\r
+  )\r
+{\r
+  EFI_STATUS                Status;\r
+\r
+  if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||\r
+      (Packet == NULL) || (OptionCount == NULL)) {\r
+\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
-  @param  This                   The Mtftp protocol instance.\r
-  @param  Token                  The user's request wrap token.\r
+  Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);\r
 \r
-  @retval EFI_SUCCESS            The ReadFile has finished, the file has been\r
-                                 downloaded if it is synchronous operation,\r
-                                 otherwise it has been  initated.\r
-  @retval Others                 Some error happened.\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (*OptionCount == 0) {\r
+    return EFI_NOT_FOUND;\r
+  }\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
+\r
+/**\r
+  Downloads a file from an MTFTPv4 server.\r
+\r
+  The ReadFile() function is used to initialize and start an MTFTPv4 download\r
+  process and optionally wait for completion. When the download operation completes,\r
+  whether successfully or not, the Token.Status field is updated by the EFI MTFTPv4\r
+  Protocol driver and then Token.Event is signaled (if it is not NULL).\r
+  Data can be downloaded from the MTFTPv4 server into either of the following locations:\r
+  1.A fixed buffer that is pointed to by Token.Buffer\r
+  2.A download service function that is pointed to by Token.CheckPacket\r
+  If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket\r
+  will be called first. If the call is successful, the packet will be stored in\r
+  Token.Buffer.\r
+\r
+  @param  This                  Pointer to the EFI_MTFTP4_PROTOCOL instance\r
+  @param  Token                 Pointer to the token structure to provide the\r
+                                parameters that are used in this operation.\r
+\r
+  @retval EFI_SUCCESS           The data file has been transferred successfully.\r
+  @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.\r
+  @retval EFI_BUFFER_TOO_SMALL  BufferSize is not large enough to hold the downloaded\r
+                                data in downloading process.\r
+  @retval EFI_ABORTED           Current operation is aborted by user.\r
+  @retval EFI_ICMP_ERROR        An ICMP ERROR packet was received.\r
+  @retval EFI_TIMEOUT           No responses were received from the MTFTPv4 server.\r
+  @retval EFI_TFTP_ERROR        An MTFTPv4 ERROR packet was received.\r
+  @retval EFI_DEVICE_ERROR      An unexpected network error or system error occurred.\r
+  @retval EFI_NO_MEDIA          There was a media error.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiMtftp4ReadFile (\r
@@ -800,18 +808,55 @@ EfiMtftp4ReadFile (
 \r
 \r
 /**\r
-  Upload a file to the server.\r
-\r
-  @param  This                   The MTFTP protocol session\r
-  @param  Token                  The user's request wrap token.\r
-\r
-  @retval EFI_SUCCESS            The WriteFile has finished, the file has been\r
-                                 uploaded if it is synchronous operation, otherwise\r
-                                 it has been  initated.\r
-  @retval Others                 Some error happened.\r
+  Sends a data file to an MTFTPv4 server. May be unsupported in some EFI implementations\r
+\r
+  The WriteFile() function is used to initialize an uploading operation with the\r
+  given option list and optionally wait for completion. If one or more of the\r
+  options is not supported by the server, the unsupported options are ignored and\r
+  a standard TFTP process starts instead. When the upload process completes,\r
+  whether successfully or not, Token.Event is signaled, and the EFI MTFTPv4 Protocol\r
+  driver updates Token.Status.\r
+  The caller can supply the data to be uploaded in the following two modes:\r
+  1.Through the user-provided buffer\r
+  2.Through a callback function\r
+  With the user-provided buffer, the Token.BufferSize field indicates the length\r
+  of the buffer, and the driver will upload the data in the buffer. With an\r
+  EFI_MTFTP4_PACKET_NEEDED callback function, the driver will call this callback\r
+  function to get more data from the user to upload. See the definition of\r
+  EFI_MTFTP4_PACKET_NEEDED for more information. These two modes cannot be used at\r
+  the same time. The callback function will be ignored if the user provides the buffer.\r
+\r
+  @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.\r
+  @param  Token                  Pointer to the token structure to provide the\r
+                                 parameters that are used in this function\r
+\r
+  @retval EFI_SUCCESS            The upload session has started.\r
+  @retval EFI_UNSUPPORTED        The operation is not supported by this implementation.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
+                                 1. This is NULL.\r
+                                 2. Token is NULL.\r
+                                 3. Token.Filename is NULL.\r
+                                 4. Token.OptionCount is not zero and\r
+                                    Token.OptionList is NULL.\r
+                                 5. One or more options in Token.OptionList have wrong\r
+                                    format.\r
+                                 6. Token.Buffer and Token.PacketNeeded are both\r
+                                    NULL.\r
+                                 7. One or more IPv4 addresses in Token.OverrideData\r
+                                    are not valid unicast IPv4 addresses if\r
+                                    Token.OverrideData is not NULL.\r
+  @retval EFI_UNSUPPORTED        One or more options in the Token.OptionList are in the\r
+                                 unsupported list of structure EFI_MTFTP4_MODE_DATA.\r
+  @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.\r
+  @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
+                                 BOOTP, RARP, etc.) is not finished yet.\r
+  @retval EFI_ALREADY_STARTED    This Token is already being used in another MTFTPv4\r
+                                 session.\r
+  @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.\r
+  @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.\r
+  @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiMtftp4WriteFile (\r
@@ -824,19 +869,64 @@ EfiMtftp4WriteFile (
 \r
 \r
 /**\r
-  Read a directory from the server. The only difference\r
-  between ReadFile and ReadDirectory is the opcode used.\r
-\r
-  @param  This                   The MTFTP protocol session\r
-  @param  Token                  The user's request wrap token.\r
-\r
-  @retval EFI_SUCCESS            The ReadDirectory has finished, the directory has\r
-                                 been  downloaded as a file if it is synchronous\r
-                                 operation,  otherwise it has been initated.\r
-  @retval Others                 Some error happened.\r
+  Downloads a data file "directory" from an MTFTPv4 server.\r
+  May be unsupported in some EFI implementations\r
+\r
+  The ReadDirectory() function is used to return a list of files on the MTFTPv4\r
+  server that are logically (or operationally) related to Token.Filename. The\r
+  directory request packet that is sent to the server is built with the option\r
+  list that was provided by caller, if present.\r
+  The file information that the server returns is put into either of the following\r
+  locations:\r
+  1.A fixed buffer that is pointed to by Token.Buffer\r
+  2.A download service function that is pointed to by Token.CheckPacket\r
+  If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket will\r
+  be called first. If the call is successful, the packet will be stored in Token.Buffer.\r
+  The returned directory listing in the Token.Buffer or EFI_MTFTP4_PACKET consists\r
+  of a list of two or three variable-length ASCII strings, each terminated by a\r
+  null character, for each file in the directory. If the multicast option is involved,\r
+  the first field of each directory entry is the static multicast IP address and\r
+  UDP port number that is associated with the file name. The format of the field\r
+  is ip:ip:ip:ip:port. If the multicast option is not involved, this field and its\r
+  terminating null character are not present.\r
+  The next field of each directory entry is the file name and the last field is\r
+  the file information string. The information string contains the file size and\r
+  the create/modify timestamp. The format of the information string is filesize\r
+  yyyy-mm-dd hh:mm:ss:ffff. The timestamp is Coordinated Universal Time\r
+  (UTC; also known as Greenwich Mean Time [GMT]).\r
+  The only difference between ReadFile and ReadDirectory is the opcode used.\r
+\r
+  @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
+  @param  Token                  Pointer to the token structure to provide the\r
+                                 parameters that are used in this function\r
+\r
+  @retval EFI_SUCCESS            The MTFTPv4 related file "directory" has been downloaded.\r
+  @retval EFI_UNSUPPORTED        The operation is not supported by this implementation.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
+                                 1. This is NULL.\r
+                                 2. Token is NULL.\r
+                                 3. Token.Filename is NULL.\r
+                                 4. Token.OptionCount is not zero and\r
+                                    Token.OptionList is NULL.\r
+                                 5. One or more options in Token.OptionList have wrong\r
+                                    format.\r
+                                 6. Token.Buffer and Token.PacketNeeded are both\r
+                                    NULL.\r
+                                 7. One or more IPv4 addresses in Token.OverrideData\r
+                                    are not valid unicast IPv4 addresses if\r
+                                    Token.OverrideData is not NULL.\r
+  @retval EFI_UNSUPPORTED        One or more options in the Token.OptionList are in the\r
+                                 unsupported list of structure EFI_MTFTP4_MODE_DATA.\r
+  @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.\r
+  @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
+                                 BOOTP, RARP, etc.) is not finished yet.\r
+  @retval EFI_ALREADY_STARTED    This Token is already being used in another MTFTPv4\r
+                                 session.\r
+  @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.\r
+  @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.\r
+  @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiMtftp4ReadDirectory (\r
@@ -849,16 +939,140 @@ EfiMtftp4ReadDirectory (
 \r
 \r
 /**\r
-  Poll the network stack to accelerate the packet process.\r
+  Gets information about a file from an MTFTPv4 server.\r
+\r
+  The GetInfo() function assembles an MTFTPv4 request packet with options;\r
+  sends it to the MTFTPv4 server; and may return an MTFTPv4 OACK, MTFTPv4 ERROR,\r
+  or ICMP ERROR packet. Retries occur only if no response packets are received\r
+  from the MTFTPv4 server before the timeout expires.\r
+  It is implemented with EfiMtftp4ReadFile: build a token, then pass it to\r
+  EfiMtftp4ReadFile. In its check packet callback abort the opertions.\r
+\r
+  @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
+  @param  OverrideData           Data that is used to override the existing\r
+                                 parameters. If NULL, the default parameters that\r
+                                 were set in the EFI_MTFTP4_PROTOCOL.Configure()\r
+                                 function are used\r
+  @param  Filename               Pointer to null-terminated ASCII file name string\r
+  @param  ModeStr                Pointer to null-terminated ASCII mode string. If NULL, "octet"\r
+                                 will be used\r
+  @param  OptionCount            Number of option/value string pairs in OptionList\r
+  @param  OptionList             Pointer to array of option/value string pairs.\r
+                                 Ignored if OptionCount is zero\r
+  @param  PacketLength           The number of bytes in the returned packet\r
+  @param  Packet                 PacketThe pointer to the received packet. This\r
+                                 buffer must be freed by the caller.\r
+\r
+  @retval EFI_SUCCESS            An MTFTPv4 OACK packet was received and is in\r
+                                 the Buffer.\r
+  @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:\r
+                                 1.This is NULL.\r
+                                 2.Filename is NULL.\r
+                                 3.OptionCount is not zero and OptionList is NULL.\r
+                                 4.One or more options in OptionList have wrong format.\r
+                                 5.PacketLength is NULL.\r
+                                 6.One or more IPv4 addresses in OverrideData are\r
+                                   not valid unicast IPv4 addresses if OverrideData\r
+                                   is not NULL.\r
+  @retval EFI_UNSUPPORTED        One or more options in the OptionList are in the\r
+                                 unsupported list of structure EFI_MTFTP4_MODE_DATA\r
+  @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.\r
+  @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
+                                 BOOTP, RARP, etc.) has not finished yet.\r
+  @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.\r
+  @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.\r
+  @retval EFI_TFTP_ERROR         An MTFTPv4 ERROR packet was received and is in\r
+                                 the Buffer.\r
+  @retval EFI_ICMP_ERROR         An ICMP ERROR packet was received and the Packet\r
+                                 is set to NULL.\r
+  @retval EFI_PROTOCOL_ERROR     An unexpected MTFTPv4 packet was received and is\r
+                                 in the Buffer.\r
+  @retval EFI_TIMEOUT            No responses were received from the MTFTPv4 server.\r
+  @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.\r
+  @retval EFI_NO_MEDIA           There was a media error.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+EfiMtftp4GetInfo (\r
+  IN     EFI_MTFTP4_PROTOCOL      *This,\r
+  IN     EFI_MTFTP4_OVERRIDE_DATA *OverrideData        OPTIONAL,\r
+  IN     UINT8                    *Filename,\r
+  IN     UINT8                    *ModeStr             OPTIONAL,\r
+  IN     UINT8                    OptionCount,\r
+  IN     EFI_MTFTP4_OPTION        *OptionList          OPTIONAL,\r
+     OUT UINT32                   *PacketLength,\r
+     OUT EFI_MTFTP4_PACKET        **Packet             OPTIONAL\r
+  )\r
+{\r
+  EFI_MTFTP4_TOKEN          Token;\r
+  MTFTP4_GETINFO_STATE      State;\r
+  EFI_STATUS                Status;\r
 \r
-  @param  This                   The MTFTP protocol instance.\r
+  if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||\r
+      ((OptionCount != 0) && (OptionList == NULL))) {\r
+    return EFI_INVALID_PARAMETER;\r
+  }\r
 \r
+  if (Packet != NULL) {\r
+    *Packet = NULL;\r
+  }\r
+\r
+  *PacketLength         = 0;\r
+  State.Packet          = Packet;\r
+  State.PacketLen       = PacketLength;\r
+  State.Status          = EFI_SUCCESS;\r
+\r
+  //\r
+  // Fill in the Token to issue an synchronous ReadFile operation\r
+  //\r
+  Token.Status          = EFI_SUCCESS;\r
+  Token.Event           = NULL;\r
+  Token.OverrideData    = OverrideData;\r
+  Token.Filename        = Filename;\r
+  Token.ModeStr         = ModeStr;\r
+  Token.OptionCount     = OptionCount;\r
+  Token.OptionList      = OptionList;\r
+  Token.BufferSize      = 0;\r
+  Token.Buffer          = NULL;\r
+  Token.Context         = &State;\r
+  Token.CheckPacket     = Mtftp4GetInfoCheckPacket;\r
+  Token.TimeoutCallback = NULL;\r
+  Token.PacketNeeded    = NULL;\r
+\r
+  Status                = EfiMtftp4ReadFile (This, &Token);\r
+\r
+  if (EFI_ABORTED == Status) {\r
+    return State.Status;\r
+  }\r
+\r
+  return Status;\r
+}\r
+\r
+/**\r
+  Polls for incoming data packets and processes outgoing data packets.\r
+\r
+  The Poll() function can be used by network drivers and applications to increase\r
+  the rate that data packets are moved between the communications device and the\r
+  transmit and receive queues.\r
+  In some systems, the periodic timer event in the managed network driver may not\r
+  poll the underlying communications device fast enough to transmit and/or receive\r
+  all data packets without missing incoming packets or dropping outgoing packets.\r
+  Drivers and applications that are experiencing packet loss should try calling\r
+  the Poll() function more often.\r
+\r
+  @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance\r
+\r
+  @retval EFI_SUCCESS            Incoming or outgoing data was processed.\r
+  @retval EFI_NOT_STARTED        This EFI MTFTPv4 Protocol instance has not been started.\r
+  @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,\r
+                                 BOOTP, RARP, etc.) is not finished yet.\r
   @retval EFI_INVALID_PARAMETER  This is NULL.\r
-  @retval EFI_NOT_STARTED        The MTFTP session hasn't been configured.\r
-  @retval EFI_DEVICE_ERROR       The MTFTP session has been destoried.\r
+  @retval EFI_DEVICE_ERROR       An unexpected system or network error occurred.\r
+  @retval EFI_TIMEOUT            Data was dropped out of the transmit and/or receive\r
+                                 queue. Consider increasing the polling rate.\r
 \r
 **/\r
-STATIC\r
 EFI_STATUS\r
 EFIAPI\r
 EfiMtftp4Poll (\r
@@ -867,6 +1081,7 @@ EfiMtftp4Poll (
 {\r
   MTFTP4_PROTOCOL           *Instance;\r
   EFI_UDP4_PROTOCOL         *Udp;\r
+  EFI_STATUS                Status;\r
 \r
   if (This == NULL) {\r
     return EFI_INVALID_PARAMETER;\r
@@ -876,12 +1091,14 @@ EfiMtftp4Poll (
 \r
   if (Instance->State == MTFTP4_STATE_UNCONFIGED) {\r
     return EFI_NOT_STARTED;\r
-  } else if (Instance->State == MTFTP4_STATE_DESTORY) {\r
+  } else if (Instance->State == MTFTP4_STATE_DESTROY) {\r
     return EFI_DEVICE_ERROR;\r
   }\r
 \r
-  Udp = Instance->UnicastPort->Udp;\r
-  return Udp->Poll (Udp);\r
+  Udp = Instance->UnicastPort->Protocol.Udp4;\r
+  Status = Udp->Poll (Udp);\r
+  Mtftp4OnTimerTick (NULL, Instance->Service);\r
+  return Status;\r
 }\r
 \r
 EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {\r