]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/UefiPxeBcDxe/PxeBcMtftp.c
54de16ca5f87e5a4a93b05bf504eb84c983daac9
[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, 127);
64 }
65
66 if (Callback != NULL) {
67
68 Status = Callback->Callback (
69 Callback,
70 Private->Function,
71 TRUE,
72 PacketLen,
73 (EFI_PXE_BASE_CODE_PACKET *) Packet
74 );
75 if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
76
77 Status = EFI_ABORTED;
78 } else {
79
80 Status = EFI_SUCCESS;
81 }
82 }
83
84 return Status;
85 }
86
87
88 /**
89 This function is to get size of a file by Tftp.
90
91 @param Private Pointer to PxeBc private data
92 @param Config Pointer to Mtftp configuration data
93 @param Filename Pointer to file name
94 @param BlockSize Pointer to block size
95 @param BufferSize Pointer to buffer size
96
97 @retval EFI_SUCCESS Get the size of file success
98 @retval EFI_NOT_FOUND Parse the tftp ptions failed.
99 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.
100 @retval Other Has not get the size of the file.
101
102 **/
103 EFI_STATUS
104 PxeBcTftpGetFileSize (
105 IN PXEBC_PRIVATE_DATA *Private,
106 IN EFI_MTFTP4_CONFIG_DATA *Config,
107 IN UINT8 *Filename,
108 IN UINTN *BlockSize,
109 IN OUT UINT64 *BufferSize
110 )
111 {
112 EFI_MTFTP4_PROTOCOL *Mtftp4;
113 EFI_MTFTP4_OPTION ReqOpt[2];
114 EFI_MTFTP4_PACKET *Packet;
115 EFI_MTFTP4_OPTION *Option;
116 UINT32 PktLen;
117 UINT8 OptBuf[128];
118 UINT32 OptCnt;
119 EFI_STATUS Status;
120
121 *BufferSize = 0;
122 Status = EFI_DEVICE_ERROR;
123 Mtftp4 = Private->Mtftp4;
124 Packet = NULL;
125 Option = NULL;
126 PktLen = 0;
127 OptCnt = 1;
128 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
129
130 Status = Mtftp4->Configure (Mtftp4, Config);
131 if (EFI_ERROR (Status)) {
132
133 return Status;
134 }
135
136 ReqOpt[0].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_TSIZE_INDEX];
137 UtoA10 (0, (CHAR8 *) OptBuf);
138 ReqOpt[0].ValueStr = OptBuf;
139
140 if (BlockSize != NULL) {
141 ReqOpt[1].OptionStr = (UINT8*)mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
142 ReqOpt[1].ValueStr = ReqOpt[0].ValueStr + AsciiStrLen ((CHAR8 *) ReqOpt[0].ValueStr) + 1;
143 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[1].ValueStr);
144 OptCnt++;
145 }
146
147 Status = Mtftp4->GetInfo (
148 Mtftp4,
149 NULL,
150 Filename,
151 NULL,
152 (UINT8) OptCnt,
153 ReqOpt,
154 &PktLen,
155 &Packet
156 );
157
158 if (EFI_ERROR (Status)) {
159 if (Status == EFI_TFTP_ERROR) {
160 Private->Mode.TftpErrorReceived = TRUE;
161 Private->Mode.TftpError.ErrorCode = (UINT8) Packet->Error.ErrorCode;
162 AsciiStrnCpy (
163 Private->Mode.TftpError.ErrorString,
164 (CHAR8 *) Packet->Error.ErrorMessage,
165 127
166 );
167 }
168 goto ON_ERROR;
169 }
170
171 OptCnt = 0;
172
173 Status = Mtftp4->ParseOptions (
174 Mtftp4,
175 PktLen,
176 Packet,
177 (UINT32 *) &OptCnt,
178 &Option
179 );
180
181 if (EFI_ERROR (Status)) {
182
183 goto ON_ERROR;
184 }
185
186 Status = EFI_NOT_FOUND;
187
188 while (OptCnt != 0) {
189
190 if (AsciiStrnCmp ((CHAR8 *) Option[OptCnt - 1].OptionStr, "tsize", 5) == 0) {
191
192 *BufferSize = AtoU64 (Option[OptCnt - 1].ValueStr);
193 Status = EFI_SUCCESS;
194 }
195
196 OptCnt--;
197 }
198
199 FreePool (Option);
200
201 ON_ERROR:
202
203 if (Packet != NULL) {
204 FreePool (Packet);
205 }
206
207 Mtftp4->Configure (Mtftp4, NULL);
208
209 return Status;
210 }
211
212
213 /**
214 This function is to get data of a file by Tftp.
215
216 @param Private Pointer to PxeBc private data
217 @param Config Pointer to Mtftp configuration data
218 @param Filename Pointer to file name
219 @param BlockSize Pointer to block size
220 @param BufferPtr Pointer to buffer
221 @param BufferSize Pointer to buffer size
222 @param DontUseBuffer Indicate whether with a receive buffer
223
224 @retval EFI_SUCCESS Read the data success from the special file.
225 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.
226 @retval other Read data from file failed.
227
228 **/
229 EFI_STATUS
230 PxeBcTftpReadFile (
231 IN PXEBC_PRIVATE_DATA *Private,
232 IN EFI_MTFTP4_CONFIG_DATA *Config,
233 IN UINT8 *Filename,
234 IN UINTN *BlockSize,
235 IN UINT8 *BufferPtr,
236 IN OUT UINT64 *BufferSize,
237 IN BOOLEAN DontUseBuffer
238 )
239 {
240 EFI_MTFTP4_PROTOCOL *Mtftp4;
241 EFI_MTFTP4_TOKEN Token;
242 EFI_MTFTP4_OPTION ReqOpt[1];
243 UINT32 OptCnt;
244 UINT8 OptBuf[128];
245 EFI_STATUS Status;
246
247 Status = EFI_DEVICE_ERROR;
248 Mtftp4 = Private->Mtftp4;
249 OptCnt = 0;
250 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
251
252 Status = Mtftp4->Configure (Mtftp4, Config);
253 if (EFI_ERROR (Status)) {
254
255 return Status;
256 }
257
258 if (BlockSize != NULL) {
259
260 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
261 ReqOpt[0].ValueStr = OptBuf;
262 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);
263 OptCnt++;
264 }
265
266 Token.Event = NULL;
267 Token.OverrideData = NULL;
268 Token.Filename = Filename;
269 Token.ModeStr = NULL;
270 Token.OptionCount = OptCnt;
271 Token.OptionList = ReqOpt;
272 Token.Context = Private;
273
274 if (DontUseBuffer) {
275 Token.BufferSize = 0;
276 Token.Buffer = NULL;
277 } else {
278 Token.BufferSize = *BufferSize;
279 Token.Buffer = BufferPtr;
280 }
281
282 Token.CheckPacket = PxeBcCheckPacket;
283 Token.TimeoutCallback = NULL;
284 Token.PacketNeeded = NULL;
285
286 Status = Mtftp4->ReadFile (Mtftp4, &Token);
287
288 *BufferSize = Token.BufferSize;
289
290 Mtftp4->Configure (Mtftp4, NULL);
291
292 return Status;
293 }
294
295
296 /**
297 This function is put data of a file by Tftp.
298
299 @param Private Pointer to PxeBc private data
300 @param Config Pointer to Mtftp configuration data
301 @param Filename Pointer to file name
302 @param Overwrite Indicate whether with overwrite attribute
303 @param BlockSize Pointer to block size
304 @param BufferPtr Pointer to buffer
305 @param BufferSize Pointer to buffer size
306
307 @retval EFI_SUCCESS Write the data success into the special file.
308 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.
309 @retval other Write data into file failed.
310
311 **/
312 EFI_STATUS
313 PxeBcTftpWriteFile (
314 IN PXEBC_PRIVATE_DATA *Private,
315 IN EFI_MTFTP4_CONFIG_DATA *Config,
316 IN UINT8 *Filename,
317 IN BOOLEAN Overwrite,
318 IN UINTN *BlockSize,
319 IN UINT8 *BufferPtr,
320 IN OUT UINT64 *BufferSize
321 )
322 {
323 EFI_MTFTP4_PROTOCOL *Mtftp4;
324 EFI_MTFTP4_TOKEN Token;
325 EFI_MTFTP4_OPTION ReqOpt[1];
326 UINT32 OptCnt;
327 UINT8 OptBuf[128];
328 EFI_STATUS Status;
329
330 Status = EFI_DEVICE_ERROR;
331 Mtftp4 = Private->Mtftp4;
332 OptCnt = 0;
333 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
334
335 Status = Mtftp4->Configure (Mtftp4, Config);
336 if (EFI_ERROR (Status)) {
337
338 return Status;
339 }
340
341 if (BlockSize != NULL) {
342
343 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
344 ReqOpt[0].ValueStr = OptBuf;
345 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);
346 OptCnt++;
347 }
348
349 Token.Event = NULL;
350 Token.OverrideData = NULL;
351 Token.Filename = Filename;
352 Token.ModeStr = NULL;
353 Token.OptionCount = OptCnt;
354 Token.OptionList = ReqOpt;
355 Token.BufferSize = *BufferSize;
356 Token.Buffer = BufferPtr;
357 Token.CheckPacket = PxeBcCheckPacket;
358 Token.TimeoutCallback = NULL;
359 Token.PacketNeeded = NULL;
360
361 Status = Mtftp4->WriteFile (Mtftp4, &Token);
362 *BufferSize = Token.BufferSize;
363
364 Mtftp4->Configure (Mtftp4, NULL);
365
366 return Status;
367 }
368
369
370 /**
371 This function is to get data(file) from a directory(may be a server) by Tftp.
372
373 @param Private Pointer to PxeBc private data.
374 @param Config Pointer to Mtftp configuration data.
375 @param Filename Pointer to file name.
376 @param BlockSize Pointer to block size.
377 @param BufferPtr Pointer to buffer.
378 @param BufferSize Pointer to buffer size.
379 @param DontUseBuffer Indicate whether with a receive buffer.
380
381 @retval EFI_SUCCES Get the data from the file included in directory success.
382 @retval EFI_DEVICE_ERROR The network device encountered an error during this operation.
383 @retval other Operation failed.
384
385 **/
386 EFI_STATUS
387 PxeBcTftpReadDirectory (
388 IN PXEBC_PRIVATE_DATA *Private,
389 IN EFI_MTFTP4_CONFIG_DATA *Config,
390 IN UINT8 *Filename,
391 IN UINTN *BlockSize,
392 IN UINT8 *BufferPtr,
393 IN OUT UINT64 *BufferSize,
394 IN BOOLEAN DontUseBuffer
395 )
396 {
397 EFI_MTFTP4_PROTOCOL *Mtftp4;
398 EFI_MTFTP4_TOKEN Token;
399 EFI_MTFTP4_OPTION ReqOpt[1];
400 UINT32 OptCnt;
401 UINT8 OptBuf[128];
402 EFI_STATUS Status;
403
404 Status = EFI_DEVICE_ERROR;
405 Mtftp4 = Private->Mtftp4;
406 OptCnt = 0;
407 Config->InitialServerPort = PXEBC_BS_DOWNLOAD_PORT;
408
409 Status = Mtftp4->Configure (Mtftp4, Config);
410 if (EFI_ERROR (Status)) {
411
412 return Status;
413 }
414
415 if (BlockSize != NULL) {
416
417 ReqOpt[0].OptionStr = (UINT8*) mMtftpOptions[PXE_MTFTP_OPTION_BLKSIZE_INDEX];
418 ReqOpt[0].ValueStr = OptBuf;
419 UtoA10 (*BlockSize, (CHAR8 *) ReqOpt[0].ValueStr);
420 OptCnt++;
421 }
422
423 Token.Event = NULL;
424 Token.OverrideData = NULL;
425 Token.Filename = Filename;
426 Token.ModeStr = NULL;
427 Token.OptionCount = OptCnt;
428 Token.OptionList = ReqOpt;
429 Token.Context = Private;
430
431 if (DontUseBuffer) {
432 Token.BufferSize = 0;
433 Token.Buffer = NULL;
434 } else {
435 Token.BufferSize = *BufferSize;
436 Token.Buffer = BufferPtr;
437 }
438
439 Token.CheckPacket = PxeBcCheckPacket;
440 Token.TimeoutCallback = NULL;
441 Token.PacketNeeded = NULL;
442
443 Status = Mtftp4->ReadDirectory (Mtftp4, &Token);
444
445 *BufferSize = Token.BufferSize;
446
447 Mtftp4->Configure (Mtftp4, NULL);
448
449 return Status;
450 }
451