]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: Use safe string functions to refine 'Tftp.c' code.
[mirror_edk2.git] / ShellPkg / Application / Shell / ShellParametersProtocol.c
CommitLineData
a405b86d 1/** @file\r
2 Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,\r
3 manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.\r
4\r
94c2a044 5 Copyright (C) 2014, Red Hat, Inc.\r
c011b6c9 6 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>\r
14030c5c 7 Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
a405b86d 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
17\r
0406a571 18#include "Shell.h"\r
a405b86d 19\r
14030c5c 20/**\r
3ab016b2 21 Return the next parameter's end from a command line string.\r
14030c5c
JC
22\r
23 @param[in] String the string to parse\r
24**/\r
25CONST CHAR16*\r
26EFIAPI\r
27FindEndOfParameter(\r
28 IN CONST CHAR16 *String\r
29 )\r
30{\r
14030c5c
JC
31 CONST CHAR16 *First;\r
32 CONST CHAR16 *CloseQuote;\r
33\r
7cc7022d 34 First = FindFirstCharacter(String, L" \"", L'^');\r
14030c5c
JC
35\r
36 //\r
37 // nothing, all one parameter remaining\r
38 //\r
39 if (*First == CHAR_NULL) {\r
40 return (First);\r
41 }\r
42\r
43 //\r
44 // If space before a quote (or neither found, i.e. both CHAR_NULL),\r
45 // then that's the end.\r
46 //\r
7cc7022d
JC
47 if (*First == L' ') {\r
48 return (First);\r
14030c5c
JC
49 }\r
50\r
7cc7022d 51 CloseQuote = FindFirstCharacter (First+1, L"\"", L'^');\r
14030c5c
JC
52\r
53 //\r
7cc7022d 54 // We did not find a terminator...\r
14030c5c
JC
55 //\r
56 if (*CloseQuote == CHAR_NULL) {\r
57 return (NULL);\r
58 }\r
59\r
60 return (FindEndOfParameter (CloseQuote+1));\r
61}\r
62\r
63/**\r
3ab016b2 64 Return the next parameter from a command line string.\r
a405b86d 65\r
66 This function moves the next parameter from Walker into TempParameter and moves\r
67 Walker up past that parameter for recursive calling. When the final parameter\r
68 is moved *Walker will be set to NULL;\r
69\r
70 Temp Parameter must be large enough to hold the parameter before calling this\r
71 function.\r
72\r
14030c5c
JC
73 This will also remove all remaining ^ characters after processing.\r
74\r
4ff7e37b 75 @param[in, out] Walker pointer to string of command line. Adjusted to\r
a405b86d 76 reminaing command line on return\r
4ff7e37b 77 @param[in, out] TempParameter pointer to string of command line item extracted.\r
33fe8308 78 @param[in] Length buffer size of TempParameter.\r
14030c5c
JC
79\r
80 @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string.\r
81 @return EFI_NOT_FOUND A closing " could not be found on the specified string\r
a405b86d 82**/\r
14030c5c 83EFI_STATUS\r
a405b86d 84EFIAPI\r
85GetNextParameter(\r
7f79b01e
JC
86 IN OUT CHAR16 **Walker,\r
87 IN OUT CHAR16 **TempParameter,\r
88 IN CONST UINTN Length\r
a405b86d 89 )\r
90{\r
7cc7022d 91 CONST CHAR16 *NextDelim;\r
a405b86d 92\r
14030c5c
JC
93 if (Walker == NULL\r
94 ||*Walker == NULL\r
95 ||TempParameter == NULL\r
96 ||*TempParameter == NULL\r
97 ){\r
98 return (EFI_INVALID_PARAMETER);\r
99 }\r
100\r
a405b86d 101\r
102 //\r
103 // make sure we dont have any leading spaces\r
104 //\r
105 while ((*Walker)[0] == L' ') {\r
106 (*Walker)++;\r
107 }\r
108\r
109 //\r
110 // make sure we still have some params now...\r
111 //\r
112 if (StrLen(*Walker) == 0) {\r
14030c5c
JC
113DEBUG_CODE_BEGIN();\r
114 *Walker = NULL;\r
115DEBUG_CODE_END();\r
116 return (EFI_INVALID_PARAMETER);\r
a405b86d 117 }\r
118\r
7cc7022d 119 NextDelim = FindEndOfParameter(*Walker);\r
14030c5c
JC
120\r
121 if (NextDelim == NULL){\r
122DEBUG_CODE_BEGIN();\r
123 *Walker = NULL;\r
124DEBUG_CODE_END();\r
125 return (EFI_NOT_FOUND);\r
126 }\r
127\r
b0f81b62 128 StrnCpyS(*TempParameter, Length / sizeof(CHAR16), (*Walker), NextDelim - *Walker);\r
14030c5c 129\r
a405b86d 130 //\r
14030c5c 131 // Add a CHAR_NULL if we didnt get one via the copy\r
a405b86d 132 //\r
14030c5c
JC
133 if (*NextDelim != CHAR_NULL) {\r
134 (*TempParameter)[NextDelim - *Walker] = CHAR_NULL;\r
135 }\r
136\r
14030c5c 137 //\r
7cc7022d 138 // Update Walker for the next iteration through the function\r
14030c5c 139 //\r
7cc7022d 140 *Walker = (CHAR16*)NextDelim;\r
14030c5c
JC
141\r
142 //\r
143 // Remove any non-escaped quotes in the string\r
7cc7022d 144 // Remove any remaining escape characters in the string\r
14030c5c 145 //\r
7cc7022d
JC
146 for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", CHAR_NULL) \r
147 ; *NextDelim != CHAR_NULL \r
148 ; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL)\r
149 ) {\r
14030c5c 150 if (*NextDelim == L'^') {\r
7cc7022d
JC
151\r
152 //\r
153 // eliminate the escape ^\r
154 //\r
155 CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));\r
14030c5c 156 NextDelim++;\r
7cc7022d
JC
157 } else if (*NextDelim == L'\"') {\r
158\r
159 //\r
160 // eliminate the unescaped quote\r
161 //\r
162 CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));\r
a405b86d 163 }\r
164 }\r
14030c5c
JC
165\r
166 return EFI_SUCCESS;\r
a405b86d 167}\r
168\r
169/**\r
733f138d 170 Function to populate Argc and Argv.\r
a405b86d 171\r
172 This function parses the CommandLine and divides it into standard C style Argc/Argv\r
173 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space\r
174 delimited and quote surrounded parameter definition.\r
175\r
14030c5c
JC
176 All special character processing (alias, environment variable, redirection, \r
177 etc... must be complete before calling this API.\r
178\r
4ff7e37b
ED
179 @param[in] CommandLine String of command line to parse\r
180 @param[in, out] Argv pointer to array of strings; one for each parameter\r
181 @param[in, out] Argc pointer to number of strings in Argv array\r
a405b86d 182\r
183 @return EFI_SUCCESS the operation was sucessful\r
184 @return EFI_OUT_OF_RESOURCES a memory allocation failed.\r
185**/\r
186EFI_STATUS\r
187EFIAPI\r
188ParseCommandLineToArgs(\r
189 IN CONST CHAR16 *CommandLine,\r
190 IN OUT CHAR16 ***Argv,\r
191 IN OUT UINTN *Argc\r
192 )\r
193{\r
194 UINTN Count;\r
195 CHAR16 *TempParameter;\r
196 CHAR16 *Walker;\r
197 CHAR16 *NewParam;\r
1fab9176 198 CHAR16 *NewCommandLine;\r
a405b86d 199 UINTN Size;\r
1fab9176 200 EFI_STATUS Status;\r
a405b86d 201\r
202 ASSERT(Argc != NULL);\r
203 ASSERT(Argv != NULL);\r
204\r
205 if (CommandLine == NULL || StrLen(CommandLine)==0) {\r
206 (*Argc) = 0;\r
207 (*Argv) = NULL;\r
208 return (EFI_SUCCESS);\r
209 }\r
210\r
1fab9176
QS
211 NewCommandLine = AllocateCopyPool(StrSize(CommandLine), CommandLine);\r
212 if (NewCommandLine == NULL){\r
213 return (EFI_OUT_OF_RESOURCES);\r
214 }\r
215\r
216 TrimSpaces(&NewCommandLine);\r
217 Size = StrSize(NewCommandLine);\r
a405b86d 218 TempParameter = AllocateZeroPool(Size);\r
219 if (TempParameter == NULL) {\r
1fab9176 220 SHELL_FREE_NON_NULL(NewCommandLine);\r
a405b86d 221 return (EFI_OUT_OF_RESOURCES);\r
222 }\r
223\r
224 for ( Count = 0\r
1fab9176 225 , Walker = (CHAR16*)NewCommandLine\r
a405b86d 226 ; Walker != NULL && *Walker != CHAR_NULL\r
14030c5c
JC
227 ; Count++\r
228 ) {\r
229 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) {\r
230 break;\r
231 }\r
232 }\r
a405b86d 233\r
a405b86d 234 //\r
235 // lets allocate the pointer array\r
236 //\r
237 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
238 if (*Argv == NULL) {\r
1fab9176
QS
239 Status = EFI_OUT_OF_RESOURCES;\r
240 goto Done;\r
a405b86d 241 }\r
242\r
243 *Argc = 0;\r
1fab9176 244 Walker = (CHAR16*)NewCommandLine;\r
a405b86d 245 while(Walker != NULL && *Walker != CHAR_NULL) {\r
246 SetMem16(TempParameter, Size, CHAR_NULL);\r
14030c5c 247 if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) {\r
1fab9176
QS
248 Status = EFI_INVALID_PARAMETER;\r
249 goto Done;\r
14030c5c
JC
250 }\r
251\r
7f79b01e
JC
252 NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter);\r
253 if (NewParam == NULL){\r
1fab9176
QS
254 Status = EFI_OUT_OF_RESOURCES;\r
255 goto Done;\r
7f79b01e 256 }\r
a405b86d 257 ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
258 (*Argc)++;\r
259 }\r
260 ASSERT(Count >= (*Argc));\r
1fab9176
QS
261 Status = EFI_SUCCESS;\r
262 \r
263Done:\r
3f869579 264 SHELL_FREE_NON_NULL(TempParameter);\r
1fab9176
QS
265 SHELL_FREE_NON_NULL(NewCommandLine);\r
266 return (Status);\r
a405b86d 267}\r
268\r
269/**\r
270 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
271 installs it on our handle and if there is an existing version of the protocol\r
272 that one is cached for removal later.\r
273\r
4ff7e37b 274 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
a405b86d 275 to the newly installed interface.\r
4ff7e37b 276 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
a405b86d 277 TRUE if this is the root shell instance.\r
278\r
279 @retval EFI_SUCCESS the operation completed successfully.\r
280 @return other the operation failed.\r
281 @sa ReinstallProtocolInterface\r
282 @sa InstallProtocolInterface\r
283 @sa ParseCommandLineToArgs\r
284**/\r
285EFI_STATUS\r
286EFIAPI\r
287CreatePopulateInstallShellParametersProtocol (\r
288 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,\r
289 IN OUT BOOLEAN *RootShellInstance\r
290 )\r
291{\r
292 EFI_STATUS Status;\r
293 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
294 CHAR16 *FullCommandLine;\r
295 UINTN Size;\r
296\r
297 Size = 0;\r
298 FullCommandLine = NULL;\r
299 LoadedImage = NULL;\r
300\r
301 //\r
302 // Assert for valid parameters\r
303 //\r
304 ASSERT(NewShellParameters != NULL);\r
305 ASSERT(RootShellInstance != NULL);\r
306\r
307 //\r
308 // See if we have a shell parameters placed on us\r
309 //\r
310 Status = gBS->OpenProtocol (\r
311 gImageHandle,\r
312 &gEfiShellParametersProtocolGuid,\r
313 (VOID **) &ShellInfoObject.OldShellParameters,\r
314 gImageHandle,\r
315 NULL,\r
316 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
317 );\r
318 //\r
319 // if we don't then we must be the root shell (error is expected)\r
320 //\r
321 if (EFI_ERROR (Status)) {\r
322 *RootShellInstance = TRUE;\r
323 }\r
324\r
325 //\r
326 // Allocate the new structure\r
327 //\r
328 *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
3c865f20 329 if ((*NewShellParameters) == NULL) {\r
330 return (EFI_OUT_OF_RESOURCES);\r
331 }\r
a405b86d 332\r
333 //\r
334 // get loaded image protocol\r
335 //\r
336 Status = gBS->OpenProtocol (\r
337 gImageHandle,\r
338 &gEfiLoadedImageProtocolGuid,\r
339 (VOID **) &LoadedImage,\r
340 gImageHandle,\r
341 NULL,\r
342 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
343 );\r
344 ASSERT_EFI_ERROR(Status);\r
345 //\r
346 // Build the full command line\r
347 //\r
e886b675 348 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 349 if (Status == EFI_BUFFER_TOO_SMALL) {\r
350 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
e886b675 351 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);\r
a405b86d 352 }\r
353 if (Status == EFI_NOT_FOUND) {\r
354 //\r
355 // no parameters via environment... ok\r
356 //\r
357 } else {\r
3c865f20 358 if (EFI_ERROR(Status)) {\r
359 return (Status);\r
360 }\r
a405b86d 361 }\r
362 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
3c865f20 363 ASSERT(FullCommandLine == NULL);\r
a405b86d 364 //\r
365 // Now we need to include a NULL terminator in the size.\r
366 //\r
367 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
368 FullCommandLine = AllocateZeroPool(Size);\r
369 }\r
a405b86d 370 if (FullCommandLine != NULL) {\r
2c5a8aed 371 CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);\r
a405b86d 372 //\r
373 // Populate Argc and Argv\r
374 //\r
375 Status = ParseCommandLineToArgs(FullCommandLine,\r
376 &(*NewShellParameters)->Argv,\r
377 &(*NewShellParameters)->Argc);\r
378\r
379 FreePool(FullCommandLine);\r
380\r
381 ASSERT_EFI_ERROR(Status);\r
382 } else {\r
383 (*NewShellParameters)->Argv = NULL;\r
384 (*NewShellParameters)->Argc = 0;\r
385 }\r
386\r
387 //\r
388 // Populate the 3 faked file systems...\r
389 //\r
390 if (*RootShellInstance) {\r
391 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;\r
392 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
393 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
394 Status = gBS->InstallProtocolInterface(&gImageHandle,\r
395 &gEfiShellParametersProtocolGuid,\r
396 EFI_NATIVE_INTERFACE,\r
397 (VOID*)(*NewShellParameters));\r
398 } else {\r
399 //\r
400 // copy from the existing ones\r
401 //\r
402 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;\r
403 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
404 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
405 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
406 &gEfiShellParametersProtocolGuid,\r
407 (VOID*)ShellInfoObject.OldShellParameters,\r
408 (VOID*)(*NewShellParameters));\r
409 }\r
410\r
411 return (Status);\r
412}\r
413\r
414/**\r
415 frees all memory used by createion and installation of shell parameters protocol\r
416 and if there was an old version installed it will restore that one.\r
417\r
418 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
419 being cleaned up.\r
420\r
421 @retval EFI_SUCCESS the cleanup was successful\r
422 @return other the cleanup failed\r
423 @sa ReinstallProtocolInterface\r
424 @sa UninstallProtocolInterface\r
425**/\r
426EFI_STATUS\r
427EFIAPI\r
428CleanUpShellParametersProtocol (\r
429 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters\r
430 )\r
431{\r
432 EFI_STATUS Status;\r
433 UINTN LoopCounter;\r
434\r
435 //\r
436 // If the old exists we need to restore it\r
437 //\r
438 if (ShellInfoObject.OldShellParameters != NULL) {\r
439 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
440 &gEfiShellParametersProtocolGuid,\r
441 (VOID*)NewShellParameters,\r
442 (VOID*)ShellInfoObject.OldShellParameters);\r
443 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
444 } else {\r
445 //\r
446 // No old one, just uninstall us...\r
447 //\r
448 Status = gBS->UninstallProtocolInterface(gImageHandle,\r
449 &gEfiShellParametersProtocolGuid,\r
450 (VOID*)NewShellParameters);\r
451 }\r
452 if (NewShellParameters->Argv != NULL) {\r
453 for ( LoopCounter = 0\r
454 ; LoopCounter < NewShellParameters->Argc\r
455 ; LoopCounter++\r
456 ){\r
457 FreePool(NewShellParameters->Argv[LoopCounter]);\r
458 }\r
459 FreePool(NewShellParameters->Argv);\r
460 }\r
461 FreePool(NewShellParameters);\r
462 return (Status);\r
463}\r
464\r
ae724571 465/**\r
466 Determin if a file name represents a unicode file.\r
467\r
468 @param[in] FileName Pointer to the filename to open.\r
469\r
470 @retval EFI_SUCCESS The file is a unicode file.\r
471 @return An error upon failure.\r
472**/\r
733f138d 473EFI_STATUS\r
474EFIAPI\r
475IsUnicodeFile(\r
476 IN CONST CHAR16 *FileName\r
477 )\r
478{\r
479 SHELL_FILE_HANDLE Handle;\r
480 EFI_STATUS Status;\r
481 UINT64 OriginalFilePosition;\r
482 UINTN CharSize;\r
483 CHAR16 CharBuffer;\r
484\r
485 Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);\r
486 if (EFI_ERROR(Status)) {\r
487 return (Status);\r
488 }\r
489 gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
490 gEfiShellProtocol->SetFilePosition(Handle, 0);\r
491 CharSize = sizeof(CHAR16);\r
492 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
493 if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {\r
494 Status = EFI_BUFFER_TOO_SMALL;\r
495 }\r
496 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
497 gEfiShellProtocol->CloseFile(Handle);\r
498 return (Status); \r
499}\r
500\r
fb84495a 501/**\r
502 Strips out quotes sections of a string.\r
503\r
504 All of the characters between quotes is replaced with spaces.\r
a1d4bfcc 505\r
4ff7e37b 506 @param[in, out] TheString A pointer to the string to update.\r
fb84495a 507**/\r
508VOID\r
509EFIAPI\r
510StripQuotes (\r
511 IN OUT CHAR16 *TheString\r
512 )\r
513{\r
514 BOOLEAN RemoveNow;\r
515\r
516 for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {\r
517 if (*TheString == L'^' && *(TheString + 1) == L'\"') {\r
518 TheString++;\r
519 } else if (*TheString == L'\"') {\r
520 RemoveNow = (BOOLEAN)!RemoveNow;\r
521 } else if (RemoveNow) {\r
522 *TheString = L' ';\r
523 }\r
524 }\r
525}\r
526\r
cf6a8f14 527/**\r
528 Calcualte the 32-bit CRC in a EFI table using the service provided by the\r
529 gRuntime service.\r
530\r
531 @param Hdr Pointer to an EFI standard header\r
532\r
533**/\r
534VOID\r
535CalculateEfiHdrCrc (\r
536 IN OUT EFI_TABLE_HEADER *Hdr\r
537 )\r
538{\r
539 UINT32 Crc;\r
540\r
541 Hdr->CRC32 = 0;\r
542\r
543 //\r
544 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then\r
545 // Crc will come back as zero if we set it to zero here\r
546 //\r
547 Crc = 0;\r
548 gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);\r
549 Hdr->CRC32 = Crc;\r
550}\r
551\r
031acf63 552/**\r
553 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.\r
554\r
555 @param[in] FileName The filename to start with.\r
556\r
557 @retval NULL FileName was invalid.\r
558 @return The modified FileName.\r
559**/\r
560CHAR16*\r
561EFIAPI\r
562FixFileName (\r
563 IN CHAR16 *FileName\r
564 )\r
565{\r
566 CHAR16 *Copy;\r
567 CHAR16 *TempLocation;\r
568\r
569 if (FileName == NULL) {\r
570 return (NULL);\r
571 }\r
572\r
573 if (FileName[0] == L'\"') {\r
574 Copy = FileName+1;\r
575 if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {\r
576 TempLocation[0] = CHAR_NULL;\r
577 } \r
578 } else {\r
579 Copy = FileName;\r
f9aefb6a 580 while(Copy[0] == L' ') {\r
581 Copy++;\r
582 }\r
031acf63 583 if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
584 TempLocation[0] = CHAR_NULL;\r
585 } \r
586 }\r
587\r
588 if (Copy[0] == CHAR_NULL) {\r
589 return (NULL);\r
590 }\r
591\r
592 return (Copy);\r
593}\r
594\r
6813ba40
JC
595/**\r
596 Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %.\r
597\r
598 @param[in] FileName The filename to start with.\r
599\r
600 @retval NULL FileName was invalid.\r
601 @return The modified FileName.\r
602**/\r
603CHAR16*\r
604EFIAPI\r
605FixVarName (\r
606 IN CHAR16 *FileName\r
607 )\r
608{\r
609 CHAR16 *Copy;\r
610 CHAR16 *TempLocation;\r
611\r
612 Copy = FileName;\r
613\r
614 if (FileName[0] == L'%') {\r
615 Copy = FileName+1;\r
616 if ((TempLocation = StrStr(Copy , L"%")) != NULL) {\r
617 TempLocation[0] = CHAR_NULL;\r
618 } \r
619 }\r
620\r
621 return (FixFileName(Copy));\r
622}\r
623\r
49bb76ff
JC
624/**\r
625 Remove the unicode file tag from the begining of the file buffer since that will not be\r
626 used by StdIn.\r
f614ce7e
SQ
627 \r
628 @param[in] Handle Pointer to the handle of the file to be processed.\r
629 \r
630 @retval EFI_SUCCESS The unicode file tag has been moved successfully.\r
49bb76ff
JC
631**/\r
632EFI_STATUS\r
633EFIAPI\r
634RemoveFileTag(\r
635 IN SHELL_FILE_HANDLE *Handle\r
636 )\r
637{\r
638 UINTN CharSize;\r
639 CHAR16 CharBuffer;\r
640\r
641 CharSize = sizeof(CHAR16);\r
642 CharBuffer = 0;\r
643 gEfiShellProtocol->ReadFile(*Handle, &CharSize, &CharBuffer);\r
644 if (CharBuffer != gUnicodeFileTag) {\r
645 gEfiShellProtocol->SetFilePosition(*Handle, 0);\r
646 }\r
647 return (EFI_SUCCESS);\r
648}\r
649\r
94c2a044
LE
650/**\r
651 Write the unicode file tag to the specified file.\r
652\r
653 It is the caller's responsibility to ensure that\r
654 ShellInfoObject.NewEfiShellProtocol has been initialized before calling this\r
655 function.\r
656\r
657 @param[in] FileHandle The file to write the unicode file tag to.\r
658\r
659 @return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile.\r
660**/\r
94c2a044
LE
661EFI_STATUS\r
662WriteFileTag (\r
663 IN SHELL_FILE_HANDLE FileHandle\r
664 )\r
665{\r
666 CHAR16 FileTag;\r
667 UINTN Size;\r
668 EFI_STATUS Status;\r
669\r
670 FileTag = gUnicodeFileTag;\r
671 Size = sizeof FileTag;\r
672 Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size,\r
673 &FileTag);\r
674 ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag);\r
675 return Status;\r
676}\r
677\r
678\r
a405b86d 679/**\r
680 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
681 structure by parsing NewCommandLine. The current values are returned to the\r
682 user.\r
683\r
8be0ba36 684 This will also update the system table.\r
a405b86d 685\r
4ff7e37b
ED
686 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
687 @param[in] NewCommandLine The new command line to parse and use.\r
688 @param[out] OldStdIn Pointer to old StdIn.\r
689 @param[out] OldStdOut Pointer to old StdOut.\r
690 @param[out] OldStdErr Pointer to old StdErr.\r
691 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 692\r
693 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
694 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
695**/\r
696EFI_STATUS\r
697EFIAPI\r
698UpdateStdInStdOutStdErr(\r
699 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 700 IN CHAR16 *NewCommandLine,\r
a405b86d 701 OUT SHELL_FILE_HANDLE *OldStdIn,\r
702 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 703 OUT SHELL_FILE_HANDLE *OldStdErr,\r
704 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 705 )\r
706{\r
707 CHAR16 *CommandLineCopy;\r
708 CHAR16 *CommandLineWalker;\r
709 CHAR16 *StdErrFileName;\r
710 CHAR16 *StdOutFileName;\r
711 CHAR16 *StdInFileName;\r
712 CHAR16 *StdInVarName;\r
713 CHAR16 *StdOutVarName;\r
714 CHAR16 *StdErrVarName;\r
715 EFI_STATUS Status;\r
716 SHELL_FILE_HANDLE TempHandle;\r
717 UINT64 FileSize;\r
718 BOOLEAN OutUnicode;\r
719 BOOLEAN InUnicode;\r
720 BOOLEAN ErrUnicode;\r
721 BOOLEAN OutAppend;\r
722 BOOLEAN ErrAppend;\r
723 UINTN Size;\r
a405b86d 724 SPLIT_LIST *Split;\r
fb84495a 725 CHAR16 *FirstLocation;\r
a405b86d 726\r
a405b86d 727 OutUnicode = TRUE;\r
728 InUnicode = TRUE;\r
729 ErrUnicode = TRUE;\r
730 StdInVarName = NULL;\r
731 StdOutVarName = NULL;\r
732 StdErrVarName = NULL;\r
733 StdErrFileName = NULL;\r
734 StdInFileName = NULL;\r
735 StdOutFileName = NULL;\r
736 ErrAppend = FALSE;\r
737 OutAppend = FALSE;\r
738 CommandLineCopy = NULL;\r
5f2915f5 739 FirstLocation = NULL;\r
a405b86d 740\r
8be0ba36 741 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
742 return (EFI_INVALID_PARAMETER);\r
a405b86d 743 }\r
744\r
8be0ba36 745 SystemTableInfo->ConIn = gST->ConIn;\r
746 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
747 SystemTableInfo->ConOut = gST->ConOut;\r
748 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
4ccd9214
ED
749 SystemTableInfo->ErrOut = gST->StdErr;\r
750 SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle;\r
8be0ba36 751 *OldStdIn = ShellParameters->StdIn;\r
752 *OldStdOut = ShellParameters->StdOut;\r
753 *OldStdErr = ShellParameters->StdErr;\r
754\r
a405b86d 755 if (NewCommandLine == NULL) {\r
756 return (EFI_SUCCESS);\r
757 }\r
758\r
759 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 760 if (CommandLineCopy == NULL) {\r
761 return (EFI_OUT_OF_RESOURCES);\r
762 }\r
a405b86d 763 Status = EFI_SUCCESS;\r
764 Split = NULL;\r
5f2915f5 765 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 766\r
fb84495a 767 StripQuotes(CommandLineCopy);\r
768\r
a405b86d 769 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
770 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
771 if (Split != NULL && Split->SplitStdIn != NULL) {\r
772 ShellParameters->StdIn = Split->SplitStdIn;\r
773 }\r
774 if (Split != NULL && Split->SplitStdOut != NULL) {\r
775 ShellParameters->StdOut = Split->SplitStdOut;\r
776 }\r
777 }\r
778\r
779 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 780 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 781 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 782 StdErrVarName = CommandLineWalker += 6;\r
783 ErrAppend = TRUE;\r
733f138d 784 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
785 Status = EFI_NOT_FOUND;\r
786 }\r
a405b86d 787 }\r
788 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 789 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 790 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 791 StdOutVarName = CommandLineWalker += 6;\r
792 OutAppend = TRUE;\r
733f138d 793 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
794 Status = EFI_NOT_FOUND;\r
795 }\r
a405b86d 796 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 797 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 798 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 799 StdOutVarName = CommandLineWalker += 5;\r
800 OutAppend = TRUE;\r
733f138d 801 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
802 Status = EFI_NOT_FOUND;\r
803 }\r
a405b86d 804 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 805 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 806 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 807 StdOutVarName = CommandLineWalker += 4;\r
808 OutAppend = FALSE;\r
733f138d 809 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
810 Status = EFI_NOT_FOUND;\r
811 }\r
a405b86d 812 }\r
813 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 814 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 815 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 816 StdOutFileName = CommandLineWalker += 6;\r
817 OutAppend = TRUE;\r
818 OutUnicode = FALSE;\r
733f138d 819 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
820 Status = EFI_NOT_FOUND;\r
821 }\r
a405b86d 822 }\r
823 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 824 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 825 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 826 if (StdOutFileName != NULL) {\r
827 Status = EFI_INVALID_PARAMETER;\r
828 } else {\r
829 StdOutFileName = CommandLineWalker += 5;\r
830 OutAppend = TRUE;\r
831 }\r
733f138d 832 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
833 Status = EFI_NOT_FOUND;\r
834 }\r
a405b86d 835 } \r
836 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 837 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 838 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 839 if (StdOutFileName != NULL) {\r
840 Status = EFI_INVALID_PARAMETER;\r
841 } else {\r
842 StdOutFileName = CommandLineWalker += 4;\r
843 OutAppend = TRUE;\r
844 }\r
733f138d 845 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
846 Status = EFI_NOT_FOUND;\r
847 }\r
a405b86d 848 }\r
849 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 850 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 851 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 852 if (StdOutFileName != NULL) {\r
853 Status = EFI_INVALID_PARAMETER;\r
854 } else {\r
855 StdOutFileName = CommandLineWalker += 5;\r
856 OutAppend = TRUE;\r
857 OutUnicode = FALSE;\r
858 }\r
733f138d 859 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
860 Status = EFI_NOT_FOUND;\r
861 }\r
a405b86d 862 } \r
863 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 864 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 865 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 866 if (StdOutFileName != NULL) {\r
867 Status = EFI_INVALID_PARAMETER;\r
868 } else {\r
869 StdOutFileName = CommandLineWalker += 5;\r
870 OutAppend = FALSE;\r
871 OutUnicode = FALSE;\r
872 }\r
733f138d 873 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
874 Status = EFI_NOT_FOUND;\r
875 }\r
a405b86d 876 } \r
877 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 878 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 879 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 880 if (StdOutFileName != NULL) {\r
881 Status = EFI_INVALID_PARAMETER;\r
882 } else {\r
883 StdOutFileName = CommandLineWalker += 4;\r
884 OutAppend = FALSE;\r
885 OutUnicode = FALSE;\r
886 }\r
733f138d 887 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
888 Status = EFI_NOT_FOUND;\r
889 }\r
a405b86d 890 }\r
891 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 892 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 893 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 894 if (StdErrFileName != NULL) {\r
895 Status = EFI_INVALID_PARAMETER;\r
896 } else {\r
897 StdErrFileName = CommandLineWalker += 5;\r
898 ErrAppend = TRUE;\r
899 }\r
733f138d 900 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
901 Status = EFI_NOT_FOUND;\r
902 }\r
a405b86d 903 }\r
904\r
905 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 906 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 907 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 908 if (StdErrVarName != NULL) {\r
909 Status = EFI_INVALID_PARAMETER;\r
910 } else {\r
911 StdErrVarName = CommandLineWalker += 5;\r
912 ErrAppend = FALSE;\r
913 }\r
733f138d 914 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
915 Status = EFI_NOT_FOUND;\r
916 }\r
a405b86d 917 }\r
918 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 919 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 920 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 921 if (StdOutVarName != NULL) {\r
922 Status = EFI_INVALID_PARAMETER;\r
923 } else {\r
924 StdOutVarName = CommandLineWalker += 5;\r
925 OutAppend = FALSE;\r
926 }\r
733f138d 927 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
928 Status = EFI_NOT_FOUND;\r
929 }\r
a405b86d 930 }\r
931 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 932 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 933 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 934 if (StdErrFileName != NULL) {\r
935 Status = EFI_INVALID_PARAMETER;\r
936 } else {\r
937 StdErrFileName = CommandLineWalker += 5;\r
938 ErrAppend = FALSE;\r
939 ErrUnicode = FALSE;\r
940 }\r
733f138d 941 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
942 Status = EFI_NOT_FOUND;\r
943 }\r
a405b86d 944 }\r
945 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 946 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 947 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 948 if (StdErrFileName != NULL) {\r
949 Status = EFI_INVALID_PARAMETER;\r
950 } else {\r
951 StdErrFileName = CommandLineWalker += 4;\r
952 ErrAppend = FALSE;\r
953 }\r
733f138d 954 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
955 Status = EFI_NOT_FOUND;\r
956 }\r
a405b86d 957 }\r
958\r
959 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 960 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 961 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 962 if (StdOutFileName != NULL) {\r
963 Status = EFI_INVALID_PARAMETER;\r
964 } else {\r
965 StdOutFileName = CommandLineWalker += 4;\r
966 OutAppend = FALSE;\r
967 }\r
733f138d 968 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
969 Status = EFI_NOT_FOUND;\r
970 }\r
a405b86d 971 }\r
972\r
973 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 974 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 975 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 976 if (StdOutFileName != NULL) {\r
977 Status = EFI_INVALID_PARAMETER;\r
978 } else {\r
979 StdOutFileName = CommandLineWalker += 3;\r
980 OutAppend = FALSE;\r
981 }\r
733f138d 982 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
983 Status = EFI_NOT_FOUND;\r
984 }\r
a405b86d 985 }\r
986\r
987 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 988 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 989 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 990 if (StdInFileName != NULL) {\r
991 Status = EFI_INVALID_PARAMETER;\r
992 } else {\r
993 StdInFileName = CommandLineWalker += 3;\r
733f138d 994 }\r
995 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
996 Status = EFI_NOT_FOUND;\r
a405b86d 997 }\r
998 }\r
999 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 1000 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 1001 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 1002 if (StdInFileName != NULL) {\r
1003 Status = EFI_INVALID_PARAMETER;\r
1004 } else {\r
733f138d 1005 StdInFileName = CommandLineWalker += 4;\r
1006 InUnicode = FALSE;\r
1007 }\r
1008 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
1009 Status = EFI_NOT_FOUND;\r
a405b86d 1010 }\r
1011 }\r
1012 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 1013 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 1014 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 1015 if (StdInVarName != NULL) {\r
1016 Status = EFI_INVALID_PARAMETER;\r
1017 } else {\r
1018 StdInVarName = CommandLineWalker += 4;\r
733f138d 1019 }\r
1020 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
1021 Status = EFI_NOT_FOUND;\r
a405b86d 1022 }\r
1023 }\r
1024\r
031acf63 1025 //\r
1026 // re-populate the string to support any filenames that were in quotes.\r
1027 //\r
e75390f0 1028 StrnCpyS(CommandLineCopy, StrSize(CommandLineCopy)/sizeof(CHAR16), NewCommandLine, StrLen(NewCommandLine));\r
031acf63 1029\r
5f2915f5 1030 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 1031 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
1032 ){\r
1033 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
1034 }\r
1035\r
a405b86d 1036 if (!EFI_ERROR(Status)) {\r
031acf63 1037\r
1038 if (StdErrFileName != NULL) {\r
1039 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
1040 Status = EFI_INVALID_PARAMETER;\r
1041 }\r
a405b86d 1042 }\r
031acf63 1043 if (StdOutFileName != NULL) {\r
1044 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
1045 Status = EFI_INVALID_PARAMETER;\r
1046 }\r
a405b86d 1047 }\r
031acf63 1048 if (StdInFileName != NULL) {\r
1049 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
1050 Status = EFI_INVALID_PARAMETER;\r
1051 }\r
a405b86d 1052 }\r
031acf63 1053 if (StdErrVarName != NULL) {\r
6813ba40 1054 if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {\r
031acf63 1055 Status = EFI_INVALID_PARAMETER;\r
1056 }\r
a405b86d 1057 }\r
031acf63 1058 if (StdOutVarName != NULL) {\r
6813ba40 1059 if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {\r
031acf63 1060 Status = EFI_INVALID_PARAMETER;\r
1061 }\r
a405b86d 1062 }\r
031acf63 1063 if (StdInVarName != NULL) {\r
6813ba40 1064 if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {\r
031acf63 1065 Status = EFI_INVALID_PARAMETER;\r
1066 }\r
a405b86d 1067 }\r
1068\r
0c956e0d 1069 //\r
1070 // Verify not the same and not duplicating something from a split\r
1071 //\r
733f138d 1072 if (\r
1073 //\r
1074 // Check that no 2 filenames are the same\r
1075 //\r
fb84495a 1076 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 1077 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
1078 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 1079 //\r
1080 // Check that no 2 variable names are the same\r
1081 //\r
a405b86d 1082 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
1083 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
1084 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 1085 //\r
1086 // When a split (using | operator) is in place some are not allowed\r
1087 //\r
a405b86d 1088 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
1089 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 1090 //\r
1091 // Check that nothing is trying to be output to 2 locations.\r
1092 //\r
a405b86d 1093 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
1094 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
1095 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 1096 //\r
733f138d 1097 // Check for no volatile environment variables\r
1098 //\r
a405b86d 1099 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
1100 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 1101 //\r
1102 // Cant redirect during a reconnect operation.\r
1103 //\r
3c865f20 1104 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
1105 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 1106 //\r
1107 // Check that filetypes (Unicode/Ascii) do not change during an append\r
1108 //\r
1109 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1110 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
1111 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
1112 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 1113 ){\r
1114 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 1115 ShellParameters->StdIn = *OldStdIn;\r
1116 ShellParameters->StdOut = *OldStdOut;\r
1117 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 1118 } else if (!EFI_ERROR(Status)){\r
a405b86d 1119 //\r
1120 // Open the Std<Whatever> and we should not have conflicts here...\r
1121 //\r
1122\r
1123 //\r
1124 // StdErr to a file\r
1125 //\r
1126 if (StdErrFileName != NULL) {\r
1127 if (!ErrAppend) {\r
1128 //\r
1129 // delete existing file.\r
1130 //\r
1131 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
1132 }\r
1133 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 1134 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
94c2a044 1135 Status = WriteFileTag (TempHandle);\r
a405b86d 1136 }\r
1137 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1138 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1139 ASSERT(TempHandle != NULL);\r
1140 }\r
1141 if (!EFI_ERROR(Status)) {\r
1142 ShellParameters->StdErr = TempHandle;\r
dcf9b428 1143 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 1144 }\r
1145 }\r
1146\r
1147 //\r
1148 // StdOut to a file\r
1149 //\r
1150 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1151 if (!OutAppend) {\r
1152 //\r
1153 // delete existing file.\r
1154 //\r
1155 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1156 }\r
1157 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 1158 if (TempHandle == NULL) {\r
1159 Status = EFI_INVALID_PARAMETER;\r
1160 } else {\r
733f138d 1161 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1162 //no-op\r
1163 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
94c2a044 1164 Status = WriteFileTag (TempHandle);\r
3c865f20 1165 } else if (OutAppend) {\r
3c865f20 1166 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1167 if (!EFI_ERROR(Status)) {\r
5967886d
LE
1168 //\r
1169 // When appending to a new unicode file, write the file tag.\r
1170 // Otherwise (ie. when appending to a new ASCII file, or an\r
1171 // existent file with any encoding), just seek to the end.\r
1172 //\r
1173 Status = (FileSize == 0 && OutUnicode) ?\r
1174 WriteFileTag (TempHandle) :\r
1175 ShellInfoObject.NewEfiShellProtocol->SetFilePosition (\r
1176 TempHandle,\r
1177 FileSize);\r
3c865f20 1178 }\r
1179 }\r
1180 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1181 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1182 ASSERT(TempHandle != NULL);\r
1183 }\r
a405b86d 1184 if (!EFI_ERROR(Status)) {\r
3c865f20 1185 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1186 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 1187 }\r
1188 }\r
a405b86d 1189 }\r
1190\r
1191 //\r
1192 // StdOut to a var\r
1193 //\r
1194 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1195 if (!OutAppend) {\r
1196 //\r
1197 // delete existing variable.\r
1198 //\r
1199 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1200 }\r
1201 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1202 ASSERT(TempHandle != NULL);\r
a405b86d 1203 ShellParameters->StdOut = TempHandle;\r
dcf9b428 1204 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);\r
a405b86d 1205 }\r
1206\r
1207 //\r
1208 // StdErr to a var\r
1209 //\r
1210 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1211 if (!ErrAppend) {\r
1212 //\r
1213 // delete existing variable.\r
1214 //\r
1215 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1216 }\r
1217 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1218 ASSERT(TempHandle != NULL);\r
a405b86d 1219 ShellParameters->StdErr = TempHandle;\r
dcf9b428 1220 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);\r
a405b86d 1221 }\r
1222\r
1223 //\r
1224 // StdIn from a var\r
1225 //\r
1226 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1227 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
532691c8 1228 if (TempHandle == NULL) {\r
1229 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1230 } else {\r
532691c8 1231 if (!InUnicode) {\r
1232 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1233 }\r
1234 Size = 0;\r
96962f0a 1235 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1236 Status = EFI_INVALID_PARAMETER;\r
1237 } else {\r
1238 ShellParameters->StdIn = TempHandle;\r
1239 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1240 }\r
a405b86d 1241 }\r
1242 }\r
1243\r
1244 //\r
1245 // StdIn from a file\r
1246 //\r
1247 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1248 Status = ShellOpenFileByName(\r
1249 StdInFileName,\r
1250 &TempHandle,\r
1251 EFI_FILE_MODE_READ,\r
1252 0);\r
49bb76ff
JC
1253 if (InUnicode) {\r
1254 //\r
1255 // Chop off the 0xFEFF if it's there...\r
1256 //\r
1257 RemoveFileTag(&TempHandle);\r
1258 } else if (!EFI_ERROR(Status)) {\r
1259 //\r
1260 // Create the ASCII->Unicode conversion layer\r
1261 //\r
a405b86d 1262 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1263 }\r
1264 if (!EFI_ERROR(Status)) {\r
1265 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1266 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1267 }\r
1268 }\r
1269 }\r
1270 }\r
1271 FreePool(CommandLineCopy);\r
8be0ba36 1272\r
cf6a8f14 1273 CalculateEfiHdrCrc(&gST->Hdr);\r
1274\r
8be0ba36 1275 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
cc31ac1e 1276 Status = EFI_OUT_OF_RESOURCES;\r
8be0ba36 1277 }\r
cc31ac1e
JC
1278\r
1279 if (Status == EFI_NOT_FOUND) {\r
1280 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
1281 } else if (EFI_ERROR(Status)) {\r
1282 ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
1283 }\r
1284\r
a405b86d 1285 return (Status);\r
1286}\r
1287\r
1288/**\r
1289 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1290 structure with StdIn and StdOut. The current values are de-allocated.\r
1291\r
4ff7e37b
ED
1292 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1293 @param[in] OldStdIn Pointer to old StdIn.\r
1294 @param[in] OldStdOut Pointer to old StdOut.\r
1295 @param[in] OldStdErr Pointer to old StdErr.\r
1296 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1297**/\r
1298EFI_STATUS\r
1299EFIAPI\r
1300RestoreStdInStdOutStdErr (\r
1301 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1302 IN SHELL_FILE_HANDLE *OldStdIn,\r
1303 IN SHELL_FILE_HANDLE *OldStdOut,\r
1304 IN SHELL_FILE_HANDLE *OldStdErr,\r
1305 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1306 )\r
1307{\r
1308 SPLIT_LIST *Split;\r
8be0ba36 1309\r
1310 if (ShellParameters == NULL \r
1311 ||OldStdIn == NULL\r
1312 ||OldStdOut == NULL\r
1313 ||OldStdErr == NULL\r
1314 ||SystemTableInfo == NULL) {\r
1315 return (EFI_INVALID_PARAMETER);\r
1316 }\r
a405b86d 1317 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1318 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1319 } else {\r
1320 Split = NULL;\r
1321 }\r
8be0ba36 1322 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1323 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1324 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1325 }\r
8be0ba36 1326 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1327 }\r
8be0ba36 1328 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1329 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1330 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1331 }\r
8be0ba36 1332 ShellParameters->StdOut = *OldStdOut;\r
1333 }\r
1334 if (ShellParameters->StdErr != *OldStdErr) {\r
1335 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1336 ShellParameters->StdErr = *OldStdErr;\r
1337 }\r
1338\r
1339 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1340 CloseSimpleTextInOnFile(gST->ConIn);\r
1341 gST->ConIn = SystemTableInfo->ConIn;\r
1342 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1343 }\r
8be0ba36 1344 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1345 CloseSimpleTextOutOnFile(gST->ConOut);\r
1346 gST->ConOut = SystemTableInfo->ConOut;\r
1347 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1348 }\r
4ccd9214 1349 if (gST->StdErr != SystemTableInfo->ErrOut) {\r
8be0ba36 1350 CloseSimpleTextOutOnFile(gST->StdErr);\r
4ccd9214
ED
1351 gST->StdErr = SystemTableInfo->ErrOut;\r
1352 gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;\r
8be0ba36 1353 }\r
1354\r
cf6a8f14 1355 CalculateEfiHdrCrc(&gST->Hdr);\r
1356\r
a405b86d 1357 return (EFI_SUCCESS);\r
1358}\r
1359/**\r
1360 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1361 structure by parsing NewCommandLine. The current values are returned to the\r
1362 user.\r
1363\r
1364 If OldArgv or OldArgc is NULL then that value is not returned.\r
1365\r
4ff7e37b
ED
1366 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1367 @param[in] NewCommandLine The new command line to parse and use.\r
1368 @param[out] OldArgv Pointer to old list of parameters.\r
1369 @param[out] OldArgc Pointer to old number of items in Argv list.\r
a405b86d 1370\r
1371 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1372 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1373**/\r
1374EFI_STATUS\r
1375EFIAPI\r
1376UpdateArgcArgv(\r
1377 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1378 IN CONST CHAR16 *NewCommandLine,\r
1379 OUT CHAR16 ***OldArgv OPTIONAL,\r
1380 OUT UINTN *OldArgc OPTIONAL\r
1381 )\r
1382{\r
1383 ASSERT(ShellParameters != NULL);\r
1384\r
1385 if (OldArgc != NULL) {\r
1386 *OldArgc = ShellParameters->Argc;\r
1387 }\r
1388 if (OldArgc != NULL) {\r
1389 *OldArgv = ShellParameters->Argv;\r
1390 }\r
1391\r
1392 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1393}\r
1394\r
1395/**\r
1396 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1397 structure with Argv and Argc. The current values are de-allocated and the\r
1398 OldArgv must not be deallocated by the caller.\r
1399\r
4ff7e37b
ED
1400 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1401 @param[in] OldArgv pointer to old list of parameters\r
1402 @param[in] OldArgc pointer to old number of items in Argv list\r
a405b86d 1403**/\r
1404VOID\r
1405EFIAPI\r
1406RestoreArgcArgv(\r
1407 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1408 IN CHAR16 ***OldArgv,\r
1409 IN UINTN *OldArgc\r
1410 )\r
1411{\r
1412 UINTN LoopCounter;\r
1413 ASSERT(ShellParameters != NULL);\r
1414 ASSERT(OldArgv != NULL);\r
1415 ASSERT(OldArgc != NULL);\r
1416\r
1417 if (ShellParameters->Argv != NULL) {\r
1418 for ( LoopCounter = 0\r
1419 ; LoopCounter < ShellParameters->Argc\r
1420 ; LoopCounter++\r
1421 ){\r
1422 FreePool(ShellParameters->Argv[LoopCounter]);\r
1423 }\r
1424 FreePool(ShellParameters->Argv);\r
1425 }\r
1426 ShellParameters->Argv = *OldArgv;\r
1427 *OldArgv = NULL;\r
1428 ShellParameters->Argc = *OldArgc;\r
1429 *OldArgc = 0;\r
1430}\r