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