Home | History | Annotate | Download | only in Mtftp4Dxe
      1 /** @file
      2   Interface routine for Mtftp4.
      3 
      4 (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
      5 Copyright (c) 2006 - 2016, Intel Corporation. All rights reserved.<BR>
      6 This program and the accompanying materials
      7 are licensed and made available under the terms and conditions of the BSD License
      8 which accompanies this distribution.  The full text of the license may be found at
      9 http://opensource.org/licenses/bsd-license.php<BR>
     10 
     11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 
     17 #include "Mtftp4Impl.h"
     18 
     19 
     20 /**
     21   Clean up the MTFTP session to get ready for new operation.
     22 
     23   @param  Instance               The MTFTP session to clean up
     24   @param  Result                 The result to return to the caller who initiated
     25                                  the operation.
     26 **/
     27 VOID
     28 Mtftp4CleanOperation (
     29   IN OUT MTFTP4_PROTOCOL        *Instance,
     30   IN     EFI_STATUS             Result
     31   )
     32 {
     33   LIST_ENTRY                *Entry;
     34   LIST_ENTRY                *Next;
     35   MTFTP4_BLOCK_RANGE        *Block;
     36   EFI_MTFTP4_TOKEN          *Token;
     37 
     38   //
     39   // Free various resources.
     40   //
     41   Token = Instance->Token;
     42 
     43   if (Token != NULL) {
     44     Token->Status = Result;
     45 
     46     if (Token->Event != NULL) {
     47       gBS->SignalEvent (Token->Event);
     48     }
     49 
     50     Instance->Token = NULL;
     51   }
     52 
     53   ASSERT (Instance->UnicastPort != NULL);
     54   UdpIoCleanIo (Instance->UnicastPort);
     55 
     56   if (Instance->LastPacket != NULL) {
     57     NetbufFree (Instance->LastPacket);
     58     Instance->LastPacket = NULL;
     59   }
     60 
     61   if (Instance->McastUdpPort != NULL) {
     62     gBS->CloseProtocol (
     63            Instance->McastUdpPort->UdpHandle,
     64            &gEfiUdp4ProtocolGuid,
     65            gMtftp4DriverBinding.DriverBindingHandle,
     66            Instance->Handle
     67            );
     68     UdpIoFreeIo (Instance->McastUdpPort);
     69     Instance->McastUdpPort = NULL;
     70   }
     71 
     72   NET_LIST_FOR_EACH_SAFE (Entry, Next, &Instance->Blocks) {
     73     Block = NET_LIST_USER_STRUCT (Entry, MTFTP4_BLOCK_RANGE, Link);
     74     RemoveEntryList (Entry);
     75     FreePool (Block);
     76   }
     77 
     78   ZeroMem (&Instance->RequestOption, sizeof (MTFTP4_OPTION));
     79 
     80   Instance->Operation     = 0;
     81 
     82   Instance->BlkSize       = MTFTP4_DEFAULT_BLKSIZE;
     83   Instance->LastBlock     = 0;
     84   Instance->ServerIp      = 0;
     85   Instance->ListeningPort = 0;
     86   Instance->ConnectedPort = 0;
     87   Instance->Gateway       = 0;
     88   Instance->PacketToLive  = 0;
     89   Instance->MaxRetry      = 0;
     90   Instance->CurRetry      = 0;
     91   Instance->Timeout       = 0;
     92   Instance->McastIp       = 0;
     93   Instance->McastPort     = 0;
     94   Instance->Master        = TRUE;
     95 }
     96 
     97 
     98 /**
     99   Check packet for GetInfo.
    100 
    101   GetInfo is implemented with EfiMtftp4ReadFile. It use Mtftp4GetInfoCheckPacket
    102   to inspect the first packet from server, then abort the session.
    103 
    104   @param  This                   The MTFTP4 protocol instance
    105   @param  Token                  The user's token
    106   @param  PacketLen              The length of the packet
    107   @param  Packet                 The received packet.
    108 
    109   @retval EFI_ABORTED            Abort the ReadFile operation and return.
    110 
    111 **/
    112 EFI_STATUS
    113 EFIAPI
    114 Mtftp4GetInfoCheckPacket (
    115   IN EFI_MTFTP4_PROTOCOL    *This,
    116   IN EFI_MTFTP4_TOKEN       *Token,
    117   IN UINT16                 PacketLen,
    118   IN EFI_MTFTP4_PACKET      *Packet
    119   )
    120 {
    121   MTFTP4_GETINFO_STATE      *State;
    122   EFI_STATUS                Status;
    123   UINT16                    OpCode;
    124   EFI_MTFTP4_ERROR_HEADER  *ErrorHeader;
    125 
    126   State   = (MTFTP4_GETINFO_STATE *) Token->Context;
    127   OpCode   = NTOHS (Packet->OpCode);
    128 
    129   //
    130   // Set the GetInfo's return status according to the OpCode.
    131   //
    132   switch (OpCode) {
    133   case EFI_MTFTP4_OPCODE_ERROR:
    134     ErrorHeader = (EFI_MTFTP4_ERROR_HEADER *) Packet;
    135     if (ErrorHeader->ErrorCode == EFI_MTFTP4_ERRORCODE_FILE_NOT_FOUND) {
    136       DEBUG ((EFI_D_ERROR, "TFTP error code 1 (File Not Found)\n"));
    137     } else {
    138       DEBUG ((EFI_D_ERROR, "TFTP error code %d\n", ErrorHeader->ErrorCode));
    139     }
    140     State->Status = EFI_TFTP_ERROR;
    141     break;
    142 
    143   case EFI_MTFTP4_OPCODE_OACK:
    144     State->Status = EFI_SUCCESS;
    145     break;
    146 
    147   default:
    148     State->Status = EFI_PROTOCOL_ERROR;
    149   }
    150 
    151   //
    152   // Allocate buffer then copy the packet over. Use gBS->AllocatePool
    153   // in case AllocatePool will implements something tricky.
    154   //
    155   Status = gBS->AllocatePool (EfiBootServicesData, PacketLen, (VOID **) State->Packet);
    156 
    157   if (EFI_ERROR (Status)) {
    158     State->Status = EFI_OUT_OF_RESOURCES;
    159     return EFI_ABORTED;
    160   }
    161 
    162   *(State->PacketLen) = PacketLen;
    163   CopyMem (*(State->Packet), Packet, PacketLen);
    164 
    165   return EFI_ABORTED;
    166 }
    167 
    168 
    169 /**
    170   Check whether the override data is valid.
    171 
    172   It will first validate whether the server is a valid unicast. If a gateway
    173   is provided in the Override, it also check that it is a unicast on the
    174   connected network.
    175 
    176   @param  Instance               The MTFTP instance
    177   @param  Override               The override data to validate.
    178 
    179   @retval TRUE                   The override data is valid
    180   @retval FALSE                  The override data is invalid
    181 
    182 **/
    183 BOOLEAN
    184 Mtftp4OverrideValid (
    185   IN MTFTP4_PROTOCOL          *Instance,
    186   IN EFI_MTFTP4_OVERRIDE_DATA *Override
    187   )
    188 {
    189   EFI_MTFTP4_CONFIG_DATA    *Config;
    190   IP4_ADDR                  Ip;
    191   IP4_ADDR                  Netmask;
    192   IP4_ADDR                  Gateway;
    193 
    194   CopyMem (&Ip, &Override->ServerIp, sizeof (IP4_ADDR));
    195   if (IP4_IS_UNSPECIFIED (NTOHL (Ip)) || IP4_IS_LOCAL_BROADCAST (NTOHL (Ip))) {
    196     return FALSE;
    197   }
    198 
    199   Config = &Instance->Config;
    200 
    201   CopyMem (&Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
    202   Gateway = NTOHL (Gateway);
    203 
    204   if (!Config->UseDefaultSetting && (Gateway != 0)) {
    205     CopyMem (&Netmask, &Config->SubnetMask, sizeof (IP4_ADDR));
    206     CopyMem (&Ip, &Config->StationIp, sizeof (IP4_ADDR));
    207 
    208     Netmask = NTOHL (Netmask);
    209     Ip      = NTOHL (Ip);
    210 
    211     if (!NetIp4IsUnicast (Gateway, Netmask) || !IP4_NET_EQUAL (Gateway, Ip, Netmask)) {
    212       return FALSE;
    213     }
    214   }
    215 
    216   return TRUE;
    217 }
    218 
    219 
    220 /**
    221   Poll the UDP to get the IP4 default address, which may be retrieved
    222   by DHCP.
    223 
    224   The default time out value is 5 seconds. If IP has retrieved the default address,
    225   the UDP is reconfigured.
    226 
    227   @param  Instance               The Mtftp instance
    228   @param  UdpIo                  The UDP_IO to poll
    229   @param  UdpCfgData             The UDP configure data to reconfigure the UDP_IO
    230 
    231   @retval TRUE                   The default address is retrieved and UDP is reconfigured.
    232   @retval FALSE                  Some error occured.
    233 
    234 **/
    235 BOOLEAN
    236 Mtftp4GetMapping (
    237   IN MTFTP4_PROTOCOL        *Instance,
    238   IN UDP_IO                 *UdpIo,
    239   IN EFI_UDP4_CONFIG_DATA   *UdpCfgData
    240   )
    241 {
    242   MTFTP4_SERVICE            *Service;
    243   EFI_IP4_MODE_DATA         Ip4Mode;
    244   EFI_UDP4_PROTOCOL         *Udp;
    245   EFI_STATUS                Status;
    246 
    247   ASSERT (Instance->Config.UseDefaultSetting);
    248 
    249   Service = Instance->Service;
    250   Udp     = UdpIo->Protocol.Udp4;
    251 
    252   Status = gBS->SetTimer (
    253                   Service->TimerToGetMap,
    254                   TimerRelative,
    255                   MTFTP4_TIME_TO_GETMAP * TICKS_PER_SECOND
    256                   );
    257   if (EFI_ERROR (Status)) {
    258     return FALSE;
    259   }
    260 
    261   while (EFI_ERROR (gBS->CheckEvent (Service->TimerToGetMap))) {
    262     Udp->Poll (Udp);
    263 
    264     if (!EFI_ERROR (Udp->GetModeData (Udp, NULL, &Ip4Mode, NULL, NULL)) &&
    265         Ip4Mode.IsConfigured) {
    266 
    267       Udp->Configure (Udp, NULL);
    268       return (BOOLEAN) (Udp->Configure (Udp, UdpCfgData) == EFI_SUCCESS);
    269     }
    270   }
    271 
    272   return FALSE;
    273 }
    274 
    275 
    276 /**
    277   Configure the UDP port for unicast receiving.
    278 
    279   @param  UdpIo                  The UDP_IO instance
    280   @param  Instance               The MTFTP session
    281 
    282   @retval EFI_SUCCESS            The UDP port is successfully configured for the
    283                                  session to unicast receive.
    284 
    285 **/
    286 EFI_STATUS
    287 Mtftp4ConfigUnicastPort (
    288   IN UDP_IO                 *UdpIo,
    289   IN MTFTP4_PROTOCOL        *Instance
    290   )
    291 {
    292   EFI_MTFTP4_CONFIG_DATA    *Config;
    293   EFI_UDP4_CONFIG_DATA      UdpConfig;
    294   EFI_STATUS                Status;
    295   IP4_ADDR                  Ip;
    296 
    297   Config = &Instance->Config;
    298 
    299   UdpConfig.AcceptBroadcast    = FALSE;
    300   UdpConfig.AcceptPromiscuous  = FALSE;
    301   UdpConfig.AcceptAnyPort      = FALSE;
    302   UdpConfig.AllowDuplicatePort = FALSE;
    303   UdpConfig.TypeOfService      = 0;
    304   UdpConfig.TimeToLive         = 64;
    305   UdpConfig.DoNotFragment      = FALSE;
    306   UdpConfig.ReceiveTimeout     = 0;
    307   UdpConfig.TransmitTimeout    = 0;
    308   UdpConfig.UseDefaultAddress  = Config->UseDefaultSetting;
    309   IP4_COPY_ADDRESS (&UdpConfig.StationAddress, &Config->StationIp);
    310   IP4_COPY_ADDRESS (&UdpConfig.SubnetMask, &Config->SubnetMask);
    311   UdpConfig.StationPort        = 0;
    312   UdpConfig.RemotePort         = 0;
    313 
    314   Ip = HTONL (Instance->ServerIp);
    315   IP4_COPY_ADDRESS (&UdpConfig.RemoteAddress, &Ip);
    316 
    317   Status = UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, &UdpConfig);
    318 
    319   if ((Status == EFI_NO_MAPPING) && Mtftp4GetMapping (Instance, UdpIo, &UdpConfig)) {
    320     return EFI_SUCCESS;
    321   }
    322 
    323   if (!Config->UseDefaultSetting && !EFI_IP4_EQUAL (&mZeroIp4Addr, &Config->GatewayIp)) {
    324     //
    325     // The station IP address is manually configured and the Gateway IP is not 0.
    326     // Add the default route for this UDP instance.
    327     //
    328     Status = UdpIo->Protocol.Udp4->Routes (
    329                                      UdpIo->Protocol.Udp4,
    330                                      FALSE,
    331                                      &mZeroIp4Addr,
    332                                      &mZeroIp4Addr,
    333                                      &Config->GatewayIp
    334                                      );
    335     if (EFI_ERROR (Status)) {
    336       UdpIo->Protocol.Udp4->Configure (UdpIo->Protocol.Udp4, NULL);
    337     }
    338   }
    339   return Status;
    340 }
    341 
    342 
    343 /**
    344   Start the MTFTP session to do the operation, such as read file,
    345   write file, and read directory.
    346 
    347   @param  This                   The MTFTP session
    348   @param  Token                  The token than encapsues the user's request.
    349   @param  Operation              The operation to do
    350 
    351   @retval EFI_INVALID_PARAMETER  Some of the parameters are invalid.
    352   @retval EFI_NOT_STARTED        The MTFTP session hasn't been configured.
    353   @retval EFI_ALREADY_STARTED    There is pending operation for the session.
    354   @retval EFI_SUCCESS            The operation is successfully started.
    355 
    356 **/
    357 EFI_STATUS
    358 Mtftp4Start (
    359   IN EFI_MTFTP4_PROTOCOL    *This,
    360   IN EFI_MTFTP4_TOKEN       *Token,
    361   IN UINT16                 Operation
    362   )
    363 {
    364   MTFTP4_PROTOCOL           *Instance;
    365   EFI_MTFTP4_OVERRIDE_DATA  *Override;
    366   EFI_MTFTP4_CONFIG_DATA    *Config;
    367   EFI_TPL                   OldTpl;
    368   EFI_STATUS                Status;
    369 
    370   //
    371   // Validate the parameters
    372   //
    373   if ((This == NULL) || (Token == NULL) || (Token->Filename == NULL) ||
    374       ((Token->OptionCount != 0) && (Token->OptionList == NULL))) {
    375     return EFI_INVALID_PARAMETER;
    376   }
    377 
    378   //
    379   // User must provide at least one method to collect the data for download.
    380   //
    381   if (((Operation == EFI_MTFTP4_OPCODE_RRQ) || (Operation == EFI_MTFTP4_OPCODE_DIR)) &&
    382       ((Token->Buffer == NULL) && (Token->CheckPacket == NULL))) {
    383     return EFI_INVALID_PARAMETER;
    384   }
    385 
    386   //
    387   // User must provide at least one method to provide the data for upload.
    388   //
    389   if ((Operation == EFI_MTFTP4_OPCODE_WRQ) &&
    390      ((Token->Buffer == NULL) && (Token->PacketNeeded == NULL))) {
    391     return EFI_INVALID_PARAMETER;
    392   }
    393 
    394   Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
    395 
    396   Status = EFI_SUCCESS;
    397   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    398 
    399   if (Instance->State != MTFTP4_STATE_CONFIGED) {
    400     Status = EFI_NOT_STARTED;
    401   }
    402 
    403   if (Instance->Operation != 0) {
    404     Status = EFI_ACCESS_DENIED;
    405   }
    406 
    407   if (EFI_ERROR (Status)) {
    408     gBS->RestoreTPL (OldTpl);
    409     return Status;
    410   }
    411 
    412   //
    413   // Set the Operation now to prevent the application start other
    414   // operations.
    415   //
    416   Instance->Operation = Operation;
    417   Override            = Token->OverrideData;
    418 
    419   if ((Override != NULL) && !Mtftp4OverrideValid (Instance, Override)) {
    420     Status = EFI_INVALID_PARAMETER;
    421     goto ON_ERROR;
    422   }
    423 
    424   if (Token->OptionCount != 0) {
    425     Status = Mtftp4ParseOption (
    426                Token->OptionList,
    427                Token->OptionCount,
    428                TRUE,
    429                &Instance->RequestOption
    430                );
    431 
    432     if (EFI_ERROR (Status)) {
    433       goto ON_ERROR;
    434     }
    435   }
    436 
    437   //
    438   // Set the operation parameters from the configuration or override data.
    439   //
    440   Config                  = &Instance->Config;
    441   Instance->Token         = Token;
    442   Instance->BlkSize       = MTFTP4_DEFAULT_BLKSIZE;
    443 
    444   CopyMem (&Instance->ServerIp, &Config->ServerIp, sizeof (IP4_ADDR));
    445   Instance->ServerIp      = NTOHL (Instance->ServerIp);
    446 
    447   Instance->ListeningPort = Config->InitialServerPort;
    448   Instance->ConnectedPort = 0;
    449 
    450   CopyMem (&Instance->Gateway, &Config->GatewayIp, sizeof (IP4_ADDR));
    451   Instance->Gateway       = NTOHL (Instance->Gateway);
    452 
    453   Instance->MaxRetry      = Config->TryCount;
    454   Instance->Timeout       = Config->TimeoutValue;
    455   Instance->Master        = TRUE;
    456 
    457   if (Override != NULL) {
    458     CopyMem (&Instance->ServerIp, &Override->ServerIp, sizeof (IP4_ADDR));
    459     CopyMem (&Instance->Gateway, &Override->GatewayIp, sizeof (IP4_ADDR));
    460 
    461     Instance->ServerIp      = NTOHL (Instance->ServerIp);
    462     Instance->Gateway       = NTOHL (Instance->Gateway);
    463 
    464     Instance->ListeningPort = Override->ServerPort;
    465     Instance->MaxRetry      = Override->TryCount;
    466     Instance->Timeout       = Override->TimeoutValue;
    467   }
    468 
    469   if (Instance->ListeningPort == 0) {
    470     Instance->ListeningPort = MTFTP4_DEFAULT_SERVER_PORT;
    471   }
    472 
    473   if (Instance->MaxRetry == 0) {
    474     Instance->MaxRetry = MTFTP4_DEFAULT_RETRY;
    475   }
    476 
    477   if (Instance->Timeout == 0) {
    478     Instance->Timeout = MTFTP4_DEFAULT_TIMEOUT;
    479   }
    480 
    481   //
    482   // Config the unicast UDP child to send initial request
    483   //
    484   Status = Mtftp4ConfigUnicastPort (Instance->UnicastPort, Instance);
    485 
    486   if (EFI_ERROR (Status)) {
    487     goto ON_ERROR;
    488   }
    489 
    490   //
    491   // Set initial status.
    492   //
    493   Token->Status = EFI_NOT_READY;
    494 
    495   //
    496   // Build and send an initial requests
    497   //
    498   if (Operation == EFI_MTFTP4_OPCODE_WRQ) {
    499     Status = Mtftp4WrqStart (Instance, Operation);
    500   } else {
    501     Status = Mtftp4RrqStart (Instance, Operation);
    502   }
    503 
    504   gBS->RestoreTPL (OldTpl);
    505 
    506   if (EFI_ERROR (Status)) {
    507     goto ON_ERROR;
    508   }
    509 
    510   if (Token->Event != NULL) {
    511     return EFI_SUCCESS;
    512   }
    513 
    514   //
    515   // Return immediately for asynchronous operation or poll the
    516   // instance for synchronous operation.
    517   //
    518   while (Token->Status == EFI_NOT_READY) {
    519     This->Poll (This);
    520   }
    521 
    522   return Token->Status;
    523 
    524 ON_ERROR:
    525   Mtftp4CleanOperation (Instance, Status);
    526   gBS->RestoreTPL (OldTpl);
    527 
    528   return Status;
    529 }
    530 
    531 
    532 /**
    533   Reads the current operational settings.
    534 
    535   The GetModeData()function reads the current operational settings of this
    536   EFI MTFTPv4 Protocol driver instance.
    537 
    538   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.
    539   @param  ModeData               Pointer to storage for the EFI MTFTPv4 Protocol
    540                                  driver mode data.
    541 
    542   @retval EFI_SUCCESS            The configuration data was successfully returned.
    543   @retval EFI_OUT_OF_RESOURCES   The required mode data could not be allocated.
    544   @retval EFI_INVALID_PARAMETER  This is NULL or ModeData is NULL.
    545 
    546 **/
    547 EFI_STATUS
    548 EFIAPI
    549 EfiMtftp4GetModeData (
    550   IN     EFI_MTFTP4_PROTOCOL    *This,
    551      OUT EFI_MTFTP4_MODE_DATA  *ModeData
    552   )
    553 {
    554   MTFTP4_PROTOCOL  *Instance;
    555   EFI_TPL          OldTpl;
    556 
    557   if ((This == NULL) || (ModeData == NULL)) {
    558     return EFI_INVALID_PARAMETER;
    559   }
    560 
    561   OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    562 
    563   Instance                         = MTFTP4_PROTOCOL_FROM_THIS (This);
    564   CopyMem(&ModeData->ConfigData, &Instance->Config, sizeof (Instance->Config));
    565   ModeData->SupportedOptionCount   = MTFTP4_SUPPORTED_OPTIONS;
    566   ModeData->SupportedOptoins       = (UINT8 **) mMtftp4SupportedOptions;
    567   ModeData->UnsupportedOptionCount = 0;
    568   ModeData->UnsupportedOptoins     = NULL;
    569 
    570   gBS->RestoreTPL (OldTpl);
    571 
    572   return EFI_SUCCESS;
    573 }
    574 
    575 
    576 
    577 /**
    578   Initializes, changes, or resets the default operational setting for this
    579   EFI MTFTPv4 Protocol driver instance.
    580 
    581   The Configure() function is used to set and change the configuration data for
    582   this EFI MTFTPv4 Protocol driver instance. The configuration data can be reset
    583   to startup defaults by calling Configure() with MtftpConfigData set to NULL.
    584   Whenever the instance is reset, any pending operation is aborted. By changing
    585   the EFI MTFTPv4 Protocol driver instance configuration data, the client can
    586   connect to different MTFTPv4 servers. The configuration parameters in
    587   MtftpConfigData are used as the default parameters in later MTFTPv4 operations
    588   and can be overridden in later operations.
    589 
    590   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance
    591   @param  ConfigData             MtftpConfigDataPointer to the configuration data
    592                                  structure
    593 
    594   @retval EFI_SUCCESS            The EFI MTFTPv4 Protocol driver was configured
    595                                  successfully.
    596   @retval EFI_INVALID_PARAMETER  One or more following conditions are TRUE:
    597                                  1.This is NULL.
    598                                  2.MtftpConfigData.UseDefaultSetting is FALSE and
    599                                    MtftpConfigData.StationIp is not a valid IPv4
    600                                    unicast address.
    601                                  3.MtftpCofigData.UseDefaultSetting is FALSE and
    602                                    MtftpConfigData.SubnetMask is invalid.
    603                                  4.MtftpCofigData.ServerIp is not a valid IPv4
    604                                    unicast address.
    605                                  5.MtftpConfigData.UseDefaultSetting is FALSE and
    606                                    MtftpConfigData.GatewayIp is not a valid IPv4
    607                                    unicast address or is not in the same subnet
    608                                    with station address.
    609   @retval EFI_ACCESS_DENIED      The EFI configuration could not be changed at this
    610                                  time because there is one MTFTP background operation
    611                                  in progress.
    612   @retval EFI_NO_MAPPING         When using a default address, configuration
    613                                  (DHCP, BOOTP, RARP, etc.) has not finished yet.
    614   @retval EFI_UNSUPPORTED        A configuration protocol (DHCP, BOOTP, RARP, etc.)
    615                                  could not be located when clients choose to use
    616                                  the default address settings.
    617   @retval EFI_OUT_OF_RESOURCES   The EFI MTFTPv4 Protocol driver instance data could
    618                                  not be allocated.
    619   @retval EFI_DEVICE_ERROR       An unexpected system or network error occurred.
    620                                  The EFI MTFTPv4 Protocol driver instance is not
    621                                  configured.
    622 
    623 **/
    624 EFI_STATUS
    625 EFIAPI
    626 EfiMtftp4Configure (
    627   IN EFI_MTFTP4_PROTOCOL    *This,
    628   IN EFI_MTFTP4_CONFIG_DATA *ConfigData
    629   )
    630 {
    631   MTFTP4_PROTOCOL           *Instance;
    632   EFI_TPL                   OldTpl;
    633   IP4_ADDR                  Ip;
    634   IP4_ADDR                  Netmask;
    635   IP4_ADDR                  Gateway;
    636   IP4_ADDR                  ServerIp;
    637 
    638   if (This == NULL) {
    639     return EFI_INVALID_PARAMETER;
    640   }
    641 
    642   Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
    643 
    644   if (ConfigData == NULL) {
    645     //
    646     // Reset the operation if ConfigData is NULL
    647     //
    648     OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    649 
    650     Mtftp4CleanOperation (Instance, EFI_ABORTED);
    651     ZeroMem (&Instance->Config, sizeof (EFI_MTFTP4_CONFIG_DATA));
    652     Instance->State = MTFTP4_STATE_UNCONFIGED;
    653 
    654     gBS->RestoreTPL (OldTpl);
    655 
    656   } else {
    657     //
    658     // Configure the parameters for new operation.
    659     //
    660     CopyMem (&Ip, &ConfigData->StationIp, sizeof (IP4_ADDR));
    661     CopyMem (&Netmask, &ConfigData->SubnetMask, sizeof (IP4_ADDR));
    662     CopyMem (&Gateway, &ConfigData->GatewayIp, sizeof (IP4_ADDR));
    663     CopyMem (&ServerIp, &ConfigData->ServerIp, sizeof (IP4_ADDR));
    664 
    665     Ip       = NTOHL (Ip);
    666     Netmask  = NTOHL (Netmask);
    667     Gateway  = NTOHL (Gateway);
    668     ServerIp = NTOHL (ServerIp);
    669 
    670     if (!ConfigData->UseDefaultSetting &&
    671        ((!IP4_IS_VALID_NETMASK (Netmask) || !NetIp4IsUnicast (Ip, Netmask)))) {
    672 
    673       return EFI_INVALID_PARAMETER;
    674     }
    675 
    676     if ((Gateway != 0) &&
    677         (!IP4_NET_EQUAL (Gateway, Ip, Netmask) || !NetIp4IsUnicast (Gateway, Netmask))) {
    678 
    679       return EFI_INVALID_PARAMETER;
    680     }
    681 
    682     OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
    683 
    684     if ((Instance->State == MTFTP4_STATE_CONFIGED) && (Instance->Operation != 0)) {
    685       gBS->RestoreTPL (OldTpl);
    686       return EFI_ACCESS_DENIED;
    687     }
    688 
    689     CopyMem(&Instance->Config, ConfigData, sizeof (*ConfigData));;
    690     Instance->State = MTFTP4_STATE_CONFIGED;
    691 
    692     gBS->RestoreTPL (OldTpl);
    693   }
    694 
    695   return EFI_SUCCESS;
    696 }
    697 
    698 
    699 
    700 /**
    701   Parses the options in an MTFTPv4 OACK packet.
    702 
    703   The ParseOptions() function parses the option fields in an MTFTPv4 OACK packet
    704   and returns the number of options that were found and optionally a list of
    705   pointers to the options in the packet.
    706   If one or more of the option fields are not valid, then EFI_PROTOCOL_ERROR is
    707   returned and *OptionCount and *OptionList stop at the last valid option.
    708   The OptionList is allocated by this function, and caller should free it when used.
    709 
    710   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.
    711   @param  PacketLen              Length of the OACK packet to be parsed.
    712   @param  Packet                 Pointer to the OACK packet to be parsed.
    713   @param  OptionCount            Pointer to the number of options in following OptionList.
    714   @param  OptionList             Pointer to EFI_MTFTP4_OPTION storage. Call the
    715                                  EFI Boot Service FreePool() to release theOptionList
    716                                  if the options in this OptionList are not needed
    717                                  any more
    718 
    719   @retval EFI_SUCCESS            The OACK packet was valid and the OptionCount and
    720                                  OptionList parameters have been updated.
    721   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
    722                                  1.PacketLen is 0.
    723                                  2.Packet is NULL or Packet is not a valid MTFTPv4 packet.
    724                                  3.OptionCount is NULL.
    725   @retval EFI_NOT_FOUND          No options were found in the OACK packet.
    726   @retval EFI_OUT_OF_RESOURCES   Storage for the OptionList array cannot be allocated.
    727   @retval EFI_PROTOCOL_ERROR     One or more of the option fields is invalid.
    728 
    729 **/
    730 EFI_STATUS
    731 EFIAPI
    732 EfiMtftp4ParseOptions (
    733   IN     EFI_MTFTP4_PROTOCOL    *This,
    734   IN     UINT32                 PacketLen,
    735   IN     EFI_MTFTP4_PACKET      *Packet,
    736      OUT UINT32                 *OptionCount,
    737      OUT EFI_MTFTP4_OPTION      **OptionList          OPTIONAL
    738   )
    739 {
    740   EFI_STATUS                Status;
    741 
    742   if ((This == NULL) || (PacketLen < MTFTP4_OPCODE_LEN) ||
    743       (Packet == NULL) || (OptionCount == NULL)) {
    744 
    745     return EFI_INVALID_PARAMETER;
    746   }
    747 
    748   Status = Mtftp4ExtractOptions (Packet, PacketLen, OptionCount, OptionList);
    749 
    750   if (EFI_ERROR (Status)) {
    751     return Status;
    752   }
    753 
    754   if (*OptionCount == 0) {
    755     return EFI_NOT_FOUND;
    756   }
    757 
    758   return EFI_SUCCESS;
    759 }
    760 
    761 
    762 /**
    763   Downloads a file from an MTFTPv4 server.
    764 
    765   The ReadFile() function is used to initialize and start an MTFTPv4 download
    766   process and optionally wait for completion. When the download operation completes,
    767   whether successfully or not, the Token.Status field is updated by the EFI MTFTPv4
    768   Protocol driver and then Token.Event is signaled (if it is not NULL).
    769   Data can be downloaded from the MTFTPv4 server into either of the following locations:
    770   1.A fixed buffer that is pointed to by Token.Buffer
    771   2.A download service function that is pointed to by Token.CheckPacket
    772   If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket
    773   will be called first. If the call is successful, the packet will be stored in
    774   Token.Buffer.
    775 
    776   @param  This                  Pointer to the EFI_MTFTP4_PROTOCOL instance
    777   @param  Token                 Pointer to the token structure to provide the
    778                                 parameters that are used in this operation.
    779 
    780   @retval EFI_SUCCESS           The data file has been transferred successfully.
    781   @retval EFI_OUT_OF_RESOURCES  Required system resources could not be allocated.
    782   @retval EFI_BUFFER_TOO_SMALL  BufferSize is not large enough to hold the downloaded
    783                                 data in downloading process.
    784   @retval EFI_ABORTED           Current operation is aborted by user.
    785   @retval EFI_ICMP_ERROR        An ICMP ERROR packet was received.
    786   @retval EFI_TIMEOUT           No responses were received from the MTFTPv4 server.
    787   @retval EFI_TFTP_ERROR        An MTFTPv4 ERROR packet was received.
    788   @retval EFI_DEVICE_ERROR      An unexpected network error or system error occurred.
    789   @retval EFI_NO_MEDIA          There was a media error.
    790 
    791 **/
    792 EFI_STATUS
    793 EFIAPI
    794 EfiMtftp4ReadFile (
    795   IN EFI_MTFTP4_PROTOCOL    *This,
    796   IN EFI_MTFTP4_TOKEN       *Token
    797   )
    798 {
    799   return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_RRQ);
    800 }
    801 
    802 
    803 /**
    804   Sends a data file to an MTFTPv4 server. May be unsupported in some EFI implementations
    805 
    806   The WriteFile() function is used to initialize an uploading operation with the
    807   given option list and optionally wait for completion. If one or more of the
    808   options is not supported by the server, the unsupported options are ignored and
    809   a standard TFTP process starts instead. When the upload process completes,
    810   whether successfully or not, Token.Event is signaled, and the EFI MTFTPv4 Protocol
    811   driver updates Token.Status.
    812   The caller can supply the data to be uploaded in the following two modes:
    813   1.Through the user-provided buffer
    814   2.Through a callback function
    815   With the user-provided buffer, the Token.BufferSize field indicates the length
    816   of the buffer, and the driver will upload the data in the buffer. With an
    817   EFI_MTFTP4_PACKET_NEEDED callback function, the driver will call this callback
    818   function to get more data from the user to upload. See the definition of
    819   EFI_MTFTP4_PACKET_NEEDED for more information. These two modes cannot be used at
    820   the same time. The callback function will be ignored if the user provides the buffer.
    821 
    822   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance.
    823   @param  Token                  Pointer to the token structure to provide the
    824                                  parameters that are used in this function
    825 
    826   @retval EFI_SUCCESS            The upload session has started.
    827   @retval EFI_UNSUPPORTED        The operation is not supported by this implementation.
    828   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
    829                                  1. This is NULL.
    830                                  2. Token is NULL.
    831                                  3. Token.Filename is NULL.
    832                                  4. Token.OptionCount is not zero and
    833                                     Token.OptionList is NULL.
    834                                  5. One or more options in Token.OptionList have wrong
    835                                     format.
    836                                  6. Token.Buffer and Token.PacketNeeded are both
    837                                     NULL.
    838                                  7. One or more IPv4 addresses in Token.OverrideData
    839                                     are not valid unicast IPv4 addresses if
    840                                     Token.OverrideData is not NULL.
    841   @retval EFI_UNSUPPORTED        One or more options in the Token.OptionList are in the
    842                                  unsupported list of structure EFI_MTFTP4_MODE_DATA.
    843   @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.
    844   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,
    845                                  BOOTP, RARP, etc.) is not finished yet.
    846   @retval EFI_ALREADY_STARTED    This Token is already being used in another MTFTPv4
    847                                  session.
    848   @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.
    849   @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.
    850   @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.
    851 
    852 **/
    853 EFI_STATUS
    854 EFIAPI
    855 EfiMtftp4WriteFile (
    856   IN EFI_MTFTP4_PROTOCOL    *This,
    857   IN EFI_MTFTP4_TOKEN       *Token
    858   )
    859 {
    860   return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_WRQ);
    861 }
    862 
    863 
    864 /**
    865   Downloads a data file "directory" from an MTFTPv4 server.
    866   May be unsupported in some EFI implementations
    867 
    868   The ReadDirectory() function is used to return a list of files on the MTFTPv4
    869   server that are logically (or operationally) related to Token.Filename. The
    870   directory request packet that is sent to the server is built with the option
    871   list that was provided by caller, if present.
    872   The file information that the server returns is put into either of the following
    873   locations:
    874   1.A fixed buffer that is pointed to by Token.Buffer
    875   2.A download service function that is pointed to by Token.CheckPacket
    876   If both Token.Buffer and Token.CheckPacket are used, then Token.CheckPacket will
    877   be called first. If the call is successful, the packet will be stored in Token.Buffer.
    878   The returned directory listing in the Token.Buffer or EFI_MTFTP4_PACKET consists
    879   of a list of two or three variable-length ASCII strings, each terminated by a
    880   null character, for each file in the directory. If the multicast option is involved,
    881   the first field of each directory entry is the static multicast IP address and
    882   UDP port number that is associated with the file name. The format of the field
    883   is ip:ip:ip:ip:port. If the multicast option is not involved, this field and its
    884   terminating null character are not present.
    885   The next field of each directory entry is the file name and the last field is
    886   the file information string. The information string contains the file size and
    887   the create/modify timestamp. The format of the information string is filesize
    888   yyyy-mm-dd hh:mm:ss:ffff. The timestamp is Coordinated Universal Time
    889   (UTC; also known as Greenwich Mean Time [GMT]).
    890   The only difference between ReadFile and ReadDirectory is the opcode used.
    891 
    892   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance
    893   @param  Token                  Pointer to the token structure to provide the
    894                                  parameters that are used in this function
    895 
    896   @retval EFI_SUCCESS            The MTFTPv4 related file "directory" has been downloaded.
    897   @retval EFI_UNSUPPORTED        The operation is not supported by this implementation.
    898   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
    899                                  1. This is NULL.
    900                                  2. Token is NULL.
    901                                  3. Token.Filename is NULL.
    902                                  4. Token.OptionCount is not zero and
    903                                     Token.OptionList is NULL.
    904                                  5. One or more options in Token.OptionList have wrong
    905                                     format.
    906                                  6. Token.Buffer and Token.PacketNeeded are both
    907                                     NULL.
    908                                  7. One or more IPv4 addresses in Token.OverrideData
    909                                     are not valid unicast IPv4 addresses if
    910                                     Token.OverrideData is not NULL.
    911   @retval EFI_UNSUPPORTED        One or more options in the Token.OptionList are in the
    912                                  unsupported list of structure EFI_MTFTP4_MODE_DATA.
    913   @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.
    914   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,
    915                                  BOOTP, RARP, etc.) is not finished yet.
    916   @retval EFI_ALREADY_STARTED    This Token is already being used in another MTFTPv4
    917                                  session.
    918   @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.
    919   @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.
    920   @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.
    921 
    922 **/
    923 EFI_STATUS
    924 EFIAPI
    925 EfiMtftp4ReadDirectory (
    926   IN EFI_MTFTP4_PROTOCOL        *This,
    927   IN EFI_MTFTP4_TOKEN           *Token
    928   )
    929 {
    930   return Mtftp4Start (This, Token, EFI_MTFTP4_OPCODE_DIR);
    931 }
    932 
    933 
    934 /**
    935   Gets information about a file from an MTFTPv4 server.
    936 
    937   The GetInfo() function assembles an MTFTPv4 request packet with options;
    938   sends it to the MTFTPv4 server; and may return an MTFTPv4 OACK, MTFTPv4 ERROR,
    939   or ICMP ERROR packet. Retries occur only if no response packets are received
    940   from the MTFTPv4 server before the timeout expires.
    941   It is implemented with EfiMtftp4ReadFile: build a token, then pass it to
    942   EfiMtftp4ReadFile. In its check packet callback abort the opertions.
    943 
    944   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance
    945   @param  OverrideData           Data that is used to override the existing
    946                                  parameters. If NULL, the default parameters that
    947                                  were set in the EFI_MTFTP4_PROTOCOL.Configure()
    948                                  function are used
    949   @param  Filename               Pointer to null-terminated ASCII file name string
    950   @param  ModeStr                Pointer to null-terminated ASCII mode string. If NULL, "octet"
    951                                  will be used
    952   @param  OptionCount            Number of option/value string pairs in OptionList
    953   @param  OptionList             Pointer to array of option/value string pairs.
    954                                  Ignored if OptionCount is zero
    955   @param  PacketLength           The number of bytes in the returned packet
    956   @param  Packet                 PacketThe pointer to the received packet. This
    957                                  buffer must be freed by the caller.
    958 
    959   @retval EFI_SUCCESS            An MTFTPv4 OACK packet was received and is in
    960                                  the Buffer.
    961   @retval EFI_INVALID_PARAMETER  One or more of the following conditions is TRUE:
    962                                  1.This is NULL.
    963                                  2.Filename is NULL.
    964                                  3.OptionCount is not zero and OptionList is NULL.
    965                                  4.One or more options in OptionList have wrong format.
    966                                  5.PacketLength is NULL.
    967                                  6.One or more IPv4 addresses in OverrideData are
    968                                    not valid unicast IPv4 addresses if OverrideData
    969                                    is not NULL.
    970   @retval EFI_UNSUPPORTED        One or more options in the OptionList are in the
    971                                  unsupported list of structure EFI_MTFTP4_MODE_DATA
    972   @retval EFI_NOT_STARTED        The EFI MTFTPv4 Protocol driver has not been started.
    973   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,
    974                                  BOOTP, RARP, etc.) has not finished yet.
    975   @retval EFI_ACCESS_DENIED      The previous operation has not completed yet.
    976   @retval EFI_OUT_OF_RESOURCES   Required system resources could not be allocated.
    977   @retval EFI_TFTP_ERROR         An MTFTPv4 ERROR packet was received and is in
    978                                  the Buffer.
    979   @retval EFI_ICMP_ERROR         An ICMP ERROR packet was received and the Packet
    980                                  is set to NULL.
    981   @retval EFI_PROTOCOL_ERROR     An unexpected MTFTPv4 packet was received and is
    982                                  in the Buffer.
    983   @retval EFI_TIMEOUT            No responses were received from the MTFTPv4 server.
    984   @retval EFI_DEVICE_ERROR       An unexpected network error or system error occurred.
    985   @retval EFI_NO_MEDIA           There was a media error.
    986 
    987 **/
    988 EFI_STATUS
    989 EFIAPI
    990 EfiMtftp4GetInfo (
    991   IN     EFI_MTFTP4_PROTOCOL      *This,
    992   IN     EFI_MTFTP4_OVERRIDE_DATA *OverrideData        OPTIONAL,
    993   IN     UINT8                    *Filename,
    994   IN     UINT8                    *ModeStr             OPTIONAL,
    995   IN     UINT8                    OptionCount,
    996   IN     EFI_MTFTP4_OPTION        *OptionList          OPTIONAL,
    997      OUT UINT32                   *PacketLength,
    998      OUT EFI_MTFTP4_PACKET        **Packet             OPTIONAL
    999   )
   1000 {
   1001   EFI_MTFTP4_TOKEN          Token;
   1002   MTFTP4_GETINFO_STATE      State;
   1003   EFI_STATUS                Status;
   1004 
   1005   if ((This == NULL) || (Filename == NULL) || (PacketLength == NULL) ||
   1006       ((OptionCount != 0) && (OptionList == NULL))) {
   1007     return EFI_INVALID_PARAMETER;
   1008   }
   1009 
   1010   if (Packet != NULL) {
   1011     *Packet = NULL;
   1012   }
   1013 
   1014   *PacketLength         = 0;
   1015   State.Packet          = Packet;
   1016   State.PacketLen       = PacketLength;
   1017   State.Status          = EFI_SUCCESS;
   1018 
   1019   //
   1020   // Fill in the Token to issue an synchronous ReadFile operation
   1021   //
   1022   Token.Status          = EFI_SUCCESS;
   1023   Token.Event           = NULL;
   1024   Token.OverrideData    = OverrideData;
   1025   Token.Filename        = Filename;
   1026   Token.ModeStr         = ModeStr;
   1027   Token.OptionCount     = OptionCount;
   1028   Token.OptionList      = OptionList;
   1029   Token.BufferSize      = 0;
   1030   Token.Buffer          = NULL;
   1031   Token.Context         = &State;
   1032   Token.CheckPacket     = Mtftp4GetInfoCheckPacket;
   1033   Token.TimeoutCallback = NULL;
   1034   Token.PacketNeeded    = NULL;
   1035 
   1036   Status                = EfiMtftp4ReadFile (This, &Token);
   1037 
   1038   if (EFI_ABORTED == Status) {
   1039     return State.Status;
   1040   }
   1041 
   1042   return Status;
   1043 }
   1044 
   1045 /**
   1046   Polls for incoming data packets and processes outgoing data packets.
   1047 
   1048   The Poll() function can be used by network drivers and applications to increase
   1049   the rate that data packets are moved between the communications device and the
   1050   transmit and receive queues.
   1051   In some systems, the periodic timer event in the managed network driver may not
   1052   poll the underlying communications device fast enough to transmit and/or receive
   1053   all data packets without missing incoming packets or dropping outgoing packets.
   1054   Drivers and applications that are experiencing packet loss should try calling
   1055   the Poll() function more often.
   1056 
   1057   @param  This                   Pointer to the EFI_MTFTP4_PROTOCOL instance
   1058 
   1059   @retval EFI_SUCCESS            Incoming or outgoing data was processed.
   1060   @retval EFI_NOT_STARTED        This EFI MTFTPv4 Protocol instance has not been started.
   1061   @retval EFI_NO_MAPPING         When using a default address, configuration (DHCP,
   1062                                  BOOTP, RARP, etc.) is not finished yet.
   1063   @retval EFI_INVALID_PARAMETER  This is NULL.
   1064   @retval EFI_DEVICE_ERROR       An unexpected system or network error occurred.
   1065   @retval EFI_TIMEOUT            Data was dropped out of the transmit and/or receive
   1066                                  queue. Consider increasing the polling rate.
   1067 
   1068 **/
   1069 EFI_STATUS
   1070 EFIAPI
   1071 EfiMtftp4Poll (
   1072   IN EFI_MTFTP4_PROTOCOL    *This
   1073   )
   1074 {
   1075   MTFTP4_PROTOCOL           *Instance;
   1076   EFI_UDP4_PROTOCOL         *Udp;
   1077 
   1078   if (This == NULL) {
   1079     return EFI_INVALID_PARAMETER;
   1080   }
   1081 
   1082   Instance = MTFTP4_PROTOCOL_FROM_THIS (This);
   1083 
   1084   if (Instance->State == MTFTP4_STATE_UNCONFIGED) {
   1085     return EFI_NOT_STARTED;
   1086   } else if (Instance->State == MTFTP4_STATE_DESTROY) {
   1087     return EFI_DEVICE_ERROR;
   1088   }
   1089 
   1090   Udp = Instance->UnicastPort->Protocol.Udp4;
   1091   return Udp->Poll (Udp);
   1092 }
   1093 
   1094 EFI_MTFTP4_PROTOCOL gMtftp4ProtocolTemplate = {
   1095   EfiMtftp4GetModeData,
   1096   EfiMtftp4Configure,
   1097   EfiMtftp4GetInfo,
   1098   EfiMtftp4ParseOptions,
   1099   EfiMtftp4ReadFile,
   1100   EfiMtftp4WriteFile,
   1101   EfiMtftp4ReadDirectory,
   1102   EfiMtftp4Poll
   1103 };
   1104