]> git.proxmox.com Git - mirror_edk2.git/blob - NetworkPkg/UefiPxeBcDxe/PxeBcMtftp.c
NetworkPkg: Add URI configuration form to HTTP boot driver.
[mirror_edk2.git] / NetworkPkg / UefiPxeBcDxe / PxeBcMtftp.c
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
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 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 **/
119 EFI_STATUS
120 PxeBcMtftp6GetFileSize (
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
221 ON_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 **/
247 EFI_STATUS
248 PxeBcMtftp6ReadFile (
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 **/
330 EFI_STATUS
331 PxeBcMtftp6WriteFile (
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 **/
405 EFI_STATUS
406 PxeBcMtftp6ReadDirectory (
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 **/
490 EFI_STATUS
491 EFIAPI
492 PxeBcMtftp4CheckPacket (
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 **/
565 EFI_STATUS
566 PxeBcMtftp4GetFileSize (
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
667 ON_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 **/
693 EFI_STATUS
694 PxeBcMtftp4ReadFile (
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 **/
776 EFI_STATUS
777 PxeBcMtftp4WriteFile (
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 **/
851 EFI_STATUS
852 PxeBcMtftp4ReadDirectory (
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 **/
933 EFI_STATUS
934 PxeBcTftpGetFileSize (
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 **/
978 EFI_STATUS
979 PxeBcTftpReadFile (
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 **/
1029 EFI_STATUS
1030 PxeBcTftpWriteFile (
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 **/
1080 EFI_STATUS
1081 PxeBcTftpReadDirectory (
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