2 Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,
3 manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.
5 Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "ShellParametersProtocol.h"
17 #include "ConsoleWrappers.h"
20 return the next parameter from a command line string;
22 This function moves the next parameter from Walker into TempParameter and moves
23 Walker up past that parameter for recursive calling. When the final parameter
24 is moved *Walker will be set to NULL;
26 Temp Parameter must be large enough to hold the parameter before calling this
29 @param[in, out] Walker pointer to string of command line. Adjusted to
30 reminaing command line on return
31 @param[in, out] TempParameter pointer to string of command line item extracted.
38 CHAR16
**TempParameter
44 ASSERT(Walker
!= NULL
);
45 ASSERT(*Walker
!= NULL
);
46 ASSERT(TempParameter
!= NULL
);
47 ASSERT(*TempParameter
!= NULL
);
50 // make sure we dont have any leading spaces
52 while ((*Walker
)[0] == L
' ') {
57 // make sure we still have some params now...
59 if (StrLen(*Walker
) == 0) {
60 ASSERT((*Walker
)[0] == CHAR_NULL
);
66 // we have a quoted parameter
67 // could be the last parameter, but SHOULD have a trailing quote
69 if ((*Walker
)[0] == L
'\"') {
71 for (TempLoc
= *Walker
+ 1 ; TempLoc
!= NULL
&& *TempLoc
!= CHAR_NULL
; TempLoc
++) {
72 if (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'\"') {
74 } else if (*TempLoc
== L
'\"') {
80 if (NextDelim
- ((*Walker
)+1) == 0) {
84 StrCpy(*TempParameter
, L
"");
85 *Walker
= NextDelim
+ 1;
86 } else if (NextDelim
!= NULL
) {
87 StrnCpy(*TempParameter
, (*Walker
)+1, NextDelim
- ((*Walker
)+1));
88 *Walker
= NextDelim
+ 1;
91 // last one... someone forgot the training quote!
93 StrCpy(*TempParameter
, *Walker
);
96 for (TempLoc
= *TempParameter
; TempLoc
!= NULL
&& *TempLoc
!= CHAR_NULL
; TempLoc
++) {
97 if (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'\"') {
98 CopyMem(TempLoc
, TempLoc
+1, StrSize(TempLoc
) - sizeof(TempLoc
[0]));
103 // we have a regular parameter (no quote) OR
104 // we have the final parameter (no trailing space)
106 NextDelim
= StrStr((*Walker
), L
" ");
107 if (NextDelim
!= NULL
) {
108 StrnCpy(*TempParameter
, *Walker
, NextDelim
- (*Walker
));
109 (*TempParameter
)[NextDelim
- (*Walker
)] = CHAR_NULL
;
110 *Walker
= NextDelim
+1;
115 StrCpy(*TempParameter
, *Walker
);
118 for (NextDelim
= *TempParameter
; NextDelim
!= NULL
&& *NextDelim
!= CHAR_NULL
; NextDelim
++) {
119 if (*NextDelim
== L
'^' && *(NextDelim
+1) == L
'^') {
120 CopyMem(NextDelim
, NextDelim
+1, StrSize(NextDelim
) - sizeof(NextDelim
[0]));
123 while ((*TempParameter
)[StrLen(*TempParameter
)-1] == L
' ') {
124 (*TempParameter
)[StrLen(*TempParameter
)-1] = CHAR_NULL
;
126 while ((*TempParameter
)[0] == L
' ') {
127 CopyMem(*TempParameter
, (*TempParameter
)+1, StrSize(*TempParameter
) - sizeof((*TempParameter
)[0]));
134 Function to populate Argc and Argv.
136 This function parses the CommandLine and divides it into standard C style Argc/Argv
137 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
138 delimited and quote surrounded parameter definition.
140 @param[in] CommandLine String of command line to parse
141 @param[in, out] Argv pointer to array of strings; one for each parameter
142 @param[in, out] Argc pointer to number of strings in Argv array
144 @return EFI_SUCCESS the operation was sucessful
145 @return EFI_OUT_OF_RESOURCES a memory allocation failed.
149 ParseCommandLineToArgs(
150 IN CONST CHAR16
*CommandLine
,
151 IN OUT CHAR16
***Argv
,
156 CHAR16
*TempParameter
;
161 ASSERT(Argc
!= NULL
);
162 ASSERT(Argv
!= NULL
);
164 if (CommandLine
== NULL
|| StrLen(CommandLine
)==0) {
167 return (EFI_SUCCESS
);
170 Size
= StrSize(CommandLine
);
171 TempParameter
= AllocateZeroPool(Size
);
172 if (TempParameter
== NULL
) {
173 return (EFI_OUT_OF_RESOURCES
);
177 , Walker
= (CHAR16
*)CommandLine
178 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
179 ; GetNextParameter(&Walker
, &TempParameter
)
184 Walker = (CHAR16*)CommandLine;
185 while(Walker != NULL) {
186 GetNextParameter(&Walker, &TempParameter);
191 // lets allocate the pointer array
193 (*Argv
) = AllocateZeroPool((Count
)*sizeof(CHAR16
*));
195 return (EFI_OUT_OF_RESOURCES
);
199 Walker
= (CHAR16
*)CommandLine
;
200 while(Walker
!= NULL
&& *Walker
!= CHAR_NULL
) {
201 SetMem16(TempParameter
, Size
, CHAR_NULL
);
202 GetNextParameter(&Walker
, &TempParameter
);
203 NewParam
= AllocateZeroPool(StrSize(TempParameter
));
204 ASSERT(NewParam
!= NULL
);
205 StrCpy(NewParam
, TempParameter
);
206 ((CHAR16
**)(*Argv
))[(*Argc
)] = NewParam
;
209 ASSERT(Count
>= (*Argc
));
210 return (EFI_SUCCESS
);
214 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
215 installs it on our handle and if there is an existing version of the protocol
216 that one is cached for removal later.
218 @param[in, out] NewShellParameters on a successful return, a pointer to pointer
219 to the newly installed interface.
220 @param[in, out] RootShellInstance on a successful return, pointer to boolean.
221 TRUE if this is the root shell instance.
223 @retval EFI_SUCCESS the operation completed successfully.
224 @return other the operation failed.
225 @sa ReinstallProtocolInterface
226 @sa InstallProtocolInterface
227 @sa ParseCommandLineToArgs
231 CreatePopulateInstallShellParametersProtocol (
232 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
**NewShellParameters
,
233 IN OUT BOOLEAN
*RootShellInstance
237 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
238 CHAR16
*FullCommandLine
;
242 FullCommandLine
= NULL
;
246 // Assert for valid parameters
248 ASSERT(NewShellParameters
!= NULL
);
249 ASSERT(RootShellInstance
!= NULL
);
252 // See if we have a shell parameters placed on us
254 Status
= gBS
->OpenProtocol (
256 &gEfiShellParametersProtocolGuid
,
257 (VOID
**) &ShellInfoObject
.OldShellParameters
,
260 EFI_OPEN_PROTOCOL_GET_PROTOCOL
263 // if we don't then we must be the root shell (error is expected)
265 if (EFI_ERROR (Status
)) {
266 *RootShellInstance
= TRUE
;
270 // Allocate the new structure
272 *NewShellParameters
= AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL
));
273 if ((*NewShellParameters
) == NULL
) {
274 return (EFI_OUT_OF_RESOURCES
);
278 // get loaded image protocol
280 Status
= gBS
->OpenProtocol (
282 &gEfiLoadedImageProtocolGuid
,
283 (VOID
**) &LoadedImage
,
286 EFI_OPEN_PROTOCOL_GET_PROTOCOL
288 ASSERT_EFI_ERROR(Status
);
290 // Build the full command line
292 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
293 if (Status
== EFI_BUFFER_TOO_SMALL
) {
294 FullCommandLine
= AllocateZeroPool(Size
+ LoadedImage
->LoadOptionsSize
);
295 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
297 if (Status
== EFI_NOT_FOUND
) {
299 // no parameters via environment... ok
302 if (EFI_ERROR(Status
)) {
306 if (Size
== 0 && LoadedImage
->LoadOptionsSize
!= 0) {
307 ASSERT(FullCommandLine
== NULL
);
309 // Now we need to include a NULL terminator in the size.
311 Size
= LoadedImage
->LoadOptionsSize
+ sizeof(FullCommandLine
[0]);
312 FullCommandLine
= AllocateZeroPool(Size
);
314 if (FullCommandLine
!= NULL
) {
315 if (LoadedImage
->LoadOptionsSize
!= 0){
316 StrCpy(FullCommandLine
, LoadedImage
->LoadOptions
);
319 // Populate Argc and Argv
321 Status
= ParseCommandLineToArgs(FullCommandLine
,
322 &(*NewShellParameters
)->Argv
,
323 &(*NewShellParameters
)->Argc
);
325 FreePool(FullCommandLine
);
327 ASSERT_EFI_ERROR(Status
);
329 (*NewShellParameters
)->Argv
= NULL
;
330 (*NewShellParameters
)->Argc
= 0;
334 // Populate the 3 faked file systems...
336 if (*RootShellInstance
) {
337 (*NewShellParameters
)->StdIn
= &FileInterfaceStdIn
;
338 (*NewShellParameters
)->StdOut
= &FileInterfaceStdOut
;
339 (*NewShellParameters
)->StdErr
= &FileInterfaceStdErr
;
340 Status
= gBS
->InstallProtocolInterface(&gImageHandle
,
341 &gEfiShellParametersProtocolGuid
,
342 EFI_NATIVE_INTERFACE
,
343 (VOID
*)(*NewShellParameters
));
346 // copy from the existing ones
348 (*NewShellParameters
)->StdIn
= ShellInfoObject
.OldShellParameters
->StdIn
;
349 (*NewShellParameters
)->StdOut
= ShellInfoObject
.OldShellParameters
->StdOut
;
350 (*NewShellParameters
)->StdErr
= ShellInfoObject
.OldShellParameters
->StdErr
;
351 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
352 &gEfiShellParametersProtocolGuid
,
353 (VOID
*)ShellInfoObject
.OldShellParameters
,
354 (VOID
*)(*NewShellParameters
));
361 frees all memory used by createion and installation of shell parameters protocol
362 and if there was an old version installed it will restore that one.
364 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
367 @retval EFI_SUCCESS the cleanup was successful
368 @return other the cleanup failed
369 @sa ReinstallProtocolInterface
370 @sa UninstallProtocolInterface
374 CleanUpShellParametersProtocol (
375 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*NewShellParameters
382 // If the old exists we need to restore it
384 if (ShellInfoObject
.OldShellParameters
!= NULL
) {
385 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
386 &gEfiShellParametersProtocolGuid
,
387 (VOID
*)NewShellParameters
,
388 (VOID
*)ShellInfoObject
.OldShellParameters
);
389 DEBUG_CODE(ShellInfoObject
.OldShellParameters
= NULL
;);
392 // No old one, just uninstall us...
394 Status
= gBS
->UninstallProtocolInterface(gImageHandle
,
395 &gEfiShellParametersProtocolGuid
,
396 (VOID
*)NewShellParameters
);
398 if (NewShellParameters
->Argv
!= NULL
) {
399 for ( LoopCounter
= 0
400 ; LoopCounter
< NewShellParameters
->Argc
403 FreePool(NewShellParameters
->Argv
[LoopCounter
]);
405 FreePool(NewShellParameters
->Argv
);
407 FreePool(NewShellParameters
);
412 Determin if a file name represents a unicode file.
414 @param[in] FileName Pointer to the filename to open.
416 @retval EFI_SUCCESS The file is a unicode file.
417 @return An error upon failure.
422 IN CONST CHAR16
*FileName
425 SHELL_FILE_HANDLE Handle
;
427 UINT64 OriginalFilePosition
;
431 Status
= gEfiShellProtocol
->OpenFileByName(FileName
, &Handle
, EFI_FILE_MODE_READ
);
432 if (EFI_ERROR(Status
)) {
435 gEfiShellProtocol
->GetFilePosition(Handle
, &OriginalFilePosition
);
436 gEfiShellProtocol
->SetFilePosition(Handle
, 0);
437 CharSize
= sizeof(CHAR16
);
438 Status
= gEfiShellProtocol
->ReadFile(Handle
, &CharSize
, &CharBuffer
);
439 if (EFI_ERROR(Status
) || CharBuffer
!= gUnicodeFileTag
) {
440 Status
= EFI_BUFFER_TOO_SMALL
;
442 gEfiShellProtocol
->SetFilePosition(Handle
, OriginalFilePosition
);
443 gEfiShellProtocol
->CloseFile(Handle
);
448 Strips out quotes sections of a string.
450 All of the characters between quotes is replaced with spaces.
452 @param[in, out] TheString A pointer to the string to update.
457 IN OUT CHAR16
*TheString
462 for (RemoveNow
= FALSE
; TheString
!= NULL
&& *TheString
!= CHAR_NULL
; TheString
++) {
463 if (*TheString
== L
'^' && *(TheString
+ 1) == L
'\"') {
465 } else if (*TheString
== L
'\"') {
466 RemoveNow
= (BOOLEAN
)!RemoveNow
;
467 } else if (RemoveNow
) {
474 Calcualte the 32-bit CRC in a EFI table using the service provided by the
477 @param Hdr Pointer to an EFI standard header
482 IN OUT EFI_TABLE_HEADER
*Hdr
490 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
491 // Crc will come back as zero if we set it to zero here
494 gBS
->CalculateCrc32 ((UINT8
*)Hdr
, Hdr
->HeaderSize
, &Crc
);
499 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.
501 @param[in] FileName The filename to start with.
503 @retval NULL FileName was invalid.
504 @return The modified FileName.
513 CHAR16
*TempLocation
;
515 if (FileName
== NULL
) {
519 if (FileName
[0] == L
'\"') {
521 if ((TempLocation
= StrStr(Copy
, L
"\"")) != NULL
) {
522 TempLocation
[0] = CHAR_NULL
;
526 while(Copy
[0] == L
' ') {
529 if ((TempLocation
= StrStr(Copy
, L
" ")) != NULL
) {
530 TempLocation
[0] = CHAR_NULL
;
534 if (Copy
[0] == CHAR_NULL
) {
542 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
543 structure by parsing NewCommandLine. The current values are returned to the
546 This will also update the system table.
548 @param[in, out] ShellParameters Pointer to parameter structure to modify.
549 @param[in] NewCommandLine The new command line to parse and use.
550 @param[out] OldStdIn Pointer to old StdIn.
551 @param[out] OldStdOut Pointer to old StdOut.
552 @param[out] OldStdErr Pointer to old StdErr.
553 @param[out] SystemTableInfo Pointer to old system table information.
555 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
556 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
560 UpdateStdInStdOutStdErr(
561 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
562 IN CHAR16
*NewCommandLine
,
563 OUT SHELL_FILE_HANDLE
*OldStdIn
,
564 OUT SHELL_FILE_HANDLE
*OldStdOut
,
565 OUT SHELL_FILE_HANDLE
*OldStdErr
,
566 OUT SYSTEM_TABLE_INFO
*SystemTableInfo
569 CHAR16
*CommandLineCopy
;
570 CHAR16
*CommandLineWalker
;
571 CHAR16
*StdErrFileName
;
572 CHAR16
*StdOutFileName
;
573 CHAR16
*StdInFileName
;
574 CHAR16
*StdInVarName
;
575 CHAR16
*StdOutVarName
;
576 CHAR16
*StdErrVarName
;
578 SHELL_FILE_HANDLE TempHandle
;
588 CHAR16
*FirstLocation
;
594 StdOutVarName
= NULL
;
595 StdErrVarName
= NULL
;
596 StdErrFileName
= NULL
;
597 StdInFileName
= NULL
;
598 StdOutFileName
= NULL
;
601 CommandLineCopy
= NULL
;
602 FirstLocation
= NULL
;
604 if (ShellParameters
== NULL
|| SystemTableInfo
== NULL
|| OldStdIn
== NULL
|| OldStdOut
== NULL
|| OldStdErr
== NULL
) {
605 return (EFI_INVALID_PARAMETER
);
608 SystemTableInfo
->ConIn
= gST
->ConIn
;
609 SystemTableInfo
->ConInHandle
= gST
->ConsoleInHandle
;
610 SystemTableInfo
->ConOut
= gST
->ConOut
;
611 SystemTableInfo
->ConOutHandle
= gST
->ConsoleOutHandle
;
612 SystemTableInfo
->ErrOut
= gST
->StdErr
;
613 SystemTableInfo
->ErrOutHandle
= gST
->StandardErrorHandle
;
614 *OldStdIn
= ShellParameters
->StdIn
;
615 *OldStdOut
= ShellParameters
->StdOut
;
616 *OldStdErr
= ShellParameters
->StdErr
;
618 if (NewCommandLine
== NULL
) {
619 return (EFI_SUCCESS
);
622 CommandLineCopy
= StrnCatGrow(&CommandLineCopy
, NULL
, NewCommandLine
, 0);
623 if (CommandLineCopy
== NULL
) {
624 return (EFI_OUT_OF_RESOURCES
);
626 Status
= EFI_SUCCESS
;
628 FirstLocation
= CommandLineCopy
+ StrLen(CommandLineCopy
);
630 StripQuotes(CommandLineCopy
);
632 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
633 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
634 if (Split
!= NULL
&& Split
->SplitStdIn
!= NULL
) {
635 ShellParameters
->StdIn
= Split
->SplitStdIn
;
637 if (Split
!= NULL
&& Split
->SplitStdOut
!= NULL
) {
638 ShellParameters
->StdOut
= Split
->SplitStdOut
;
642 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>>v ")) != NULL
) {
643 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
644 SetMem16(CommandLineWalker
, 12, L
' ');
645 StdErrVarName
= CommandLineWalker
+= 6;
647 if (StrStr(CommandLineWalker
, L
" 2>>v ") != NULL
) {
648 Status
= EFI_NOT_FOUND
;
651 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>v ")) != NULL
) {
652 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
653 SetMem16(CommandLineWalker
, 12, L
' ');
654 StdOutVarName
= CommandLineWalker
+= 6;
656 if (StrStr(CommandLineWalker
, L
" 1>>v ") != NULL
) {
657 Status
= EFI_NOT_FOUND
;
659 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>v ")) != NULL
) {
660 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
661 SetMem16(CommandLineWalker
, 10, L
' ');
662 StdOutVarName
= CommandLineWalker
+= 5;
664 if (StrStr(CommandLineWalker
, L
" >>v ") != NULL
) {
665 Status
= EFI_NOT_FOUND
;
667 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >v ")) != NULL
) {
668 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
669 SetMem16(CommandLineWalker
, 8, L
' ');
670 StdOutVarName
= CommandLineWalker
+= 4;
672 if (StrStr(CommandLineWalker
, L
" >v ") != NULL
) {
673 Status
= EFI_NOT_FOUND
;
676 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>a ")) != NULL
) {
677 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
678 SetMem16(CommandLineWalker
, 12, L
' ');
679 StdOutFileName
= CommandLineWalker
+= 6;
682 if (StrStr(CommandLineWalker
, L
" 1>>a ") != NULL
) {
683 Status
= EFI_NOT_FOUND
;
686 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>> ")) != NULL
) {
687 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
688 SetMem16(CommandLineWalker
, 10, L
' ');
689 if (StdOutFileName
!= NULL
) {
690 Status
= EFI_INVALID_PARAMETER
;
692 StdOutFileName
= CommandLineWalker
+= 5;
695 if (StrStr(CommandLineWalker
, L
" 1>> ") != NULL
) {
696 Status
= EFI_NOT_FOUND
;
699 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >> ")) != NULL
) {
700 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
701 SetMem16(CommandLineWalker
, 8, L
' ');
702 if (StdOutFileName
!= NULL
) {
703 Status
= EFI_INVALID_PARAMETER
;
705 StdOutFileName
= CommandLineWalker
+= 4;
708 if (StrStr(CommandLineWalker
, L
" >> ") != NULL
) {
709 Status
= EFI_NOT_FOUND
;
712 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>a ")) != NULL
) {
713 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
714 SetMem16(CommandLineWalker
, 10, L
' ');
715 if (StdOutFileName
!= NULL
) {
716 Status
= EFI_INVALID_PARAMETER
;
718 StdOutFileName
= CommandLineWalker
+= 5;
722 if (StrStr(CommandLineWalker
, L
" >>a ") != NULL
) {
723 Status
= EFI_NOT_FOUND
;
726 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>a ")) != NULL
) {
727 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
728 SetMem16(CommandLineWalker
, 10, L
' ');
729 if (StdOutFileName
!= NULL
) {
730 Status
= EFI_INVALID_PARAMETER
;
732 StdOutFileName
= CommandLineWalker
+= 5;
736 if (StrStr(CommandLineWalker
, L
" 1>a ") != NULL
) {
737 Status
= EFI_NOT_FOUND
;
740 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >a ")) != NULL
) {
741 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
742 SetMem16(CommandLineWalker
, 8, L
' ');
743 if (StdOutFileName
!= NULL
) {
744 Status
= EFI_INVALID_PARAMETER
;
746 StdOutFileName
= CommandLineWalker
+= 4;
750 if (StrStr(CommandLineWalker
, L
" >a ") != NULL
) {
751 Status
= EFI_NOT_FOUND
;
754 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>> ")) != NULL
) {
755 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
756 SetMem16(CommandLineWalker
, 10, L
' ');
757 if (StdErrFileName
!= NULL
) {
758 Status
= EFI_INVALID_PARAMETER
;
760 StdErrFileName
= CommandLineWalker
+= 5;
763 if (StrStr(CommandLineWalker
, L
" 2>> ") != NULL
) {
764 Status
= EFI_NOT_FOUND
;
768 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>v ")) != NULL
) {
769 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
770 SetMem16(CommandLineWalker
, 10, L
' ');
771 if (StdErrVarName
!= NULL
) {
772 Status
= EFI_INVALID_PARAMETER
;
774 StdErrVarName
= CommandLineWalker
+= 5;
777 if (StrStr(CommandLineWalker
, L
" 2>v ") != NULL
) {
778 Status
= EFI_NOT_FOUND
;
781 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>v ")) != NULL
) {
782 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
783 SetMem16(CommandLineWalker
, 10, L
' ');
784 if (StdOutVarName
!= NULL
) {
785 Status
= EFI_INVALID_PARAMETER
;
787 StdOutVarName
= CommandLineWalker
+= 5;
790 if (StrStr(CommandLineWalker
, L
" 1>v ") != NULL
) {
791 Status
= EFI_NOT_FOUND
;
794 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>a ")) != NULL
) {
795 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
796 SetMem16(CommandLineWalker
, 10, L
' ');
797 if (StdErrFileName
!= NULL
) {
798 Status
= EFI_INVALID_PARAMETER
;
800 StdErrFileName
= CommandLineWalker
+= 5;
804 if (StrStr(CommandLineWalker
, L
" 2>a ") != NULL
) {
805 Status
= EFI_NOT_FOUND
;
808 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2> ")) != NULL
) {
809 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
810 SetMem16(CommandLineWalker
, 8, L
' ');
811 if (StdErrFileName
!= NULL
) {
812 Status
= EFI_INVALID_PARAMETER
;
814 StdErrFileName
= CommandLineWalker
+= 4;
817 if (StrStr(CommandLineWalker
, L
" 2> ") != NULL
) {
818 Status
= EFI_NOT_FOUND
;
822 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1> ")) != NULL
) {
823 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
824 SetMem16(CommandLineWalker
, 8, L
' ');
825 if (StdOutFileName
!= NULL
) {
826 Status
= EFI_INVALID_PARAMETER
;
828 StdOutFileName
= CommandLineWalker
+= 4;
831 if (StrStr(CommandLineWalker
, L
" 1> ") != NULL
) {
832 Status
= EFI_NOT_FOUND
;
836 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" > ")) != NULL
) {
837 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
838 SetMem16(CommandLineWalker
, 6, L
' ');
839 if (StdOutFileName
!= NULL
) {
840 Status
= EFI_INVALID_PARAMETER
;
842 StdOutFileName
= CommandLineWalker
+= 3;
845 if (StrStr(CommandLineWalker
, L
" > ") != NULL
) {
846 Status
= EFI_NOT_FOUND
;
850 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" < ")) != NULL
) {
851 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
852 SetMem16(CommandLineWalker
, 6, L
' ');
853 if (StdInFileName
!= NULL
) {
854 Status
= EFI_INVALID_PARAMETER
;
856 StdInFileName
= CommandLineWalker
+= 3;
858 if (StrStr(CommandLineWalker
, L
" < ") != NULL
) {
859 Status
= EFI_NOT_FOUND
;
862 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <a ")) != NULL
) {
863 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
864 SetMem16(CommandLineWalker
, 8, L
' ');
865 if (StdInFileName
!= NULL
) {
866 Status
= EFI_INVALID_PARAMETER
;
868 StdInFileName
= CommandLineWalker
+= 4;
871 if (StrStr(CommandLineWalker
, L
" <a ") != NULL
) {
872 Status
= EFI_NOT_FOUND
;
875 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <v ")) != NULL
) {
876 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
877 SetMem16(CommandLineWalker
, 8, L
' ');
878 if (StdInVarName
!= NULL
) {
879 Status
= EFI_INVALID_PARAMETER
;
881 StdInVarName
= CommandLineWalker
+= 4;
883 if (StrStr(CommandLineWalker
, L
" <v ") != NULL
) {
884 Status
= EFI_NOT_FOUND
;
889 // re-populate the string to support any filenames that were in quotes.
891 StrCpy(CommandLineCopy
, NewCommandLine
);
893 if (FirstLocation
!= CommandLineCopy
+ StrLen(CommandLineCopy
)
894 && ((UINTN
)(FirstLocation
- CommandLineCopy
) < StrLen(NewCommandLine
))
896 *(NewCommandLine
+ (UINTN
)(FirstLocation
- CommandLineCopy
)) = CHAR_NULL
;
899 if (!EFI_ERROR(Status
)) {
901 if (StdErrFileName
!= NULL
) {
902 if ((StdErrFileName
= FixFileName(StdErrFileName
)) == NULL
) {
903 Status
= EFI_INVALID_PARAMETER
;
906 if (StdOutFileName
!= NULL
) {
907 if ((StdOutFileName
= FixFileName(StdOutFileName
)) == NULL
) {
908 Status
= EFI_INVALID_PARAMETER
;
911 if (StdInFileName
!= NULL
) {
912 if ((StdInFileName
= FixFileName(StdInFileName
)) == NULL
) {
913 Status
= EFI_INVALID_PARAMETER
;
916 if (StdErrVarName
!= NULL
) {
917 if ((StdErrVarName
= FixFileName(StdErrVarName
)) == NULL
) {
918 Status
= EFI_INVALID_PARAMETER
;
921 if (StdOutVarName
!= NULL
) {
922 if ((StdOutVarName
= FixFileName(StdOutVarName
)) == NULL
) {
923 Status
= EFI_INVALID_PARAMETER
;
926 if (StdInVarName
!= NULL
) {
927 if ((StdInVarName
= FixFileName(StdInVarName
)) == NULL
) {
928 Status
= EFI_INVALID_PARAMETER
;
933 // Verify not the same and not duplicating something from a split
937 // Check that no 2 filenames are the same
939 (StdErrFileName
!= NULL
&& StdOutFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdOutFileName
) == 0)
940 ||(StdErrFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdInFileName
) == 0)
941 ||(StdOutFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdOutFileName
, &StdInFileName
) == 0)
943 // Check that no 2 variable names are the same
945 ||(StdErrVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdInVarName
) == 0)
946 ||(StdOutVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdOutVarName
, &StdInVarName
) == 0)
947 ||(StdErrVarName
!= NULL
&& StdOutVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdOutVarName
) == 0)
949 // When a split (using | operator) is in place some are not allowed
951 ||(Split
!= NULL
&& Split
->SplitStdIn
!= NULL
&& (StdInVarName
!= NULL
|| StdInFileName
!= NULL
))
952 ||(Split
!= NULL
&& Split
->SplitStdOut
!= NULL
&& (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
))
954 // Check that nothing is trying to be output to 2 locations.
956 ||(StdErrFileName
!= NULL
&& StdErrVarName
!= NULL
)
957 ||(StdOutFileName
!= NULL
&& StdOutVarName
!= NULL
)
958 ||(StdInFileName
!= NULL
&& StdInVarName
!= NULL
)
960 // Check for no volatile environment variables
962 ||(StdErrVarName
!= NULL
&& !IsVolatileEnv(StdErrVarName
))
963 ||(StdOutVarName
!= NULL
&& !IsVolatileEnv(StdOutVarName
))
965 // Cant redirect during a reconnect operation.
967 ||(StrStr(NewCommandLine
, L
"connect -r") != NULL
968 && (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
|| StdErrFileName
!= NULL
|| StdErrVarName
!= NULL
))
970 // Check that filetypes (Unicode/Ascii) do not change during an append
972 ||(StdOutFileName
!= NULL
&& OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
973 ||(StdErrFileName
!= NULL
&& ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
974 ||(StdOutFileName
!= NULL
&& !OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
975 ||(StdErrFileName
!= NULL
&& !ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
977 Status
= EFI_INVALID_PARAMETER
;
978 ShellParameters
->StdIn
= *OldStdIn
;
979 ShellParameters
->StdOut
= *OldStdOut
;
980 ShellParameters
->StdErr
= *OldStdErr
;
981 } else if (!EFI_ERROR(Status
)){
983 // Open the Std<Whatever> and we should not have conflicts here...
989 if (StdErrFileName
!= NULL
) {
992 // delete existing file.
994 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdErrFileName
);
996 Status
= ShellOpenFileByName(StdErrFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
997 if (!ErrAppend
&& ErrUnicode
&& !EFI_ERROR(Status
)) {
999 // Write out the gUnicodeFileTag
1001 Size
= sizeof(CHAR16
);
1002 TagBuffer
[0] = gUnicodeFileTag
;
1003 TagBuffer
[1] = CHAR_NULL
;
1004 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1006 if (!ErrUnicode
&& !EFI_ERROR(Status
)) {
1007 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1008 ASSERT(TempHandle
!= NULL
);
1010 if (!EFI_ERROR(Status
)) {
1011 ShellParameters
->StdErr
= TempHandle
;
1012 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1019 if (!EFI_ERROR(Status
) && StdOutFileName
!= NULL
) {
1022 // delete existing file.
1024 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdOutFileName
);
1026 Status
= ShellOpenFileByName(StdOutFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
1027 if (TempHandle
== NULL
) {
1028 Status
= EFI_INVALID_PARAMETER
;
1030 if (StrStr(StdOutFileName
, L
"NUL")==StdOutFileName
) {
1032 } else if (!OutAppend
&& OutUnicode
&& !EFI_ERROR(Status
)) {
1034 // Write out the gUnicodeFileTag
1036 Size
= sizeof(CHAR16
);
1037 TagBuffer
[0] = gUnicodeFileTag
;
1038 TagBuffer
[1] = CHAR_NULL
;
1039 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1040 } else if (OutAppend
) {
1042 // Move to end of file
1044 Status
= ShellInfoObject
.NewEfiShellProtocol
->GetFileSize(TempHandle
, &FileSize
);
1045 if (!EFI_ERROR(Status
)) {
1046 Status
= ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition(TempHandle
, FileSize
);
1049 if (!OutUnicode
&& !EFI_ERROR(Status
)) {
1050 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1051 ASSERT(TempHandle
!= NULL
);
1053 if (!EFI_ERROR(Status
)) {
1054 ShellParameters
->StdOut
= TempHandle
;
1055 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1063 if (!EFI_ERROR(Status
) && StdOutVarName
!= NULL
) {
1066 // delete existing variable.
1068 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName
, 0, L
"");
1070 TempHandle
= CreateFileInterfaceEnv(StdOutVarName
);
1071 ASSERT(TempHandle
!= NULL
);
1072 ShellParameters
->StdOut
= TempHandle
;
1073 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1079 if (!EFI_ERROR(Status
) && StdErrVarName
!= NULL
) {
1082 // delete existing variable.
1084 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName
, 0, L
"");
1086 TempHandle
= CreateFileInterfaceEnv(StdErrVarName
);
1087 ASSERT(TempHandle
!= NULL
);
1088 ShellParameters
->StdErr
= TempHandle
;
1089 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1095 if (!EFI_ERROR(Status
) && StdInVarName
!= NULL
) {
1096 TempHandle
= CreateFileInterfaceEnv(StdInVarName
);
1097 if (TempHandle
== NULL
) {
1098 Status
= EFI_OUT_OF_RESOURCES
;
1101 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1104 if (TempHandle
== NULL
|| ((EFI_FILE_PROTOCOL
*)TempHandle
)->Read(TempHandle
, &Size
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
1105 Status
= EFI_INVALID_PARAMETER
;
1107 ShellParameters
->StdIn
= TempHandle
;
1108 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1114 // StdIn from a file
1116 if (!EFI_ERROR(Status
) && StdInFileName
!= NULL
) {
1117 Status
= ShellOpenFileByName(
1122 if (!InUnicode
&& !EFI_ERROR(Status
)) {
1123 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1125 if (!EFI_ERROR(Status
)) {
1126 ShellParameters
->StdIn
= TempHandle
;
1127 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1132 FreePool(CommandLineCopy
);
1134 CalculateEfiHdrCrc(&gST
->Hdr
);
1136 if (gST
->ConIn
== NULL
||gST
->ConOut
== NULL
) {
1137 return (EFI_OUT_OF_RESOURCES
);
1143 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1144 structure with StdIn and StdOut. The current values are de-allocated.
1146 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1147 @param[in] OldStdIn Pointer to old StdIn.
1148 @param[in] OldStdOut Pointer to old StdOut.
1149 @param[in] OldStdErr Pointer to old StdErr.
1150 @param[in] SystemTableInfo Pointer to old system table information.
1154 RestoreStdInStdOutStdErr (
1155 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1156 IN SHELL_FILE_HANDLE
*OldStdIn
,
1157 IN SHELL_FILE_HANDLE
*OldStdOut
,
1158 IN SHELL_FILE_HANDLE
*OldStdErr
,
1159 IN SYSTEM_TABLE_INFO
*SystemTableInfo
1164 if (ShellParameters
== NULL
1168 ||SystemTableInfo
== NULL
) {
1169 return (EFI_INVALID_PARAMETER
);
1171 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1172 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1176 if (ShellParameters
->StdIn
!= *OldStdIn
) {
1177 if ((Split
!= NULL
&& Split
->SplitStdIn
!= ShellParameters
->StdIn
) || Split
== NULL
) {
1178 gEfiShellProtocol
->CloseFile(ShellParameters
->StdIn
);
1180 ShellParameters
->StdIn
= *OldStdIn
;
1182 if (ShellParameters
->StdOut
!= *OldStdOut
) {
1183 if ((Split
!= NULL
&& Split
->SplitStdOut
!= ShellParameters
->StdOut
) || Split
== NULL
) {
1184 gEfiShellProtocol
->CloseFile(ShellParameters
->StdOut
);
1186 ShellParameters
->StdOut
= *OldStdOut
;
1188 if (ShellParameters
->StdErr
!= *OldStdErr
) {
1189 gEfiShellProtocol
->CloseFile(ShellParameters
->StdErr
);
1190 ShellParameters
->StdErr
= *OldStdErr
;
1193 if (gST
->ConIn
!= SystemTableInfo
->ConIn
) {
1194 CloseSimpleTextInOnFile(gST
->ConIn
);
1195 gST
->ConIn
= SystemTableInfo
->ConIn
;
1196 gST
->ConsoleInHandle
= SystemTableInfo
->ConInHandle
;
1198 if (gST
->ConOut
!= SystemTableInfo
->ConOut
) {
1199 CloseSimpleTextOutOnFile(gST
->ConOut
);
1200 gST
->ConOut
= SystemTableInfo
->ConOut
;
1201 gST
->ConsoleOutHandle
= SystemTableInfo
->ConOutHandle
;
1203 if (gST
->StdErr
!= SystemTableInfo
->ErrOut
) {
1204 CloseSimpleTextOutOnFile(gST
->StdErr
);
1205 gST
->StdErr
= SystemTableInfo
->ErrOut
;
1206 gST
->StandardErrorHandle
= SystemTableInfo
->ErrOutHandle
;
1209 CalculateEfiHdrCrc(&gST
->Hdr
);
1211 return (EFI_SUCCESS
);
1214 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1215 structure by parsing NewCommandLine. The current values are returned to the
1218 If OldArgv or OldArgc is NULL then that value is not returned.
1220 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1221 @param[in] NewCommandLine The new command line to parse and use.
1222 @param[out] OldArgv Pointer to old list of parameters.
1223 @param[out] OldArgc Pointer to old number of items in Argv list.
1225 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
1226 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1231 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1232 IN CONST CHAR16
*NewCommandLine
,
1233 OUT CHAR16
***OldArgv OPTIONAL
,
1234 OUT UINTN
*OldArgc OPTIONAL
1237 ASSERT(ShellParameters
!= NULL
);
1239 if (OldArgc
!= NULL
) {
1240 *OldArgc
= ShellParameters
->Argc
;
1242 if (OldArgc
!= NULL
) {
1243 *OldArgv
= ShellParameters
->Argv
;
1246 return (ParseCommandLineToArgs(NewCommandLine
, &(ShellParameters
->Argv
), &(ShellParameters
->Argc
)));
1250 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1251 structure with Argv and Argc. The current values are de-allocated and the
1252 OldArgv must not be deallocated by the caller.
1254 @param[in, out] ShellParameters pointer to parameter structure to modify
1255 @param[in] OldArgv pointer to old list of parameters
1256 @param[in] OldArgc pointer to old number of items in Argv list
1261 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1262 IN CHAR16
***OldArgv
,
1267 ASSERT(ShellParameters
!= NULL
);
1268 ASSERT(OldArgv
!= NULL
);
1269 ASSERT(OldArgc
!= NULL
);
1271 if (ShellParameters
->Argv
!= NULL
) {
1272 for ( LoopCounter
= 0
1273 ; LoopCounter
< ShellParameters
->Argc
1276 FreePool(ShellParameters
->Argv
[LoopCounter
]);
1278 FreePool(ShellParameters
->Argv
);
1280 ShellParameters
->Argv
= *OldArgv
;
1282 ShellParameters
->Argc
= *OldArgc
;