]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c
Append the terminating null character at the end of the string to avoid buffer overflow.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / UefiPxeBcDxe / PxeBcMtftp.c
CommitLineData
dc361cc5 1/** @file\r
f737cfb9 2 PxeBc MTFTP functions.\r
3 \r
35d74819 4Copyright (c) 2007 - 2014, Intel Corporation. All rights reserved.<BR>\r
e5eed7d3 5This program and the accompanying materials\r
dc361cc5 6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
dc361cc5 13**/\r
14\r
15#include "PxeBcImpl.h"\r
16\r
0adb8a3c 17CHAR8 *mMtftpOptions[PXE_MTFTP_OPTION_MAXIMUM_INDEX] = {\r
dc361cc5 18 "blksize",\r
19 "timeout",\r
20 "tsize",\r
21 "multicast"\r
22};\r
23\r
24\r
25/**\r
26 This is a callback function when packets received/transmitted in Mtftp driver.\r
27\r
f737cfb9 28 A callback function that is provided by the caller to intercept \r
29 the EFI_MTFTP4_OPCODE_DATA or EFI_MTFTP4_OPCODE_DATA8 packets processed in the\r
30 EFI_MTFTP4_PROTOCOL.ReadFile() function, and alternatively to intercept \r
31 EFI_MTFTP4_OPCODE_OACK or EFI_MTFTP4_OPCODE_ERROR packets during a call to \r
32 EFI_MTFTP4_PROTOCOL.ReadFile(), WriteFile() or ReadDirectory().\r
33 \r
dc361cc5 34 @param This Pointer to Mtftp protocol instance\r
35 @param Token Pointer to Mtftp token\r
36 @param PacketLen Length of Mtftp packet\r
37 @param Packet Pointer to Mtftp packet\r
38\r
f737cfb9 39 @retval EFI_SUCCESS Operation sucess\r
40 @retval EFI_ABORTED Abort transfer process \r
dc361cc5 41\r
42**/\r
43EFI_STATUS\r
6d3ea23f 44EFIAPI\r
dc361cc5 45PxeBcCheckPacket (\r
46 IN EFI_MTFTP4_PROTOCOL *This,\r
47 IN EFI_MTFTP4_TOKEN *Token,\r
48 IN UINT16 PacketLen,\r
49 IN EFI_MTFTP4_PACKET *Packet\r
50 )\r
51{\r
52 PXEBC_PRIVATE_DATA *Private;\r
53 EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;\r
54 EFI_STATUS Status;\r
55\r
ea886bef 56 Private = (PXEBC_PRIVATE_DATA *) Token->Context;\r
dc361cc5 57 Callback = Private->PxeBcCallback;\r
58 Status = EFI_SUCCESS;\r
59\r
982a9eae 60 if (Packet->OpCode == EFI_MTFTP4_OPCODE_ERROR) {\r
61 Private->Mode.TftpErrorReceived = TRUE;\r
62 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;\r
a361d391
QS
63 AsciiStrnCpy (Private->Mode.TftpError.ErrorString, (CHAR8 *) Packet->Error.ErrorMessage, PXE_MTFTP_ERROR_STRING_LENGTH);\r
64 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';\r
982a9eae 65 }\r
66\r
dc361cc5 67 if (Callback != NULL) {\r
68\r
69 Status = Callback->Callback (\r
70 Callback,\r
71 Private->Function,\r
72 TRUE,\r
73 PacketLen,\r
74 (EFI_PXE_BASE_CODE_PACKET *) Packet\r
75 );\r
76 if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {\r
77\r
78 Status = EFI_ABORTED;\r
79 } else {\r
80\r
81 Status = EFI_SUCCESS;\r
82 }\r
83 }\r
84\r
85 return Status;\r
86}\r
87\r
88\r
89/**\r
90 This function is to get size of a file by Tftp.\r
f737cfb9 91 \r
dc361cc5 92 @param Private Pointer to PxeBc private data\r
93 @param Config Pointer to Mtftp configuration data\r
94 @param Filename Pointer to file name\r
95 @param BlockSize Pointer to block size\r
96 @param BufferSize Pointer to buffer size\r
97\r
f737cfb9 98 @retval EFI_SUCCESS Get the size of file success\r
99 @retval EFI_NOT_FOUND Parse the tftp ptions failed.\r
100 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.\r
101 @retval Other Has not get the size of the file.\r
102 \r
dc361cc5 103**/\r
104EFI_STATUS\r
105PxeBcTftpGetFileSize (\r
106 IN PXEBC_PRIVATE_DATA *Private,\r
107 IN EFI_MTFTP4_CONFIG_DATA *Config,\r
108 IN UINT8 *Filename,\r
109 IN UINTN *BlockSize,\r
110 IN OUT UINT64 *BufferSize\r
111 )\r
112{\r
113 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
114 EFI_MTFTP4_OPTION ReqOpt[2];\r
115 EFI_MTFTP4_PACKET *Packet;\r
116 EFI_MTFTP4_OPTION *Option;\r
117 UINT32 PktLen;\r
118 UINT8 OptBuf[128];\r
119 UINT32 OptCnt;\r
120 EFI_STATUS Status;\r
121\r
122 *BufferSize = 0;\r
123 Status = EFI_DEVICE_ERROR;\r
124 Mtftp4 = Private->Mtftp4;\r
125 Packet = NULL;\r
126 Option = NULL;\r
127 PktLen = 0;\r
128 OptCnt = 1;\r
129 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
130\r
131 Status = Mtftp4->Configure (Mtftp4, Config);\r
132 if (EFI_ERROR (Status)) {\r
133\r
134 return Status;\r
135 }\r
136\r
9c87ebc0 137 ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX];\r
dc361cc5 138 UtoA10 (0, (CHAR8 *) OptBuf);\r
139 ReqOpt[0].ValueStr = OptBuf;\r
140\r
141 if (BlockSize != NULL) {\r
9c87ebc0 142 ReqOpt[1].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
dc361cc5 143 ReqOpt[1].ValueStr = ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1;\r
144 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[1].ValueStr);\r
145 OptCnt++;\r
146 }\r
147\r
148 Status = Mtftp4->GetInfo (\r
149 Mtftp4,\r
35d74819 150 NULL,\r
dc361cc5 151 Filename,\r
152 NULL,\r
153 (UINT8) OptCnt,\r
154 ReqOpt,\r
155 &PktLen,\r
156 &Packet\r
157 );\r
158\r
159 if (EFI_ERROR (Status)) {\r
169a3461 160 if (Status == EFI_TFTP_ERROR) {\r
982a9eae 161 Private->Mode.TftpErrorReceived = TRUE;\r
162 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;\r
f737cfb9 163 AsciiStrnCpy (\r
164 Private->Mode.TftpError.ErrorString, \r
165 (CHAR8 *) Packet->Error.ErrorMessage, \r
a361d391 166 PXE_MTFTP_ERROR_STRING_LENGTH\r
f737cfb9 167 );\r
a361d391 168 Private->Mode.TftpError.ErrorString[PXE_MTFTP_ERROR_STRING_LENGTH - 1] = '\0';\r
982a9eae 169 }\r
dc361cc5 170 goto ON_ERROR;\r
171 }\r
172\r
173 OptCnt = 0;\r
174\r
175 Status = Mtftp4->ParseOptions (\r
176 Mtftp4,\r
177 PktLen,\r
178 Packet,\r
179 (UINT32 *) &OptCnt,\r
180 &Option\r
181 );\r
182\r
183 if (EFI_ERROR (Status)) {\r
184\r
185 goto ON_ERROR;\r
186 }\r
187\r
188 Status = EFI_NOT_FOUND;\r
189\r
190 while (OptCnt != 0) {\r
191\r
192 if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) {\r
193\r
194 *BufferSize = AtoU64 (Option[OptCnt - 1].ValueStr);\r
195 Status = EFI_SUCCESS;\r
196 }\r
197\r
198 OptCnt--;\r
199 }\r
200\r
766c7483 201 FreePool (Option);\r
dc361cc5 202\r
203ON_ERROR:\r
204\r
205 if (Packet != NULL) {\r
766c7483 206 FreePool (Packet);\r
dc361cc5 207 }\r
208\r
209 Mtftp4->Configure (Mtftp4, NULL);\r
210\r
211 return Status;\r
212}\r
213\r
214\r
215/**\r
216 This function is to get data of a file by Tftp.\r
217\r
218 @param Private Pointer to PxeBc private data\r
219 @param Config Pointer to Mtftp configuration data\r
220 @param Filename Pointer to file name\r
221 @param BlockSize Pointer to block size\r
222 @param BufferPtr Pointer to buffer\r
223 @param BufferSize Pointer to buffer size\r
224 @param DontUseBuffer Indicate whether with a receive buffer\r
225\r
f737cfb9 226 @retval EFI_SUCCESS Read the data success from the special file.\r
227 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.\r
228 @retval other Read data from file failed.\r
229 \r
dc361cc5 230**/\r
231EFI_STATUS\r
232PxeBcTftpReadFile (\r
233 IN PXEBC_PRIVATE_DATA *Private,\r
234 IN EFI_MTFTP4_CONFIG_DATA *Config,\r
235 IN UINT8 *Filename,\r
236 IN UINTN *BlockSize,\r
237 IN UINT8 *BufferPtr,\r
238 IN OUT UINT64 *BufferSize,\r
239 IN BOOLEAN DontUseBuffer\r
240 )\r
241{\r
242 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
243 EFI_MTFTP4_TOKEN Token;\r
244 EFI_MTFTP4_OPTION ReqOpt[1];\r
245 UINT32 OptCnt;\r
246 UINT8 OptBuf[128];\r
247 EFI_STATUS Status;\r
248\r
249 Status = EFI_DEVICE_ERROR;\r
250 Mtftp4 = Private->Mtftp4;\r
251 OptCnt = 0;\r
252 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
253\r
254 Status = Mtftp4->Configure (Mtftp4, Config);\r
255 if (EFI_ERROR (Status)) {\r
256\r
257 return Status;\r
258 }\r
259\r
260 if (BlockSize != NULL) {\r
261\r
8792362f 262 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
dc361cc5 263 ReqOpt[0].ValueStr = OptBuf;\r
264 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);\r
265 OptCnt++;\r
266 }\r
267\r
268 Token.Event = NULL;\r
269 Token.OverrideData = NULL;\r
270 Token.Filename = Filename;\r
271 Token.ModeStr = NULL;\r
272 Token.OptionCount = OptCnt;\r
273 Token.OptionList = ReqOpt;\r
ea886bef 274 Token.Context = Private;\r
dc361cc5 275\r
276 if (DontUseBuffer) {\r
277 Token.BufferSize = 0;\r
278 Token.Buffer = NULL;\r
279 } else {\r
280 Token.BufferSize = *BufferSize;\r
281 Token.Buffer = BufferPtr;\r
282 }\r
283\r
284 Token.CheckPacket = PxeBcCheckPacket;\r
285 Token.TimeoutCallback = NULL;\r
286 Token.PacketNeeded = NULL;\r
287\r
288 Status = Mtftp4->ReadFile (Mtftp4, &Token);\r
289\r
290 *BufferSize = Token.BufferSize;\r
291\r
292 Mtftp4->Configure (Mtftp4, NULL);\r
293\r
294 return Status;\r
295}\r
296\r
297\r
298/**\r
299 This function is put data of a file by Tftp.\r
300\r
301 @param Private Pointer to PxeBc private data\r
302 @param Config Pointer to Mtftp configuration data\r
303 @param Filename Pointer to file name\r
304 @param Overwrite Indicate whether with overwrite attribute\r
305 @param BlockSize Pointer to block size\r
306 @param BufferPtr Pointer to buffer\r
307 @param BufferSize Pointer to buffer size\r
308\r
f737cfb9 309 @retval EFI_SUCCESS Write the data success into the special file.\r
310 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.\r
311 @retval other Write data into file failed.\r
312 \r
dc361cc5 313**/\r
314EFI_STATUS\r
315PxeBcTftpWriteFile (\r
316 IN PXEBC_PRIVATE_DATA *Private,\r
317 IN EFI_MTFTP4_CONFIG_DATA *Config,\r
318 IN UINT8 *Filename,\r
319 IN BOOLEAN Overwrite,\r
320 IN UINTN *BlockSize,\r
321 IN UINT8 *BufferPtr,\r
322 IN OUT UINT64 *BufferSize\r
323 )\r
324{\r
325 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
326 EFI_MTFTP4_TOKEN Token;\r
327 EFI_MTFTP4_OPTION ReqOpt[1];\r
328 UINT32 OptCnt;\r
329 UINT8 OptBuf[128];\r
330 EFI_STATUS Status;\r
331\r
332 Status = EFI_DEVICE_ERROR;\r
333 Mtftp4 = Private->Mtftp4;\r
334 OptCnt = 0;\r
335 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
336\r
337 Status = Mtftp4->Configure (Mtftp4, Config);\r
338 if (EFI_ERROR (Status)) {\r
339\r
340 return Status;\r
341 }\r
342\r
343 if (BlockSize != NULL) {\r
344\r
8792362f 345 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
dc361cc5 346 ReqOpt[0].ValueStr = OptBuf;\r
347 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);\r
348 OptCnt++;\r
349 }\r
350\r
351 Token.Event = NULL;\r
352 Token.OverrideData = NULL;\r
353 Token.Filename = Filename;\r
354 Token.ModeStr = NULL;\r
355 Token.OptionCount = OptCnt;\r
356 Token.OptionList = ReqOpt;\r
357 Token.BufferSize = *BufferSize;\r
358 Token.Buffer = BufferPtr;\r
359 Token.CheckPacket = PxeBcCheckPacket;\r
360 Token.TimeoutCallback = NULL;\r
361 Token.PacketNeeded = NULL;\r
362\r
363 Status = Mtftp4->WriteFile (Mtftp4, &Token);\r
364 *BufferSize = Token.BufferSize;\r
365\r
366 Mtftp4->Configure (Mtftp4, NULL);\r
367\r
368 return Status;\r
369}\r
370\r
371\r
372/**\r
f737cfb9 373 This function is to get data(file) from a directory(may be a server) by Tftp.\r
374\r
375 @param Private Pointer to PxeBc private data.\r
376 @param Config Pointer to Mtftp configuration data.\r
377 @param Filename Pointer to file name.\r
378 @param BlockSize Pointer to block size.\r
379 @param BufferPtr Pointer to buffer.\r
380 @param BufferSize Pointer to buffer size.\r
381 @param DontUseBuffer Indicate whether with a receive buffer.\r
382\r
383 @retval EFI_SUCCES Get the data from the file included in directory success. \r
384 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.\r
385 @retval other Operation failed.\r
386 \r
dc361cc5 387**/\r
dc361cc5 388EFI_STATUS\r
389PxeBcTftpReadDirectory (\r
390 IN PXEBC_PRIVATE_DATA *Private,\r
391 IN EFI_MTFTP4_CONFIG_DATA *Config,\r
392 IN UINT8 *Filename,\r
393 IN UINTN *BlockSize,\r
394 IN UINT8 *BufferPtr,\r
395 IN OUT UINT64 *BufferSize,\r
396 IN BOOLEAN DontUseBuffer\r
397 )\r
398{\r
399 EFI_MTFTP4_PROTOCOL *Mtftp4;\r
400 EFI_MTFTP4_TOKEN Token;\r
401 EFI_MTFTP4_OPTION ReqOpt[1];\r
402 UINT32 OptCnt;\r
403 UINT8 OptBuf[128];\r
404 EFI_STATUS Status;\r
405\r
406 Status = EFI_DEVICE_ERROR;\r
407 Mtftp4 = Private->Mtftp4;\r
408 OptCnt = 0;\r
409 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;\r
410\r
411 Status = Mtftp4->Configure (Mtftp4, Config);\r
412 if (EFI_ERROR (Status)) {\r
413\r
414 return Status;\r
415 }\r
416\r
417 if (BlockSize != NULL) {\r
418\r
8792362f 419 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];\r
dc361cc5 420 ReqOpt[0].ValueStr = OptBuf;\r
421 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);\r
422 OptCnt++;\r
423 }\r
424\r
425 Token.Event = NULL;\r
426 Token.OverrideData = NULL;\r
427 Token.Filename = Filename;\r
428 Token.ModeStr = NULL;\r
429 Token.OptionCount = OptCnt;\r
430 Token.OptionList = ReqOpt;\r
ea886bef 431 Token.Context = Private;\r
dc361cc5 432\r
433 if (DontUseBuffer) {\r
434 Token.BufferSize = 0;\r
435 Token.Buffer = NULL;\r
436 } else {\r
437 Token.BufferSize = *BufferSize;\r
438 Token.Buffer = BufferPtr;\r
439 }\r
440\r
441 Token.CheckPacket = PxeBcCheckPacket;\r
442 Token.TimeoutCallback = NULL;\r
443 Token.PacketNeeded = NULL;\r
444\r
445 Status = Mtftp4->ReadDirectory (Mtftp4, &Token);\r
446\r
447 *BufferSize = Token.BufferSize;\r
448\r
449 Mtftp4->Configure (Mtftp4, NULL);\r
450\r
451 return Status;\r
452}\r
453\r