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