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