Home | History | Annotate | Download | only in UefiPxeBcDxe
      1 /** @file
      2   Functions implementation related with Mtftp for UefiPxeBc Driver.
      3 
      4   Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
      5 
      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.
     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 #include "PxeBcImpl.h"
     17 
     18 CHAR8 *mMtftpOptions[PXE_MTFTP_OPTION_MAXIMUM_INDEX] = {
     19   "blksize",
     20   "timeout",
     21   "tsize",
     22   "multicast"
     23 };
     24 
     25 
     26 /**
     27   This is a callback function when packets are received or transmitted in Mtftp driver.
     28 
     29   A callback function that is provided by the caller to intercept
     30   the EFI_MTFTP6_OPCODE_DATA or EFI_MTFTP6_OPCODE_DATA8 packets processed in the
     31   EFI_MTFTP6_PROTOCOL.ReadFile() function, and alternatively to intercept
     32   EFI_MTFTP6_OPCODE_OACK or EFI_MTFTP6_OPCODE_ERROR packets during a call to
     33   EFI_MTFTP6_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory().
     34 
     35   @param[in]  This           Pointer to EFI_MTFTP6_PROTOCOL.
     36   @param[in]  Token          Pointer to EFI_MTFTP6_TOKEN.
     37   @param[in]  PacketLen      Length of EFI_MTFTP6_PACKET.
     38   @param[in]  Packet         Pointer to EFI_MTFTP6_PACKET to be checked.
     39 
     40   @retval EFI_SUCCESS    The current operation succeeded.
     41   @retval EFI_ABORTED    Abort the current transfer process.
     42 
     43 **/
     44 EFI_STATUS
     45 EFIAPI
     46 PxeBcMtftp6CheckPacket (
     47   IN EFI_MTFTP6_PROTOCOL              *This,
     48   IN EFI_MTFTP6_TOKEN                 *Token,
     49   IN UINT16                           PacketLen,
     50   IN EFI_MTFTP6_PACKET                *Packet
     51   )
     52 {
     53   PXEBC_PRIVATE_DATA                  *Private;
     54   EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;
     55   EFI_STATUS                          Status;
     56 
     57   Private   = (PXEBC_PRIVATE_DATA *) Token->Context;
     58   Callback  = Private->PxeBcCallback;
     59   Status    = EFI_SUCCESS;
     60 
     61   if (Packet->OpCode == EFI_MTFTP6_OPCODE_ERROR) {
     62     //
     63     // Store the tftp error message into mode data and set the received flag.
     64     //
     65     Private->Mode.TftpErrorReceived   = TRUE;
     66     Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;
     67     AsciiStrnCpyS (
     68       Private->Mode.TftpError.ErrorString,
     69       PXE_MTFTP_ERROR_STRING_LENGTH,
     70       (CHAR8 *) Packet->Error.ErrorMessage,
     71       PXE_MTFTP_ERROR_STRING_LENGTH - 1
     72       );
     73     Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';
     74   }
     75 
     76   if (Callback != NULL) {
     77     //
     78     // Callback to user if has when received any tftp packet.
     79     //
     80     Status = Callback->Callback (
     81                         Callback,
     82                         Private->Function,
     83                         TRUE,
     84                         PacketLen,
     85                         (EFI_PXE_BASE_CODE_PACKET *) Packet
     86                         );
     87     if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
     88       //
     89       // User wants to abort current process if not EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE.
     90       //
     91       Status = EFI_ABORTED;
     92     } else {
     93       //
     94       // User wants to continue current process if EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE.
     95       //
     96       Status = EFI_SUCCESS;
     97     }
     98   }
     99 
    100   return Status;
    101 }
    102 
    103 
    104 /**
    105   This function is to get the size of a file using Tftp.
    106 
    107   @param[in]      Private        Pointer to PxeBc private data.
    108   @param[in]      Config         Pointer to EFI_MTFTP6_CONFIG_DATA.
    109   @param[in]      Filename       Pointer to boot file name.
    110   @param[in]      BlockSize      Pointer to required block size.
    111   @param[in, out] BufferSize     Pointer to buffer size.
    112 
    113   @retval EFI_SUCCESS        Sucessfully obtained the size of file.
    114   @retval EFI_NOT_FOUND      Parse the tftp ptions failed.
    115   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    116   @retval Others             Has not obtained the size of the file.
    117 
    118 **/
    119 EFI_STATUS
    120 PxeBcMtftp6GetFileSize (
    121   IN     PXEBC_PRIVATE_DATA           *Private,
    122   IN     EFI_MTFTP6_CONFIG_DATA       *Config,
    123   IN     UINT8                        *Filename,
    124   IN     UINTN                        *BlockSize,
    125   IN OUT UINT64                       *BufferSize
    126   )
    127 {
    128   EFI_MTFTP6_PROTOCOL                 *Mtftp6;
    129   EFI_MTFTP6_OPTION                   ReqOpt[2];
    130   EFI_MTFTP6_PACKET                   *Packet;
    131   EFI_MTFTP6_OPTION                   *Option;
    132   UINT32                              PktLen;
    133   UINT8                               OptBuf[128];
    134   UINT32                              OptCnt;
    135   EFI_STATUS                          Status;
    136 
    137   *BufferSize               = 0;
    138   Status                    = EFI_DEVICE_ERROR;
    139   Mtftp6                    = Private->Mtftp6;
    140   Packet                    = NULL;
    141   Option                    = NULL;
    142   PktLen                    = 0;
    143   OptCnt                    = 1;
    144   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    145 
    146   Status = Mtftp6->Configure (Mtftp6, Config);
    147   if (EFI_ERROR (Status)) {
    148     return Status;
    149   }
    150 
    151   //
    152   // Build the required options for get info.
    153   //
    154   ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX];
    155   PxeBcUintnToAscDec (0, OptBuf, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    156   ReqOpt[0].ValueStr  = OptBuf;
    157 
    158   if (BlockSize != NULL) {
    159     ReqOpt[1].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    160     ReqOpt[1].ValueStr  = (UINT8 *) (ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1);
    161     PxeBcUintnToAscDec (*BlockSize, ReqOpt[1].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX - (AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1));
    162     OptCnt++;
    163   }
    164 
    165   Status = Mtftp6->GetInfo (
    166                      Mtftp6,
    167                      NULL,
    168                      Filename,
    169                      NULL,
    170                      (UINT8) OptCnt,
    171                      ReqOpt,
    172                      &PktLen,
    173                      &Packet
    174                      );
    175   if (EFI_ERROR (Status)) {
    176     if (Status == EFI_TFTP_ERROR) {
    177       //
    178       // Store the tftp error message into mode data and set the received flag.
    179       //
    180       Private->Mode.TftpErrorReceived   = TRUE;
    181       Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;
    182       AsciiStrnCpyS (
    183         Private->Mode.TftpError.ErrorString,
    184         PXE_MTFTP_ERROR_STRING_LENGTH,
    185         (CHAR8 *) Packet->Error.ErrorMessage,
    186         PXE_MTFTP_ERROR_STRING_LENGTH - 1
    187         );
    188       Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';
    189     }
    190     goto ON_ERROR;
    191   }
    192 
    193   //
    194   // Parse the options in the reply packet.
    195   //
    196   OptCnt = 0;
    197   Status = Mtftp6->ParseOptions (
    198                      Mtftp6,
    199                      PktLen,
    200                      Packet,
    201                      (UINT32 *) &OptCnt,
    202                      &Option
    203                      );
    204   if (EFI_ERROR (Status)) {
    205     goto ON_ERROR;
    206   }
    207 
    208   //
    209   // Parse out the value of "tsize" option.
    210   //
    211   Status = EFI_NOT_FOUND;
    212   while (OptCnt != 0) {
    213     if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) {
    214       *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr));
    215       Status      = EFI_SUCCESS;
    216     }
    217     OptCnt--;
    218   }
    219   FreePool (Option);
    220 
    221 ON_ERROR:
    222   if (Packet != NULL) {
    223     FreePool (Packet);
    224   }
    225   Mtftp6->Configure (Mtftp6, NULL);
    226 
    227   return Status;
    228 }
    229 
    230 
    231 /**
    232   This function is to get data of a file using Tftp.
    233 
    234   @param[in]      Private        Pointer to PxeBc private data.
    235   @param[in]      Config         Pointer to EFI_MTFTP6_CONFIG_DATA.
    236   @param[in]      Filename       Pointer to boot file name.
    237   @param[in]      BlockSize      Pointer to required block size.
    238   @param[in]      BufferPtr      Pointer to buffer.
    239   @param[in, out] BufferSize     Pointer to buffer size.
    240   @param[in]      DontUseBuffer  Indicates whether with a receive buffer.
    241 
    242   @retval EFI_SUCCESS        Successfully read the data from the special file.
    243   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    244   @retval Others             Read data from file failed.
    245 
    246 **/
    247 EFI_STATUS
    248 PxeBcMtftp6ReadFile (
    249   IN    PXEBC_PRIVATE_DATA            *Private,
    250   IN     EFI_MTFTP6_CONFIG_DATA       *Config,
    251   IN     UINT8                        *Filename,
    252   IN     UINTN                        *BlockSize,
    253   IN     UINT8                        *BufferPtr,
    254   IN OUT UINT64                       *BufferSize,
    255   IN     BOOLEAN                      DontUseBuffer
    256   )
    257 {
    258   EFI_MTFTP6_PROTOCOL                 *Mtftp6;
    259   EFI_MTFTP6_TOKEN                    Token;
    260   EFI_MTFTP6_OPTION                   ReqOpt[1];
    261   UINT32                              OptCnt;
    262   UINT8                               OptBuf[128];
    263   EFI_STATUS                          Status;
    264 
    265   Status                    = EFI_DEVICE_ERROR;
    266   Mtftp6                    = Private->Mtftp6;
    267   OptCnt                    = 0;
    268   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    269 
    270   Status = Mtftp6->Configure (Mtftp6, Config);
    271   if (EFI_ERROR (Status)) {
    272     return Status;
    273   }
    274 
    275   if (BlockSize != NULL) {
    276     ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    277     ReqOpt[0].ValueStr  = OptBuf;
    278     PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    279     OptCnt++;
    280   }
    281 
    282   Token.Event         = NULL;
    283   Token.OverrideData  = NULL;
    284   Token.Filename      = Filename;
    285   Token.ModeStr       = NULL;
    286   Token.OptionCount   = OptCnt;
    287   Token.OptionList    = ReqOpt;
    288   Token.Context       = Private;
    289 
    290   if (DontUseBuffer) {
    291     Token.BufferSize  = 0;
    292     Token.Buffer      = NULL;
    293   } else {
    294     Token.BufferSize  = *BufferSize;
    295     Token.Buffer      = BufferPtr;
    296   }
    297 
    298   Token.CheckPacket     = PxeBcMtftp6CheckPacket;
    299   Token.TimeoutCallback = NULL;
    300   Token.PacketNeeded    = NULL;
    301 
    302   Status = Mtftp6->ReadFile (Mtftp6, &Token);
    303   //
    304   // Get the real size of received buffer.
    305   //
    306   *BufferSize = Token.BufferSize;
    307 
    308   Mtftp6->Configure (Mtftp6, NULL);
    309 
    310   return Status;
    311 }
    312 
    313 
    314 /**
    315   This function is used to write the data of a file using Tftp.
    316 
    317   @param[in]       Private        Pointer to PxeBc private data.
    318   @param[in]       Config         Pointer to EFI_MTFTP6_CONFIG_DATA.
    319   @param[in]       Filename       Pointer to boot file name.
    320   @param[in]       Overwrite      Indicate whether with overwrite attribute.
    321   @param[in]       BlockSize      Pointer to required block size.
    322   @param[in]       BufferPtr      Pointer to buffer.
    323   @param[in, out]  BufferSize     Pointer to buffer size.
    324 
    325   @retval EFI_SUCCESS        Successfully wrote the data into a special file.
    326   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    327   @retval other              Write data into file failed.
    328 
    329 **/
    330 EFI_STATUS
    331 PxeBcMtftp6WriteFile (
    332   IN     PXEBC_PRIVATE_DATA           *Private,
    333   IN     EFI_MTFTP6_CONFIG_DATA       *Config,
    334   IN     UINT8                        *Filename,
    335   IN     BOOLEAN                      Overwrite,
    336   IN     UINTN                        *BlockSize,
    337   IN     UINT8                        *BufferPtr,
    338   IN OUT UINT64                       *BufferSize
    339   )
    340 {
    341   EFI_MTFTP6_PROTOCOL                 *Mtftp6;
    342   EFI_MTFTP6_TOKEN                    Token;
    343   EFI_MTFTP6_OPTION                   ReqOpt[1];
    344   UINT32                              OptCnt;
    345   UINT8                               OptBuf[128];
    346   EFI_STATUS                          Status;
    347 
    348   Status                    = EFI_DEVICE_ERROR;
    349   Mtftp6                    = Private->Mtftp6;
    350   OptCnt                    = 0;
    351   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    352 
    353   Status = Mtftp6->Configure (Mtftp6, Config);
    354   if (EFI_ERROR (Status)) {
    355     return Status;
    356   }
    357 
    358   if (BlockSize != NULL) {
    359     ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    360     ReqOpt[0].ValueStr  = OptBuf;
    361     PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    362     OptCnt++;
    363   }
    364 
    365   Token.Event           = NULL;
    366   Token.OverrideData    = NULL;
    367   Token.Filename        = Filename;
    368   Token.ModeStr         = NULL;
    369   Token.OptionCount     = OptCnt;
    370   Token.OptionList      = ReqOpt;
    371   Token.BufferSize      = *BufferSize;
    372   Token.Buffer          = BufferPtr;
    373   Token.CheckPacket     = PxeBcMtftp6CheckPacket;
    374   Token.TimeoutCallback = NULL;
    375   Token.PacketNeeded    = NULL;
    376 
    377   Status = Mtftp6->WriteFile (Mtftp6, &Token);
    378   //
    379   // Get the real size of transmitted buffer.
    380   //
    381   *BufferSize = Token.BufferSize;
    382 
    383   Mtftp6->Configure (Mtftp6, NULL);
    384 
    385   return Status;
    386 }
    387 
    388 
    389 /**
    390   This function is to read the data (file) from a directory using Tftp.
    391 
    392   @param[in]       Private        Pointer to PxeBc private data.
    393   @param[in]       Config         Pointer to EFI_MTFTP6_CONFIG_DATA.
    394   @param[in]       Filename       Pointer to boot file name.
    395   @param[in]       BlockSize      Pointer to required block size.
    396   @param[in]       BufferPtr      Pointer to buffer.
    397   @param[in, out]  BufferSize     Pointer to buffer size.
    398   @param[in]       DontUseBuffer  Indicates whether to use a receive buffer.
    399 
    400   @retval EFI_SUCCESS        Successfully obtained the data from the file included in directory.
    401   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    402   @retval Others             Operation failed.
    403 
    404 **/
    405 EFI_STATUS
    406 PxeBcMtftp6ReadDirectory (
    407   IN     PXEBC_PRIVATE_DATA            *Private,
    408   IN     EFI_MTFTP6_CONFIG_DATA        *Config,
    409   IN     UINT8                         *Filename,
    410   IN     UINTN                         *BlockSize,
    411   IN     UINT8                         *BufferPtr,
    412   IN OUT UINT64                        *BufferSize,
    413   IN     BOOLEAN                       DontUseBuffer
    414   )
    415 {
    416   EFI_MTFTP6_PROTOCOL                  *Mtftp6;
    417   EFI_MTFTP6_TOKEN                     Token;
    418   EFI_MTFTP6_OPTION                    ReqOpt[1];
    419   UINT32                               OptCnt;
    420   UINT8                                OptBuf[128];
    421   EFI_STATUS                           Status;
    422 
    423   Status                    = EFI_DEVICE_ERROR;
    424   Mtftp6                    = Private->Mtftp6;
    425   OptCnt                    = 0;
    426   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    427 
    428   Status = Mtftp6->Configure (Mtftp6, Config);
    429   if (EFI_ERROR (Status)) {
    430     return Status;
    431   }
    432 
    433   if (BlockSize != NULL) {
    434     ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    435     ReqOpt[0].ValueStr  = OptBuf;
    436     PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    437     OptCnt++;
    438   }
    439 
    440   Token.Event         = NULL;
    441   Token.OverrideData  = NULL;
    442   Token.Filename      = Filename;
    443   Token.ModeStr       = NULL;
    444   Token.OptionCount   = OptCnt;
    445   Token.OptionList    = ReqOpt;
    446   Token.Context       = Private;
    447 
    448   if (DontUseBuffer) {
    449     Token.BufferSize  = 0;
    450     Token.Buffer      = NULL;
    451   } else {
    452     Token.BufferSize  = *BufferSize;
    453     Token.Buffer      = BufferPtr;
    454   }
    455 
    456   Token.CheckPacket     = PxeBcMtftp6CheckPacket;
    457   Token.TimeoutCallback = NULL;
    458   Token.PacketNeeded    = NULL;
    459 
    460   Status = Mtftp6->ReadDirectory (Mtftp6, &Token);
    461   //
    462   // Get the real size of received buffer.
    463   //
    464   *BufferSize = Token.BufferSize;
    465 
    466   Mtftp6->Configure (Mtftp6, NULL);
    467 
    468   return Status;
    469 }
    470 
    471 
    472 /**
    473   This is a callback function when packets are received or transmitted in Mtftp driver.
    474 
    475   A callback function that is provided by the caller to intercept
    476   the EFI_MTFTP6_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the
    477   EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept
    478   EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to
    479   EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory().
    480 
    481   @param[in]  This           Pointer to EFI_MTFTP4_PROTOCOL.
    482   @param[in]  Token          Pointer to EFI_MTFTP4_TOKEN.
    483   @param[in]  PacketLen      Length of EFI_MTFTP4_PACKET.
    484   @param[in]  Packet         Pointer to EFI_MTFTP4_PACKET to be checked.
    485 
    486   @retval EFI_SUCCESS    The current operation succeeeded.
    487   @retval EFI_ABORTED    Abort the current transfer process.
    488 
    489 **/
    490 EFI_STATUS
    491 EFIAPI
    492 PxeBcMtftp4CheckPacket (
    493   IN EFI_MTFTP4_PROTOCOL        *This,
    494   IN EFI_MTFTP4_TOKEN           *Token,
    495   IN UINT16                     PacketLen,
    496   IN EFI_MTFTP4_PACKET          *Packet
    497   )
    498 {
    499   PXEBC_PRIVATE_DATA                  *Private;
    500   EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;
    501   EFI_STATUS                          Status;
    502 
    503   Private   = (PXEBC_PRIVATE_DATA *) Token->Context;
    504   Callback  = Private->PxeBcCallback;
    505   Status    = EFI_SUCCESS;
    506 
    507   if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) {
    508     //
    509     // Store the tftp error message into mode data and set the received flag.
    510     //
    511     Private->Mode.TftpErrorReceived   = TRUE;
    512     Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;
    513     AsciiStrnCpyS (
    514       Private->Mode.TftpError.ErrorString,
    515       PXE_MTFTP_ERROR_STRING_LENGTH,
    516       (CHAR8 *) Packet->Error.ErrorMessage,
    517       PXE_MTFTP_ERROR_STRING_LENGTH - 1
    518       );
    519     Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';
    520   }
    521 
    522   if (Callback != NULL) {
    523     //
    524     // Callback to user if has when received any tftp packet.
    525     //
    526     Status = Callback->Callback (
    527                         Callback,
    528                         Private->Function,
    529                         TRUE,
    530                         PacketLen,
    531                         (EFI_PXE_BASE_CODE_PACKET *) Packet
    532                         );
    533     if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
    534       //
    535       // User wants to abort current process if not EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE.
    536       //
    537       Status = EFI_ABORTED;
    538     } else {
    539       //
    540       // User wants to continue current process if EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE.
    541       //
    542       Status = EFI_SUCCESS;
    543     }
    544   }
    545 
    546   return Status;
    547 }
    548 
    549 
    550 /**
    551   This function is to get size of a file using Tftp.
    552 
    553   @param[in]      Private        Pointer to PxeBc private data.
    554   @param[in]      Config         Pointer to EFI_MTFTP4_CONFIG_DATA.
    555   @param[in]      Filename       Pointer to boot file name.
    556   @param[in]      BlockSize      Pointer to required block size.
    557   @param[in, out] BufferSize     Pointer to buffer size.
    558 
    559   @retval EFI_SUCCESS        Successfully obtained the size of file.
    560   @retval EFI_NOT_FOUND      Parse the tftp options failed.
    561   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    562   @retval Others             Did not obtain the size of the file.
    563 
    564 **/
    565 EFI_STATUS
    566 PxeBcMtftp4GetFileSize (
    567   IN     PXEBC_PRIVATE_DATA         *Private,
    568   IN     EFI_MTFTP4_CONFIG_DATA     *Config,
    569   IN     UINT8                      *Filename,
    570   IN     UINTN                      *BlockSize,
    571   IN OUT UINT64                     *BufferSize
    572   )
    573 {
    574   EFI_MTFTP4_PROTOCOL *Mtftp4;
    575   EFI_MTFTP4_OPTION   ReqOpt[2];
    576   EFI_MTFTP4_PACKET   *Packet;
    577   EFI_MTFTP4_OPTION   *Option;
    578   UINT32              PktLen;
    579   UINT8               OptBuf[128];
    580   UINT32              OptCnt;
    581   EFI_STATUS          Status;
    582 
    583   *BufferSize               = 0;
    584   Status                    = EFI_DEVICE_ERROR;
    585   Mtftp4                    = Private->Mtftp4;
    586   Packet                    = NULL;
    587   Option                    = NULL;
    588   PktLen                    = 0;
    589   OptCnt                    = 1;
    590   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    591 
    592   Status = Mtftp4->Configure (Mtftp4, Config);
    593   if (EFI_ERROR (Status)) {
    594     return Status;
    595   }
    596 
    597   //
    598   // Build the required options for get info.
    599   //
    600   ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX];
    601   PxeBcUintnToAscDec (0, OptBuf, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    602   ReqOpt[0].ValueStr  = OptBuf;
    603 
    604   if (BlockSize != NULL) {
    605     ReqOpt[1].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    606     ReqOpt[1].ValueStr  = (UINT8 *) (ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1);
    607     PxeBcUintnToAscDec (*BlockSize, ReqOpt[1].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX - (AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1));
    608     OptCnt++;
    609   }
    610 
    611   Status = Mtftp4->GetInfo (
    612                      Mtftp4,
    613                      NULL,
    614                      Filename,
    615                      NULL,
    616                      (UINT8) OptCnt,
    617                      ReqOpt,
    618                      &PktLen,
    619                      &Packet
    620                      );
    621   if (EFI_ERROR (Status)) {
    622     if (Status == EFI_TFTP_ERROR) {
    623       //
    624       // Store the tftp error message into mode data and set the received flag.
    625       //
    626       Private->Mode.TftpErrorReceived   = TRUE;
    627       Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;
    628       AsciiStrnCpyS (
    629         Private->Mode.TftpError.ErrorString,
    630         PXE_MTFTP_ERROR_STRING_LENGTH,
    631         (CHAR8 *) Packet->Error.ErrorMessage,
    632         PXE_MTFTP_ERROR_STRING_LENGTH - 1
    633         );
    634       Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';
    635     }
    636     goto ON_ERROR;
    637   }
    638 
    639   //
    640   // Parse the options in the reply packet.
    641   //
    642   OptCnt = 0;
    643   Status = Mtftp4->ParseOptions (
    644                      Mtftp4,
    645                      PktLen,
    646                      Packet,
    647                      (UINT32 *) &OptCnt,
    648                      &Option
    649                      );
    650   if (EFI_ERROR (Status)) {
    651     goto ON_ERROR;
    652   }
    653 
    654   //
    655   // Parse out the value of "tsize" option.
    656   //
    657   Status = EFI_NOT_FOUND;
    658   while (OptCnt != 0) {
    659     if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) {
    660       *BufferSize = AsciiStrDecimalToUint64 ((CHAR8 *) (Option[OptCnt - 1].ValueStr));
    661       Status      = EFI_SUCCESS;
    662     }
    663     OptCnt--;
    664   }
    665   FreePool (Option);
    666 
    667 ON_ERROR:
    668   if (Packet != NULL) {
    669     FreePool (Packet);
    670   }
    671   Mtftp4->Configure (Mtftp4, NULL);
    672 
    673   return Status;
    674 }
    675 
    676 
    677 /**
    678   This function is to read the data of a file using Tftp.
    679 
    680   @param[in]      Private        Pointer to PxeBc private data.
    681   @param[in]      Config         Pointer to EFI_MTFTP4_CONFIG_DATA.
    682   @param[in]      Filename       Pointer to boot file name.
    683   @param[in]      BlockSize      Pointer to required block size.
    684   @param[in]      BufferPtr      Pointer to buffer.
    685   @param[in, out] BufferSize     Pointer to buffer size.
    686   @param[in]      DontUseBuffer  Indicates whether to use a receive buffer.
    687 
    688   @retval EFI_SUCCESS        Successfully read the data from the special file.
    689   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    690   @retval Others             Read data from file failed.
    691 
    692 **/
    693 EFI_STATUS
    694 PxeBcMtftp4ReadFile (
    695   IN     PXEBC_PRIVATE_DATA         *Private,
    696   IN     EFI_MTFTP4_CONFIG_DATA     *Config,
    697   IN     UINT8                      *Filename,
    698   IN     UINTN                      *BlockSize,
    699   IN     UINT8                      *BufferPtr,
    700   IN OUT UINT64                     *BufferSize,
    701   IN     BOOLEAN                    DontUseBuffer
    702   )
    703 {
    704   EFI_MTFTP4_PROTOCOL *Mtftp4;
    705   EFI_MTFTP4_TOKEN    Token;
    706   EFI_MTFTP4_OPTION   ReqOpt[1];
    707   UINT32              OptCnt;
    708   UINT8               OptBuf[128];
    709   EFI_STATUS          Status;
    710 
    711   Status                    = EFI_DEVICE_ERROR;
    712   Mtftp4                    = Private->Mtftp4;
    713   OptCnt                    = 0;
    714   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    715 
    716   Status = Mtftp4->Configure (Mtftp4, Config);
    717   if (EFI_ERROR (Status)) {
    718     return Status;
    719   }
    720 
    721   if (BlockSize != NULL) {
    722     ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    723     ReqOpt[0].ValueStr  = OptBuf;
    724     PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    725     OptCnt++;
    726   }
    727 
    728   Token.Event         = NULL;
    729   Token.OverrideData  = NULL;
    730   Token.Filename      = Filename;
    731   Token.ModeStr       = NULL;
    732   Token.OptionCount   = OptCnt;
    733   Token.OptionList    = ReqOpt;
    734   Token.Context       = Private;
    735 
    736   if (DontUseBuffer) {
    737     Token.BufferSize  = 0;
    738     Token.Buffer      = NULL;
    739   } else {
    740     Token.BufferSize  = *BufferSize;
    741     Token.Buffer      = BufferPtr;
    742   }
    743 
    744   Token.CheckPacket     = PxeBcMtftp4CheckPacket;
    745   Token.TimeoutCallback = NULL;
    746   Token.PacketNeeded    = NULL;
    747 
    748   Status = Mtftp4->ReadFile (Mtftp4, &Token);
    749   //
    750   // Get the real size of received buffer.
    751   //
    752   *BufferSize = Token.BufferSize;
    753 
    754   Mtftp4->Configure (Mtftp4, NULL);
    755 
    756   return Status;
    757 }
    758 
    759 
    760 /**
    761   This function is to write the data of a file using Tftp.
    762 
    763   @param[in]       Private        Pointer to PxeBc private data.
    764   @param[in]       Config         Pointer to EFI_MTFTP4_CONFIG_DATA.
    765   @param[in]       Filename       Pointer to boot file name.
    766   @param[in]       Overwrite      Indicates whether to use the overwrite attribute.
    767   @param[in]       BlockSize      Pointer to required block size.
    768   @param[in]       BufferPtr      Pointer to buffer.
    769   @param[in, out]  BufferSize     Pointer to buffer size.
    770 
    771   @retval EFI_SUCCESS        Successfully write the data  into the special file.
    772   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    773   @retval other              Write data into file failed.
    774 
    775 **/
    776 EFI_STATUS
    777 PxeBcMtftp4WriteFile (
    778   IN     PXEBC_PRIVATE_DATA         *Private,
    779   IN     EFI_MTFTP4_CONFIG_DATA     *Config,
    780   IN     UINT8                      *Filename,
    781   IN     BOOLEAN                    Overwrite,
    782   IN     UINTN                      *BlockSize,
    783   IN     UINT8                      *BufferPtr,
    784   IN OUT UINT64                     *BufferSize
    785   )
    786 {
    787   EFI_MTFTP4_PROTOCOL *Mtftp4;
    788   EFI_MTFTP4_TOKEN    Token;
    789   EFI_MTFTP4_OPTION   ReqOpt[1];
    790   UINT32              OptCnt;
    791   UINT8               OptBuf[128];
    792   EFI_STATUS          Status;
    793 
    794   Status                    = EFI_DEVICE_ERROR;
    795   Mtftp4                    = Private->Mtftp4;
    796   OptCnt                    = 0;
    797   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    798 
    799   Status  = Mtftp4->Configure (Mtftp4, Config);
    800   if (EFI_ERROR (Status)) {
    801     return Status;
    802   }
    803 
    804   if (BlockSize != NULL) {
    805     ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    806     ReqOpt[0].ValueStr  = OptBuf;
    807     PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    808     OptCnt++;
    809   }
    810 
    811   Token.Event           = NULL;
    812   Token.OverrideData    = NULL;
    813   Token.Filename        = Filename;
    814   Token.ModeStr         = NULL;
    815   Token.OptionCount     = OptCnt;
    816   Token.OptionList      = ReqOpt;
    817   Token.BufferSize      = *BufferSize;
    818   Token.Buffer          = BufferPtr;
    819   Token.CheckPacket     = PxeBcMtftp4CheckPacket;
    820   Token.TimeoutCallback = NULL;
    821   Token.PacketNeeded    = NULL;
    822 
    823   Status = Mtftp4->WriteFile (Mtftp4, &Token);
    824   //
    825   // Get the real size of transmitted buffer.
    826   //
    827   *BufferSize = Token.BufferSize;
    828 
    829   Mtftp4->Configure (Mtftp4, NULL);
    830 
    831   return Status;
    832 }
    833 
    834 
    835 /**
    836   This function is to get data (file) from a directory using Tftp.
    837 
    838   @param[in]       Private        Pointer to PxeBc private data.
    839   @param[in]       Config         Pointer to EFI_MTFTP4_CONFIG_DATA.
    840   @param[in]       Filename       Pointer to boot file name.
    841   @param[in]       BlockSize      Pointer to required block size.
    842   @param[in]       BufferPtr      Pointer to buffer.
    843   @param[in, out]  BufferSize     Pointer to buffer size.
    844   @param[in]       DontUseBuffer  Indicates whether to use a receive buffer.
    845 
    846   @retval EFI_SUCCES         Successfully obtained the data from the file included in the directory.
    847   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    848   @retval Others             Operation failed.
    849 
    850 **/
    851 EFI_STATUS
    852 PxeBcMtftp4ReadDirectory (
    853   IN     PXEBC_PRIVATE_DATA            *Private,
    854   IN     EFI_MTFTP4_CONFIG_DATA        *Config,
    855   IN     UINT8                         *Filename,
    856   IN     UINTN                         *BlockSize,
    857   IN     UINT8                         *BufferPtr,
    858   IN OUT UINT64                        *BufferSize,
    859   IN     BOOLEAN                       DontUseBuffer
    860   )
    861 {
    862   EFI_MTFTP4_PROTOCOL *Mtftp4;
    863   EFI_MTFTP4_TOKEN    Token;
    864   EFI_MTFTP4_OPTION   ReqOpt[1];
    865   UINT32              OptCnt;
    866   UINT8               OptBuf[128];
    867   EFI_STATUS          Status;
    868 
    869   Status                    = EFI_DEVICE_ERROR;
    870   Mtftp4                    = Private->Mtftp4;
    871   OptCnt                    = 0;
    872   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    873 
    874   Status = Mtftp4->Configure (Mtftp4, Config);
    875   if (EFI_ERROR (Status)) {
    876     return Status;
    877   }
    878 
    879   if (BlockSize != NULL) {
    880     ReqOpt[0].OptionStr = (UINT8 *) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    881     ReqOpt[0].ValueStr  = OptBuf;
    882     PxeBcUintnToAscDec (*BlockSize, ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    883     OptCnt++;
    884   }
    885 
    886   Token.Event         = NULL;
    887   Token.OverrideData  = NULL;
    888   Token.Filename      = Filename;
    889   Token.ModeStr       = NULL;
    890   Token.OptionCount   = OptCnt;
    891   Token.OptionList    = ReqOpt;
    892   Token.Context       = Private;
    893 
    894   if (DontUseBuffer) {
    895     Token.BufferSize  = 0;
    896     Token.Buffer      = NULL;
    897   } else {
    898     Token.BufferSize  = *BufferSize;
    899     Token.Buffer      = BufferPtr;
    900   }
    901 
    902   Token.CheckPacket     = PxeBcMtftp4CheckPacket;
    903   Token.TimeoutCallback = NULL;
    904   Token.PacketNeeded    = NULL;
    905 
    906   Status = Mtftp4->ReadDirectory (Mtftp4, &Token);
    907   //
    908   // Get the real size of received buffer.
    909   //
    910   *BufferSize = Token.BufferSize;
    911 
    912   Mtftp4->Configure (Mtftp4, NULL);
    913 
    914   return Status;
    915 }
    916 
    917 
    918 /**
    919   This function is wrapper to get the file size using TFTP.
    920 
    921   @param[in]      Private        Pointer to PxeBc private data.
    922   @param[in]      Config         Pointer to configure data.
    923   @param[in]      Filename       Pointer to boot file name.
    924   @param[in]      BlockSize      Pointer to required block size.
    925   @param[in, out] BufferSize     Pointer to buffer size.
    926 
    927   @retval EFI_SUCCESS        Successfully obtained the size of file.
    928   @retval EFI_NOT_FOUND      Parse the tftp options failed.
    929   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    930   @retval Others             Did not obtain the size of the file.
    931 
    932 **/
    933 EFI_STATUS
    934 PxeBcTftpGetFileSize (
    935   IN     PXEBC_PRIVATE_DATA         *Private,
    936   IN     VOID                       *Config,
    937   IN     UINT8                      *Filename,
    938   IN     UINTN                      *BlockSize,
    939   IN OUT UINT64                     *BufferSize
    940   )
    941 {
    942   if (Private->PxeBc.Mode->UsingIpv6) {
    943     return PxeBcMtftp6GetFileSize (
    944              Private,
    945              (EFI_MTFTP6_CONFIG_DATA *) Config,
    946              Filename,
    947              BlockSize,
    948              BufferSize
    949              );
    950   } else {
    951     return PxeBcMtftp4GetFileSize (
    952              Private,
    953              (EFI_MTFTP4_CONFIG_DATA *) Config,
    954              Filename,
    955              BlockSize,
    956              BufferSize
    957              );
    958   }
    959 }
    960 
    961 
    962 /**
    963   This function is a wrapper to get file using TFTP.
    964 
    965   @param[in]      Private        Pointer to PxeBc private data.
    966   @param[in]      Config         Pointer to config data.
    967   @param[in]      Filename       Pointer to boot file name.
    968   @param[in]      BlockSize      Pointer to required block size.
    969   @param[in]      BufferPtr      Pointer to buffer.
    970   @param[in, out] BufferSize     Pointer to buffer size.
    971   @param[in]      DontUseBuffer  Indicates whether to use a receive buffer.
    972 
    973   @retval EFI_SUCCESS        Sucessfully read the data from the special file.
    974   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    975   @retval Others             Read data from file failed.
    976 
    977 **/
    978 EFI_STATUS
    979 PxeBcTftpReadFile (
    980   IN     PXEBC_PRIVATE_DATA         *Private,
    981   IN     VOID                       *Config,
    982   IN     UINT8                      *Filename,
    983   IN     UINTN                      *BlockSize,
    984   IN     UINT8                      *BufferPtr,
    985   IN OUT UINT64                     *BufferSize,
    986   IN     BOOLEAN                    DontUseBuffer
    987   )
    988 {
    989   if (Private->PxeBc.Mode->UsingIpv6) {
    990     return PxeBcMtftp6ReadFile (
    991              Private,
    992              (EFI_MTFTP6_CONFIG_DATA *) Config,
    993              Filename,
    994              BlockSize,
    995              BufferPtr,
    996              BufferSize,
    997              DontUseBuffer
    998              );
    999   } else {
   1000     return PxeBcMtftp4ReadFile (
   1001              Private,
   1002              (EFI_MTFTP4_CONFIG_DATA *) Config,
   1003              Filename,
   1004              BlockSize,
   1005              BufferPtr,
   1006              BufferSize,
   1007              DontUseBuffer
   1008              );
   1009   }
   1010 }
   1011 
   1012 
   1013 /**
   1014   This function is a wrapper to write file using TFTP.
   1015 
   1016   @param[in]       Private        Pointer to PxeBc private data.
   1017   @param[in]       Config         Pointer to config data.
   1018   @param[in]       Filename       Pointer to boot file name.
   1019   @param[in]       Overwrite      Indicate whether with overwrite attribute.
   1020   @param[in]       BlockSize      Pointer to required block size.
   1021   @param[in]       BufferPtr      Pointer to buffer.
   1022   @param[in, out]  BufferSize     Pointer to buffer size.
   1023 
   1024   @retval EFI_SUCCESS        Successfully wrote the data into a special file.
   1025   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
   1026   @retval other              Write data into file failed.
   1027 
   1028 **/
   1029 EFI_STATUS
   1030 PxeBcTftpWriteFile (
   1031   IN     PXEBC_PRIVATE_DATA         *Private,
   1032   IN     VOID                       *Config,
   1033   IN     UINT8                      *Filename,
   1034   IN     BOOLEAN                    Overwrite,
   1035   IN     UINTN                      *BlockSize,
   1036   IN     UINT8                      *BufferPtr,
   1037   IN OUT UINT64                     *BufferSize
   1038   )
   1039 {
   1040   if (Private->PxeBc.Mode->UsingIpv6) {
   1041     return PxeBcMtftp6WriteFile (
   1042              Private,
   1043              (EFI_MTFTP6_CONFIG_DATA *) Config,
   1044              Filename,
   1045              Overwrite,
   1046              BlockSize,
   1047              BufferPtr,
   1048              BufferSize
   1049              );
   1050   } else {
   1051     return PxeBcMtftp4WriteFile (
   1052              Private,
   1053              (EFI_MTFTP4_CONFIG_DATA *) Config,
   1054              Filename,
   1055              Overwrite,
   1056              BlockSize,
   1057              BufferPtr,
   1058              BufferSize
   1059              );
   1060   }
   1061 }
   1062 
   1063 
   1064 /**
   1065   This function is a wrapper to get the data (file) from a directory using TFTP.
   1066 
   1067   @param[in]       Private        Pointer to PxeBc private data.
   1068   @param[in]       Config         Pointer to config data.
   1069   @param[in]       Filename       Pointer to boot file name.
   1070   @param[in]       BlockSize      Pointer to required block size.
   1071   @param[in]       BufferPtr      Pointer to buffer.
   1072   @param[in, out]  BufferSize     Pointer to buffer size.
   1073   @param[in]       DontUseBuffer  Indicatse whether to use a receive buffer.
   1074 
   1075   @retval EFI_SUCCES         Successfully obtained the data from the file included in the directory.
   1076   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
   1077   @retval Others             Operation failed.
   1078 
   1079 **/
   1080 EFI_STATUS
   1081 PxeBcTftpReadDirectory (
   1082   IN     PXEBC_PRIVATE_DATA            *Private,
   1083   IN     VOID                          *Config,
   1084   IN     UINT8                         *Filename,
   1085   IN     UINTN                         *BlockSize,
   1086   IN     UINT8                         *BufferPtr,
   1087   IN OUT UINT64                        *BufferSize,
   1088   IN     BOOLEAN                       DontUseBuffer
   1089   )
   1090 {
   1091   if (Private->PxeBc.Mode->UsingIpv6) {
   1092     return PxeBcMtftp6ReadDirectory (
   1093              Private,
   1094              (EFI_MTFTP6_CONFIG_DATA *) Config,
   1095              Filename,
   1096              BlockSize,
   1097              BufferPtr,
   1098              BufferSize,
   1099              DontUseBuffer
   1100              );
   1101   } else {
   1102     return PxeBcMtftp4ReadDirectory (
   1103              Private,
   1104              (EFI_MTFTP4_CONFIG_DATA *) Config,
   1105              Filename,
   1106              BlockSize,
   1107              BufferPtr,
   1108              BufferSize,
   1109              DontUseBuffer
   1110              );
   1111   }
   1112 }
   1113 
   1114