• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
PxeBcCheckPacket(IN EFI_MTFTP4_PROTOCOL * This,IN EFI_MTFTP4_TOKEN * Token,IN UINT16 PacketLen,IN EFI_MTFTP4_PACKET * Packet)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
PxeBcTftpGetFileSize(IN PXEBC_PRIVATE_DATA * Private,IN EFI_MTFTP4_CONFIG_DATA * Config,IN UINT8 * Filename,IN UINTN * BlockSize,IN OUT UINT64 * BufferSize)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
PxeBcTftpReadFile(IN PXEBC_PRIVATE_DATA * Private,IN EFI_MTFTP4_CONFIG_DATA * Config,IN UINT8 * Filename,IN UINTN * BlockSize,IN UINT8 * BufferPtr,IN OUT UINT64 * BufferSize,IN BOOLEAN DontUseBuffer)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
PxeBcTftpWriteFile(IN PXEBC_PRIVATE_DATA * Private,IN EFI_MTFTP4_CONFIG_DATA * Config,IN UINT8 * Filename,IN BOOLEAN Overwrite,IN UINTN * BlockSize,IN UINT8 * BufferPtr,IN OUT UINT64 * BufferSize)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
PxeBcTftpReadDirectory(IN PXEBC_PRIVATE_DATA * Private,IN EFI_MTFTP4_CONFIG_DATA * Config,IN UINT8 * Filename,IN UINTN * BlockSize,IN UINT8 * BufferPtr,IN OUT UINT64 * BufferSize,IN BOOLEAN DontUseBuffer)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