]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Application/Shell/ShellParametersProtocol.c
ShellPkg: fix redirection file parsing to allow spaces before filename.
[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
f9aefb6a 5 Copyright (c) 2009 - 2012, 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
4ff7e37b 29 @param[in, out] Walker pointer to string of command line. Adjusted to\r
a405b86d 30 reminaing command line on return\r
4ff7e37b 31 @param[in, out] TempParameter pointer to string of command line item extracted.\r
a405b86d 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
4ff7e37b
ED
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
a405b86d 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
4ff7e37b 218 @param[in, out] NewShellParameters on a successful return, a pointer to pointer\r
a405b86d 219 to the newly installed interface.\r
4ff7e37b 220 @param[in, out] RootShellInstance on a successful return, pointer to boolean.\r
a405b86d 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
4ff7e37b 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
cf6a8f14 473/**\r
474 Calcualte the 32-bit CRC in a EFI table using the service provided by the\r
475 gRuntime service.\r
476\r
477 @param Hdr Pointer to an EFI standard header\r
478\r
479**/\r
480VOID\r
481CalculateEfiHdrCrc (\r
482 IN OUT EFI_TABLE_HEADER *Hdr\r
483 )\r
484{\r
485 UINT32 Crc;\r
486\r
487 Hdr->CRC32 = 0;\r
488\r
489 //\r
490 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then\r
491 // Crc will come back as zero if we set it to zero here\r
492 //\r
493 Crc = 0;\r
494 gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);\r
495 Hdr->CRC32 = Crc;\r
496}\r
497\r
031acf63 498/**\r
499 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.\r
500\r
501 @param[in] FileName The filename to start with.\r
502\r
503 @retval NULL FileName was invalid.\r
504 @return The modified FileName.\r
505**/\r
506CHAR16*\r
507EFIAPI\r
508FixFileName (\r
509 IN CHAR16 *FileName\r
510 )\r
511{\r
512 CHAR16 *Copy;\r
513 CHAR16 *TempLocation;\r
514\r
515 if (FileName == NULL) {\r
516 return (NULL);\r
517 }\r
518\r
519 if (FileName[0] == L'\"') {\r
520 Copy = FileName+1;\r
521 if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {\r
522 TempLocation[0] = CHAR_NULL;\r
523 } \r
524 } else {\r
525 Copy = FileName;\r
f9aefb6a 526 while(Copy[0] == L' ') {\r
527 Copy++;\r
528 }\r
031acf63 529 if ((TempLocation = StrStr(Copy , L" ")) != NULL) {\r
530 TempLocation[0] = CHAR_NULL;\r
531 } \r
532 }\r
533\r
534 if (Copy[0] == CHAR_NULL) {\r
535 return (NULL);\r
536 }\r
537\r
538 return (Copy);\r
539}\r
540\r
a405b86d 541/**\r
542 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
543 structure by parsing NewCommandLine. The current values are returned to the\r
544 user.\r
545\r
8be0ba36 546 This will also update the system table.\r
a405b86d 547\r
4ff7e37b
ED
548 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
549 @param[in] NewCommandLine The new command line to parse and use.\r
550 @param[out] OldStdIn Pointer to old StdIn.\r
551 @param[out] OldStdOut Pointer to old StdOut.\r
552 @param[out] OldStdErr Pointer to old StdErr.\r
553 @param[out] SystemTableInfo Pointer to old system table information.\r
a405b86d 554\r
555 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
556 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
557**/\r
558EFI_STATUS\r
559EFIAPI\r
560UpdateStdInStdOutStdErr(\r
561 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
fb84495a 562 IN CHAR16 *NewCommandLine,\r
a405b86d 563 OUT SHELL_FILE_HANDLE *OldStdIn,\r
564 OUT SHELL_FILE_HANDLE *OldStdOut,\r
8be0ba36 565 OUT SHELL_FILE_HANDLE *OldStdErr,\r
566 OUT SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 567 )\r
568{\r
569 CHAR16 *CommandLineCopy;\r
570 CHAR16 *CommandLineWalker;\r
571 CHAR16 *StdErrFileName;\r
572 CHAR16 *StdOutFileName;\r
573 CHAR16 *StdInFileName;\r
574 CHAR16 *StdInVarName;\r
575 CHAR16 *StdOutVarName;\r
576 CHAR16 *StdErrVarName;\r
577 EFI_STATUS Status;\r
578 SHELL_FILE_HANDLE TempHandle;\r
579 UINT64 FileSize;\r
580 BOOLEAN OutUnicode;\r
581 BOOLEAN InUnicode;\r
582 BOOLEAN ErrUnicode;\r
583 BOOLEAN OutAppend;\r
584 BOOLEAN ErrAppend;\r
585 UINTN Size;\r
586 CHAR16 TagBuffer[2];\r
587 SPLIT_LIST *Split;\r
fb84495a 588 CHAR16 *FirstLocation;\r
a405b86d 589\r
a405b86d 590 OutUnicode = TRUE;\r
591 InUnicode = TRUE;\r
592 ErrUnicode = TRUE;\r
593 StdInVarName = NULL;\r
594 StdOutVarName = NULL;\r
595 StdErrVarName = NULL;\r
596 StdErrFileName = NULL;\r
597 StdInFileName = NULL;\r
598 StdOutFileName = NULL;\r
599 ErrAppend = FALSE;\r
600 OutAppend = FALSE;\r
601 CommandLineCopy = NULL;\r
5f2915f5 602 FirstLocation = NULL;\r
a405b86d 603\r
8be0ba36 604 if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) {\r
605 return (EFI_INVALID_PARAMETER);\r
a405b86d 606 }\r
607\r
8be0ba36 608 SystemTableInfo->ConIn = gST->ConIn;\r
609 SystemTableInfo->ConInHandle = gST->ConsoleInHandle;\r
610 SystemTableInfo->ConOut = gST->ConOut;\r
611 SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle;\r
612 SystemTableInfo->ConErr = gST->StdErr;\r
613 SystemTableInfo->ConErrHandle = gST->StandardErrorHandle;\r
614 *OldStdIn = ShellParameters->StdIn;\r
615 *OldStdOut = ShellParameters->StdOut;\r
616 *OldStdErr = ShellParameters->StdErr;\r
617\r
a405b86d 618 if (NewCommandLine == NULL) {\r
619 return (EFI_SUCCESS);\r
620 }\r
621\r
622 CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0);\r
532691c8 623 if (CommandLineCopy == NULL) {\r
624 return (EFI_OUT_OF_RESOURCES);\r
625 }\r
a405b86d 626 Status = EFI_SUCCESS;\r
627 Split = NULL;\r
5f2915f5 628 FirstLocation = CommandLineCopy + StrLen(CommandLineCopy);\r
a405b86d 629\r
fb84495a 630 StripQuotes(CommandLineCopy);\r
631\r
a405b86d 632 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
633 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
634 if (Split != NULL && Split->SplitStdIn != NULL) {\r
635 ShellParameters->StdIn = Split->SplitStdIn;\r
636 }\r
637 if (Split != NULL && Split->SplitStdOut != NULL) {\r
638 ShellParameters->StdOut = Split->SplitStdOut;\r
639 }\r
640 }\r
641\r
642 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) {\r
fb84495a 643 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 644 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 645 StdErrVarName = CommandLineWalker += 6;\r
646 ErrAppend = TRUE;\r
733f138d 647 if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) {\r
648 Status = EFI_NOT_FOUND;\r
649 }\r
a405b86d 650 }\r
651 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) {\r
fb84495a 652 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 653 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 654 StdOutVarName = CommandLineWalker += 6;\r
655 OutAppend = TRUE;\r
733f138d 656 if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) {\r
657 Status = EFI_NOT_FOUND;\r
658 }\r
a405b86d 659 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) {\r
fb84495a 660 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 661 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 662 StdOutVarName = CommandLineWalker += 5;\r
663 OutAppend = TRUE;\r
733f138d 664 if (StrStr(CommandLineWalker, L" >>v ") != NULL) {\r
665 Status = EFI_NOT_FOUND;\r
666 }\r
a405b86d 667 } else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) {\r
fb84495a 668 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 669 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 670 StdOutVarName = CommandLineWalker += 4;\r
671 OutAppend = FALSE;\r
733f138d 672 if (StrStr(CommandLineWalker, L" >v ") != NULL) {\r
673 Status = EFI_NOT_FOUND;\r
674 }\r
a405b86d 675 }\r
676 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) {\r
fb84495a 677 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 678 SetMem16(CommandLineWalker, 12, L' ');\r
a405b86d 679 StdOutFileName = CommandLineWalker += 6;\r
680 OutAppend = TRUE;\r
681 OutUnicode = FALSE;\r
733f138d 682 if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) {\r
683 Status = EFI_NOT_FOUND;\r
684 }\r
a405b86d 685 }\r
686 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) {\r
fb84495a 687 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 688 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 689 if (StdOutFileName != NULL) {\r
690 Status = EFI_INVALID_PARAMETER;\r
691 } else {\r
692 StdOutFileName = CommandLineWalker += 5;\r
693 OutAppend = TRUE;\r
694 }\r
733f138d 695 if (StrStr(CommandLineWalker, L" 1>> ") != NULL) {\r
696 Status = EFI_NOT_FOUND;\r
697 }\r
a405b86d 698 } \r
699 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) {\r
fb84495a 700 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 701 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 702 if (StdOutFileName != NULL) {\r
703 Status = EFI_INVALID_PARAMETER;\r
704 } else {\r
705 StdOutFileName = CommandLineWalker += 4;\r
706 OutAppend = TRUE;\r
707 }\r
733f138d 708 if (StrStr(CommandLineWalker, L" >> ") != NULL) {\r
709 Status = EFI_NOT_FOUND;\r
710 }\r
a405b86d 711 }\r
712 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) {\r
fb84495a 713 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 714 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 715 if (StdOutFileName != NULL) {\r
716 Status = EFI_INVALID_PARAMETER;\r
717 } else {\r
718 StdOutFileName = CommandLineWalker += 5;\r
719 OutAppend = TRUE;\r
720 OutUnicode = FALSE;\r
721 }\r
733f138d 722 if (StrStr(CommandLineWalker, L" >>a ") != NULL) {\r
723 Status = EFI_NOT_FOUND;\r
724 }\r
a405b86d 725 } \r
726 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) {\r
fb84495a 727 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 728 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 729 if (StdOutFileName != NULL) {\r
730 Status = EFI_INVALID_PARAMETER;\r
731 } else {\r
732 StdOutFileName = CommandLineWalker += 5;\r
733 OutAppend = FALSE;\r
734 OutUnicode = FALSE;\r
735 }\r
733f138d 736 if (StrStr(CommandLineWalker, L" 1>a ") != NULL) {\r
737 Status = EFI_NOT_FOUND;\r
738 }\r
a405b86d 739 } \r
740 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) {\r
fb84495a 741 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 742 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 743 if (StdOutFileName != NULL) {\r
744 Status = EFI_INVALID_PARAMETER;\r
745 } else {\r
746 StdOutFileName = CommandLineWalker += 4;\r
747 OutAppend = FALSE;\r
748 OutUnicode = FALSE;\r
749 }\r
733f138d 750 if (StrStr(CommandLineWalker, L" >a ") != NULL) {\r
751 Status = EFI_NOT_FOUND;\r
752 }\r
a405b86d 753 }\r
754 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) {\r
fb84495a 755 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 756 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 757 if (StdErrFileName != NULL) {\r
758 Status = EFI_INVALID_PARAMETER;\r
759 } else {\r
760 StdErrFileName = CommandLineWalker += 5;\r
761 ErrAppend = TRUE;\r
762 }\r
733f138d 763 if (StrStr(CommandLineWalker, L" 2>> ") != NULL) {\r
764 Status = EFI_NOT_FOUND;\r
765 }\r
a405b86d 766 }\r
767\r
768 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) {\r
fb84495a 769 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 770 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 771 if (StdErrVarName != NULL) {\r
772 Status = EFI_INVALID_PARAMETER;\r
773 } else {\r
774 StdErrVarName = CommandLineWalker += 5;\r
775 ErrAppend = FALSE;\r
776 }\r
733f138d 777 if (StrStr(CommandLineWalker, L" 2>v ") != NULL) {\r
778 Status = EFI_NOT_FOUND;\r
779 }\r
a405b86d 780 }\r
781 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) {\r
fb84495a 782 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 783 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 784 if (StdOutVarName != NULL) {\r
785 Status = EFI_INVALID_PARAMETER;\r
786 } else {\r
787 StdOutVarName = CommandLineWalker += 5;\r
788 OutAppend = FALSE;\r
789 }\r
733f138d 790 if (StrStr(CommandLineWalker, L" 1>v ") != NULL) {\r
791 Status = EFI_NOT_FOUND;\r
792 }\r
a405b86d 793 }\r
794 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) {\r
fb84495a 795 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 796 SetMem16(CommandLineWalker, 10, L' ');\r
a405b86d 797 if (StdErrFileName != NULL) {\r
798 Status = EFI_INVALID_PARAMETER;\r
799 } else {\r
800 StdErrFileName = CommandLineWalker += 5;\r
801 ErrAppend = FALSE;\r
802 ErrUnicode = FALSE;\r
803 }\r
733f138d 804 if (StrStr(CommandLineWalker, L" 2>a ") != NULL) {\r
805 Status = EFI_NOT_FOUND;\r
806 }\r
a405b86d 807 }\r
808 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) {\r
fb84495a 809 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 810 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 811 if (StdErrFileName != NULL) {\r
812 Status = EFI_INVALID_PARAMETER;\r
813 } else {\r
814 StdErrFileName = CommandLineWalker += 4;\r
815 ErrAppend = FALSE;\r
816 }\r
733f138d 817 if (StrStr(CommandLineWalker, L" 2> ") != NULL) {\r
818 Status = EFI_NOT_FOUND;\r
819 }\r
a405b86d 820 }\r
821\r
822 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) {\r
fb84495a 823 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 824 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 825 if (StdOutFileName != NULL) {\r
826 Status = EFI_INVALID_PARAMETER;\r
827 } else {\r
828 StdOutFileName = CommandLineWalker += 4;\r
829 OutAppend = FALSE;\r
830 }\r
733f138d 831 if (StrStr(CommandLineWalker, L" 1> ") != NULL) {\r
832 Status = EFI_NOT_FOUND;\r
833 }\r
a405b86d 834 }\r
835\r
836 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) {\r
fb84495a 837 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 838 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 839 if (StdOutFileName != NULL) {\r
840 Status = EFI_INVALID_PARAMETER;\r
841 } else {\r
842 StdOutFileName = CommandLineWalker += 3;\r
843 OutAppend = FALSE;\r
844 }\r
733f138d 845 if (StrStr(CommandLineWalker, L" > ") != NULL) {\r
846 Status = EFI_NOT_FOUND;\r
847 }\r
a405b86d 848 }\r
849\r
850 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) {\r
fb84495a 851 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 852 SetMem16(CommandLineWalker, 6, L' ');\r
a405b86d 853 if (StdInFileName != NULL) {\r
854 Status = EFI_INVALID_PARAMETER;\r
855 } else {\r
856 StdInFileName = CommandLineWalker += 3;\r
733f138d 857 }\r
858 if (StrStr(CommandLineWalker, L" < ") != NULL) {\r
859 Status = EFI_NOT_FOUND;\r
a405b86d 860 }\r
861 }\r
862 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) {\r
fb84495a 863 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 864 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 865 if (StdInFileName != NULL) {\r
866 Status = EFI_INVALID_PARAMETER;\r
867 } else {\r
733f138d 868 StdInFileName = CommandLineWalker += 4;\r
869 InUnicode = FALSE;\r
870 }\r
871 if (StrStr(CommandLineWalker, L" <a ") != NULL) {\r
872 Status = EFI_NOT_FOUND;\r
a405b86d 873 }\r
874 }\r
875 if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) {\r
fb84495a 876 FirstLocation = MIN(CommandLineWalker, FirstLocation);\r
733f138d 877 SetMem16(CommandLineWalker, 8, L' ');\r
a405b86d 878 if (StdInVarName != NULL) {\r
879 Status = EFI_INVALID_PARAMETER;\r
880 } else {\r
881 StdInVarName = CommandLineWalker += 4;\r
733f138d 882 }\r
883 if (StrStr(CommandLineWalker, L" <v ") != NULL) {\r
884 Status = EFI_NOT_FOUND;\r
a405b86d 885 }\r
886 }\r
887\r
031acf63 888 //\r
889 // re-populate the string to support any filenames that were in quotes.\r
890 //\r
891 StrCpy(CommandLineCopy, NewCommandLine);\r
892\r
5f2915f5 893 if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy)\r
fb84495a 894 && ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine))\r
895 ){\r
896 *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;\r
897 }\r
898\r
a405b86d 899 if (!EFI_ERROR(Status)) {\r
031acf63 900\r
901 if (StdErrFileName != NULL) {\r
902 if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {\r
903 Status = EFI_INVALID_PARAMETER;\r
904 }\r
a405b86d 905 }\r
031acf63 906 if (StdOutFileName != NULL) {\r
907 if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {\r
908 Status = EFI_INVALID_PARAMETER;\r
909 }\r
a405b86d 910 }\r
031acf63 911 if (StdInFileName != NULL) {\r
912 if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {\r
913 Status = EFI_INVALID_PARAMETER;\r
914 }\r
a405b86d 915 }\r
031acf63 916 if (StdErrVarName != NULL) {\r
917 if ((StdErrVarName = FixFileName(StdErrVarName)) == NULL) {\r
918 Status = EFI_INVALID_PARAMETER;\r
919 }\r
a405b86d 920 }\r
031acf63 921 if (StdOutVarName != NULL) {\r
922 if ((StdOutVarName = FixFileName(StdOutVarName)) == NULL) {\r
923 Status = EFI_INVALID_PARAMETER;\r
924 }\r
a405b86d 925 }\r
031acf63 926 if (StdInVarName != NULL) {\r
927 if ((StdInVarName = FixFileName(StdInVarName)) == NULL) {\r
928 Status = EFI_INVALID_PARAMETER;\r
929 }\r
a405b86d 930 }\r
931\r
0c956e0d 932 //\r
933 // Verify not the same and not duplicating something from a split\r
934 //\r
733f138d 935 if (\r
936 //\r
937 // Check that no 2 filenames are the same\r
938 //\r
fb84495a 939 (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)\r
a405b86d 940 ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)\r
941 ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)\r
733f138d 942 //\r
943 // Check that no 2 variable names are the same\r
944 //\r
a405b86d 945 ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)\r
946 ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)\r
947 ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)\r
733f138d 948 //\r
949 // When a split (using | operator) is in place some are not allowed\r
950 //\r
a405b86d 951 ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))\r
952 ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))\r
733f138d 953 //\r
954 // Check that nothing is trying to be output to 2 locations.\r
955 //\r
a405b86d 956 ||(StdErrFileName != NULL && StdErrVarName != NULL)\r
957 ||(StdOutFileName != NULL && StdOutVarName != NULL)\r
958 ||(StdInFileName != NULL && StdInVarName != NULL)\r
733f138d 959 //\r
733f138d 960 // Check for no volatile environment variables\r
961 //\r
a405b86d 962 ||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName))\r
963 ||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName))\r
733f138d 964 //\r
965 // Cant redirect during a reconnect operation.\r
966 //\r
3c865f20 967 ||(StrStr(NewCommandLine, L"connect -r") != NULL \r
968 && (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL))\r
733f138d 969 //\r
970 // Check that filetypes (Unicode/Ascii) do not change during an append\r
971 //\r
972 ||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
973 ||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
974 ||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName))))\r
975 ||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName))))\r
a405b86d 976 ){\r
977 Status = EFI_INVALID_PARAMETER;\r
a9ca0684 978 ShellParameters->StdIn = *OldStdIn;\r
979 ShellParameters->StdOut = *OldStdOut;\r
980 ShellParameters->StdErr = *OldStdErr;\r
fb84495a 981 } else if (!EFI_ERROR(Status)){\r
a405b86d 982 //\r
983 // Open the Std<Whatever> and we should not have conflicts here...\r
984 //\r
985\r
986 //\r
987 // StdErr to a file\r
988 //\r
989 if (StdErrFileName != NULL) {\r
990 if (!ErrAppend) {\r
991 //\r
992 // delete existing file.\r
993 //\r
994 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName);\r
995 }\r
996 Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
a405b86d 997 if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) {\r
998 //\r
733f138d 999 // Write out the gUnicodeFileTag\r
a405b86d 1000 //\r
1001 Size = sizeof(CHAR16);\r
733f138d 1002 TagBuffer[0] = gUnicodeFileTag;\r
a405b86d 1003 TagBuffer[1] = CHAR_NULL;\r
1004 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1005 }\r
1006 if (!ErrUnicode && !EFI_ERROR(Status)) {\r
1007 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1008 ASSERT(TempHandle != NULL);\r
1009 }\r
1010 if (!EFI_ERROR(Status)) {\r
1011 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1012 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1013 }\r
1014 }\r
1015\r
1016 //\r
1017 // StdOut to a file\r
1018 //\r
1019 if (!EFI_ERROR(Status) && StdOutFileName != NULL) {\r
1020 if (!OutAppend) {\r
1021 //\r
1022 // delete existing file.\r
1023 //\r
1024 ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName);\r
1025 }\r
1026 Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0);\r
3c865f20 1027 if (TempHandle == NULL) {\r
1028 Status = EFI_INVALID_PARAMETER;\r
1029 } else {\r
733f138d 1030 if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {\r
1031 //no-op\r
1032 } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {\r
3c865f20 1033 //\r
733f138d 1034 // Write out the gUnicodeFileTag\r
3c865f20 1035 //\r
1036 Size = sizeof(CHAR16);\r
733f138d 1037 TagBuffer[0] = gUnicodeFileTag;\r
3c865f20 1038 TagBuffer[1] = CHAR_NULL;\r
1039 ShellInfoObject.NewEfiShellProtocol->WriteFile(TempHandle, &Size, TagBuffer);\r
1040 } else if (OutAppend) {\r
1041 //\r
1042 // Move to end of file\r
1043 //\r
1044 Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);\r
1045 if (!EFI_ERROR(Status)) {\r
1046 Status = ShellInfoObject.NewEfiShellProtocol->SetFilePosition(TempHandle, FileSize);\r
1047 }\r
1048 }\r
1049 if (!OutUnicode && !EFI_ERROR(Status)) {\r
1050 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1051 ASSERT(TempHandle != NULL);\r
1052 }\r
a405b86d 1053 if (!EFI_ERROR(Status)) {\r
3c865f20 1054 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1055 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1056 }\r
1057 }\r
a405b86d 1058 }\r
1059\r
1060 //\r
1061 // StdOut to a var\r
1062 //\r
1063 if (!EFI_ERROR(Status) && StdOutVarName != NULL) {\r
1064 if (!OutAppend) {\r
1065 //\r
1066 // delete existing variable.\r
1067 //\r
1068 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");\r
1069 }\r
1070 TempHandle = CreateFileInterfaceEnv(StdOutVarName);\r
1071 ASSERT(TempHandle != NULL);\r
a405b86d 1072 ShellParameters->StdOut = TempHandle;\r
8be0ba36 1073 gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle);\r
a405b86d 1074 }\r
1075\r
1076 //\r
1077 // StdErr to a var\r
1078 //\r
1079 if (!EFI_ERROR(Status) && StdErrVarName != NULL) {\r
1080 if (!ErrAppend) {\r
1081 //\r
1082 // delete existing variable.\r
1083 //\r
1084 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");\r
1085 }\r
1086 TempHandle = CreateFileInterfaceEnv(StdErrVarName);\r
1087 ASSERT(TempHandle != NULL);\r
a405b86d 1088 ShellParameters->StdErr = TempHandle;\r
8be0ba36 1089 gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle);\r
a405b86d 1090 }\r
1091\r
1092 //\r
1093 // StdIn from a var\r
1094 //\r
1095 if (!EFI_ERROR(Status) && StdInVarName != NULL) {\r
1096 TempHandle = CreateFileInterfaceEnv(StdInVarName);\r
532691c8 1097 if (TempHandle == NULL) {\r
1098 Status = EFI_OUT_OF_RESOURCES;\r
a405b86d 1099 } else {\r
532691c8 1100 if (!InUnicode) {\r
1101 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1102 }\r
1103 Size = 0;\r
96962f0a 1104 if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {\r
532691c8 1105 Status = EFI_INVALID_PARAMETER;\r
1106 } else {\r
1107 ShellParameters->StdIn = TempHandle;\r
1108 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
1109 }\r
a405b86d 1110 }\r
1111 }\r
1112\r
1113 //\r
1114 // StdIn from a file\r
1115 //\r
1116 if (!EFI_ERROR(Status) && StdInFileName != NULL) {\r
1117 Status = ShellOpenFileByName(\r
1118 StdInFileName,\r
1119 &TempHandle,\r
1120 EFI_FILE_MODE_READ,\r
1121 0);\r
1122 if (!InUnicode && !EFI_ERROR(Status)) {\r
1123 TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);\r
1124 }\r
1125 if (!EFI_ERROR(Status)) {\r
1126 ShellParameters->StdIn = TempHandle;\r
8be0ba36 1127 gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);\r
a405b86d 1128 }\r
1129 }\r
1130 }\r
1131 }\r
1132 FreePool(CommandLineCopy);\r
8be0ba36 1133\r
cf6a8f14 1134 CalculateEfiHdrCrc(&gST->Hdr);\r
1135\r
8be0ba36 1136 if (gST->ConIn == NULL ||gST->ConOut == NULL) {\r
1137 return (EFI_OUT_OF_RESOURCES);\r
1138 }\r
a405b86d 1139 return (Status);\r
1140}\r
1141\r
1142/**\r
1143 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol\r
1144 structure with StdIn and StdOut. The current values are de-allocated.\r
1145\r
4ff7e37b
ED
1146 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1147 @param[in] OldStdIn Pointer to old StdIn.\r
1148 @param[in] OldStdOut Pointer to old StdOut.\r
1149 @param[in] OldStdErr Pointer to old StdErr.\r
1150 @param[in] SystemTableInfo Pointer to old system table information.\r
a405b86d 1151**/\r
1152EFI_STATUS\r
1153EFIAPI\r
1154RestoreStdInStdOutStdErr (\r
1155 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
8be0ba36 1156 IN SHELL_FILE_HANDLE *OldStdIn,\r
1157 IN SHELL_FILE_HANDLE *OldStdOut,\r
1158 IN SHELL_FILE_HANDLE *OldStdErr,\r
1159 IN SYSTEM_TABLE_INFO *SystemTableInfo\r
a405b86d 1160 )\r
1161{\r
1162 SPLIT_LIST *Split;\r
8be0ba36 1163\r
1164 if (ShellParameters == NULL \r
1165 ||OldStdIn == NULL\r
1166 ||OldStdOut == NULL\r
1167 ||OldStdErr == NULL\r
1168 ||SystemTableInfo == NULL) {\r
1169 return (EFI_INVALID_PARAMETER);\r
1170 }\r
a405b86d 1171 if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
1172 Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
1173 } else {\r
1174 Split = NULL;\r
1175 }\r
8be0ba36 1176 if (ShellParameters->StdIn != *OldStdIn) {\r
a405b86d 1177 if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {\r
1178 gEfiShellProtocol->CloseFile(ShellParameters->StdIn);\r
1179 }\r
8be0ba36 1180 ShellParameters->StdIn = *OldStdIn;\r
a405b86d 1181 }\r
8be0ba36 1182 if (ShellParameters->StdOut != *OldStdOut) {\r
a405b86d 1183 if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {\r
1184 gEfiShellProtocol->CloseFile(ShellParameters->StdOut);\r
1185 }\r
8be0ba36 1186 ShellParameters->StdOut = *OldStdOut;\r
1187 }\r
1188 if (ShellParameters->StdErr != *OldStdErr) {\r
1189 gEfiShellProtocol->CloseFile(ShellParameters->StdErr);\r
1190 ShellParameters->StdErr = *OldStdErr;\r
1191 }\r
1192\r
1193 if (gST->ConIn != SystemTableInfo->ConIn) {\r
1194 CloseSimpleTextInOnFile(gST->ConIn);\r
1195 gST->ConIn = SystemTableInfo->ConIn;\r
1196 gST->ConsoleInHandle = SystemTableInfo->ConInHandle;\r
a405b86d 1197 }\r
8be0ba36 1198 if (gST->ConOut != SystemTableInfo->ConOut) {\r
1199 CloseSimpleTextOutOnFile(gST->ConOut);\r
1200 gST->ConOut = SystemTableInfo->ConOut;\r
1201 gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;\r
1202 }\r
1203 if (gST->StdErr != SystemTableInfo->ConErr) {\r
1204 CloseSimpleTextOutOnFile(gST->StdErr);\r
1205 gST->StdErr = SystemTableInfo->ConErr;\r
1206 gST->StandardErrorHandle = SystemTableInfo->ConErrHandle;\r
1207 }\r
1208\r
cf6a8f14 1209 CalculateEfiHdrCrc(&gST->Hdr);\r
1210\r
a405b86d 1211 return (EFI_SUCCESS);\r
1212}\r
1213/**\r
1214 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1215 structure by parsing NewCommandLine. The current values are returned to the\r
1216 user.\r
1217\r
1218 If OldArgv or OldArgc is NULL then that value is not returned.\r
1219\r
4ff7e37b
ED
1220 @param[in, out] ShellParameters Pointer to parameter structure to modify.\r
1221 @param[in] NewCommandLine The new command line to parse and use.\r
1222 @param[out] OldArgv Pointer to old list of parameters.\r
1223 @param[out] OldArgc Pointer to old number of items in Argv list.\r
a405b86d 1224\r
1225 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.\r
1226 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
1227**/\r
1228EFI_STATUS\r
1229EFIAPI\r
1230UpdateArgcArgv(\r
1231 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1232 IN CONST CHAR16 *NewCommandLine,\r
1233 OUT CHAR16 ***OldArgv OPTIONAL,\r
1234 OUT UINTN *OldArgc OPTIONAL\r
1235 )\r
1236{\r
1237 ASSERT(ShellParameters != NULL);\r
1238\r
1239 if (OldArgc != NULL) {\r
1240 *OldArgc = ShellParameters->Argc;\r
1241 }\r
1242 if (OldArgc != NULL) {\r
1243 *OldArgv = ShellParameters->Argv;\r
1244 }\r
1245\r
1246 return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc)));\r
1247}\r
1248\r
1249/**\r
1250 Funcion will replace the current Argc and Argv in the ShellParameters protocol\r
1251 structure with Argv and Argc. The current values are de-allocated and the\r
1252 OldArgv must not be deallocated by the caller.\r
1253\r
4ff7e37b
ED
1254 @param[in, out] ShellParameters pointer to parameter structure to modify\r
1255 @param[in] OldArgv pointer to old list of parameters\r
1256 @param[in] OldArgc pointer to old number of items in Argv list\r
a405b86d 1257**/\r
1258VOID\r
1259EFIAPI\r
1260RestoreArgcArgv(\r
1261 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,\r
1262 IN CHAR16 ***OldArgv,\r
1263 IN UINTN *OldArgc\r
1264 )\r
1265{\r
1266 UINTN LoopCounter;\r
1267 ASSERT(ShellParameters != NULL);\r
1268 ASSERT(OldArgv != NULL);\r
1269 ASSERT(OldArgc != NULL);\r
1270\r
1271 if (ShellParameters->Argv != NULL) {\r
1272 for ( LoopCounter = 0\r
1273 ; LoopCounter < ShellParameters->Argc\r
1274 ; LoopCounter++\r
1275 ){\r
1276 FreePool(ShellParameters->Argv[LoopCounter]);\r
1277 }\r
1278 FreePool(ShellParameters->Argv);\r
1279 }\r
1280 ShellParameters->Argv = *OldArgv;\r
1281 *OldArgv = NULL;\r
1282 ShellParameters->Argc = *OldArgc;\r
1283 *OldArgc = 0;\r
1284}\r