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