Home | History | Annotate | Download | only in UefiPxeBcDxe
      1 /** @file
      2   PxeBc MTFTP functions.
      3 
      4 Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR>
      5 This program and the accompanying materials
      6 are licensed and made available under the terms and conditions of the BSD License
      7 which accompanies this distribution.  The full text of the license may be found at
      8 http://opensource.org/licenses/bsd-license.php
      9 
     10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     12 
     13 **/
     14 
     15 #include "PxeBcImpl.h"
     16 
     17 CHAR8 *mMtftpOptions[PXE_MTFTP_OPTION_MAXIMUM_INDEX] = {
     18   "blksize",
     19   "timeout",
     20   "tsize",
     21   "multicast"
     22 };
     23 
     24 
     25 /**
     26   This is a callback function when packets received/transmitted in Mtftp driver.
     27 
     28   A callback function that is provided by the caller to intercept
     29   the EFI_MTFTP4_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the
     30   EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept
     31   EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to
     32   EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory().
     33 
     34   @param  This           Pointer to Mtftp protocol instance
     35   @param  Token          Pointer to Mtftp token
     36   @param  PacketLen      Length of Mtftp packet
     37   @param  Packet         Pointer to Mtftp packet
     38 
     39   @retval EFI_SUCCESS    Operation sucess
     40   @retval EFI_ABORTED    Abort transfer process
     41 
     42 **/
     43 EFI_STATUS
     44 EFIAPI
     45 PxeBcCheckPacket (
     46   IN EFI_MTFTP4_PROTOCOL        *This,
     47   IN EFI_MTFTP4_TOKEN           *Token,
     48   IN UINT16                     PacketLen,
     49   IN EFI_MTFTP4_PACKET          *Packet
     50   )
     51 {
     52   PXEBC_PRIVATE_DATA                  *Private;
     53   EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;
     54   EFI_STATUS                          Status;
     55 
     56   Private   = (PXEBC_PRIVATE_DATA *) Token->Context;
     57   Callback  = Private->PxeBcCallback;
     58   Status    = EFI_SUCCESS;
     59 
     60   if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) {
     61     Private->Mode.TftpErrorReceived = TRUE;
     62     Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;
     63     AsciiStrnCpyS (Private->Mode.TftpError.ErrorString, PXE_MTFTP_ERROR_STRING_LENGTH, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH - 1);
     64     Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';
     65   }
     66 
     67   if (Callback != NULL) {
     68 
     69     Status = Callback->Callback (
     70                         Callback,
     71                         Private->Function,
     72                         TRUE,
     73                         PacketLen,
     74                         (EFI_PXE_BASE_CODE_PACKET *) Packet
     75                         );
     76     if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
     77 
     78       Status = EFI_ABORTED;
     79     } else {
     80 
     81       Status = EFI_SUCCESS;
     82     }
     83   }
     84 
     85   return Status;
     86 }
     87 
     88 
     89 /**
     90   This function is to get size of a file by Tftp.
     91 
     92   @param  Private        Pointer to PxeBc private data
     93   @param  Config         Pointer to Mtftp configuration data
     94   @param  Filename       Pointer to file name
     95   @param  BlockSize      Pointer to block size
     96   @param  BufferSize     Pointer to buffer size
     97 
     98   @retval EFI_SUCCESS        Get the size of file success
     99   @retval EFI_NOT_FOUND      Parse the tftp ptions failed.
    100   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    101   @retval Other              Has not get the size of the file.
    102 
    103 **/
    104 EFI_STATUS
    105 PxeBcTftpGetFileSize (
    106   IN PXEBC_PRIVATE_DATA         *Private,
    107   IN EFI_MTFTP4_CONFIG_DATA     *Config,
    108   IN UINT8                      *Filename,
    109   IN UINTN                      *BlockSize,
    110   IN OUT UINT64                 *BufferSize
    111   )
    112 {
    113   EFI_MTFTP4_PROTOCOL *Mtftp4;
    114   EFI_MTFTP4_OPTION   ReqOpt[2];
    115   EFI_MTFTP4_PACKET   *Packet;
    116   EFI_MTFTP4_OPTION   *Option;
    117   UINT32              PktLen;
    118   UINT8               OptBuf[128];
    119   UINT32              OptCnt;
    120   EFI_STATUS          Status;
    121 
    122   *BufferSize               = 0;
    123   Status                    = EFI_DEVICE_ERROR;
    124   Mtftp4                    = Private->Mtftp4;
    125   Packet                    = NULL;
    126   Option                    = NULL;
    127   PktLen                    = 0;
    128   OptCnt                    = 1;
    129   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    130 
    131   Status = Mtftp4->Configure (Mtftp4, Config);
    132   if (EFI_ERROR (Status)) {
    133 
    134     return Status;
    135   }
    136 
    137   ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX];
    138   UtoA10 (0, (CHAR8 *) OptBuf, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    139   ReqOpt[0].ValueStr = OptBuf;
    140 
    141   if (BlockSize != NULL) {
    142     ReqOpt[1].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    143     ReqOpt[1].ValueStr  = ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1;
    144     UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[1].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX - (AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1));
    145     OptCnt++;
    146   }
    147 
    148   Status = Mtftp4->GetInfo (
    149                     Mtftp4,
    150                     NULL,
    151                     Filename,
    152                     NULL,
    153                     (UINT8) OptCnt,
    154                     ReqOpt,
    155                     &PktLen,
    156                     &Packet
    157                     );
    158 
    159   if (EFI_ERROR (Status)) {
    160     if (Status == EFI_TFTP_ERROR) {
    161       Private->Mode.TftpErrorReceived = TRUE;
    162       Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;
    163       AsciiStrnCpyS (
    164         Private->Mode.TftpError.ErrorString,
    165         PXE_MTFTP_ERROR_STRING_LENGTH,
    166         (CHAR8 *) Packet->Error.ErrorMessage,
    167         PXE_MTFTP_ERROR_STRING_LENGTH - 1
    168         );
    169       Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';
    170     }
    171     goto ON_ERROR;
    172   }
    173 
    174   OptCnt = 0;
    175 
    176   Status = Mtftp4->ParseOptions (
    177                     Mtftp4,
    178                     PktLen,
    179                     Packet,
    180                     (UINT32 *) &OptCnt,
    181                     &Option
    182                     );
    183 
    184   if (EFI_ERROR (Status)) {
    185 
    186     goto ON_ERROR;
    187   }
    188 
    189   Status = EFI_NOT_FOUND;
    190 
    191   while (OptCnt != 0) {
    192 
    193     if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) {
    194 
    195       *BufferSize = AtoU64 (Option[OptCnt - 1].ValueStr);
    196       Status      = EFI_SUCCESS;
    197     }
    198 
    199     OptCnt--;
    200   }
    201 
    202   FreePool (Option);
    203 
    204 ON_ERROR:
    205 
    206   if (Packet != NULL) {
    207     FreePool (Packet);
    208   }
    209 
    210   Mtftp4->Configure (Mtftp4, NULL);
    211 
    212   return Status;
    213 }
    214 
    215 
    216 /**
    217   This function is to get data of a file by Tftp.
    218 
    219   @param  Private        Pointer to PxeBc private data
    220   @param  Config         Pointer to Mtftp configuration data
    221   @param  Filename       Pointer to file name
    222   @param  BlockSize      Pointer to block size
    223   @param  BufferPtr      Pointer to buffer
    224   @param  BufferSize     Pointer to buffer size
    225   @param  DontUseBuffer  Indicate whether with a receive buffer
    226 
    227   @retval EFI_SUCCESS        Read the data success from the special file.
    228   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    229   @retval other              Read data from file failed.
    230 
    231 **/
    232 EFI_STATUS
    233 PxeBcTftpReadFile (
    234   IN PXEBC_PRIVATE_DATA         *Private,
    235   IN EFI_MTFTP4_CONFIG_DATA     *Config,
    236   IN UINT8                      *Filename,
    237   IN UINTN                      *BlockSize,
    238   IN UINT8                      *BufferPtr,
    239   IN OUT UINT64                 *BufferSize,
    240   IN BOOLEAN                    DontUseBuffer
    241   )
    242 {
    243   EFI_MTFTP4_PROTOCOL *Mtftp4;
    244   EFI_MTFTP4_TOKEN    Token;
    245   EFI_MTFTP4_OPTION   ReqOpt[1];
    246   UINT32              OptCnt;
    247   UINT8               OptBuf[128];
    248   EFI_STATUS          Status;
    249 
    250   Status                    = EFI_DEVICE_ERROR;
    251   Mtftp4                    = Private->Mtftp4;
    252   OptCnt                    = 0;
    253   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    254 
    255   Status = Mtftp4->Configure (Mtftp4, Config);
    256   if (EFI_ERROR (Status)) {
    257 
    258     return Status;
    259   }
    260 
    261   if (BlockSize != NULL) {
    262 
    263     ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    264     ReqOpt[0].ValueStr  = OptBuf;
    265     UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    266     OptCnt++;
    267   }
    268 
    269   Token.Event         = NULL;
    270   Token.OverrideData  = NULL;
    271   Token.Filename      = Filename;
    272   Token.ModeStr       = NULL;
    273   Token.OptionCount   = OptCnt;
    274   Token.OptionList    = ReqOpt;
    275   Token.Context       = Private;
    276 
    277   if (DontUseBuffer) {
    278     Token.BufferSize  = 0;
    279     Token.Buffer      = NULL;
    280   } else {
    281     Token.BufferSize  = *BufferSize;
    282     Token.Buffer      = BufferPtr;
    283   }
    284 
    285   Token.CheckPacket     = PxeBcCheckPacket;
    286   Token.TimeoutCallback = NULL;
    287   Token.PacketNeeded    = NULL;
    288 
    289   Status = Mtftp4->ReadFile (Mtftp4, &Token);
    290 
    291   *BufferSize = Token.BufferSize;
    292 
    293   Mtftp4->Configure (Mtftp4, NULL);
    294 
    295   return Status;
    296 }
    297 
    298 
    299 /**
    300   This function is put data of a file by Tftp.
    301 
    302   @param  Private        Pointer to PxeBc private data
    303   @param  Config         Pointer to Mtftp configuration data
    304   @param  Filename       Pointer to file name
    305   @param  Overwrite      Indicate whether with overwrite attribute
    306   @param  BlockSize      Pointer to block size
    307   @param  BufferPtr      Pointer to buffer
    308   @param  BufferSize     Pointer to buffer size
    309 
    310   @retval EFI_SUCCESS        Write the data success into the special file.
    311   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    312   @retval other              Write data into file failed.
    313 
    314 **/
    315 EFI_STATUS
    316 PxeBcTftpWriteFile (
    317   IN PXEBC_PRIVATE_DATA         *Private,
    318   IN EFI_MTFTP4_CONFIG_DATA     *Config,
    319   IN UINT8                      *Filename,
    320   IN BOOLEAN                    Overwrite,
    321   IN UINTN                      *BlockSize,
    322   IN UINT8                      *BufferPtr,
    323   IN OUT UINT64                 *BufferSize
    324   )
    325 {
    326   EFI_MTFTP4_PROTOCOL *Mtftp4;
    327   EFI_MTFTP4_TOKEN    Token;
    328   EFI_MTFTP4_OPTION   ReqOpt[1];
    329   UINT32              OptCnt;
    330   UINT8               OptBuf[128];
    331   EFI_STATUS          Status;
    332 
    333   Status                    = EFI_DEVICE_ERROR;
    334   Mtftp4                    = Private->Mtftp4;
    335   OptCnt                    = 0;
    336   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    337 
    338   Status  = Mtftp4->Configure (Mtftp4, Config);
    339   if (EFI_ERROR (Status)) {
    340 
    341     return Status;
    342   }
    343 
    344   if (BlockSize != NULL) {
    345 
    346     ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    347     ReqOpt[0].ValueStr  = OptBuf;
    348     UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    349     OptCnt++;
    350   }
    351 
    352   Token.Event           = NULL;
    353   Token.OverrideData    = NULL;
    354   Token.Filename        = Filename;
    355   Token.ModeStr         = NULL;
    356   Token.OptionCount     = OptCnt;
    357   Token.OptionList      = ReqOpt;
    358   Token.BufferSize      = *BufferSize;
    359   Token.Buffer          = BufferPtr;
    360   Token.CheckPacket     = PxeBcCheckPacket;
    361   Token.TimeoutCallback = NULL;
    362   Token.PacketNeeded    = NULL;
    363 
    364   Status      = Mtftp4->WriteFile (Mtftp4, &Token);
    365   *BufferSize = Token.BufferSize;
    366 
    367   Mtftp4->Configure (Mtftp4, NULL);
    368 
    369   return Status;
    370 }
    371 
    372 
    373 /**
    374   This function is to get data(file) from a directory(may be a server) by Tftp.
    375 
    376   @param  Private        Pointer to PxeBc private data.
    377   @param  Config         Pointer to Mtftp configuration data.
    378   @param  Filename       Pointer to file name.
    379   @param  BlockSize      Pointer to block size.
    380   @param  BufferPtr      Pointer to buffer.
    381   @param  BufferSize     Pointer to buffer size.
    382   @param  DontUseBuffer  Indicate whether with a receive buffer.
    383 
    384   @retval EFI_SUCCES         Get the data from the file included in directory success.
    385   @retval EFI_DEVICE_ERROR   The network device encountered an error during this operation.
    386   @retval other              Operation failed.
    387 
    388 **/
    389 EFI_STATUS
    390 PxeBcTftpReadDirectory (
    391   IN PXEBC_PRIVATE_DATA            *Private,
    392   IN EFI_MTFTP4_CONFIG_DATA        *Config,
    393   IN UINT8                         *Filename,
    394   IN UINTN                         *BlockSize,
    395   IN UINT8                         *BufferPtr,
    396   IN OUT UINT64                    *BufferSize,
    397   IN BOOLEAN                       DontUseBuffer
    398   )
    399 {
    400   EFI_MTFTP4_PROTOCOL *Mtftp4;
    401   EFI_MTFTP4_TOKEN    Token;
    402   EFI_MTFTP4_OPTION   ReqOpt[1];
    403   UINT32              OptCnt;
    404   UINT8               OptBuf[128];
    405   EFI_STATUS          Status;
    406 
    407   Status                    = EFI_DEVICE_ERROR;
    408   Mtftp4                    = Private->Mtftp4;
    409   OptCnt                    = 0;
    410   Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
    411 
    412   Status = Mtftp4->Configure (Mtftp4, Config);
    413   if (EFI_ERROR (Status)) {
    414 
    415     return Status;
    416   }
    417 
    418   if (BlockSize != NULL) {
    419 
    420     ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
    421     ReqOpt[0].ValueStr  = OptBuf;
    422     UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr, PXE_MTFTP_OPTBUF_MAXNUM_INDEX);
    423     OptCnt++;
    424   }
    425 
    426   Token.Event         = NULL;
    427   Token.OverrideData  = NULL;
    428   Token.Filename      = Filename;
    429   Token.ModeStr       = NULL;
    430   Token.OptionCount   = OptCnt;
    431   Token.OptionList    = ReqOpt;
    432   Token.Context       = Private;
    433 
    434   if (DontUseBuffer) {
    435     Token.BufferSize  = 0;
    436     Token.Buffer      = NULL;
    437   } else {
    438     Token.BufferSize  = *BufferSize;
    439     Token.Buffer      = BufferPtr;
    440   }
    441 
    442   Token.CheckPacket     = PxeBcCheckPacket;
    443   Token.TimeoutCallback = NULL;
    444   Token.PacketNeeded    = NULL;
    445 
    446   Status = Mtftp4->ReadDirectory (Mtftp4, &Token);
    447 
    448   *BufferSize = Token.BufferSize;
    449 
    450   Mtftp4->Configure (Mtftp4, NULL);
    451 
    452   return Status;
    453 }
    454 
    455