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