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