2 Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,
3 manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.
5 Copyright (C) 2014, Red Hat, Inc.
6 (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
7 Copyright (c) 2009 - 2016, 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
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.
20 BOOLEAN AsciiRedirection
= FALSE
;
23 Function to populate Argc and Argv.
25 This function parses the CommandLine and divides it into standard C style Argc/Argv
26 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
27 delimited and quote surrounded parameter definition.
29 All special character processing (alias, environment variable, redirection,
30 etc... must be complete before calling this API.
32 @param[in] CommandLine String of command line to parse
33 @param[in] StripQuotation if TRUE then strip the quotation marks surrounding
35 @param[in, out] Argv pointer to array of strings; one for each parameter
36 @param[in, out] Argc pointer to number of strings in Argv array
38 @return EFI_SUCCESS the operation was sucessful
39 @return EFI_OUT_OF_RESOURCES a memory allocation failed.
43 ParseCommandLineToArgs(
44 IN CONST CHAR16
*CommandLine
,
45 IN BOOLEAN StripQuotation
,
46 IN OUT CHAR16
***Argv
,
51 CHAR16
*TempParameter
;
54 CHAR16
*NewCommandLine
;
61 if (CommandLine
== NULL
|| StrLen(CommandLine
)==0) {
67 NewCommandLine
= AllocateCopyPool(StrSize(CommandLine
), CommandLine
);
68 if (NewCommandLine
== NULL
){
69 return (EFI_OUT_OF_RESOURCES
);
72 TrimSpaces(&NewCommandLine
);
73 Size
= StrSize(NewCommandLine
);
74 TempParameter
= AllocateZeroPool(Size
);
75 if (TempParameter
== NULL
) {
76 SHELL_FREE_NON_NULL(NewCommandLine
);
77 return (EFI_OUT_OF_RESOURCES
);
81 , Walker
= (CHAR16
*)NewCommandLine
82 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
85 if (EFI_ERROR (ShellGetNextParameter (&Walker
, TempParameter
, Size
, TRUE
))) {
91 // lets allocate the pointer array
93 (*Argv
) = AllocateZeroPool((Count
)*sizeof(CHAR16
*));
95 Status
= EFI_OUT_OF_RESOURCES
;
100 Walker
= (CHAR16
*)NewCommandLine
;
101 while(Walker
!= NULL
&& *Walker
!= CHAR_NULL
) {
102 SetMem16(TempParameter
, Size
, CHAR_NULL
);
103 if (EFI_ERROR (ShellGetNextParameter (&Walker
, TempParameter
, Size
, StripQuotation
))) {
104 Status
= EFI_INVALID_PARAMETER
;
108 NewParam
= AllocateCopyPool(StrSize(TempParameter
), TempParameter
);
109 if (NewParam
== NULL
){
110 Status
= EFI_OUT_OF_RESOURCES
;
113 ((CHAR16
**)(*Argv
))[(*Argc
)] = NewParam
;
116 ASSERT(Count
>= (*Argc
));
117 Status
= EFI_SUCCESS
;
120 SHELL_FREE_NON_NULL(TempParameter
);
121 SHELL_FREE_NON_NULL(NewCommandLine
);
126 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
127 installs it on our handle and if there is an existing version of the protocol
128 that one is cached for removal later.
130 @param[in, out] NewShellParameters on a successful return, a pointer to pointer
131 to the newly installed interface.
132 @param[in, out] RootShellInstance on a successful return, pointer to boolean.
133 TRUE if this is the root shell instance.
135 @retval EFI_SUCCESS the operation completed successfully.
136 @return other the operation failed.
137 @sa ReinstallProtocolInterface
138 @sa InstallProtocolInterface
139 @sa ParseCommandLineToArgs
143 CreatePopulateInstallShellParametersProtocol (
144 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
**NewShellParameters
,
145 IN OUT BOOLEAN
*RootShellInstance
149 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
150 CHAR16
*FullCommandLine
;
154 FullCommandLine
= NULL
;
158 // Assert for valid parameters
160 ASSERT(NewShellParameters
!= NULL
);
161 ASSERT(RootShellInstance
!= NULL
);
164 // See if we have a shell parameters placed on us
166 Status
= gBS
->OpenProtocol (
168 &gEfiShellParametersProtocolGuid
,
169 (VOID
**) &ShellInfoObject
.OldShellParameters
,
172 EFI_OPEN_PROTOCOL_GET_PROTOCOL
175 // if we don't then we must be the root shell (error is expected)
177 if (EFI_ERROR (Status
)) {
178 *RootShellInstance
= TRUE
;
182 // Allocate the new structure
184 *NewShellParameters
= AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL
));
185 if ((*NewShellParameters
) == NULL
) {
186 return (EFI_OUT_OF_RESOURCES
);
190 // get loaded image protocol
192 Status
= gBS
->OpenProtocol (
194 &gEfiLoadedImageProtocolGuid
,
195 (VOID
**) &LoadedImage
,
198 EFI_OPEN_PROTOCOL_GET_PROTOCOL
200 ASSERT_EFI_ERROR(Status
);
202 // Build the full command line
204 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, FullCommandLine
);
205 if (Status
== EFI_BUFFER_TOO_SMALL
) {
206 FullCommandLine
= AllocateZeroPool(Size
+ LoadedImage
->LoadOptionsSize
);
207 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, FullCommandLine
);
209 if (Status
== EFI_NOT_FOUND
) {
211 // no parameters via environment... ok
214 if (EFI_ERROR(Status
)) {
218 if (Size
== 0 && LoadedImage
->LoadOptionsSize
!= 0) {
219 ASSERT(FullCommandLine
== NULL
);
221 // Now we need to include a NULL terminator in the size.
223 Size
= LoadedImage
->LoadOptionsSize
+ sizeof(FullCommandLine
[0]);
224 FullCommandLine
= AllocateZeroPool(Size
);
226 if (FullCommandLine
!= NULL
) {
227 CopyMem (FullCommandLine
, LoadedImage
->LoadOptions
, LoadedImage
->LoadOptionsSize
);
229 // Populate Argc and Argv
231 Status
= ParseCommandLineToArgs(FullCommandLine
,
233 &(*NewShellParameters
)->Argv
,
234 &(*NewShellParameters
)->Argc
);
236 FreePool(FullCommandLine
);
238 ASSERT_EFI_ERROR(Status
);
240 (*NewShellParameters
)->Argv
= NULL
;
241 (*NewShellParameters
)->Argc
= 0;
245 // Populate the 3 faked file systems...
247 if (*RootShellInstance
) {
248 (*NewShellParameters
)->StdIn
= &FileInterfaceStdIn
;
249 (*NewShellParameters
)->StdOut
= &FileInterfaceStdOut
;
250 (*NewShellParameters
)->StdErr
= &FileInterfaceStdErr
;
251 Status
= gBS
->InstallProtocolInterface(&gImageHandle
,
252 &gEfiShellParametersProtocolGuid
,
253 EFI_NATIVE_INTERFACE
,
254 (VOID
*)(*NewShellParameters
));
257 // copy from the existing ones
259 (*NewShellParameters
)->StdIn
= ShellInfoObject
.OldShellParameters
->StdIn
;
260 (*NewShellParameters
)->StdOut
= ShellInfoObject
.OldShellParameters
->StdOut
;
261 (*NewShellParameters
)->StdErr
= ShellInfoObject
.OldShellParameters
->StdErr
;
262 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
263 &gEfiShellParametersProtocolGuid
,
264 (VOID
*)ShellInfoObject
.OldShellParameters
,
265 (VOID
*)(*NewShellParameters
));
272 frees all memory used by createion and installation of shell parameters protocol
273 and if there was an old version installed it will restore that one.
275 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
278 @retval EFI_SUCCESS the cleanup was successful
279 @return other the cleanup failed
280 @sa ReinstallProtocolInterface
281 @sa UninstallProtocolInterface
285 CleanUpShellParametersProtocol (
286 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*NewShellParameters
293 // If the old exists we need to restore it
295 if (ShellInfoObject
.OldShellParameters
!= NULL
) {
296 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
297 &gEfiShellParametersProtocolGuid
,
298 (VOID
*)NewShellParameters
,
299 (VOID
*)ShellInfoObject
.OldShellParameters
);
300 DEBUG_CODE(ShellInfoObject
.OldShellParameters
= NULL
;);
303 // No old one, just uninstall us...
305 Status
= gBS
->UninstallProtocolInterface(gImageHandle
,
306 &gEfiShellParametersProtocolGuid
,
307 (VOID
*)NewShellParameters
);
309 if (NewShellParameters
->Argv
!= NULL
) {
310 for ( LoopCounter
= 0
311 ; LoopCounter
< NewShellParameters
->Argc
314 FreePool(NewShellParameters
->Argv
[LoopCounter
]);
316 FreePool(NewShellParameters
->Argv
);
318 FreePool(NewShellParameters
);
323 Determin if a file name represents a unicode file.
325 @param[in] FileName Pointer to the filename to open.
327 @retval EFI_SUCCESS The file is a unicode file.
328 @return An error upon failure.
333 IN CONST CHAR16
*FileName
336 SHELL_FILE_HANDLE Handle
;
338 UINT64 OriginalFilePosition
;
342 Status
= gEfiShellProtocol
->OpenFileByName(FileName
, &Handle
, EFI_FILE_MODE_READ
);
343 if (EFI_ERROR(Status
)) {
346 gEfiShellProtocol
->GetFilePosition(Handle
, &OriginalFilePosition
);
347 gEfiShellProtocol
->SetFilePosition(Handle
, 0);
348 CharSize
= sizeof(CHAR16
);
349 Status
= gEfiShellProtocol
->ReadFile(Handle
, &CharSize
, &CharBuffer
);
350 if (EFI_ERROR(Status
) || CharBuffer
!= gUnicodeFileTag
) {
351 Status
= EFI_BUFFER_TOO_SMALL
;
353 gEfiShellProtocol
->SetFilePosition(Handle
, OriginalFilePosition
);
354 gEfiShellProtocol
->CloseFile(Handle
);
359 Strips out quotes sections of a string.
361 All of the characters between quotes is replaced with spaces.
363 @param[in, out] TheString A pointer to the string to update.
368 IN OUT CHAR16
*TheString
373 for (RemoveNow
= FALSE
; TheString
!= NULL
&& *TheString
!= CHAR_NULL
; TheString
++) {
374 if (*TheString
== L
'^' && *(TheString
+ 1) == L
'\"') {
376 } else if (*TheString
== L
'\"') {
377 RemoveNow
= (BOOLEAN
)!RemoveNow
;
378 } else if (RemoveNow
) {
385 Calcualte the 32-bit CRC in a EFI table using the service provided by the
388 @param Hdr Pointer to an EFI standard header
393 IN OUT EFI_TABLE_HEADER
*Hdr
401 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
402 // Crc will come back as zero if we set it to zero here
405 gBS
->CalculateCrc32 ((UINT8
*)Hdr
, Hdr
->HeaderSize
, &Crc
);
410 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.
412 @param[in] FileName The filename to start with.
414 @retval NULL FileName was invalid.
415 @return The modified FileName.
424 CHAR16
*TempLocation
;
426 if (FileName
== NULL
) {
430 if (FileName
[0] == L
'\"') {
432 if ((TempLocation
= StrStr(Copy
, L
"\"")) != NULL
) {
433 TempLocation
[0] = CHAR_NULL
;
437 while(Copy
[0] == L
' ') {
440 if ((TempLocation
= StrStr(Copy
, L
" ")) != NULL
) {
441 TempLocation
[0] = CHAR_NULL
;
445 if (Copy
[0] == CHAR_NULL
) {
453 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 %.
455 @param[in] FileName The filename to start with.
457 @retval NULL FileName was invalid.
458 @return The modified FileName.
467 CHAR16
*TempLocation
;
471 if (FileName
[0] == L
'%') {
473 if ((TempLocation
= StrStr(Copy
, L
"%")) != NULL
) {
474 TempLocation
[0] = CHAR_NULL
;
478 return (FixFileName(Copy
));
482 Remove the unicode file tag from the begining of the file buffer since that will not be
485 @param[in] Handle Pointer to the handle of the file to be processed.
487 @retval EFI_SUCCESS The unicode file tag has been moved successfully.
492 IN SHELL_FILE_HANDLE
*Handle
498 CharSize
= sizeof(CHAR16
);
500 gEfiShellProtocol
->ReadFile(*Handle
, &CharSize
, &CharBuffer
);
501 if (CharBuffer
!= gUnicodeFileTag
) {
502 gEfiShellProtocol
->SetFilePosition(*Handle
, 0);
504 return (EFI_SUCCESS
);
508 Write the unicode file tag to the specified file.
510 It is the caller's responsibility to ensure that
511 ShellInfoObject.NewEfiShellProtocol has been initialized before calling this
514 @param[in] FileHandle The file to write the unicode file tag to.
516 @return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile.
520 IN SHELL_FILE_HANDLE FileHandle
527 FileTag
= gUnicodeFileTag
;
528 Size
= sizeof FileTag
;
529 Status
= ShellInfoObject
.NewEfiShellProtocol
->WriteFile (FileHandle
, &Size
,
531 ASSERT (EFI_ERROR (Status
) || Size
== sizeof FileTag
);
537 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
538 structure by parsing NewCommandLine. The current values are returned to the
541 This will also update the system table.
543 @param[in, out] ShellParameters Pointer to parameter structure to modify.
544 @param[in] NewCommandLine The new command line to parse and use.
545 @param[out] OldStdIn Pointer to old StdIn.
546 @param[out] OldStdOut Pointer to old StdOut.
547 @param[out] OldStdErr Pointer to old StdErr.
548 @param[out] SystemTableInfo Pointer to old system table information.
550 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
551 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
555 UpdateStdInStdOutStdErr(
556 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
557 IN CHAR16
*NewCommandLine
,
558 OUT SHELL_FILE_HANDLE
*OldStdIn
,
559 OUT SHELL_FILE_HANDLE
*OldStdOut
,
560 OUT SHELL_FILE_HANDLE
*OldStdErr
,
561 OUT SYSTEM_TABLE_INFO
*SystemTableInfo
564 CHAR16
*CommandLineCopy
;
565 CHAR16
*CommandLineWalker
;
566 CHAR16
*StdErrFileName
;
567 CHAR16
*StdOutFileName
;
568 CHAR16
*StdInFileName
;
569 CHAR16
*StdInVarName
;
570 CHAR16
*StdOutVarName
;
571 CHAR16
*StdErrVarName
;
573 SHELL_FILE_HANDLE TempHandle
;
582 CHAR16
*FirstLocation
;
587 AsciiRedirection
= FALSE
;
590 StdOutVarName
= NULL
;
591 StdErrVarName
= NULL
;
592 StdErrFileName
= NULL
;
593 StdInFileName
= NULL
;
594 StdOutFileName
= NULL
;
597 CommandLineCopy
= NULL
;
598 FirstLocation
= NULL
;
600 if (ShellParameters
== NULL
|| SystemTableInfo
== NULL
|| OldStdIn
== NULL
|| OldStdOut
== NULL
|| OldStdErr
== NULL
) {
601 return (EFI_INVALID_PARAMETER
);
604 SystemTableInfo
->ConIn
= gST
->ConIn
;
605 SystemTableInfo
->ConInHandle
= gST
->ConsoleInHandle
;
606 SystemTableInfo
->ConOut
= gST
->ConOut
;
607 SystemTableInfo
->ConOutHandle
= gST
->ConsoleOutHandle
;
608 SystemTableInfo
->ErrOut
= gST
->StdErr
;
609 SystemTableInfo
->ErrOutHandle
= gST
->StandardErrorHandle
;
610 *OldStdIn
= ShellParameters
->StdIn
;
611 *OldStdOut
= ShellParameters
->StdOut
;
612 *OldStdErr
= ShellParameters
->StdErr
;
614 if (NewCommandLine
== NULL
) {
615 return (EFI_SUCCESS
);
618 CommandLineCopy
= StrnCatGrow(&CommandLineCopy
, NULL
, NewCommandLine
, 0);
619 if (CommandLineCopy
== NULL
) {
620 return (EFI_OUT_OF_RESOURCES
);
622 Status
= EFI_SUCCESS
;
624 FirstLocation
= CommandLineCopy
+ StrLen(CommandLineCopy
);
626 StripQuotes(CommandLineCopy
);
628 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
629 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
630 if (Split
!= NULL
&& Split
->SplitStdIn
!= NULL
) {
631 ShellParameters
->StdIn
= Split
->SplitStdIn
;
633 if (Split
!= NULL
&& Split
->SplitStdOut
!= NULL
) {
634 ShellParameters
->StdOut
= Split
->SplitStdOut
;
638 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>>v ")) != NULL
) {
639 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
640 SetMem16(CommandLineWalker
, 12, L
' ');
641 StdErrVarName
= CommandLineWalker
+= 6;
643 if (StrStr(CommandLineWalker
, L
" 2>>v ") != NULL
) {
644 Status
= EFI_NOT_FOUND
;
647 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>v ")) != NULL
) {
648 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
649 SetMem16(CommandLineWalker
, 12, L
' ');
650 StdOutVarName
= CommandLineWalker
+= 6;
652 if (StrStr(CommandLineWalker
, L
" 1>>v ") != NULL
) {
653 Status
= EFI_NOT_FOUND
;
655 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>v ")) != NULL
) {
656 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
657 SetMem16(CommandLineWalker
, 10, L
' ');
658 StdOutVarName
= CommandLineWalker
+= 5;
660 if (StrStr(CommandLineWalker
, L
" >>v ") != NULL
) {
661 Status
= EFI_NOT_FOUND
;
663 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >v ")) != NULL
) {
664 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
665 SetMem16(CommandLineWalker
, 8, L
' ');
666 StdOutVarName
= CommandLineWalker
+= 4;
668 if (StrStr(CommandLineWalker
, L
" >v ") != NULL
) {
669 Status
= EFI_NOT_FOUND
;
672 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>a ")) != NULL
) {
673 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
674 SetMem16(CommandLineWalker
, 12, L
' ');
675 StdOutFileName
= CommandLineWalker
+= 6;
678 if (StrStr(CommandLineWalker
, L
" 1>>a ") != NULL
) {
679 Status
= EFI_NOT_FOUND
;
682 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>> ")) != NULL
) {
683 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
684 SetMem16(CommandLineWalker
, 10, L
' ');
685 if (StdOutFileName
!= NULL
) {
686 Status
= EFI_INVALID_PARAMETER
;
688 StdOutFileName
= CommandLineWalker
+= 5;
691 if (StrStr(CommandLineWalker
, L
" 1>> ") != NULL
) {
692 Status
= EFI_NOT_FOUND
;
695 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >> ")) != NULL
) {
696 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
697 SetMem16(CommandLineWalker
, 8, L
' ');
698 if (StdOutFileName
!= NULL
) {
699 Status
= EFI_INVALID_PARAMETER
;
701 StdOutFileName
= CommandLineWalker
+= 4;
704 if (StrStr(CommandLineWalker
, L
" >> ") != NULL
) {
705 Status
= EFI_NOT_FOUND
;
708 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>a ")) != NULL
) {
709 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
710 SetMem16(CommandLineWalker
, 10, L
' ');
711 if (StdOutFileName
!= NULL
) {
712 Status
= EFI_INVALID_PARAMETER
;
714 StdOutFileName
= CommandLineWalker
+= 5;
718 if (StrStr(CommandLineWalker
, L
" >>a ") != NULL
) {
719 Status
= EFI_NOT_FOUND
;
722 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>a ")) != NULL
) {
723 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
724 SetMem16(CommandLineWalker
, 10, L
' ');
725 if (StdOutFileName
!= NULL
) {
726 Status
= EFI_INVALID_PARAMETER
;
728 StdOutFileName
= CommandLineWalker
+= 5;
732 if (StrStr(CommandLineWalker
, L
" 1>a ") != NULL
) {
733 Status
= EFI_NOT_FOUND
;
736 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >a ")) != NULL
) {
737 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
738 SetMem16(CommandLineWalker
, 8, L
' ');
739 if (StdOutFileName
!= NULL
) {
740 Status
= EFI_INVALID_PARAMETER
;
742 StdOutFileName
= CommandLineWalker
+= 4;
746 if (StrStr(CommandLineWalker
, L
" >a ") != NULL
) {
747 Status
= EFI_NOT_FOUND
;
750 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>> ")) != NULL
) {
751 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
752 SetMem16(CommandLineWalker
, 10, L
' ');
753 if (StdErrFileName
!= NULL
) {
754 Status
= EFI_INVALID_PARAMETER
;
756 StdErrFileName
= CommandLineWalker
+= 5;
759 if (StrStr(CommandLineWalker
, L
" 2>> ") != NULL
) {
760 Status
= EFI_NOT_FOUND
;
764 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>v ")) != NULL
) {
765 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
766 SetMem16(CommandLineWalker
, 10, L
' ');
767 if (StdErrVarName
!= NULL
) {
768 Status
= EFI_INVALID_PARAMETER
;
770 StdErrVarName
= CommandLineWalker
+= 5;
773 if (StrStr(CommandLineWalker
, L
" 2>v ") != NULL
) {
774 Status
= EFI_NOT_FOUND
;
777 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>v ")) != NULL
) {
778 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
779 SetMem16(CommandLineWalker
, 10, L
' ');
780 if (StdOutVarName
!= NULL
) {
781 Status
= EFI_INVALID_PARAMETER
;
783 StdOutVarName
= CommandLineWalker
+= 5;
786 if (StrStr(CommandLineWalker
, L
" 1>v ") != NULL
) {
787 Status
= EFI_NOT_FOUND
;
790 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>a ")) != NULL
) {
791 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
792 SetMem16(CommandLineWalker
, 10, L
' ');
793 if (StdErrFileName
!= NULL
) {
794 Status
= EFI_INVALID_PARAMETER
;
796 StdErrFileName
= CommandLineWalker
+= 5;
800 if (StrStr(CommandLineWalker
, L
" 2>a ") != NULL
) {
801 Status
= EFI_NOT_FOUND
;
804 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2> ")) != NULL
) {
805 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
806 SetMem16(CommandLineWalker
, 8, L
' ');
807 if (StdErrFileName
!= NULL
) {
808 Status
= EFI_INVALID_PARAMETER
;
810 StdErrFileName
= CommandLineWalker
+= 4;
813 if (StrStr(CommandLineWalker
, L
" 2> ") != NULL
) {
814 Status
= EFI_NOT_FOUND
;
818 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1> ")) != NULL
) {
819 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
820 SetMem16(CommandLineWalker
, 8, L
' ');
821 if (StdOutFileName
!= NULL
) {
822 Status
= EFI_INVALID_PARAMETER
;
824 StdOutFileName
= CommandLineWalker
+= 4;
827 if (StrStr(CommandLineWalker
, L
" 1> ") != NULL
) {
828 Status
= EFI_NOT_FOUND
;
832 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" > ")) != NULL
) {
833 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
834 SetMem16(CommandLineWalker
, 6, L
' ');
835 if (StdOutFileName
!= NULL
) {
836 Status
= EFI_INVALID_PARAMETER
;
838 StdOutFileName
= CommandLineWalker
+= 3;
841 if (StrStr(CommandLineWalker
, L
" > ") != NULL
) {
842 Status
= EFI_NOT_FOUND
;
846 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" < ")) != NULL
) {
847 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
848 SetMem16(CommandLineWalker
, 6, L
' ');
849 if (StdInFileName
!= NULL
) {
850 Status
= EFI_INVALID_PARAMETER
;
852 StdInFileName
= CommandLineWalker
+= 3;
854 if (StrStr(CommandLineWalker
, L
" < ") != NULL
) {
855 Status
= EFI_NOT_FOUND
;
858 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <a ")) != NULL
) {
859 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
860 SetMem16(CommandLineWalker
, 8, L
' ');
861 if (StdInFileName
!= NULL
) {
862 Status
= EFI_INVALID_PARAMETER
;
864 StdInFileName
= CommandLineWalker
+= 4;
866 AsciiRedirection
= TRUE
;
868 if (StrStr(CommandLineWalker
, L
" <a ") != NULL
) {
869 Status
= EFI_NOT_FOUND
;
872 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <v ")) != NULL
) {
873 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
874 SetMem16(CommandLineWalker
, 8, L
' ');
875 if (StdInVarName
!= NULL
) {
876 Status
= EFI_INVALID_PARAMETER
;
878 StdInVarName
= CommandLineWalker
+= 4;
880 if (StrStr(CommandLineWalker
, L
" <v ") != NULL
) {
881 Status
= EFI_NOT_FOUND
;
886 // re-populate the string to support any filenames that were in quotes.
888 StrnCpyS(CommandLineCopy
, StrSize(CommandLineCopy
)/sizeof(CHAR16
), NewCommandLine
, StrLen(NewCommandLine
));
890 if (FirstLocation
!= CommandLineCopy
+ StrLen(CommandLineCopy
)
891 && ((UINTN
)(FirstLocation
- CommandLineCopy
) < StrLen(NewCommandLine
))
893 *(NewCommandLine
+ (UINTN
)(FirstLocation
- CommandLineCopy
)) = CHAR_NULL
;
896 if (!EFI_ERROR(Status
)) {
898 if (StdErrFileName
!= NULL
) {
899 if ((StdErrFileName
= FixFileName(StdErrFileName
)) == NULL
) {
900 Status
= EFI_INVALID_PARAMETER
;
903 if (StdOutFileName
!= NULL
) {
904 if ((StdOutFileName
= FixFileName(StdOutFileName
)) == NULL
) {
905 Status
= EFI_INVALID_PARAMETER
;
908 if (StdInFileName
!= NULL
) {
909 if ((StdInFileName
= FixFileName(StdInFileName
)) == NULL
) {
910 Status
= EFI_INVALID_PARAMETER
;
913 if (StdErrVarName
!= NULL
) {
914 if ((StdErrVarName
= FixVarName(StdErrVarName
)) == NULL
) {
915 Status
= EFI_INVALID_PARAMETER
;
918 if (StdOutVarName
!= NULL
) {
919 if ((StdOutVarName
= FixVarName(StdOutVarName
)) == NULL
) {
920 Status
= EFI_INVALID_PARAMETER
;
923 if (StdInVarName
!= NULL
) {
924 if ((StdInVarName
= FixVarName(StdInVarName
)) == NULL
) {
925 Status
= EFI_INVALID_PARAMETER
;
930 // Verify not the same and not duplicating something from a split
934 // Check that no 2 filenames are the same
936 (StdErrFileName
!= NULL
&& StdOutFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdOutFileName
) == 0)
937 ||(StdErrFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdInFileName
) == 0)
938 ||(StdOutFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdOutFileName
, &StdInFileName
) == 0)
940 // Check that no 2 variable names are the same
942 ||(StdErrVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdInVarName
) == 0)
943 ||(StdOutVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdOutVarName
, &StdInVarName
) == 0)
944 ||(StdErrVarName
!= NULL
&& StdOutVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdOutVarName
) == 0)
946 // When a split (using | operator) is in place some are not allowed
948 ||(Split
!= NULL
&& Split
->SplitStdIn
!= NULL
&& (StdInVarName
!= NULL
|| StdInFileName
!= NULL
))
949 ||(Split
!= NULL
&& Split
->SplitStdOut
!= NULL
&& (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
))
951 // Check that nothing is trying to be output to 2 locations.
953 ||(StdErrFileName
!= NULL
&& StdErrVarName
!= NULL
)
954 ||(StdOutFileName
!= NULL
&& StdOutVarName
!= NULL
)
955 ||(StdInFileName
!= NULL
&& StdInVarName
!= NULL
)
957 // Check for no volatile environment variables
959 ||(StdErrVarName
!= NULL
&& !EFI_ERROR (IsVolatileEnv (StdErrVarName
, &Volatile
)) && !Volatile
)
960 ||(StdOutVarName
!= NULL
&& !EFI_ERROR (IsVolatileEnv (StdOutVarName
, &Volatile
)) && !Volatile
)
962 // Cant redirect during a reconnect operation.
964 ||(StrStr(NewCommandLine
, L
"connect -r") != NULL
965 && (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
|| StdErrFileName
!= NULL
|| StdErrVarName
!= NULL
))
967 // Check that filetypes (Unicode/Ascii) do not change during an append
969 ||(StdOutFileName
!= NULL
&& OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
970 ||(StdErrFileName
!= NULL
&& ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
971 ||(StdOutFileName
!= NULL
&& !OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
972 ||(StdErrFileName
!= NULL
&& !ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
974 Status
= EFI_INVALID_PARAMETER
;
975 ShellParameters
->StdIn
= *OldStdIn
;
976 ShellParameters
->StdOut
= *OldStdOut
;
977 ShellParameters
->StdErr
= *OldStdErr
;
978 } else if (!EFI_ERROR(Status
)){
980 // Open the Std<Whatever> and we should not have conflicts here...
986 if (StdErrFileName
!= NULL
) {
989 // delete existing file.
991 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdErrFileName
);
993 Status
= ShellOpenFileByName(StdErrFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
994 if (!ErrAppend
&& ErrUnicode
&& !EFI_ERROR(Status
)) {
995 Status
= WriteFileTag (TempHandle
);
997 if (!ErrUnicode
&& !EFI_ERROR(Status
)) {
998 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
999 ASSERT(TempHandle
!= NULL
);
1001 if (!EFI_ERROR(Status
)) {
1002 ShellParameters
->StdErr
= TempHandle
;
1003 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
, gST
->StdErr
);
1010 if (!EFI_ERROR(Status
) && StdOutFileName
!= NULL
) {
1013 // delete existing file.
1015 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdOutFileName
);
1017 Status
= ShellOpenFileByName(StdOutFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
1018 if (TempHandle
== NULL
) {
1019 Status
= EFI_INVALID_PARAMETER
;
1021 if (StrStr(StdOutFileName
, L
"NUL")==StdOutFileName
) {
1023 } else if (!OutAppend
&& OutUnicode
&& !EFI_ERROR(Status
)) {
1024 Status
= WriteFileTag (TempHandle
);
1025 } else if (OutAppend
) {
1026 Status
= ShellInfoObject
.NewEfiShellProtocol
->GetFileSize(TempHandle
, &FileSize
);
1027 if (!EFI_ERROR(Status
)) {
1029 // When appending to a new unicode file, write the file tag.
1030 // Otherwise (ie. when appending to a new ASCII file, or an
1031 // existent file with any encoding), just seek to the end.
1033 Status
= (FileSize
== 0 && OutUnicode
) ?
1034 WriteFileTag (TempHandle
) :
1035 ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition (
1040 if (!OutUnicode
&& !EFI_ERROR(Status
)) {
1041 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1042 ASSERT(TempHandle
!= NULL
);
1044 if (!EFI_ERROR(Status
)) {
1045 ShellParameters
->StdOut
= TempHandle
;
1046 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
, gST
->ConOut
);
1054 if (!EFI_ERROR(Status
) && StdOutVarName
!= NULL
) {
1057 // delete existing variable.
1059 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName
, 0, L
"");
1061 TempHandle
= CreateFileInterfaceEnv(StdOutVarName
);
1062 ASSERT(TempHandle
!= NULL
);
1063 ShellParameters
->StdOut
= TempHandle
;
1064 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
, gST
->ConOut
);
1070 if (!EFI_ERROR(Status
) && StdErrVarName
!= NULL
) {
1073 // delete existing variable.
1075 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName
, 0, L
"");
1077 TempHandle
= CreateFileInterfaceEnv(StdErrVarName
);
1078 ASSERT(TempHandle
!= NULL
);
1079 ShellParameters
->StdErr
= TempHandle
;
1080 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
, gST
->StdErr
);
1086 if (!EFI_ERROR(Status
) && StdInVarName
!= NULL
) {
1087 TempHandle
= CreateFileInterfaceEnv(StdInVarName
);
1088 if (TempHandle
== NULL
) {
1089 Status
= EFI_OUT_OF_RESOURCES
;
1092 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1095 if (TempHandle
== NULL
|| ((EFI_FILE_PROTOCOL
*)TempHandle
)->Read(TempHandle
, &Size
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
1096 Status
= EFI_INVALID_PARAMETER
;
1098 ShellParameters
->StdIn
= TempHandle
;
1099 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1105 // StdIn from a file
1107 if (!EFI_ERROR(Status
) && StdInFileName
!= NULL
) {
1108 Status
= ShellOpenFileByName(
1113 if (!EFI_ERROR(Status
)) {
1116 // Create the ASCII->Unicode conversion layer
1118 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1120 ShellParameters
->StdIn
= TempHandle
;
1121 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1126 FreePool(CommandLineCopy
);
1128 CalculateEfiHdrCrc(&gST
->Hdr
);
1130 if (gST
->ConIn
== NULL
||gST
->ConOut
== NULL
) {
1131 Status
= EFI_OUT_OF_RESOURCES
;
1134 if (Status
== EFI_NOT_FOUND
) {
1135 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR
), ShellInfoObject
.HiiHandle
);
1136 } else if (EFI_ERROR(Status
)) {
1137 ShellPrintHiiEx(-1, -1, NULL
, STRING_TOKEN (STR_SHELL_INVALID_REDIR
), ShellInfoObject
.HiiHandle
);
1144 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1145 structure with StdIn and StdOut. The current values are de-allocated.
1147 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1148 @param[in] OldStdIn Pointer to old StdIn.
1149 @param[in] OldStdOut Pointer to old StdOut.
1150 @param[in] OldStdErr Pointer to old StdErr.
1151 @param[in] SystemTableInfo Pointer to old system table information.
1155 RestoreStdInStdOutStdErr (
1156 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1157 IN SHELL_FILE_HANDLE
*OldStdIn
,
1158 IN SHELL_FILE_HANDLE
*OldStdOut
,
1159 IN SHELL_FILE_HANDLE
*OldStdErr
,
1160 IN SYSTEM_TABLE_INFO
*SystemTableInfo
1165 if (ShellParameters
== NULL
1169 ||SystemTableInfo
== NULL
) {
1170 return (EFI_INVALID_PARAMETER
);
1172 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1173 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1177 if (ShellParameters
->StdIn
!= *OldStdIn
) {
1178 if ((Split
!= NULL
&& Split
->SplitStdIn
!= ShellParameters
->StdIn
) || Split
== NULL
) {
1179 gEfiShellProtocol
->CloseFile(ShellParameters
->StdIn
);
1181 ShellParameters
->StdIn
= *OldStdIn
;
1183 if (ShellParameters
->StdOut
!= *OldStdOut
) {
1184 if ((Split
!= NULL
&& Split
->SplitStdOut
!= ShellParameters
->StdOut
) || Split
== NULL
) {
1185 gEfiShellProtocol
->CloseFile(ShellParameters
->StdOut
);
1187 ShellParameters
->StdOut
= *OldStdOut
;
1189 if (ShellParameters
->StdErr
!= *OldStdErr
) {
1190 gEfiShellProtocol
->CloseFile(ShellParameters
->StdErr
);
1191 ShellParameters
->StdErr
= *OldStdErr
;
1194 if (gST
->ConIn
!= SystemTableInfo
->ConIn
) {
1195 CloseSimpleTextInOnFile(gST
->ConIn
);
1196 gST
->ConIn
= SystemTableInfo
->ConIn
;
1197 gST
->ConsoleInHandle
= SystemTableInfo
->ConInHandle
;
1199 if (gST
->ConOut
!= SystemTableInfo
->ConOut
) {
1200 CloseSimpleTextOutOnFile(gST
->ConOut
);
1201 gST
->ConOut
= SystemTableInfo
->ConOut
;
1202 gST
->ConsoleOutHandle
= SystemTableInfo
->ConOutHandle
;
1204 if (gST
->StdErr
!= SystemTableInfo
->ErrOut
) {
1205 CloseSimpleTextOutOnFile(gST
->StdErr
);
1206 gST
->StdErr
= SystemTableInfo
->ErrOut
;
1207 gST
->StandardErrorHandle
= SystemTableInfo
->ErrOutHandle
;
1210 CalculateEfiHdrCrc(&gST
->Hdr
);
1212 return (EFI_SUCCESS
);
1215 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1216 structure by parsing NewCommandLine. The current values are returned to the
1219 If OldArgv or OldArgc is NULL then that value is not returned.
1221 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1222 @param[in] NewCommandLine The new command line to parse and use.
1223 @param[in] Type The type of operation.
1224 @param[out] OldArgv Pointer to old list of parameters.
1225 @param[out] OldArgc Pointer to old number of items in Argv list.
1227 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
1228 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1233 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1234 IN CONST CHAR16
*NewCommandLine
,
1235 IN SHELL_OPERATION_TYPES Type
,
1236 OUT CHAR16
***OldArgv OPTIONAL
,
1237 OUT UINTN
*OldArgc OPTIONAL
1240 BOOLEAN StripParamQuotation
;
1242 ASSERT(ShellParameters
!= NULL
);
1243 StripParamQuotation
= TRUE
;
1245 if (OldArgc
!= NULL
) {
1246 *OldArgc
= ShellParameters
->Argc
;
1248 if (OldArgc
!= NULL
) {
1249 *OldArgv
= ShellParameters
->Argv
;
1252 if (Type
== Script_File_Name
) {
1253 StripParamQuotation
= FALSE
;
1256 return ParseCommandLineToArgs( NewCommandLine
,
1257 StripParamQuotation
,
1258 &(ShellParameters
->Argv
),
1259 &(ShellParameters
->Argc
)
1264 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1265 structure with Argv and Argc. The current values are de-allocated and the
1266 OldArgv must not be deallocated by the caller.
1268 @param[in, out] ShellParameters pointer to parameter structure to modify
1269 @param[in] OldArgv pointer to old list of parameters
1270 @param[in] OldArgc pointer to old number of items in Argv list
1275 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1276 IN CHAR16
***OldArgv
,
1281 ASSERT(ShellParameters
!= NULL
);
1282 ASSERT(OldArgv
!= NULL
);
1283 ASSERT(OldArgc
!= NULL
);
1285 if (ShellParameters
->Argv
!= NULL
) {
1286 for ( LoopCounter
= 0
1287 ; LoopCounter
< ShellParameters
->Argc
1290 FreePool(ShellParameters
->Argv
[LoopCounter
]);
1292 FreePool(ShellParameters
->Argv
);
1294 ShellParameters
->Argv
= *OldArgv
;
1296 ShellParameters
->Argc
= *OldArgc
;