]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellParametersProtocol - remove parsing from within quoted parameters.
[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
733f138d 5 Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>\r
a405b86d 6 This program and the accompanying materials\r
7 are licensed and made available under the terms and conditions of the BSD License\r
8 which accompanies this distribution. The full text of the license may be found at\r
9 http://opensource.org/licenses/bsd-license.php\r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
13\r
14**/\r
15\r
16#include "ShellParametersProtocol.h"\r
8be0ba36 17#include "ConsoleWrappers.h"\r
a405b86d 18\r
19/**\r
20 return the next parameter from a command line string;\r
21\r
22 This function moves the next parameter from Walker into TempParameter and moves\r
23 Walker up past that parameter for recursive calling. When the final parameter\r
24 is moved *Walker will be set to NULL;\r
25\r
26 Temp Parameter must be large enough to hold the parameter before calling this\r
27 function.\r
28\r
29 @param[in,out] Walker pointer to string of command line. Adjusted to\r
30 reminaing command line on return\r
31 @param[in,out] TempParameter pointer to string of command line item extracted.\r
32\r
33**/\r
34VOID\r
35EFIAPI\r
36GetNextParameter(\r
37 CHAR16 **Walker,\r
38 CHAR16 **TempParameter\r
39 )\r
40{\r
41 CHAR16 *NextDelim;\r
42 CHAR16 *TempLoc;\r
43\r
44 ASSERT(Walker != NULL);\r
45 ASSERT(*Walker != NULL);\r
46 ASSERT(TempParameter != NULL);\r
47 ASSERT(*TempParameter != NULL);\r
48\r
49 //\r
50 // make sure we dont have any leading spaces\r
51 //\r
52 while ((*Walker)[0] == L' ') {\r
53 (*Walker)++;\r
54 }\r
55\r
56 //\r
57 // make sure we still have some params now...\r
58 //\r
59 if (StrLen(*Walker) == 0) {\r
60 ASSERT((*Walker)[0] == CHAR_NULL);\r
61 *Walker = NULL;\r
62 return;\r
63 }\r
64\r
65 //\r
66 // we have a quoted parameter\r
67 // could be the last parameter, but SHOULD have a trailing quote\r
68 //\r
69 if ((*Walker)[0] == L'\"') {\r
70 NextDelim = NULL;\r
71 for (TempLoc = *Walker + 1 ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
d8f8021c 72 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
a405b86d 73 TempLoc++;\r
a405b86d 74 } else if (*TempLoc == L'\"') {\r
75 NextDelim = TempLoc;\r
76 break;\r
77 }\r
78 }\r
79\r
80 if (NextDelim - ((*Walker)+1) == 0) {\r
81 //\r
82 // found ""\r
83 //\r
84 StrCpy(*TempParameter, L"");\r
85 *Walker = NextDelim + 1;\r
86 } else if (NextDelim != NULL) {\r
87 StrnCpy(*TempParameter, (*Walker)+1, NextDelim - ((*Walker)+1));\r
88 *Walker = NextDelim + 1;\r
89 } else {\r
90 //\r
91 // last one... someone forgot the training quote!\r
92 //\r
93 StrCpy(*TempParameter, *Walker);\r
94 *Walker = NULL;\r
95 }\r
96 for (TempLoc = *TempParameter ; TempLoc != NULL && *TempLoc != CHAR_NULL ; TempLoc++) {\r
d8f8021c 97 if (*TempLoc == L'^' && *(TempLoc+1) == L'\"') {\r
a405b86d 98 CopyMem(TempLoc, TempLoc+1, StrSize(TempLoc) - sizeof(TempLoc[0]));\r
99 }\r
100 }\r
101 } else {\r
102 //\r
103 // we have a regular parameter (no quote) OR\r
104 // we have the final parameter (no trailing space)\r
105 //\r
106 NextDelim = StrStr((*Walker), L" ");\r
107 if (NextDelim != NULL) {\r
108 StrnCpy(*TempParameter, *Walker, NextDelim - (*Walker));\r
109 (*TempParameter)[NextDelim - (*Walker)] = CHAR_NULL;\r
110 *Walker = NextDelim+1;\r
111 } else {\r
112 //\r
113 // last one.\r
114 //\r
115 StrCpy(*TempParameter, *Walker);\r
116 *Walker = NULL;\r
117 }\r
118 for (NextDelim = *TempParameter ; NextDelim != NULL && *NextDelim != CHAR_NULL ; NextDelim++) {\r
119 if (*NextDelim == L'^' && *(NextDelim+1) == L'^') {\r
120 CopyMem(NextDelim, NextDelim+1, StrSize(NextDelim) - sizeof(NextDelim[0]));\r
d8f8021c 121 }\r
a405b86d 122 }\r
123 while ((*TempParameter)[StrLen(*TempParameter)-1] == L' ') {\r
124 (*TempParameter)[StrLen(*TempParameter)-1] = CHAR_NULL;\r
125 }\r
126 while ((*TempParameter)[0] == L' ') {\r
127 CopyMem(*TempParameter, (*TempParameter)+1, StrSize(*TempParameter) - sizeof((*TempParameter)[0]));\r
128 }\r
129 }\r
130 return;\r
131}\r
132\r
133/**\r
733f138d 134 Function to populate Argc and Argv.\r
a405b86d 135\r
136 This function parses the CommandLine and divides it into standard C style Argc/Argv\r
137 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space\r
138 delimited and quote surrounded parameter definition.\r
139\r
140 @param[in] CommandLine String of command line to parse\r
141 @param[in,out] Argv pointer to array of strings; one for each parameter\r
142 @param[in,out] Argc pointer to number of strings in Argv array\r
143\r
144 @return EFI_SUCCESS the operation was sucessful\r
145 @return EFI_OUT_OF_RESOURCES a memory allocation failed.\r
146**/\r
147EFI_STATUS\r
148EFIAPI\r
149ParseCommandLineToArgs(\r
150 IN CONST CHAR16 *CommandLine,\r
151 IN OUT CHAR16 ***Argv,\r
152 IN OUT UINTN *Argc\r
153 )\r
154{\r
155 UINTN Count;\r
156 CHAR16 *TempParameter;\r
157 CHAR16 *Walker;\r
158 CHAR16 *NewParam;\r
159 UINTN Size;\r
160\r
161 ASSERT(Argc != NULL);\r
162 ASSERT(Argv != NULL);\r
163\r
164 if (CommandLine == NULL || StrLen(CommandLine)==0) {\r
165 (*Argc) = 0;\r
166 (*Argv) = NULL;\r
167 return (EFI_SUCCESS);\r
168 }\r
169\r
170 Size = StrSize(CommandLine);\r
171 TempParameter = AllocateZeroPool(Size);\r
172 if (TempParameter == NULL) {\r
173 return (EFI_OUT_OF_RESOURCES);\r
174 }\r
175\r
176 for ( Count = 0\r
177 , Walker = (CHAR16*)CommandLine\r
178 ; Walker != NULL && *Walker != CHAR_NULL\r
179 ; GetNextParameter(&Walker, &TempParameter)\r
180 , Count++\r
181 );\r
182\r
183/* Count = 0;\r
184 Walker = (CHAR16*)CommandLine;\r
185 while(Walker != NULL) {\r
186 GetNextParameter(&Walker, &TempParameter);\r
187 Count++;\r
188 }\r
189*/\r
190 //\r
191 // lets allocate the pointer array\r
192 //\r
193 (*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*));\r
194 if (*Argv == NULL) {\r
195 return (EFI_OUT_OF_RESOURCES);\r
196 }\r
197\r
198 *Argc = 0;\r
199 Walker = (CHAR16*)CommandLine;\r
200 while(Walker != NULL && *Walker != CHAR_NULL) {\r
201 SetMem16(TempParameter, Size, CHAR_NULL);\r
202 GetNextParameter(&Walker, &TempParameter);\r
203 NewParam = AllocateZeroPool(StrSize(TempParameter));\r
204 ASSERT(NewParam != NULL);\r
205 StrCpy(NewParam, TempParameter);\r
206 ((CHAR16**)(*Argv))[(*Argc)] = NewParam;\r
207 (*Argc)++;\r
208 }\r
209 ASSERT(Count >= (*Argc));\r
210 return (EFI_SUCCESS);\r
211}\r
212\r
213/**\r
214 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then\r
215 installs it on our handle and if there is an existing version of the protocol\r
216 that one is cached for removal later.\r
217\r
218 @param[in,out] NewShellParameters on a successful return, a pointer to pointer\r
219 to the newly installed interface.\r
220 @param[in,out] RootShellInstance on a successful return, pointer to boolean.\r
221 TRUE if this is the root shell instance.\r
222\r
223 @retval EFI_SUCCESS the operation completed successfully.\r
224 @return other the operation failed.\r
225 @sa ReinstallProtocolInterface\r
226 @sa InstallProtocolInterface\r
227 @sa ParseCommandLineToArgs\r
228**/\r
229EFI_STATUS\r
230EFIAPI\r
231CreatePopulateInstallShellParametersProtocol (\r
232 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,\r
233 IN OUT BOOLEAN *RootShellInstance\r
234 )\r
235{\r
236 EFI_STATUS Status;\r
237 EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;\r
238 CHAR16 *FullCommandLine;\r
239 UINTN Size;\r
240\r
241 Size = 0;\r
242 FullCommandLine = NULL;\r
243 LoadedImage = NULL;\r
244\r
245 //\r
246 // Assert for valid parameters\r
247 //\r
248 ASSERT(NewShellParameters != NULL);\r
249 ASSERT(RootShellInstance != NULL);\r
250\r
251 //\r
252 // See if we have a shell parameters placed on us\r
253 //\r
254 Status = gBS->OpenProtocol (\r
255 gImageHandle,\r
256 &gEfiShellParametersProtocolGuid,\r
257 (VOID **) &ShellInfoObject.OldShellParameters,\r
258 gImageHandle,\r
259 NULL,\r
260 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
261 );\r
262 //\r
263 // if we don't then we must be the root shell (error is expected)\r
264 //\r
265 if (EFI_ERROR (Status)) {\r
266 *RootShellInstance = TRUE;\r
267 }\r
268\r
269 //\r
270 // Allocate the new structure\r
271 //\r
272 *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));\r
3c865f20 273 if ((*NewShellParameters) == NULL) {\r
274 return (EFI_OUT_OF_RESOURCES);\r
275 }\r
a405b86d 276\r
277 //\r
278 // get loaded image protocol\r
279 //\r
280 Status = gBS->OpenProtocol (\r
281 gImageHandle,\r
282 &gEfiLoadedImageProtocolGuid,\r
283 (VOID **) &LoadedImage,\r
284 gImageHandle,\r
285 NULL,\r
286 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
287 );\r
288 ASSERT_EFI_ERROR(Status);\r
289 //\r
290 // Build the full command line\r
291 //\r
292 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
293 if (Status == EFI_BUFFER_TOO_SMALL) {\r
294 FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);\r
295 Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, &FullCommandLine);\r
296 }\r
297 if (Status == EFI_NOT_FOUND) {\r
298 //\r
299 // no parameters via environment... ok\r
300 //\r
301 } else {\r
3c865f20 302 if (EFI_ERROR(Status)) {\r
303 return (Status);\r
304 }\r
a405b86d 305 }\r
306 if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {\r
3c865f20 307 ASSERT(FullCommandLine == NULL);\r
a405b86d 308 //\r
309 // Now we need to include a NULL terminator in the size.\r
310 //\r
311 Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);\r
312 FullCommandLine = AllocateZeroPool(Size);\r
313 }\r
a405b86d 314 if (FullCommandLine != NULL) {\r
3c865f20 315 if (LoadedImage->LoadOptionsSize != 0){\r
316 StrCpy(FullCommandLine, LoadedImage->LoadOptions);\r
317 }\r
a405b86d 318 //\r
319 // Populate Argc and Argv\r
320 //\r
321 Status = ParseCommandLineToArgs(FullCommandLine,\r
322 &(*NewShellParameters)->Argv,\r
323 &(*NewShellParameters)->Argc);\r
324\r
325 FreePool(FullCommandLine);\r
326\r
327 ASSERT_EFI_ERROR(Status);\r
328 } else {\r
329 (*NewShellParameters)->Argv = NULL;\r
330 (*NewShellParameters)->Argc = 0;\r
331 }\r
332\r
333 //\r
334 // Populate the 3 faked file systems...\r
335 //\r
336 if (*RootShellInstance) {\r
337 (*NewShellParameters)->StdIn = &FileInterfaceStdIn;\r
338 (*NewShellParameters)->StdOut = &FileInterfaceStdOut;\r
339 (*NewShellParameters)->StdErr = &FileInterfaceStdErr;\r
340 Status = gBS->InstallProtocolInterface(&gImageHandle,\r
341 &gEfiShellParametersProtocolGuid,\r
342 EFI_NATIVE_INTERFACE,\r
343 (VOID*)(*NewShellParameters));\r
344 } else {\r
345 //\r
346 // copy from the existing ones\r
347 //\r
348 (*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn;\r
349 (*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut;\r
350 (*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr;\r
351 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
352 &gEfiShellParametersProtocolGuid,\r
353 (VOID*)ShellInfoObject.OldShellParameters,\r
354 (VOID*)(*NewShellParameters));\r
355 }\r
356\r
357 return (Status);\r
358}\r
359\r
360/**\r
361 frees all memory used by createion and installation of shell parameters protocol\r
362 and if there was an old version installed it will restore that one.\r
363\r
364 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is\r
365 being cleaned up.\r
366\r
367 @retval EFI_SUCCESS the cleanup was successful\r
368 @return other the cleanup failed\r
369 @sa ReinstallProtocolInterface\r
370 @sa UninstallProtocolInterface\r
371**/\r
372EFI_STATUS\r
373EFIAPI\r
374CleanUpShellParametersProtocol (\r
375 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters\r
376 )\r
377{\r
378 EFI_STATUS Status;\r
379 UINTN LoopCounter;\r
380\r
381 //\r
382 // If the old exists we need to restore it\r
383 //\r
384 if (ShellInfoObject.OldShellParameters != NULL) {\r
385 Status = gBS->ReinstallProtocolInterface(gImageHandle,\r
386 &gEfiShellParametersProtocolGuid,\r
387 (VOID*)NewShellParameters,\r
388 (VOID*)ShellInfoObject.OldShellParameters);\r
389 DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);\r
390 } else {\r
391 //\r
392 // No old one, just uninstall us...\r
393 //\r
394 Status = gBS->UninstallProtocolInterface(gImageHandle,\r
395 &gEfiShellParametersProtocolGuid,\r
396 (VOID*)NewShellParameters);\r
397 }\r
398 if (NewShellParameters->Argv != NULL) {\r
399 for ( LoopCounter = 0\r
400 ; LoopCounter < NewShellParameters->Argc\r
401 ; LoopCounter++\r
402 ){\r
403 FreePool(NewShellParameters->Argv[LoopCounter]);\r
404 }\r
405 FreePool(NewShellParameters->Argv);\r
406 }\r
407 FreePool(NewShellParameters);\r
408 return (Status);\r
409}\r
410\r
ae724571 411/**\r
412 Determin if a file name represents a unicode file.\r
413\r
414 @param[in] FileName Pointer to the filename to open.\r
415\r
416 @retval EFI_SUCCESS The file is a unicode file.\r
417 @return An error upon failure.\r
418**/\r
733f138d 419EFI_STATUS\r
420EFIAPI\r
421IsUnicodeFile(\r
422 IN CONST CHAR16 *FileName\r
423 )\r
424{\r
425 SHELL_FILE_HANDLE Handle;\r
426 EFI_STATUS Status;\r
427 UINT64 OriginalFilePosition;\r
428 UINTN CharSize;\r
429 CHAR16 CharBuffer;\r
430\r
431 Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);\r
432 if (EFI_ERROR(Status)) {\r
433 return (Status);\r
434 }\r
435 gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);\r
436 gEfiShellProtocol->SetFilePosition(Handle, 0);\r
437 CharSize = sizeof(CHAR16);\r
438 Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);\r
439 if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {\r
440 Status = EFI_BUFFER_TOO_SMALL;\r
441 }\r
442 gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);\r
443 gEfiShellProtocol->CloseFile(Handle);\r
444 return (Status); \r
445}\r
446\r
fb84495a 447/**\r
448 Strips out quotes sections of a string.\r
449\r
450 All of the characters between quotes is replaced with spaces.\r
a1d4bfcc 451\r
452 @param[in,out] TheString A pointer to the string to update.\r
fb84495a 453**/\r
454VOID\r
455EFIAPI\r
456StripQuotes (\r
457 IN OUT CHAR16 *TheString\r
458 )\r
459{\r
460 BOOLEAN RemoveNow;\r
461\r
462 for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {\r
463 if (*TheString == L'^' && *(TheString + 1) == L'\"') {\r
464 TheString++;\r
465 } else if (*TheString == L'\"') {\r
466 RemoveNow = (BOOLEAN)!RemoveNow;\r
467 } else if (RemoveNow) {\r
468 *TheString = L' ';\r
469 }\r
470 }\r
471}\r
472\r
a405b86d 473/**\r
474 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
475 structure by parsing NewCommandLine. The current values are returned to the\r
476 user.\r
477\r
8be0ba36 478 This will also update the system table.\r
a405b86d 479\r
480 @param[in,out] ShellParameters Pointer to parameter structure to modify.\r
481 @param[in] NewCommandLine The new command line to parse and use.\r
482 @param[out] OldStdIn Pointer to old StdIn.\r
483 @param[out] OldStdOut Pointer to old StdOut.\r
484 @param[out] OldStdErr Pointer to old StdErr.\r
8be0ba36 485 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 486\r
487 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
488 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
489**/\r
490EFI_STATUS\r
491EFIAPI\r
492UpdateStdInStdOutStdErr(\r
493 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 494 IN CHAR16 *NewCommandLine,\r
a405b86d 495 OUT SHELL_FILE_HANDLE *OldStdIn,\r
496 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 497 OUT SHELL_FILE_HANDLE *OldStdErr,\r
498 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 499 )\r
500{\r
501 CHAR16 *CommandLineCopy;\r
502 CHAR16 *CommandLineWalker;\r
503 CHAR16 *StdErrFileName;\r
504 CHAR16 *StdOutFileName;\r
505 CHAR16 *StdInFileName;\r
506 CHAR16 *StdInVarName;\r
507 CHAR16 *StdOutVarName;\r
508 CHAR16 *StdErrVarName;\r
509 EFI_STATUS Status;\r
510 SHELL_FILE_HANDLE TempHandle;\r
511 UINT64 FileSize;\r
512 BOOLEAN OutUnicode;\r
513 BOOLEAN InUnicode;\r
514 BOOLEAN ErrUnicode;\r
515 BOOLEAN OutAppend;\r
516 BOOLEAN ErrAppend;\r
517 UINTN Size;\r
518 CHAR16 TagBuffer[2];\r
519 SPLIT_LIST *Split;\r
fb84495a 520 CHAR16 *FirstLocation;\r
a405b86d 521\r
a405b86d 522 OutUnicode = TRUE;\r
523 InUnicode = TRUE;\r
524 ErrUnicode = TRUE;\r
525 StdInVarName = NULL;\r
526 StdOutVarName = NULL;\r
527 StdErrVarName = NULL;\r
528 StdErrFileName = NULL;\r
529 StdInFileName = NULL;\r
530 StdOutFileName = NULL;\r
531 ErrAppend = FALSE;\r
532 OutAppend = FALSE;\r
533 CommandLineCopy = NULL;\r
5f2915f5 534 FirstLocation = NULL;\r
a405b86d 535\r
8be0ba36 536 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
537 return (EFI_INVALID_PARAMETER);\r
a405b86d 538 }\r
539\r
8be0ba36 540 SystemTableInfo->ConIn = gST->ConIn;\r
541 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
542 SystemTableInfo->ConOut = gST->ConOut;\r
543 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
544 SystemTableInfo->ConErr = gST->StdErr;\r
545 SystemTableInfo->ConErrHandle = gST->StandardErrorHandle;\r
546 *OldStdIn = ShellParameters->StdIn;\r
547 *OldStdOut = ShellParameters->StdOut;\r
548 *OldStdErr = ShellParameters->StdErr;\r
549\r
a405b86d 550 if (NewCommandLine == NULL) {\r
551 return (EFI_SUCCESS);\r
552 }\r
553\r
554 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
555 Status = EFI_SUCCESS;\r
556 Split = NULL;\r
5f2915f5 557 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 558\r
fb84495a 559 StripQuotes(CommandLineCopy);\r
560\r
a405b86d 561 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
562 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
563 if (Split != NULL && Split->SplitStdIn != NULL) {\r
564 ShellParameters->StdIn = Split->SplitStdIn;\r
565 }\r
566 if (Split != NULL && Split->SplitStdOut != NULL) {\r
567 ShellParameters->StdOut = Split->SplitStdOut;\r
568 }\r
569 }\r
570\r
571 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 572 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 573 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 574 StdErrVarName = CommandLineWalker += 6;\r
575 ErrAppend = TRUE;\r
733f138d 576 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
577 Status = EFI_NOT_FOUND;\r
578 }\r
a405b86d 579 }\r
580 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 581 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 582 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 583 StdOutVarName = CommandLineWalker += 6;\r
584 OutAppend = TRUE;\r
733f138d 585 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
586 Status = EFI_NOT_FOUND;\r
587 }\r
a405b86d 588 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 589 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 590 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 591 StdOutVarName = CommandLineWalker += 5;\r
592 OutAppend = TRUE;\r
733f138d 593 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
594 Status = EFI_NOT_FOUND;\r
595 }\r
a405b86d 596 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 597 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 598 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 599 StdOutVarName = CommandLineWalker += 4;\r
600 OutAppend = FALSE;\r
733f138d 601 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
602 Status = EFI_NOT_FOUND;\r
603 }\r
a405b86d 604 }\r
605 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 606 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 607 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 608 StdOutFileName = CommandLineWalker += 6;\r
609 OutAppend = TRUE;\r
610 OutUnicode = FALSE;\r
733f138d 611 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
612 Status = EFI_NOT_FOUND;\r
613 }\r
a405b86d 614 }\r
615 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 616 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 617 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 618 if (StdOutFileName != NULL) {\r
619 Status = EFI_INVALID_PARAMETER;\r
620 } else {\r
621 StdOutFileName = CommandLineWalker += 5;\r
622 OutAppend = TRUE;\r
623 }\r
733f138d 624 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
625 Status = EFI_NOT_FOUND;\r
626 }\r
a405b86d 627 } \r
628 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 629 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 630 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 631 if (StdOutFileName != NULL) {\r
632 Status = EFI_INVALID_PARAMETER;\r
633 } else {\r
634 StdOutFileName = CommandLineWalker += 4;\r
635 OutAppend = TRUE;\r
636 }\r
733f138d 637 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
638 Status = EFI_NOT_FOUND;\r
639 }\r
a405b86d 640 }\r
641 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 642 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 643 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 644 if (StdOutFileName != NULL) {\r
645 Status = EFI_INVALID_PARAMETER;\r
646 } else {\r
647 StdOutFileName = CommandLineWalker += 5;\r
648 OutAppend = TRUE;\r
649 OutUnicode = FALSE;\r
650 }\r
733f138d 651 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
652 Status = EFI_NOT_FOUND;\r
653 }\r
a405b86d 654 } \r
655 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 656 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 657 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 658 if (StdOutFileName != NULL) {\r
659 Status = EFI_INVALID_PARAMETER;\r
660 } else {\r
661 StdOutFileName = CommandLineWalker += 5;\r
662 OutAppend = FALSE;\r
663 OutUnicode = FALSE;\r
664 }\r
733f138d 665 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
666 Status = EFI_NOT_FOUND;\r
667 }\r
a405b86d 668 } \r
669 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 670 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 671 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 672 if (StdOutFileName != NULL) {\r
673 Status = EFI_INVALID_PARAMETER;\r
674 } else {\r
675 StdOutFileName = CommandLineWalker += 4;\r
676 OutAppend = FALSE;\r
677 OutUnicode = FALSE;\r
678 }\r
733f138d 679 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
680 Status = EFI_NOT_FOUND;\r
681 }\r
a405b86d 682 }\r
683 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 684 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 685 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 686 if (StdErrFileName != NULL) {\r
687 Status = EFI_INVALID_PARAMETER;\r
688 } else {\r
689 StdErrFileName = CommandLineWalker += 5;\r
690 ErrAppend = TRUE;\r
691 }\r
733f138d 692 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
693 Status = EFI_NOT_FOUND;\r
694 }\r
a405b86d 695 }\r
696\r
697 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 698 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 699 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 700 if (StdErrVarName != NULL) {\r
701 Status = EFI_INVALID_PARAMETER;\r
702 } else {\r
703 StdErrVarName = CommandLineWalker += 5;\r
704 ErrAppend = FALSE;\r
705 }\r
733f138d 706 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
707 Status = EFI_NOT_FOUND;\r
708 }\r
a405b86d 709 }\r
710 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 711 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 712 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 713 if (StdOutVarName != NULL) {\r
714 Status = EFI_INVALID_PARAMETER;\r
715 } else {\r
716 StdOutVarName = CommandLineWalker += 5;\r
717 OutAppend = FALSE;\r
718 }\r
733f138d 719 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
720 Status = EFI_NOT_FOUND;\r
721 }\r
a405b86d 722 }\r
723 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 724 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 725 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 726 if (StdErrFileName != NULL) {\r
727 Status = EFI_INVALID_PARAMETER;\r
728 } else {\r
729 StdErrFileName = CommandLineWalker += 5;\r
730 ErrAppend = FALSE;\r
731 ErrUnicode = FALSE;\r
732 }\r
733f138d 733 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
734 Status = EFI_NOT_FOUND;\r
735 }\r
a405b86d 736 }\r
737 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 738 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 739 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 740 if (StdErrFileName != NULL) {\r
741 Status = EFI_INVALID_PARAMETER;\r
742 } else {\r
743 StdErrFileName = CommandLineWalker += 4;\r
744 ErrAppend = FALSE;\r
745 }\r
733f138d 746 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
747 Status = EFI_NOT_FOUND;\r
748 }\r
a405b86d 749 }\r
750\r
751 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 752 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 753 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 754 if (StdOutFileName != NULL) {\r
755 Status = EFI_INVALID_PARAMETER;\r
756 } else {\r
757 StdOutFileName = CommandLineWalker += 4;\r
758 OutAppend = FALSE;\r
759 }\r
733f138d 760 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
761 Status = EFI_NOT_FOUND;\r
762 }\r
a405b86d 763 }\r
764\r
765 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 766 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 767 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 768 if (StdOutFileName != NULL) {\r
769 Status = EFI_INVALID_PARAMETER;\r
770 } else {\r
771 StdOutFileName = CommandLineWalker += 3;\r
772 OutAppend = FALSE;\r
773 }\r
733f138d 774 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
775 Status = EFI_NOT_FOUND;\r
776 }\r
a405b86d 777 }\r
778\r
779 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 780 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 781 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 782 if (StdInFileName != NULL) {\r
783 Status = EFI_INVALID_PARAMETER;\r
784 } else {\r
785 StdInFileName = CommandLineWalker += 3;\r
733f138d 786 }\r
787 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
788 Status = EFI_NOT_FOUND;\r
a405b86d 789 }\r
790 }\r
791 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 792 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 793 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 794 if (StdInFileName != NULL) {\r
795 Status = EFI_INVALID_PARAMETER;\r
796 } else {\r
733f138d 797 StdInFileName = CommandLineWalker += 4;\r
798 InUnicode = FALSE;\r
799 }\r
800 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
801 Status = EFI_NOT_FOUND;\r
a405b86d 802 }\r
803 }\r
804 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 if (StdInVarName != NULL) {\r
808 Status = EFI_INVALID_PARAMETER;\r
809 } else {\r
810 StdInVarName = CommandLineWalker += 4;\r
733f138d 811 }\r
812 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
813 Status = EFI_NOT_FOUND;\r
a405b86d 814 }\r
815 }\r
816\r
5f2915f5 817 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 818 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
819 ){\r
820 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
821 }\r
822\r
a405b86d 823 if (!EFI_ERROR(Status)) {\r
824 if (StdErrFileName != NULL && (CommandLineWalker = StrStr(StdErrFileName, L" ")) != NULL) {\r
825 CommandLineWalker[0] = CHAR_NULL;\r
826 }\r
827 if (StdOutFileName != NULL && (CommandLineWalker = StrStr(StdOutFileName, L" ")) != NULL) {\r
828 CommandLineWalker[0] = CHAR_NULL;\r
829 }\r
830 if (StdInFileName != NULL && (CommandLineWalker = StrStr(StdInFileName , L" ")) != NULL) {\r
831 CommandLineWalker[0] = CHAR_NULL;\r
832 }\r
833 if (StdErrVarName != NULL && (CommandLineWalker = StrStr(StdErrVarName , L" ")) != NULL) {\r
834 CommandLineWalker[0] = CHAR_NULL;\r
835 }\r
836 if (StdOutVarName != NULL && (CommandLineWalker = StrStr(StdOutVarName , L" ")) != NULL) {\r
837 CommandLineWalker[0] = CHAR_NULL;\r
838 }\r
839 if (StdInVarName != NULL && (CommandLineWalker = StrStr(StdInVarName , L" ")) != NULL) {\r
840 CommandLineWalker[0] = CHAR_NULL;\r
841 }\r
842\r
0c956e0d 843 //\r
844 // Verify not the same and not duplicating something from a split\r
845 //\r
733f138d 846 if (\r
847 //\r
848 // Check that no 2 filenames are the same\r
849 //\r
fb84495a 850 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 851 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
852 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 853 //\r
854 // Check that no 2 variable names are the same\r
855 //\r
a405b86d 856 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
857 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
858 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 859 //\r
860 // When a split (using | operator) is in place some are not allowed\r
861 //\r
a405b86d 862 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
863 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 864 //\r
865 // Check that nothing is trying to be output to 2 locations.\r
866 //\r
a405b86d 867 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
868 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
869 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 870 //\r
733f138d 871 // Check for no volatile environment variables\r
872 //\r
a405b86d 873 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
874 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 875 //\r
876 // Cant redirect during a reconnect operation.\r
877 //\r
3c865f20 878 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
879 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 880 //\r
881 // Check that filetypes (Unicode/Ascii) do not change during an append\r
882 //\r
883 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
884 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
885 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
886 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 887 ){\r
888 Status = EFI_INVALID_PARAMETER;\r
fb84495a 889 } else if (!EFI_ERROR(Status)){\r
a405b86d 890 //\r
891 // Open the Std<Whatever> and we should not have conflicts here...\r
892 //\r
893\r
894 //\r
895 // StdErr to a file\r
896 //\r
897 if (StdErrFileName != NULL) {\r
898 if (!ErrAppend) {\r
899 //\r
900 // delete existing file.\r
901 //\r
902 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
903 }\r
904 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 905 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
906 //\r
733f138d 907 // Write out the gUnicodeFileTag\r
a405b86d 908 //\r
909 Size = sizeof(CHAR16);\r
733f138d 910 TagBuffer[0] = gUnicodeFileTag;\r
a405b86d 911 TagBuffer[1] = CHAR_NULL;\r
912 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
913 }\r
914 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
915 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
916 ASSERT(TempHandle != NULL);\r
917 }\r
918 if (!EFI_ERROR(Status)) {\r
919 ShellParameters->StdErr = TempHandle;\r
8be0ba36 920 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 921 }\r
922 }\r
923\r
924 //\r
925 // StdOut to a file\r
926 //\r
927 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
928 if (!OutAppend) {\r
929 //\r
930 // delete existing file.\r
931 //\r
932 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
933 }\r
934 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 935 if (TempHandle == NULL) {\r
936 Status = EFI_INVALID_PARAMETER;\r
937 } else {\r
733f138d 938 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
939 //no-op\r
940 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
3c865f20 941 //\r
733f138d 942 // Write out the gUnicodeFileTag\r
3c865f20 943 //\r
944 Size = sizeof(CHAR16);\r
733f138d 945 TagBuffer[0] = gUnicodeFileTag;\r
3c865f20 946 TagBuffer[1] = CHAR_NULL;\r
947 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
948 } else if (OutAppend) {\r
949 //\r
950 // Move to end of file\r
951 //\r
952 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
953 if (!EFI_ERROR(Status)) {\r
954 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
955 }\r
956 }\r
957 if (!OutUnicode && !EFI_ERROR(Status)) {\r
958 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
959 ASSERT(TempHandle != NULL);\r
960 }\r
a405b86d 961 if (!EFI_ERROR(Status)) {\r
3c865f20 962 ShellParameters->StdOut = TempHandle;\r
8be0ba36 963 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 964 }\r
965 }\r
a405b86d 966 }\r
967\r
968 //\r
969 // StdOut to a var\r
970 //\r
971 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
972 if (!OutAppend) {\r
973 //\r
974 // delete existing variable.\r
975 //\r
976 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
977 }\r
978 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
979 ASSERT(TempHandle != NULL);\r
a405b86d 980 ShellParameters->StdOut = TempHandle;\r
8be0ba36 981 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 982 }\r
983\r
984 //\r
985 // StdErr to a var\r
986 //\r
987 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
988 if (!ErrAppend) {\r
989 //\r
990 // delete existing variable.\r
991 //\r
992 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
993 }\r
994 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
995 ASSERT(TempHandle != NULL);\r
a405b86d 996 ShellParameters->StdErr = TempHandle;\r
8be0ba36 997 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 998 }\r
999\r
1000 //\r
1001 // StdIn from a var\r
1002 //\r
1003 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1004 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
1005 if (!InUnicode) {\r
1006 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1007 }\r
1008 Size = 0;\r
1009 ASSERT(TempHandle != NULL);\r
1010 if (((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
1011 Status = EFI_INVALID_PARAMETER;\r
1012 } else {\r
1013 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1014 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1015 }\r
1016 }\r
1017\r
1018 //\r
1019 // StdIn from a file\r
1020 //\r
1021 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1022 Status = ShellOpenFileByName(\r
1023 StdInFileName,\r
1024 &TempHandle,\r
1025 EFI_FILE_MODE_READ,\r
1026 0);\r
1027 if (!InUnicode && !EFI_ERROR(Status)) {\r
1028 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1029 }\r
1030 if (!EFI_ERROR(Status)) {\r
1031 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1032 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1033 }\r
1034 }\r
1035 }\r
1036 }\r
1037 FreePool(CommandLineCopy);\r
8be0ba36 1038\r
1039 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1040 return (EFI_OUT_OF_RESOURCES);\r
1041 }\r
a405b86d 1042 return (Status);\r
1043}\r
1044\r
1045/**\r
1046 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1047 structure with StdIn and StdOut. The current values are de-allocated.\r
1048\r
8be0ba36 1049 @param[in,out] ShellParameters Pointer to parameter structure to modify.\r
1050 @param[in] OldStdIn Pointer to old StdIn.\r
1051 @param[in] OldStdOut Pointer to old StdOut.\r
1052 @param[in] OldStdErr Pointer to old StdErr.\r
1053 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1054**/\r
1055EFI_STATUS\r
1056EFIAPI\r
1057RestoreStdInStdOutStdErr (\r
1058 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1059 IN SHELL_FILE_HANDLE *OldStdIn,\r
1060 IN SHELL_FILE_HANDLE *OldStdOut,\r
1061 IN SHELL_FILE_HANDLE *OldStdErr,\r
1062 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1063 )\r
1064{\r
1065 SPLIT_LIST *Split;\r
8be0ba36 1066\r
1067 if (ShellParameters == NULL \r
1068 ||OldStdIn == NULL\r
1069 ||OldStdOut == NULL\r
1070 ||OldStdErr == NULL\r
1071 ||SystemTableInfo == NULL) {\r
1072 return (EFI_INVALID_PARAMETER);\r
1073 }\r
a405b86d 1074 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1075 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1076 } else {\r
1077 Split = NULL;\r
1078 }\r
8be0ba36 1079 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1080 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1081 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1082 }\r
8be0ba36 1083 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1084 }\r
8be0ba36 1085 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1086 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1087 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1088 }\r
8be0ba36 1089 ShellParameters->StdOut = *OldStdOut;\r
1090 }\r
1091 if (ShellParameters->StdErr != *OldStdErr) {\r
1092 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1093 ShellParameters->StdErr = *OldStdErr;\r
1094 }\r
1095\r
1096 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1097 CloseSimpleTextInOnFile(gST->ConIn);\r
1098 gST->ConIn = SystemTableInfo->ConIn;\r
1099 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1100 }\r
8be0ba36 1101 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1102 CloseSimpleTextOutOnFile(gST->ConOut);\r
1103 gST->ConOut = SystemTableInfo->ConOut;\r
1104 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1105 }\r
1106 if (gST->StdErr != SystemTableInfo->ConErr) {\r
1107 CloseSimpleTextOutOnFile(gST->StdErr);\r
1108 gST->StdErr = SystemTableInfo->ConErr;\r
1109 gST->StandardErrorHandle = SystemTableInfo->ConErrHandle;\r
1110 }\r
1111\r
a405b86d 1112 return (EFI_SUCCESS);\r
1113}\r
1114/**\r
1115 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1116 structure by parsing NewCommandLine. The current values are returned to the\r
1117 user.\r
1118\r
1119 If OldArgv or OldArgc is NULL then that value is not returned.\r
1120\r
1121 @param[in,out] ShellParameters Pointer to parameter structure to modify.\r
1122 @param[in] NewCommandLine The new command line to parse and use.\r
1123 @param[out] OldArgv Pointer to old list of parameters.\r
1124 @param[out] OldArgc Pointer to old number of items in Argv list.\r
1125\r
1126 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1127 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1128**/\r
1129EFI_STATUS\r
1130EFIAPI\r
1131UpdateArgcArgv(\r
1132 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1133 IN CONST CHAR16 *NewCommandLine,\r
1134 OUT CHAR16 ***OldArgv OPTIONAL,\r
1135 OUT UINTN *OldArgc OPTIONAL\r
1136 )\r
1137{\r
1138 ASSERT(ShellParameters != NULL);\r
1139\r
1140 if (OldArgc != NULL) {\r
1141 *OldArgc = ShellParameters->Argc;\r
1142 }\r
1143 if (OldArgc != NULL) {\r
1144 *OldArgv = ShellParameters->Argv;\r
1145 }\r
1146\r
1147 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1148}\r
1149\r
1150/**\r
1151 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1152 structure with Argv and Argc. The current values are de-allocated and the\r
1153 OldArgv must not be deallocated by the caller.\r
1154\r
1155 @param[in,out] ShellParameters pointer to parameter structure to modify\r
1156 @param[in] OldArgv pointer to old list of parameters\r
1157 @param[in] OldArgc pointer to old number of items in Argv list\r
1158**/\r
1159VOID\r
1160EFIAPI\r
1161RestoreArgcArgv(\r
1162 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1163 IN CHAR16 ***OldArgv,\r
1164 IN UINTN *OldArgc\r
1165 )\r
1166{\r
1167 UINTN LoopCounter;\r
1168 ASSERT(ShellParameters != NULL);\r
1169 ASSERT(OldArgv != NULL);\r
1170 ASSERT(OldArgc != NULL);\r
1171\r
1172 if (ShellParameters->Argv != NULL) {\r
1173 for ( LoopCounter = 0\r
1174 ; LoopCounter < ShellParameters->Argc\r
1175 ; LoopCounter++\r
1176 ){\r
1177 FreePool(ShellParameters->Argv[LoopCounter]);\r
1178 }\r
1179 FreePool(ShellParameters->Argv);\r
1180 }\r
1181 ShellParameters->Argv = *OldArgv;\r
1182 *OldArgv = NULL;\r
1183 ShellParameters->Argc = *OldArgc;\r
1184 *OldArgc = 0;\r
1185}\r