]>
Commit | Line | Data |
---|---|---|
68074260 RC |
1 | /** @file\r |
2 | The implementation for the 'tftp' Shell command.\r | |
3 | \r | |
4 | Copyright (c) 2015, ARM Ltd. All rights reserved.<BR>\r | |
ba0014b9 | 5 | Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved. <BR>\r |
6add86ab | 6 | (C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR>\r |
68074260 RC |
7 | \r |
8 | This program and the accompanying materials\r | |
9 | are licensed and made available under the terms and conditions of the BSD License\r | |
10 | which accompanies this distribution. The full text of the license may be found at\r | |
11 | http://opensource.org/licenses/bsd-license.php.\r | |
12 | \r | |
13 | THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r | |
14 | WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r | |
15 | **/\r | |
16 | \r | |
09610023 | 17 | #include "Tftp.h"\r |
68074260 | 18 | \r |
6add86ab | 19 | #define IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH 32\r |
09610023 | 20 | EFI_HANDLE mTftpHiiHandle;\r |
6add86ab | 21 | \r |
68074260 RC |
22 | /*\r |
23 | Constant strings and definitions related to the message indicating the amount of\r | |
24 | progress in the dowloading of a TFTP file.\r | |
25 | */\r | |
26 | \r | |
27 | // Frame for the progression slider\r | |
28 | STATIC CONST CHAR16 mTftpProgressFrame[] = L"[ ]";\r | |
29 | \r | |
30 | // Number of steps in the progression slider\r | |
31 | #define TFTP_PROGRESS_SLIDER_STEPS ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 3)\r | |
32 | \r | |
33 | // Size in number of characters plus one (final zero) of the message to\r | |
34 | // indicate the progress of a TFTP download. The format is "[(progress slider:\r | |
35 | // 40 characters)] (nb of KBytes downloaded so far: 7 characters) Kb". There\r | |
36 | // are thus the number of characters in mTftpProgressFrame[] plus 11 characters\r | |
37 | // (2 // spaces, "Kb" and seven characters for the number of KBytes).\r | |
38 | #define TFTP_PROGRESS_MESSAGE_SIZE ((sizeof (mTftpProgressFrame) / sizeof (CHAR16)) + 12)\r | |
39 | \r | |
40 | // String to delete the TFTP progress message to be able to update it :\r | |
41 | // (TFTP_PROGRESS_MESSAGE_SIZE-1) '\b'\r | |
42 | STATIC CONST CHAR16 mTftpProgressDelete[] = L"\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b";\r | |
43 | \r | |
0fcf66a4 QS |
44 | /**\r |
45 | Check and convert the UINT16 option values of the 'tftp' command\r | |
46 | \r | |
47 | @param[in] ValueStr Value as an Unicode encoded string\r | |
48 | @param[out] Value UINT16 value\r | |
49 | \r | |
50 | @return TRUE The value was returned.\r | |
51 | @return FALSE A parsing error occured.\r | |
52 | **/\r | |
ba0014b9 LG |
53 | STATIC\r |
54 | BOOLEAN\r | |
0fcf66a4 | 55 | StringToUint16 (\r |
68074260 RC |
56 | IN CONST CHAR16 *ValueStr,\r |
57 | OUT UINT16 *Value\r | |
58 | );\r | |
59 | \r | |
0fcf66a4 QS |
60 | /**\r |
61 | Get the name of the NIC.\r | |
62 | \r | |
63 | @param[in] ControllerHandle The network physical device handle.\r | |
64 | @param[in] NicNumber The network physical device number.\r | |
65 | @param[out] NicName Address where to store the NIC name.\r | |
66 | The memory area has to be at least\r | |
ba0014b9 | 67 | IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH\r |
6add86ab | 68 | double byte wide.\r |
0fcf66a4 QS |
69 | \r |
70 | @return EFI_SUCCESS The name of the NIC was returned.\r | |
71 | @return Others The creation of the child for the Managed\r | |
72 | Network Service failed or the opening of\r | |
73 | the Managed Network Protocol failed or\r | |
74 | the operational parameters for the\r | |
75 | Managed Network Protocol could not be\r | |
76 | read.\r | |
77 | **/\r | |
ba0014b9 LG |
78 | STATIC\r |
79 | EFI_STATUS\r | |
0fcf66a4 | 80 | GetNicName (\r |
68074260 | 81 | IN EFI_HANDLE ControllerHandle,\r |
a0f2af3a | 82 | IN UINTN NicNumber,\r |
68074260 RC |
83 | OUT CHAR16 *NicName\r |
84 | );\r | |
85 | \r | |
0fcf66a4 QS |
86 | /**\r |
87 | Create a child for the service identified by its service binding protocol GUID\r | |
88 | and get from the child the interface of the protocol identified by its GUID.\r | |
89 | \r | |
90 | @param[in] ControllerHandle Controller handle.\r | |
91 | @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r | |
92 | service to be created.\r | |
93 | @param[in] ProtocolGuid GUID of the protocol to be open.\r | |
94 | @param[out] ChildHandle Address where the handler of the\r | |
95 | created child is returned. NULL is\r | |
96 | returned in case of error.\r | |
97 | @param[out] Interface Address where a pointer to the\r | |
98 | protocol interface is returned in\r | |
99 | case of success.\r | |
100 | \r | |
101 | @return EFI_SUCCESS The child was created and the protocol opened.\r | |
102 | @return Others Either the creation of the child or the opening\r | |
103 | of the protocol failed.\r | |
104 | **/\r | |
ba0014b9 LG |
105 | STATIC\r |
106 | EFI_STATUS\r | |
0fcf66a4 | 107 | CreateServiceChildAndOpenProtocol (\r |
68074260 RC |
108 | IN EFI_HANDLE ControllerHandle,\r |
109 | IN EFI_GUID *ServiceBindingProtocolGuid,\r | |
110 | IN EFI_GUID *ProtocolGuid,\r | |
111 | OUT EFI_HANDLE *ChildHandle,\r | |
112 | OUT VOID **Interface\r | |
113 | );\r | |
114 | \r | |
0fcf66a4 QS |
115 | /**\r |
116 | Close the protocol identified by its GUID on the child handle of the service\r | |
117 | identified by its service binding protocol GUID, then destroy the child\r | |
118 | handle.\r | |
119 | \r | |
120 | @param[in] ControllerHandle Controller handle.\r | |
121 | @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r | |
122 | service to be destroyed.\r | |
123 | @param[in] ProtocolGuid GUID of the protocol to be closed.\r | |
124 | @param[in] ChildHandle Handle of the child to be destroyed.\r | |
125 | \r | |
126 | **/\r | |
ba0014b9 LG |
127 | STATIC\r |
128 | VOID\r | |
0fcf66a4 | 129 | CloseProtocolAndDestroyServiceChild (\r |
68074260 RC |
130 | IN EFI_HANDLE ControllerHandle,\r |
131 | IN EFI_GUID *ServiceBindingProtocolGuid,\r | |
132 | IN EFI_GUID *ProtocolGuid,\r | |
133 | IN EFI_HANDLE ChildHandle\r | |
134 | );\r | |
135 | \r | |
0fcf66a4 QS |
136 | /**\r |
137 | Worker function that gets the size in numbers of bytes of a file from a TFTP\r | |
138 | server before to download the file.\r | |
139 | \r | |
140 | @param[in] Mtftp4 MTFTP4 protocol interface\r | |
141 | @param[in] FilePath Path of the file, ASCII encoded\r | |
142 | @param[out] FileSize Address where to store the file size in number of\r | |
143 | bytes.\r | |
144 | \r | |
145 | @retval EFI_SUCCESS The size of the file was returned.\r | |
146 | @retval EFI_UNSUPPORTED The server does not support the "tsize" option.\r | |
147 | @retval Others Error when retrieving the information from the server\r | |
148 | (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)\r | |
149 | or error when parsing the response of the server.\r | |
150 | **/\r | |
ba0014b9 LG |
151 | STATIC\r |
152 | EFI_STATUS\r | |
0fcf66a4 | 153 | GetFileSize (\r |
68074260 RC |
154 | IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r |
155 | IN CONST CHAR8 *FilePath,\r | |
156 | OUT UINTN *FileSize\r | |
157 | );\r | |
158 | \r | |
0fcf66a4 QS |
159 | /**\r |
160 | Worker function that download the data of a file from a TFTP server given\r | |
161 | the path of the file and its size.\r | |
162 | \r | |
163 | @param[in] Mtftp4 MTFTP4 protocol interface\r | |
164 | @param[in] FilePath Path of the file, Unicode encoded\r | |
165 | @param[in] AsciiFilePath Path of the file, ASCII encoded\r | |
166 | @param[in] FileSize Size of the file in number of bytes\r | |
2be45bfe | 167 | @param[in] BlockSize Value of the TFTP blksize option\r |
0fcf66a4 QS |
168 | @param[out] Data Address where to store the address of the buffer\r |
169 | where the data of the file were downloaded in\r | |
170 | case of success.\r | |
171 | \r | |
172 | @retval EFI_SUCCESS The file was downloaded.\r | |
173 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r | |
174 | @retval Others The downloading of the file from the server failed\r | |
175 | (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).\r | |
176 | \r | |
177 | **/\r | |
ba0014b9 LG |
178 | STATIC\r |
179 | EFI_STATUS\r | |
0fcf66a4 | 180 | DownloadFile (\r |
68074260 RC |
181 | IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r |
182 | IN CONST CHAR16 *FilePath,\r | |
183 | IN CONST CHAR8 *AsciiFilePath,\r | |
184 | IN UINTN FileSize,\r | |
2be45bfe | 185 | IN UINT16 BlockSize,\r |
5c6fdb5e | 186 | IN UINT16 WindowSize,\r |
68074260 RC |
187 | OUT VOID **Data\r |
188 | );\r | |
189 | \r | |
0fcf66a4 QS |
190 | /**\r |
191 | Update the progress of a file download\r | |
192 | This procedure is called each time a new TFTP packet is received.\r | |
193 | \r | |
194 | @param[in] This MTFTP4 protocol interface\r | |
195 | @param[in] Token Parameters for the download of the file\r | |
196 | @param[in] PacketLen Length of the packet\r | |
197 | @param[in] Packet Address of the packet\r | |
198 | \r | |
199 | @retval EFI_SUCCESS All packets are accepted.\r | |
200 | \r | |
201 | **/\r | |
ba0014b9 LG |
202 | STATIC\r |
203 | EFI_STATUS\r | |
7367e66f | 204 | EFIAPI\r |
0fcf66a4 | 205 | CheckPacket (\r |
68074260 RC |
206 | IN EFI_MTFTP4_PROTOCOL *This,\r |
207 | IN EFI_MTFTP4_TOKEN *Token,\r | |
208 | IN UINT16 PacketLen,\r | |
209 | IN EFI_MTFTP4_PACKET *Packet\r | |
210 | );\r | |
211 | \r | |
212 | EFI_MTFTP4_CONFIG_DATA DefaultMtftp4ConfigData = {\r | |
213 | TRUE, // Use default setting\r | |
214 | { { 0, 0, 0, 0 } }, // StationIp - Not relevant as UseDefaultSetting=TRUE\r | |
215 | { { 0, 0, 0, 0 } }, // SubnetMask - Not relevant as UseDefaultSetting=TRUE\r | |
216 | 0, // LocalPort - Automatically assigned port number.\r | |
217 | { { 0, 0, 0, 0 } }, // GatewayIp - Not relevant as UseDefaultSetting=TRUE\r | |
218 | { { 0, 0, 0, 0 } }, // ServerIp - Not known yet\r | |
219 | 69, // InitialServerPort - Standard TFTP server port\r | |
220 | 6, // TryCount - Max number of retransmissions.\r | |
221 | 4 // TimeoutValue - Retransmission timeout in seconds.\r | |
222 | };\r | |
223 | \r | |
224 | STATIC CONST SHELL_PARAM_ITEM ParamList[] = {\r | |
225 | {L"-i", TypeValue},\r | |
226 | {L"-l", TypeValue},\r | |
227 | {L"-r", TypeValue},\r | |
228 | {L"-c", TypeValue},\r | |
229 | {L"-t", TypeValue},\r | |
2be45bfe | 230 | {L"-s", TypeValue},\r |
5c6fdb5e | 231 | {L"-w", TypeValue},\r |
68074260 RC |
232 | {NULL , TypeMax}\r |
233 | };\r | |
234 | \r | |
2be45bfe FS |
235 | ///\r |
236 | /// The default block size (512) of tftp is defined in the RFC1350.\r | |
237 | ///\r | |
238 | #define MTFTP_DEFAULT_BLKSIZE 512\r | |
239 | ///\r | |
240 | /// The valid range of block size option is defined in the RFC2348.\r | |
241 | ///\r | |
242 | #define MTFTP_MIN_BLKSIZE 8\r | |
243 | #define MTFTP_MAX_BLKSIZE 65464\r | |
5c6fdb5e JW |
244 | ///\r |
245 | /// The default windowsize (1) of tftp.\r | |
246 | ///\r | |
247 | #define MTFTP_DEFAULT_WINDOWSIZE 1\r | |
248 | ///\r | |
249 | /// The valid range of window size option.\r | |
250 | /// Note that: RFC 7440 does not mention max window size value, but for the\r | |
251 | /// stability reason, the value is limited to 64.\r | |
252 | ///\r | |
253 | #define MTFTP_MIN_WINDOWSIZE 1\r | |
254 | #define MTFTP_MAX_WINDOWSIZE 64\r | |
2be45bfe | 255 | \r |
68074260 RC |
256 | /**\r |
257 | Function for 'tftp' command.\r | |
258 | \r | |
259 | @param[in] ImageHandle Handle to the Image (NULL if Internal).\r | |
260 | @param[in] SystemTable Pointer to the System Table (NULL if Internal).\r | |
261 | \r | |
262 | @return SHELL_SUCCESS The 'tftp' command completed successfully.\r | |
263 | @return SHELL_ABORTED The Shell Library initialization failed.\r | |
264 | @return SHELL_INVALID_PARAMETER At least one of the command's arguments is\r | |
265 | not valid.\r | |
266 | @return SHELL_OUT_OF_RESOURCES A memory allocation failed.\r | |
267 | @return SHELL_NOT_FOUND Network Interface Card not found or server\r | |
268 | error or file error.\r | |
269 | \r | |
270 | **/\r | |
271 | SHELL_STATUS\r | |
09610023 | 272 | RunTftp (\r |
68074260 RC |
273 | IN EFI_HANDLE ImageHandle,\r |
274 | IN EFI_SYSTEM_TABLE *SystemTable\r | |
275 | )\r | |
276 | {\r | |
277 | SHELL_STATUS ShellStatus;\r | |
278 | EFI_STATUS Status;\r | |
279 | LIST_ENTRY *CheckPackage;\r | |
280 | CHAR16 *ProblemParam;\r | |
281 | UINTN ParamCount;\r | |
282 | CONST CHAR16 *UserNicName;\r | |
283 | BOOLEAN NicFound;\r | |
284 | CONST CHAR16 *ValueStr;\r | |
285 | CONST CHAR16 *RemoteFilePath;\r | |
286 | CHAR8 *AsciiRemoteFilePath;\r | |
46213c8e | 287 | UINTN FilePathSize;\r |
68074260 RC |
288 | CONST CHAR16 *Walker;\r |
289 | CONST CHAR16 *LocalFilePath;\r | |
290 | EFI_MTFTP4_CONFIG_DATA Mtftp4ConfigData;\r | |
291 | EFI_HANDLE *Handles;\r | |
292 | UINTN HandleCount;\r | |
293 | UINTN NicNumber;\r | |
6add86ab | 294 | CHAR16 NicName[IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH];\r |
68074260 RC |
295 | EFI_HANDLE ControllerHandle;\r |
296 | EFI_HANDLE Mtftp4ChildHandle;\r | |
297 | EFI_MTFTP4_PROTOCOL *Mtftp4;\r | |
298 | UINTN FileSize;\r | |
34cd44d4 | 299 | UINTN DataSize;\r |
68074260 RC |
300 | VOID *Data;\r |
301 | SHELL_FILE_HANDLE FileHandle;\r | |
2be45bfe | 302 | UINT16 BlockSize;\r |
5c6fdb5e | 303 | UINT16 WindowSize;\r |
68074260 RC |
304 | \r |
305 | ShellStatus = SHELL_INVALID_PARAMETER;\r | |
306 | ProblemParam = NULL;\r | |
307 | NicFound = FALSE;\r | |
308 | AsciiRemoteFilePath = NULL;\r | |
309 | Handles = NULL;\r | |
6add86ab | 310 | FileSize = 0;\r |
34cd44d4 | 311 | DataSize = 0;\r |
2be45bfe | 312 | BlockSize = MTFTP_DEFAULT_BLKSIZE;\r |
5c6fdb5e | 313 | WindowSize = MTFTP_DEFAULT_WINDOWSIZE;\r |
68074260 RC |
314 | \r |
315 | //\r | |
316 | // Initialize the Shell library (we must be in non-auto-init...)\r | |
317 | //\r | |
318 | Status = ShellInitialize ();\r | |
319 | if (EFI_ERROR (Status)) {\r | |
320 | ASSERT_EFI_ERROR (Status);\r | |
321 | return SHELL_ABORTED;\r | |
322 | }\r | |
323 | \r | |
324 | //\r | |
325 | // Parse the command line.\r | |
326 | //\r | |
327 | Status = ShellCommandLineParse (ParamList, &CheckPackage, &ProblemParam, TRUE);\r | |
328 | if (EFI_ERROR (Status)) {\r | |
329 | if ((Status == EFI_VOLUME_CORRUPTED) &&\r | |
330 | (ProblemParam != NULL) ) {\r | |
331 | ShellPrintHiiEx (\r | |
09610023 | 332 | -1, -1, NULL, STRING_TOKEN (STR_GEN_PROBLEM), mTftpHiiHandle,\r |
68074260 RC |
333 | L"tftp", ProblemParam\r |
334 | );\r | |
335 | FreePool (ProblemParam);\r | |
336 | } else {\r | |
337 | ASSERT (FALSE);\r | |
338 | }\r | |
339 | goto Error;\r | |
340 | }\r | |
341 | \r | |
342 | //\r | |
343 | // Check the number of parameters\r | |
344 | //\r | |
345 | ParamCount = ShellCommandLineGetCount (CheckPackage);\r | |
346 | if (ParamCount > 4) {\r | |
347 | ShellPrintHiiEx (\r | |
348 | -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_MANY),\r | |
09610023 | 349 | mTftpHiiHandle, L"tftp"\r |
68074260 RC |
350 | );\r |
351 | goto Error;\r | |
352 | }\r | |
353 | if (ParamCount < 3) {\r | |
354 | ShellPrintHiiEx (\r | |
355 | -1, -1, NULL, STRING_TOKEN (STR_GEN_TOO_FEW),\r | |
09610023 | 356 | mTftpHiiHandle, L"tftp"\r |
68074260 RC |
357 | );\r |
358 | goto Error;\r | |
359 | }\r | |
360 | \r | |
ba601bdd | 361 | CopyMem (&Mtftp4ConfigData, &DefaultMtftp4ConfigData, sizeof (EFI_MTFTP4_CONFIG_DATA));\r |
68074260 RC |
362 | \r |
363 | //\r | |
364 | // Check the host IPv4 address\r | |
365 | //\r | |
366 | ValueStr = ShellCommandLineGetRawValue (CheckPackage, 1);\r | |
367 | Status = NetLibStrToIp4 (ValueStr, &Mtftp4ConfigData.ServerIp);\r | |
368 | if (EFI_ERROR (Status)) {\r | |
369 | ShellPrintHiiEx (\r | |
370 | -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r | |
09610023 | 371 | mTftpHiiHandle, L"tftp", ValueStr\r |
68074260 RC |
372 | );\r |
373 | goto Error;\r | |
374 | }\r | |
375 | \r | |
376 | RemoteFilePath = ShellCommandLineGetRawValue (CheckPackage, 2);\r | |
c6173804 | 377 | ASSERT(RemoteFilePath != NULL);\r |
46213c8e SZ |
378 | FilePathSize = StrLen (RemoteFilePath) + 1;\r |
379 | AsciiRemoteFilePath = AllocatePool (FilePathSize);\r | |
68074260 RC |
380 | if (AsciiRemoteFilePath == NULL) {\r |
381 | ShellStatus = SHELL_OUT_OF_RESOURCES;\r | |
382 | goto Error;\r | |
383 | }\r | |
46213c8e | 384 | UnicodeStrToAsciiStrS (RemoteFilePath, AsciiRemoteFilePath, FilePathSize);\r |
68074260 RC |
385 | \r |
386 | if (ParamCount == 4) {\r | |
387 | LocalFilePath = ShellCommandLineGetRawValue (CheckPackage, 3);\r | |
388 | } else {\r | |
389 | Walker = RemoteFilePath + StrLen (RemoteFilePath);\r | |
390 | while ((--Walker) >= RemoteFilePath) {\r | |
391 | if ((*Walker == L'\\') ||\r | |
392 | (*Walker == L'/' ) ) {\r | |
393 | break;\r | |
394 | }\r | |
395 | }\r | |
396 | LocalFilePath = Walker + 1;\r | |
397 | }\r | |
398 | \r | |
399 | //\r | |
400 | // Get the name of the Network Interface Card to be used if any.\r | |
401 | //\r | |
402 | UserNicName = ShellCommandLineGetValue (CheckPackage, L"-i");\r | |
403 | \r | |
404 | ValueStr = ShellCommandLineGetValue (CheckPackage, L"-l");\r | |
405 | if (ValueStr != NULL) {\r | |
406 | if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.LocalPort)) {\r | |
407 | goto Error;\r | |
408 | }\r | |
409 | }\r | |
410 | \r | |
411 | ValueStr = ShellCommandLineGetValue (CheckPackage, L"-r");\r | |
412 | if (ValueStr != NULL) {\r | |
413 | if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.InitialServerPort)) {\r | |
414 | goto Error;\r | |
415 | }\r | |
416 | }\r | |
417 | \r | |
418 | ValueStr = ShellCommandLineGetValue (CheckPackage, L"-c");\r | |
419 | if (ValueStr != NULL) {\r | |
420 | if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TryCount)) {\r | |
421 | goto Error;\r | |
422 | }\r | |
423 | }\r | |
424 | \r | |
425 | ValueStr = ShellCommandLineGetValue (CheckPackage, L"-t");\r | |
426 | if (ValueStr != NULL) {\r | |
427 | if (!StringToUint16 (ValueStr, &Mtftp4ConfigData.TimeoutValue)) {\r | |
428 | goto Error;\r | |
429 | }\r | |
430 | if (Mtftp4ConfigData.TimeoutValue == 0) {\r | |
431 | ShellPrintHiiEx (\r | |
432 | -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r | |
09610023 | 433 | mTftpHiiHandle, L"tftp", ValueStr\r |
68074260 RC |
434 | );\r |
435 | goto Error;\r | |
436 | }\r | |
437 | }\r | |
438 | \r | |
2be45bfe FS |
439 | ValueStr = ShellCommandLineGetValue (CheckPackage, L"-s");\r |
440 | if (ValueStr != NULL) {\r | |
441 | if (!StringToUint16 (ValueStr, &BlockSize)) {\r | |
442 | goto Error;\r | |
443 | }\r | |
444 | if (BlockSize < MTFTP_MIN_BLKSIZE || BlockSize > MTFTP_MAX_BLKSIZE) {\r | |
445 | ShellPrintHiiEx (\r | |
446 | -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r | |
09610023 | 447 | mTftpHiiHandle, L"tftp", ValueStr\r |
2be45bfe FS |
448 | );\r |
449 | goto Error;\r | |
450 | }\r | |
451 | }\r | |
452 | \r | |
5c6fdb5e JW |
453 | ValueStr = ShellCommandLineGetValue (CheckPackage, L"-w");\r |
454 | if (ValueStr != NULL) {\r | |
455 | if (!StringToUint16 (ValueStr, &WindowSize)) {\r | |
456 | goto Error;\r | |
457 | }\r | |
458 | if (WindowSize < MTFTP_MIN_WINDOWSIZE || WindowSize > MTFTP_MAX_WINDOWSIZE) {\r | |
459 | ShellPrintHiiEx (\r | |
460 | -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r | |
461 | mTftpHiiHandle, L"tftp", ValueStr\r | |
462 | );\r | |
463 | goto Error;\r | |
464 | }\r | |
465 | }\r | |
466 | \r | |
68074260 RC |
467 | //\r |
468 | // Locate all MTFTP4 Service Binding protocols\r | |
469 | //\r | |
470 | ShellStatus = SHELL_NOT_FOUND;\r | |
471 | Status = gBS->LocateHandleBuffer (\r | |
472 | ByProtocol,\r | |
473 | &gEfiManagedNetworkServiceBindingProtocolGuid,\r | |
474 | NULL,\r | |
475 | &HandleCount,\r | |
476 | &Handles\r | |
477 | );\r | |
478 | if (EFI_ERROR (Status) || (HandleCount == 0)) {\r | |
479 | ShellPrintHiiEx (\r | |
480 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NO_NIC),\r | |
09610023 | 481 | mTftpHiiHandle\r |
68074260 RC |
482 | );\r |
483 | goto Error;\r | |
484 | }\r | |
485 | \r | |
486 | for (NicNumber = 0;\r | |
487 | (NicNumber < HandleCount) && (ShellStatus != SHELL_SUCCESS);\r | |
488 | NicNumber++) {\r | |
489 | ControllerHandle = Handles[NicNumber];\r | |
490 | Data = NULL;\r | |
491 | \r | |
492 | Status = GetNicName (ControllerHandle, NicNumber, NicName);\r | |
493 | if (EFI_ERROR (Status)) {\r | |
494 | ShellPrintHiiEx (\r | |
495 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NAME),\r | |
09610023 | 496 | mTftpHiiHandle, NicNumber, Status\r |
68074260 RC |
497 | );\r |
498 | continue;\r | |
499 | }\r | |
500 | \r | |
501 | if (UserNicName != NULL) {\r | |
502 | if (StrCmp (NicName, UserNicName) != 0) {\r | |
503 | continue;\r | |
504 | }\r | |
505 | NicFound = TRUE;\r | |
506 | }\r | |
507 | \r | |
508 | Status = CreateServiceChildAndOpenProtocol (\r | |
509 | ControllerHandle,\r | |
510 | &gEfiMtftp4ServiceBindingProtocolGuid,\r | |
511 | &gEfiMtftp4ProtocolGuid,\r | |
512 | &Mtftp4ChildHandle,\r | |
513 | (VOID**)&Mtftp4\r | |
514 | );\r | |
515 | if (EFI_ERROR (Status)) {\r | |
516 | ShellPrintHiiEx (\r | |
517 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_OPEN_PROTOCOL),\r | |
09610023 | 518 | mTftpHiiHandle, NicName, Status\r |
68074260 RC |
519 | );\r |
520 | continue;\r | |
521 | }\r | |
522 | \r | |
523 | Status = Mtftp4->Configure (Mtftp4, &Mtftp4ConfigData);\r | |
524 | if (EFI_ERROR (Status)) {\r | |
525 | ShellPrintHiiEx (\r | |
526 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_CONFIGURE),\r | |
09610023 | 527 | mTftpHiiHandle, NicName, Status\r |
68074260 RC |
528 | );\r |
529 | goto NextHandle;\r | |
530 | }\r | |
531 | \r | |
532 | Status = GetFileSize (Mtftp4, AsciiRemoteFilePath, &FileSize);\r | |
533 | if (EFI_ERROR (Status)) {\r | |
534 | ShellPrintHiiEx (\r | |
535 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_FILE_SIZE),\r | |
09610023 | 536 | mTftpHiiHandle, RemoteFilePath, NicName, Status\r |
68074260 RC |
537 | );\r |
538 | goto NextHandle;\r | |
539 | }\r | |
540 | \r | |
5c6fdb5e | 541 | Status = DownloadFile (Mtftp4, RemoteFilePath, AsciiRemoteFilePath, FileSize, BlockSize, WindowSize, &Data);\r |
68074260 RC |
542 | if (EFI_ERROR (Status)) {\r |
543 | ShellPrintHiiEx (\r | |
544 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_DOWNLOAD),\r | |
09610023 | 545 | mTftpHiiHandle, RemoteFilePath, NicName, Status\r |
68074260 RC |
546 | );\r |
547 | goto NextHandle;\r | |
548 | }\r | |
549 | \r | |
280f49b8 JW |
550 | DataSize = FileSize;\r |
551 | \r | |
68074260 RC |
552 | if (!EFI_ERROR (ShellFileExists (LocalFilePath))) {\r |
553 | ShellDeleteFileByName (LocalFilePath);\r | |
554 | }\r | |
555 | \r | |
556 | Status = ShellOpenFileByName (\r | |
557 | LocalFilePath,\r | |
558 | &FileHandle,\r | |
559 | EFI_FILE_MODE_CREATE |\r | |
560 | EFI_FILE_MODE_WRITE |\r | |
561 | EFI_FILE_MODE_READ,\r | |
562 | 0\r | |
563 | );\r | |
564 | if (EFI_ERROR (Status)) {\r | |
565 | ShellPrintHiiEx (\r | |
566 | -1, -1, NULL, STRING_TOKEN (STR_GEN_FILE_OPEN_FAIL),\r | |
09610023 | 567 | mTftpHiiHandle, L"tftp", LocalFilePath\r |
68074260 RC |
568 | );\r |
569 | goto NextHandle;\r | |
570 | }\r | |
571 | \r | |
572 | Status = ShellWriteFile (FileHandle, &FileSize, Data);\r | |
573 | if (!EFI_ERROR (Status)) {\r | |
574 | ShellStatus = SHELL_SUCCESS;\r | |
575 | } else {\r | |
576 | ShellPrintHiiEx (\r | |
577 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_WRITE),\r | |
09610023 | 578 | mTftpHiiHandle, LocalFilePath, Status\r |
68074260 RC |
579 | );\r |
580 | }\r | |
581 | ShellCloseFile (&FileHandle);\r | |
582 | \r | |
583 | NextHandle:\r | |
584 | \r | |
585 | if (Data != NULL) {\r | |
34cd44d4 | 586 | gBS->FreePages ((EFI_PHYSICAL_ADDRESS)(UINTN)Data, EFI_SIZE_TO_PAGES (DataSize));\r |
68074260 RC |
587 | }\r |
588 | \r | |
589 | CloseProtocolAndDestroyServiceChild (\r | |
590 | ControllerHandle,\r | |
591 | &gEfiMtftp4ServiceBindingProtocolGuid,\r | |
592 | &gEfiMtftp4ProtocolGuid,\r | |
593 | Mtftp4ChildHandle\r | |
594 | );\r | |
595 | }\r | |
596 | \r | |
a0f2af3a | 597 | if ((UserNicName != NULL) && (!NicFound)) {\r |
68074260 RC |
598 | ShellPrintHiiEx (\r |
599 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_ERR_NIC_NOT_FOUND),\r | |
09610023 | 600 | mTftpHiiHandle, UserNicName\r |
68074260 RC |
601 | );\r |
602 | }\r | |
603 | \r | |
604 | Error:\r | |
605 | \r | |
606 | ShellCommandLineFreeVarList (CheckPackage);\r | |
607 | if (AsciiRemoteFilePath != NULL) {\r | |
608 | FreePool (AsciiRemoteFilePath);\r | |
609 | }\r | |
610 | if (Handles != NULL) {\r | |
611 | FreePool (Handles);\r | |
612 | }\r | |
613 | \r | |
614 | return ShellStatus;\r | |
615 | }\r | |
616 | \r | |
617 | /**\r | |
618 | Check and convert the UINT16 option values of the 'tftp' command\r | |
619 | \r | |
620 | @param[in] ValueStr Value as an Unicode encoded string\r | |
621 | @param[out] Value UINT16 value\r | |
622 | \r | |
623 | @return TRUE The value was returned.\r | |
624 | @return FALSE A parsing error occured.\r | |
625 | **/\r | |
626 | STATIC\r | |
627 | BOOLEAN\r | |
628 | StringToUint16 (\r | |
629 | IN CONST CHAR16 *ValueStr,\r | |
630 | OUT UINT16 *Value\r | |
631 | )\r | |
632 | {\r | |
633 | UINTN Val;\r | |
634 | \r | |
635 | Val = ShellStrToUintn (ValueStr);\r | |
636 | if (Val > MAX_UINT16) {\r | |
637 | ShellPrintHiiEx (\r | |
638 | -1, -1, NULL, STRING_TOKEN (STR_GEN_PARAM_INV),\r | |
09610023 | 639 | mTftpHiiHandle, L"tftp", ValueStr\r |
68074260 RC |
640 | );\r |
641 | return FALSE;\r | |
642 | }\r | |
643 | \r | |
6add86ab | 644 | *Value = (UINT16)Val;\r |
68074260 RC |
645 | return TRUE;\r |
646 | }\r | |
647 | \r | |
648 | /**\r | |
649 | Get the name of the NIC.\r | |
650 | \r | |
651 | @param[in] ControllerHandle The network physical device handle.\r | |
652 | @param[in] NicNumber The network physical device number.\r | |
653 | @param[out] NicName Address where to store the NIC name.\r | |
654 | The memory area has to be at least\r | |
ba0014b9 | 655 | IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH\r |
6add86ab | 656 | double byte wide.\r |
68074260 RC |
657 | \r |
658 | @return EFI_SUCCESS The name of the NIC was returned.\r | |
659 | @return Others The creation of the child for the Managed\r | |
660 | Network Service failed or the opening of\r | |
661 | the Managed Network Protocol failed or\r | |
662 | the operational parameters for the\r | |
663 | Managed Network Protocol could not be\r | |
664 | read.\r | |
665 | **/\r | |
666 | STATIC\r | |
667 | EFI_STATUS\r | |
668 | GetNicName (\r | |
669 | IN EFI_HANDLE ControllerHandle,\r | |
670 | IN UINTN NicNumber,\r | |
671 | OUT CHAR16 *NicName\r | |
672 | )\r | |
673 | {\r | |
674 | EFI_STATUS Status;\r | |
675 | EFI_HANDLE MnpHandle;\r | |
676 | EFI_MANAGED_NETWORK_PROTOCOL *Mnp;\r | |
677 | EFI_SIMPLE_NETWORK_MODE SnpMode;\r | |
678 | \r | |
679 | Status = CreateServiceChildAndOpenProtocol (\r | |
680 | ControllerHandle,\r | |
681 | &gEfiManagedNetworkServiceBindingProtocolGuid,\r | |
682 | &gEfiManagedNetworkProtocolGuid,\r | |
683 | &MnpHandle,\r | |
684 | (VOID**)&Mnp\r | |
685 | );\r | |
686 | if (EFI_ERROR (Status)) {\r | |
687 | goto Error;\r | |
688 | }\r | |
689 | \r | |
690 | Status = Mnp->GetModeData (Mnp, NULL, &SnpMode);\r | |
691 | if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {\r | |
692 | goto Error;\r | |
693 | }\r | |
694 | \r | |
695 | UnicodeSPrint (\r | |
696 | NicName,\r | |
6add86ab | 697 | IP4_CONFIG2_INTERFACE_INFO_NAME_LENGTH,\r |
68074260 RC |
698 | SnpMode.IfType == NET_IFTYPE_ETHERNET ?\r |
699 | L"eth%d" :\r | |
700 | L"unk%d" ,\r | |
701 | NicNumber\r | |
702 | );\r | |
703 | \r | |
704 | Status = EFI_SUCCESS;\r | |
705 | \r | |
706 | Error:\r | |
707 | \r | |
708 | if (MnpHandle != NULL) {\r | |
709 | CloseProtocolAndDestroyServiceChild (\r | |
710 | ControllerHandle,\r | |
711 | &gEfiManagedNetworkServiceBindingProtocolGuid,\r | |
712 | &gEfiManagedNetworkProtocolGuid,\r | |
713 | MnpHandle\r | |
714 | );\r | |
715 | }\r | |
716 | \r | |
717 | return Status;\r | |
718 | }\r | |
719 | \r | |
720 | /**\r | |
721 | Create a child for the service identified by its service binding protocol GUID\r | |
722 | and get from the child the interface of the protocol identified by its GUID.\r | |
723 | \r | |
724 | @param[in] ControllerHandle Controller handle.\r | |
725 | @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r | |
726 | service to be created.\r | |
727 | @param[in] ProtocolGuid GUID of the protocol to be open.\r | |
728 | @param[out] ChildHandle Address where the handler of the\r | |
729 | created child is returned. NULL is\r | |
730 | returned in case of error.\r | |
731 | @param[out] Interface Address where a pointer to the\r | |
732 | protocol interface is returned in\r | |
733 | case of success.\r | |
734 | \r | |
735 | @return EFI_SUCCESS The child was created and the protocol opened.\r | |
736 | @return Others Either the creation of the child or the opening\r | |
737 | of the protocol failed.\r | |
738 | **/\r | |
739 | STATIC\r | |
740 | EFI_STATUS\r | |
741 | CreateServiceChildAndOpenProtocol (\r | |
742 | IN EFI_HANDLE ControllerHandle,\r | |
743 | IN EFI_GUID *ServiceBindingProtocolGuid,\r | |
744 | IN EFI_GUID *ProtocolGuid,\r | |
745 | OUT EFI_HANDLE *ChildHandle,\r | |
746 | OUT VOID **Interface\r | |
747 | )\r | |
748 | {\r | |
749 | EFI_STATUS Status;\r | |
750 | \r | |
751 | *ChildHandle = NULL;\r | |
752 | Status = NetLibCreateServiceChild (\r | |
753 | ControllerHandle,\r | |
754 | gImageHandle,\r | |
755 | ServiceBindingProtocolGuid,\r | |
756 | ChildHandle\r | |
757 | );\r | |
758 | if (!EFI_ERROR (Status)) {\r | |
759 | Status = gBS->OpenProtocol (\r | |
760 | *ChildHandle,\r | |
761 | ProtocolGuid,\r | |
762 | Interface,\r | |
763 | gImageHandle,\r | |
764 | ControllerHandle,\r | |
765 | EFI_OPEN_PROTOCOL_GET_PROTOCOL\r | |
766 | );\r | |
767 | if (EFI_ERROR (Status)) {\r | |
768 | NetLibDestroyServiceChild (\r | |
769 | ControllerHandle,\r | |
770 | gImageHandle,\r | |
771 | ServiceBindingProtocolGuid,\r | |
772 | *ChildHandle\r | |
773 | );\r | |
774 | *ChildHandle = NULL;\r | |
775 | }\r | |
776 | }\r | |
777 | \r | |
778 | return Status;\r | |
779 | }\r | |
780 | \r | |
781 | /**\r | |
782 | Close the protocol identified by its GUID on the child handle of the service\r | |
783 | identified by its service binding protocol GUID, then destroy the child\r | |
784 | handle.\r | |
785 | \r | |
786 | @param[in] ControllerHandle Controller handle.\r | |
787 | @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the\r | |
788 | service to be destroyed.\r | |
789 | @param[in] ProtocolGuid GUID of the protocol to be closed.\r | |
790 | @param[in] ChildHandle Handle of the child to be destroyed.\r | |
791 | \r | |
792 | **/\r | |
793 | STATIC\r | |
794 | VOID\r | |
795 | CloseProtocolAndDestroyServiceChild (\r | |
796 | IN EFI_HANDLE ControllerHandle,\r | |
797 | IN EFI_GUID *ServiceBindingProtocolGuid,\r | |
798 | IN EFI_GUID *ProtocolGuid,\r | |
799 | IN EFI_HANDLE ChildHandle\r | |
800 | )\r | |
801 | {\r | |
802 | gBS->CloseProtocol (\r | |
803 | ChildHandle,\r | |
804 | ProtocolGuid,\r | |
805 | gImageHandle,\r | |
806 | ControllerHandle\r | |
807 | );\r | |
808 | \r | |
809 | NetLibDestroyServiceChild (\r | |
810 | ControllerHandle,\r | |
811 | gImageHandle,\r | |
812 | ServiceBindingProtocolGuid,\r | |
813 | ChildHandle\r | |
814 | );\r | |
815 | }\r | |
816 | \r | |
817 | /**\r | |
818 | Worker function that gets the size in numbers of bytes of a file from a TFTP\r | |
819 | server before to download the file.\r | |
820 | \r | |
821 | @param[in] Mtftp4 MTFTP4 protocol interface\r | |
822 | @param[in] FilePath Path of the file, ASCII encoded\r | |
823 | @param[out] FileSize Address where to store the file size in number of\r | |
824 | bytes.\r | |
825 | \r | |
826 | @retval EFI_SUCCESS The size of the file was returned.\r | |
827 | @retval EFI_UNSUPPORTED The server does not support the "tsize" option.\r | |
828 | @retval Others Error when retrieving the information from the server\r | |
829 | (see EFI_MTFTP4_PROTOCOL.GetInfo() status codes)\r | |
830 | or error when parsing the response of the server.\r | |
831 | **/\r | |
832 | STATIC\r | |
833 | EFI_STATUS\r | |
834 | GetFileSize (\r | |
835 | IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r | |
836 | IN CONST CHAR8 *FilePath,\r | |
837 | OUT UINTN *FileSize\r | |
838 | )\r | |
839 | {\r | |
840 | EFI_STATUS Status;\r | |
841 | EFI_MTFTP4_OPTION ReqOpt[1];\r | |
842 | EFI_MTFTP4_PACKET *Packet;\r | |
843 | UINT32 PktLen;\r | |
844 | EFI_MTFTP4_OPTION *TableOfOptions;\r | |
845 | EFI_MTFTP4_OPTION *Option;\r | |
846 | UINT32 OptCnt;\r | |
847 | UINT8 OptBuf[128];\r | |
848 | \r | |
849 | ReqOpt[0].OptionStr = (UINT8*)"tsize";\r | |
850 | OptBuf[0] = '0';\r | |
851 | OptBuf[1] = 0;\r | |
852 | ReqOpt[0].ValueStr = OptBuf;\r | |
853 | \r | |
854 | Status = Mtftp4->GetInfo (\r | |
855 | Mtftp4,\r | |
856 | NULL,\r | |
857 | (UINT8*)FilePath,\r | |
858 | NULL,\r | |
859 | 1,\r | |
860 | ReqOpt,\r | |
861 | &PktLen,\r | |
862 | &Packet\r | |
863 | );\r | |
864 | \r | |
865 | if (EFI_ERROR (Status)) {\r | |
866 | goto Error;\r | |
867 | }\r | |
868 | \r | |
869 | Status = Mtftp4->ParseOptions (\r | |
870 | Mtftp4,\r | |
871 | PktLen,\r | |
872 | Packet,\r | |
873 | (UINT32 *) &OptCnt,\r | |
874 | &TableOfOptions\r | |
875 | );\r | |
876 | if (EFI_ERROR (Status)) {\r | |
877 | goto Error;\r | |
878 | }\r | |
879 | \r | |
880 | Option = TableOfOptions;\r | |
881 | while (OptCnt != 0) {\r | |
882 | if (AsciiStrnCmp ((CHAR8 *)Option->OptionStr, "tsize", 5) == 0) {\r | |
883 | *FileSize = AsciiStrDecimalToUintn ((CHAR8 *)Option->ValueStr);\r | |
884 | break;\r | |
885 | }\r | |
886 | OptCnt--;\r | |
887 | Option++;\r | |
888 | }\r | |
889 | FreePool (TableOfOptions);\r | |
890 | \r | |
891 | if (OptCnt == 0) {\r | |
892 | Status = EFI_UNSUPPORTED;\r | |
893 | }\r | |
894 | \r | |
895 | Error :\r | |
896 | \r | |
897 | return Status;\r | |
898 | }\r | |
899 | \r | |
900 | /**\r | |
901 | Worker function that download the data of a file from a TFTP server given\r | |
902 | the path of the file and its size.\r | |
903 | \r | |
904 | @param[in] Mtftp4 MTFTP4 protocol interface\r | |
905 | @param[in] FilePath Path of the file, Unicode encoded\r | |
906 | @param[in] AsciiFilePath Path of the file, ASCII encoded\r | |
907 | @param[in] FileSize Size of the file in number of bytes\r | |
2be45bfe | 908 | @param[in] BlockSize Value of the TFTP blksize option\r |
68074260 RC |
909 | @param[out] Data Address where to store the address of the buffer\r |
910 | where the data of the file were downloaded in\r | |
911 | case of success.\r | |
912 | \r | |
913 | @retval EFI_SUCCESS The file was downloaded.\r | |
914 | @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r | |
915 | @retval Others The downloading of the file from the server failed\r | |
916 | (see EFI_MTFTP4_PROTOCOL.ReadFile() status codes).\r | |
917 | \r | |
918 | **/\r | |
919 | STATIC\r | |
920 | EFI_STATUS\r | |
921 | DownloadFile (\r | |
922 | IN EFI_MTFTP4_PROTOCOL *Mtftp4,\r | |
923 | IN CONST CHAR16 *FilePath,\r | |
924 | IN CONST CHAR8 *AsciiFilePath,\r | |
925 | IN UINTN FileSize,\r | |
2be45bfe | 926 | IN UINT16 BlockSize,\r |
5c6fdb5e | 927 | IN UINT16 WindowSize,\r |
68074260 RC |
928 | OUT VOID **Data\r |
929 | )\r | |
930 | {\r | |
931 | EFI_STATUS Status;\r | |
932 | EFI_PHYSICAL_ADDRESS PagesAddress;\r | |
933 | VOID *Buffer;\r | |
934 | DOWNLOAD_CONTEXT *TftpContext;\r | |
935 | EFI_MTFTP4_TOKEN Mtftp4Token;\r | |
5c6fdb5e JW |
936 | UINT8 BlksizeBuf[10];\r |
937 | UINT8 WindowsizeBuf[10];\r | |
68074260 | 938 | \r |
61d3f100 JW |
939 | ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN));\r |
940 | \r | |
68074260 RC |
941 | // Downloaded file can be large. BS.AllocatePages() is more faster\r |
942 | // than AllocatePool() and avoid fragmentation.\r | |
943 | // The downloaded file could be an EFI application. Marking the\r | |
944 | // allocated page as EfiBootServicesCode would allow to execute a\r | |
945 | // potential downloaded EFI application.\r | |
946 | Status = gBS->AllocatePages (\r | |
947 | AllocateAnyPages,\r | |
948 | EfiBootServicesCode,\r | |
949 | EFI_SIZE_TO_PAGES (FileSize),\r | |
950 | &PagesAddress\r | |
951 | );\r | |
952 | if (EFI_ERROR (Status)) {\r | |
953 | return Status;\r | |
954 | }\r | |
955 | \r | |
956 | Buffer = (VOID*)(UINTN)PagesAddress;\r | |
957 | TftpContext = AllocatePool (sizeof (DOWNLOAD_CONTEXT));\r | |
958 | if (TftpContext == NULL) {\r | |
959 | Status = EFI_OUT_OF_RESOURCES;\r | |
960 | goto Error;\r | |
961 | }\r | |
962 | TftpContext->FileSize = FileSize;\r | |
963 | TftpContext->DownloadedNbOfBytes = 0;\r | |
964 | TftpContext->LastReportedNbOfBytes = 0;\r | |
965 | \r | |
68074260 RC |
966 | Mtftp4Token.Filename = (UINT8*)AsciiFilePath;\r |
967 | Mtftp4Token.BufferSize = FileSize;\r | |
968 | Mtftp4Token.Buffer = Buffer;\r | |
969 | Mtftp4Token.CheckPacket = CheckPacket;\r | |
970 | Mtftp4Token.Context = (VOID*)TftpContext;\r | |
5c6fdb5e JW |
971 | Mtftp4Token.OptionCount = 0;\r |
972 | Mtftp4Token.OptionList = AllocatePool (sizeof (EFI_MTFTP4_OPTION) * 2);\r | |
973 | if (Mtftp4Token.OptionList == NULL) {\r | |
974 | Status = EFI_OUT_OF_RESOURCES;\r | |
975 | goto Error;\r | |
976 | }\r | |
977 | \r | |
2be45bfe | 978 | if (BlockSize != MTFTP_DEFAULT_BLKSIZE) {\r |
5c6fdb5e JW |
979 | Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "blksize";\r |
980 | AsciiSPrint ((CHAR8 *) BlksizeBuf, sizeof (BlksizeBuf), "%d", BlockSize);\r | |
981 | Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = BlksizeBuf;\r | |
982 | Mtftp4Token.OptionCount ++;\r | |
983 | }\r | |
2be45bfe | 984 | \r |
5c6fdb5e JW |
985 | if (WindowSize != MTFTP_DEFAULT_WINDOWSIZE) {\r |
986 | Mtftp4Token.OptionList[Mtftp4Token.OptionCount].OptionStr = (UINT8 *) "windowsize";\r | |
987 | AsciiSPrint ((CHAR8 *) WindowsizeBuf, sizeof (WindowsizeBuf), "%d", WindowSize);\r | |
988 | Mtftp4Token.OptionList[Mtftp4Token.OptionCount].ValueStr = WindowsizeBuf;\r | |
989 | Mtftp4Token.OptionCount ++;\r | |
2be45bfe | 990 | }\r |
68074260 RC |
991 | \r |
992 | ShellPrintHiiEx (\r | |
993 | -1, -1, NULL, STRING_TOKEN (STR_TFTP_DOWNLOADING),\r | |
09610023 | 994 | mTftpHiiHandle, FilePath\r |
68074260 RC |
995 | );\r |
996 | \r | |
997 | Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token);\r | |
998 | ShellPrintHiiEx (\r | |
999 | -1, -1, NULL, STRING_TOKEN (STR_GEN_CRLF),\r | |
09610023 | 1000 | mTftpHiiHandle\r |
68074260 RC |
1001 | );\r |
1002 | \r | |
1003 | Error :\r | |
1004 | \r | |
5c6fdb5e | 1005 | if (TftpContext != NULL) {\r |
68074260 RC |
1006 | FreePool (TftpContext);\r |
1007 | }\r | |
1008 | \r | |
5c6fdb5e JW |
1009 | if (Mtftp4Token.OptionList != NULL) {\r |
1010 | FreePool (Mtftp4Token.OptionList);\r | |
1011 | }\r | |
1012 | \r | |
68074260 RC |
1013 | if (EFI_ERROR (Status)) {\r |
1014 | gBS->FreePages (PagesAddress, EFI_SIZE_TO_PAGES (FileSize));\r | |
1015 | return Status;\r | |
1016 | }\r | |
1017 | \r | |
1018 | *Data = Buffer;\r | |
1019 | \r | |
1020 | return EFI_SUCCESS;\r | |
1021 | }\r | |
1022 | \r | |
1023 | /**\r | |
1024 | Update the progress of a file download\r | |
1025 | This procedure is called each time a new TFTP packet is received.\r | |
1026 | \r | |
1027 | @param[in] This MTFTP4 protocol interface\r | |
1028 | @param[in] Token Parameters for the download of the file\r | |
1029 | @param[in] PacketLen Length of the packet\r | |
1030 | @param[in] Packet Address of the packet\r | |
1031 | \r | |
1032 | @retval EFI_SUCCESS All packets are accepted.\r | |
1033 | \r | |
1034 | **/\r | |
1035 | STATIC\r | |
1036 | EFI_STATUS\r | |
7367e66f | 1037 | EFIAPI\r |
68074260 RC |
1038 | CheckPacket (\r |
1039 | IN EFI_MTFTP4_PROTOCOL *This,\r | |
1040 | IN EFI_MTFTP4_TOKEN *Token,\r | |
1041 | IN UINT16 PacketLen,\r | |
1042 | IN EFI_MTFTP4_PACKET *Packet\r | |
1043 | )\r | |
1044 | {\r | |
1045 | DOWNLOAD_CONTEXT *Context;\r | |
1046 | CHAR16 Progress[TFTP_PROGRESS_MESSAGE_SIZE];\r | |
6add86ab | 1047 | UINTN NbOfKb;\r |
68074260 | 1048 | UINTN Index;\r |
310b053a JC |
1049 | UINTN LastStep;\r |
1050 | UINTN Step;\r | |
da6b8feb | 1051 | EFI_STATUS Status;\r |
68074260 RC |
1052 | \r |
1053 | if ((NTOHS (Packet->OpCode)) != EFI_MTFTP4_OPCODE_DATA) {\r | |
1054 | return EFI_SUCCESS;\r | |
1055 | }\r | |
1056 | \r | |
1057 | Context = (DOWNLOAD_CONTEXT*)Token->Context;\r | |
1058 | if (Context->DownloadedNbOfBytes == 0) {\r | |
1059 | ShellPrintEx (-1, -1, L"%s 0 Kb", mTftpProgressFrame);\r | |
1060 | }\r | |
1061 | \r | |
1062 | //\r | |
1063 | // The data in the packet are prepended with two UINT16 :\r | |
1064 | // . OpCode = EFI_MTFTP4_OPCODE_DATA\r | |
1065 | // . Block = the number of this block of data\r | |
1066 | //\r | |
1067 | Context->DownloadedNbOfBytes += PacketLen - sizeof (Packet->OpCode)\r | |
1068 | - sizeof (Packet->Data.Block);\r | |
1069 | NbOfKb = Context->DownloadedNbOfBytes / 1024;\r | |
1070 | \r | |
1071 | Progress[0] = L'\0';\r | |
6add86ab JC |
1072 | LastStep = (Context->LastReportedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r |
1073 | Step = (Context->DownloadedNbOfBytes * TFTP_PROGRESS_SLIDER_STEPS) / Context->FileSize;\r | |
1074 | \r | |
68074260 RC |
1075 | if (Step <= LastStep) {\r |
1076 | return EFI_SUCCESS;\r | |
1077 | }\r | |
1078 | \r | |
1079 | ShellPrintEx (-1, -1, L"%s", mTftpProgressDelete);\r | |
1080 | \r | |
da6b8feb QS |
1081 | Status = StrCpyS (Progress, TFTP_PROGRESS_MESSAGE_SIZE, mTftpProgressFrame);\r |
1082 | if (EFI_ERROR(Status)) {\r | |
1083 | return Status;\r | |
1084 | }\r | |
68074260 RC |
1085 | for (Index = 1; Index < Step; Index++) {\r |
1086 | Progress[Index] = L'=';\r | |
1087 | }\r | |
1088 | Progress[Step] = L'>';\r | |
1089 | \r | |
1090 | UnicodeSPrint (\r | |
1091 | Progress + (sizeof (mTftpProgressFrame) / sizeof (CHAR16)) - 1,\r | |
1092 | sizeof (Progress) - sizeof (mTftpProgressFrame),\r | |
1093 | L" %7d Kb",\r | |
1094 | NbOfKb\r | |
1095 | );\r | |
1096 | Context->LastReportedNbOfBytes = Context->DownloadedNbOfBytes;\r | |
1097 | \r | |
1098 | ShellPrintEx (-1, -1, L"%s", Progress);\r | |
1099 | \r | |
1100 | return EFI_SUCCESS;\r | |
1101 | }\r | |
09610023 RN |
1102 | \r |
1103 | /**\r | |
1104 | Retrive HII package list from ImageHandle and publish to HII database.\r | |
1105 | \r | |
1106 | @param ImageHandle The image handle of the process.\r | |
1107 | \r | |
1108 | @return HII handle.\r | |
1109 | **/\r | |
1110 | EFI_HANDLE\r | |
1111 | InitializeHiiPackage (\r | |
1112 | EFI_HANDLE ImageHandle\r | |
1113 | )\r | |
1114 | {\r | |
1115 | EFI_STATUS Status;\r | |
1116 | EFI_HII_PACKAGE_LIST_HEADER *PackageList;\r | |
1117 | EFI_HANDLE HiiHandle;\r | |
1118 | \r | |
1119 | //\r | |
1120 | // Retrieve HII package list from ImageHandle\r | |
1121 | //\r | |
1122 | Status = gBS->OpenProtocol (\r | |
1123 | ImageHandle,\r | |
1124 | &gEfiHiiPackageListProtocolGuid,\r | |
1125 | (VOID **)&PackageList,\r | |
1126 | ImageHandle,\r | |
1127 | NULL,\r | |
1128 | EFI_OPEN_PROTOCOL_GET_PROTOCOL\r | |
1129 | );\r | |
1130 | ASSERT_EFI_ERROR (Status);\r | |
1131 | if (EFI_ERROR (Status)) {\r | |
1132 | return NULL;\r | |
1133 | }\r | |
1134 | \r | |
1135 | //\r | |
1136 | // Publish HII package list to HII Database.\r | |
1137 | //\r | |
1138 | Status = gHiiDatabase->NewPackageList (\r | |
1139 | gHiiDatabase,\r | |
1140 | PackageList,\r | |
1141 | NULL,\r | |
1142 | &HiiHandle\r | |
1143 | );\r | |
1144 | ASSERT_EFI_ERROR (Status);\r | |
1145 | if (EFI_ERROR (Status)) {\r | |
1146 | return NULL;\r | |
1147 | }\r | |
1148 | return HiiHandle;\r | |
1149 | }\r |