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