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