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