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
18CHAR8 *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**/
44EFI_STATUS
45EFIAPI
46PxeBcMtftp6CheckPacket (
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**/
119EFI_STATUS
120PxeBcMtftp6GetFileSize (
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
221ON_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**/
247EFI_STATUS
248PxeBcMtftp6ReadFile (
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**/
330EFI_STATUS
331PxeBcMtftp6WriteFile (
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**/
405EFI_STATUS
406PxeBcMtftp6ReadDirectory (
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**/
490EFI_STATUS
491EFIAPI
492PxeBcMtftp4CheckPacket (
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**/
565EFI_STATUS
566PxeBcMtftp4GetFileSize (
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
667ON_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**/
693EFI_STATUS
694PxeBcMtftp4ReadFile (
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**/
776EFI_STATUS
777PxeBcMtftp4WriteFile (
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**/
851EFI_STATUS
852PxeBcMtftp4ReadDirectory (
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**/
933EFI_STATUS
934PxeBcTftpGetFileSize (
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**/
978EFI_STATUS
979PxeBcTftpReadFile (
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**/
1029EFI_STATUS
1030PxeBcTftpWriteFile (
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**/
1080EFI_STATUS
1081PxeBcTftpReadDirectory (
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