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 SHELL_FREE_NON_NULL(TempParameter
);
196 return (EFI_OUT_OF_RESOURCES
);
200 Walker
= (CHAR16
*)CommandLine
;
201 while(Walker
!= NULL
&& *Walker
!= CHAR_NULL
) {
202 SetMem16(TempParameter
, Size
, CHAR_NULL
);
203 GetNextParameter(&Walker
, &TempParameter
);
204 NewParam
= AllocateZeroPool(StrSize(TempParameter
));
205 ASSERT(NewParam
!= NULL
);
206 StrCpy(NewParam
, TempParameter
);
207 ((CHAR16
**)(*Argv
))[(*Argc
)] = NewParam
;
210 ASSERT(Count
>= (*Argc
));
211 SHELL_FREE_NON_NULL(TempParameter
);
212 return (EFI_SUCCESS
);
216 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
217 installs it on our handle and if there is an existing version of the protocol
218 that one is cached for removal later.
220 @param[in, out] NewShellParameters on a successful return, a pointer to pointer
221 to the newly installed interface.
222 @param[in, out] RootShellInstance on a successful return, pointer to boolean.
223 TRUE if this is the root shell instance.
225 @retval EFI_SUCCESS the operation completed successfully.
226 @return other the operation failed.
227 @sa ReinstallProtocolInterface
228 @sa InstallProtocolInterface
229 @sa ParseCommandLineToArgs
233 CreatePopulateInstallShellParametersProtocol (
234 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
**NewShellParameters
,
235 IN OUT BOOLEAN
*RootShellInstance
239 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
240 CHAR16
*FullCommandLine
;
244 FullCommandLine
= NULL
;
248 // Assert for valid parameters
250 ASSERT(NewShellParameters
!= NULL
);
251 ASSERT(RootShellInstance
!= NULL
);
254 // See if we have a shell parameters placed on us
256 Status
= gBS
->OpenProtocol (
258 &gEfiShellParametersProtocolGuid
,
259 (VOID
**) &ShellInfoObject
.OldShellParameters
,
262 EFI_OPEN_PROTOCOL_GET_PROTOCOL
265 // if we don't then we must be the root shell (error is expected)
267 if (EFI_ERROR (Status
)) {
268 *RootShellInstance
= TRUE
;
272 // Allocate the new structure
274 *NewShellParameters
= AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL
));
275 if ((*NewShellParameters
) == NULL
) {
276 return (EFI_OUT_OF_RESOURCES
);
280 // get loaded image protocol
282 Status
= gBS
->OpenProtocol (
284 &gEfiLoadedImageProtocolGuid
,
285 (VOID
**) &LoadedImage
,
288 EFI_OPEN_PROTOCOL_GET_PROTOCOL
290 ASSERT_EFI_ERROR(Status
);
292 // Build the full command line
294 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
295 if (Status
== EFI_BUFFER_TOO_SMALL
) {
296 FullCommandLine
= AllocateZeroPool(Size
+ LoadedImage
->LoadOptionsSize
);
297 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
299 if (Status
== EFI_NOT_FOUND
) {
301 // no parameters via environment... ok
304 if (EFI_ERROR(Status
)) {
308 if (Size
== 0 && LoadedImage
->LoadOptionsSize
!= 0) {
309 ASSERT(FullCommandLine
== NULL
);
311 // Now we need to include a NULL terminator in the size.
313 Size
= LoadedImage
->LoadOptionsSize
+ sizeof(FullCommandLine
[0]);
314 FullCommandLine
= AllocateZeroPool(Size
);
316 if (FullCommandLine
!= NULL
) {
317 if (LoadedImage
->LoadOptionsSize
!= 0){
318 StrCpy(FullCommandLine
, LoadedImage
->LoadOptions
);
321 // Populate Argc and Argv
323 Status
= ParseCommandLineToArgs(FullCommandLine
,
324 &(*NewShellParameters
)->Argv
,
325 &(*NewShellParameters
)->Argc
);
327 FreePool(FullCommandLine
);
329 ASSERT_EFI_ERROR(Status
);
331 (*NewShellParameters
)->Argv
= NULL
;
332 (*NewShellParameters
)->Argc
= 0;
336 // Populate the 3 faked file systems...
338 if (*RootShellInstance
) {
339 (*NewShellParameters
)->StdIn
= &FileInterfaceStdIn
;
340 (*NewShellParameters
)->StdOut
= &FileInterfaceStdOut
;
341 (*NewShellParameters
)->StdErr
= &FileInterfaceStdErr
;
342 Status
= gBS
->InstallProtocolInterface(&gImageHandle
,
343 &gEfiShellParametersProtocolGuid
,
344 EFI_NATIVE_INTERFACE
,
345 (VOID
*)(*NewShellParameters
));
348 // copy from the existing ones
350 (*NewShellParameters
)->StdIn
= ShellInfoObject
.OldShellParameters
->StdIn
;
351 (*NewShellParameters
)->StdOut
= ShellInfoObject
.OldShellParameters
->StdOut
;
352 (*NewShellParameters
)->StdErr
= ShellInfoObject
.OldShellParameters
->StdErr
;
353 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
354 &gEfiShellParametersProtocolGuid
,
355 (VOID
*)ShellInfoObject
.OldShellParameters
,
356 (VOID
*)(*NewShellParameters
));
363 frees all memory used by createion and installation of shell parameters protocol
364 and if there was an old version installed it will restore that one.
366 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
369 @retval EFI_SUCCESS the cleanup was successful
370 @return other the cleanup failed
371 @sa ReinstallProtocolInterface
372 @sa UninstallProtocolInterface
376 CleanUpShellParametersProtocol (
377 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*NewShellParameters
384 // If the old exists we need to restore it
386 if (ShellInfoObject
.OldShellParameters
!= NULL
) {
387 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
388 &gEfiShellParametersProtocolGuid
,
389 (VOID
*)NewShellParameters
,
390 (VOID
*)ShellInfoObject
.OldShellParameters
);
391 DEBUG_CODE(ShellInfoObject
.OldShellParameters
= NULL
;);
394 // No old one, just uninstall us...
396 Status
= gBS
->UninstallProtocolInterface(gImageHandle
,
397 &gEfiShellParametersProtocolGuid
,
398 (VOID
*)NewShellParameters
);
400 if (NewShellParameters
->Argv
!= NULL
) {
401 for ( LoopCounter
= 0
402 ; LoopCounter
< NewShellParameters
->Argc
405 FreePool(NewShellParameters
->Argv
[LoopCounter
]);
407 FreePool(NewShellParameters
->Argv
);
409 FreePool(NewShellParameters
);
414 Determin if a file name represents a unicode file.
416 @param[in] FileName Pointer to the filename to open.
418 @retval EFI_SUCCESS The file is a unicode file.
419 @return An error upon failure.
424 IN CONST CHAR16
*FileName
427 SHELL_FILE_HANDLE Handle
;
429 UINT64 OriginalFilePosition
;
433 Status
= gEfiShellProtocol
->OpenFileByName(FileName
, &Handle
, EFI_FILE_MODE_READ
);
434 if (EFI_ERROR(Status
)) {
437 gEfiShellProtocol
->GetFilePosition(Handle
, &OriginalFilePosition
);
438 gEfiShellProtocol
->SetFilePosition(Handle
, 0);
439 CharSize
= sizeof(CHAR16
);
440 Status
= gEfiShellProtocol
->ReadFile(Handle
, &CharSize
, &CharBuffer
);
441 if (EFI_ERROR(Status
) || CharBuffer
!= gUnicodeFileTag
) {
442 Status
= EFI_BUFFER_TOO_SMALL
;
444 gEfiShellProtocol
->SetFilePosition(Handle
, OriginalFilePosition
);
445 gEfiShellProtocol
->CloseFile(Handle
);
450 Strips out quotes sections of a string.
452 All of the characters between quotes is replaced with spaces.
454 @param[in, out] TheString A pointer to the string to update.
459 IN OUT CHAR16
*TheString
464 for (RemoveNow
= FALSE
; TheString
!= NULL
&& *TheString
!= CHAR_NULL
; TheString
++) {
465 if (*TheString
== L
'^' && *(TheString
+ 1) == L
'\"') {
467 } else if (*TheString
== L
'\"') {
468 RemoveNow
= (BOOLEAN
)!RemoveNow
;
469 } else if (RemoveNow
) {
476 Calcualte the 32-bit CRC in a EFI table using the service provided by the
479 @param Hdr Pointer to an EFI standard header
484 IN OUT EFI_TABLE_HEADER
*Hdr
492 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
493 // Crc will come back as zero if we set it to zero here
496 gBS
->CalculateCrc32 ((UINT8
*)Hdr
, Hdr
->HeaderSize
, &Crc
);
501 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.
503 @param[in] FileName The filename to start with.
505 @retval NULL FileName was invalid.
506 @return The modified FileName.
515 CHAR16
*TempLocation
;
517 if (FileName
== NULL
) {
521 if (FileName
[0] == L
'\"') {
523 if ((TempLocation
= StrStr(Copy
, L
"\"")) != NULL
) {
524 TempLocation
[0] = CHAR_NULL
;
528 while(Copy
[0] == L
' ') {
531 if ((TempLocation
= StrStr(Copy
, L
" ")) != NULL
) {
532 TempLocation
[0] = CHAR_NULL
;
536 if (Copy
[0] == CHAR_NULL
) {
544 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
545 structure by parsing NewCommandLine. The current values are returned to the
548 This will also update the system table.
550 @param[in, out] ShellParameters Pointer to parameter structure to modify.
551 @param[in] NewCommandLine The new command line to parse and use.
552 @param[out] OldStdIn Pointer to old StdIn.
553 @param[out] OldStdOut Pointer to old StdOut.
554 @param[out] OldStdErr Pointer to old StdErr.
555 @param[out] SystemTableInfo Pointer to old system table information.
557 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
558 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
562 UpdateStdInStdOutStdErr(
563 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
564 IN CHAR16
*NewCommandLine
,
565 OUT SHELL_FILE_HANDLE
*OldStdIn
,
566 OUT SHELL_FILE_HANDLE
*OldStdOut
,
567 OUT SHELL_FILE_HANDLE
*OldStdErr
,
568 OUT SYSTEM_TABLE_INFO
*SystemTableInfo
571 CHAR16
*CommandLineCopy
;
572 CHAR16
*CommandLineWalker
;
573 CHAR16
*StdErrFileName
;
574 CHAR16
*StdOutFileName
;
575 CHAR16
*StdInFileName
;
576 CHAR16
*StdInVarName
;
577 CHAR16
*StdOutVarName
;
578 CHAR16
*StdErrVarName
;
580 SHELL_FILE_HANDLE TempHandle
;
590 CHAR16
*FirstLocation
;
596 StdOutVarName
= NULL
;
597 StdErrVarName
= NULL
;
598 StdErrFileName
= NULL
;
599 StdInFileName
= NULL
;
600 StdOutFileName
= NULL
;
603 CommandLineCopy
= NULL
;
604 FirstLocation
= NULL
;
606 if (ShellParameters
== NULL
|| SystemTableInfo
== NULL
|| OldStdIn
== NULL
|| OldStdOut
== NULL
|| OldStdErr
== NULL
) {
607 return (EFI_INVALID_PARAMETER
);
610 SystemTableInfo
->ConIn
= gST
->ConIn
;
611 SystemTableInfo
->ConInHandle
= gST
->ConsoleInHandle
;
612 SystemTableInfo
->ConOut
= gST
->ConOut
;
613 SystemTableInfo
->ConOutHandle
= gST
->ConsoleOutHandle
;
614 SystemTableInfo
->ErrOut
= gST
->StdErr
;
615 SystemTableInfo
->ErrOutHandle
= gST
->StandardErrorHandle
;
616 *OldStdIn
= ShellParameters
->StdIn
;
617 *OldStdOut
= ShellParameters
->StdOut
;
618 *OldStdErr
= ShellParameters
->StdErr
;
620 if (NewCommandLine
== NULL
) {
621 return (EFI_SUCCESS
);
624 CommandLineCopy
= StrnCatGrow(&CommandLineCopy
, NULL
, NewCommandLine
, 0);
625 if (CommandLineCopy
== NULL
) {
626 return (EFI_OUT_OF_RESOURCES
);
628 Status
= EFI_SUCCESS
;
630 FirstLocation
= CommandLineCopy
+ StrLen(CommandLineCopy
);
632 StripQuotes(CommandLineCopy
);
634 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
635 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
636 if (Split
!= NULL
&& Split
->SplitStdIn
!= NULL
) {
637 ShellParameters
->StdIn
= Split
->SplitStdIn
;
639 if (Split
!= NULL
&& Split
->SplitStdOut
!= NULL
) {
640 ShellParameters
->StdOut
= Split
->SplitStdOut
;
644 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>>v ")) != NULL
) {
645 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
646 SetMem16(CommandLineWalker
, 12, L
' ');
647 StdErrVarName
= CommandLineWalker
+= 6;
649 if (StrStr(CommandLineWalker
, L
" 2>>v ") != NULL
) {
650 Status
= EFI_NOT_FOUND
;
653 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>v ")) != NULL
) {
654 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
655 SetMem16(CommandLineWalker
, 12, L
' ');
656 StdOutVarName
= CommandLineWalker
+= 6;
658 if (StrStr(CommandLineWalker
, L
" 1>>v ") != NULL
) {
659 Status
= EFI_NOT_FOUND
;
661 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>v ")) != NULL
) {
662 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
663 SetMem16(CommandLineWalker
, 10, L
' ');
664 StdOutVarName
= CommandLineWalker
+= 5;
666 if (StrStr(CommandLineWalker
, L
" >>v ") != NULL
) {
667 Status
= EFI_NOT_FOUND
;
669 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >v ")) != NULL
) {
670 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
671 SetMem16(CommandLineWalker
, 8, L
' ');
672 StdOutVarName
= CommandLineWalker
+= 4;
674 if (StrStr(CommandLineWalker
, L
" >v ") != NULL
) {
675 Status
= EFI_NOT_FOUND
;
678 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>a ")) != NULL
) {
679 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
680 SetMem16(CommandLineWalker
, 12, L
' ');
681 StdOutFileName
= CommandLineWalker
+= 6;
684 if (StrStr(CommandLineWalker
, L
" 1>>a ") != NULL
) {
685 Status
= EFI_NOT_FOUND
;
688 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>> ")) != NULL
) {
689 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
690 SetMem16(CommandLineWalker
, 10, L
' ');
691 if (StdOutFileName
!= NULL
) {
692 Status
= EFI_INVALID_PARAMETER
;
694 StdOutFileName
= CommandLineWalker
+= 5;
697 if (StrStr(CommandLineWalker
, L
" 1>> ") != NULL
) {
698 Status
= EFI_NOT_FOUND
;
701 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >> ")) != NULL
) {
702 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
703 SetMem16(CommandLineWalker
, 8, L
' ');
704 if (StdOutFileName
!= NULL
) {
705 Status
= EFI_INVALID_PARAMETER
;
707 StdOutFileName
= CommandLineWalker
+= 4;
710 if (StrStr(CommandLineWalker
, L
" >> ") != NULL
) {
711 Status
= EFI_NOT_FOUND
;
714 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>a ")) != NULL
) {
715 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
716 SetMem16(CommandLineWalker
, 10, L
' ');
717 if (StdOutFileName
!= NULL
) {
718 Status
= EFI_INVALID_PARAMETER
;
720 StdOutFileName
= CommandLineWalker
+= 5;
724 if (StrStr(CommandLineWalker
, L
" >>a ") != NULL
) {
725 Status
= EFI_NOT_FOUND
;
728 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>a ")) != NULL
) {
729 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
730 SetMem16(CommandLineWalker
, 10, L
' ');
731 if (StdOutFileName
!= NULL
) {
732 Status
= EFI_INVALID_PARAMETER
;
734 StdOutFileName
= CommandLineWalker
+= 5;
738 if (StrStr(CommandLineWalker
, L
" 1>a ") != NULL
) {
739 Status
= EFI_NOT_FOUND
;
742 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >a ")) != NULL
) {
743 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
744 SetMem16(CommandLineWalker
, 8, L
' ');
745 if (StdOutFileName
!= NULL
) {
746 Status
= EFI_INVALID_PARAMETER
;
748 StdOutFileName
= CommandLineWalker
+= 4;
752 if (StrStr(CommandLineWalker
, L
" >a ") != NULL
) {
753 Status
= EFI_NOT_FOUND
;
756 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>> ")) != NULL
) {
757 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
758 SetMem16(CommandLineWalker
, 10, L
' ');
759 if (StdErrFileName
!= NULL
) {
760 Status
= EFI_INVALID_PARAMETER
;
762 StdErrFileName
= CommandLineWalker
+= 5;
765 if (StrStr(CommandLineWalker
, L
" 2>> ") != NULL
) {
766 Status
= EFI_NOT_FOUND
;
770 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>v ")) != NULL
) {
771 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
772 SetMem16(CommandLineWalker
, 10, L
' ');
773 if (StdErrVarName
!= NULL
) {
774 Status
= EFI_INVALID_PARAMETER
;
776 StdErrVarName
= CommandLineWalker
+= 5;
779 if (StrStr(CommandLineWalker
, L
" 2>v ") != NULL
) {
780 Status
= EFI_NOT_FOUND
;
783 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>v ")) != NULL
) {
784 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
785 SetMem16(CommandLineWalker
, 10, L
' ');
786 if (StdOutVarName
!= NULL
) {
787 Status
= EFI_INVALID_PARAMETER
;
789 StdOutVarName
= CommandLineWalker
+= 5;
792 if (StrStr(CommandLineWalker
, L
" 1>v ") != NULL
) {
793 Status
= EFI_NOT_FOUND
;
796 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>a ")) != NULL
) {
797 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
798 SetMem16(CommandLineWalker
, 10, L
' ');
799 if (StdErrFileName
!= NULL
) {
800 Status
= EFI_INVALID_PARAMETER
;
802 StdErrFileName
= CommandLineWalker
+= 5;
806 if (StrStr(CommandLineWalker
, L
" 2>a ") != NULL
) {
807 Status
= EFI_NOT_FOUND
;
810 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2> ")) != NULL
) {
811 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
812 SetMem16(CommandLineWalker
, 8, L
' ');
813 if (StdErrFileName
!= NULL
) {
814 Status
= EFI_INVALID_PARAMETER
;
816 StdErrFileName
= CommandLineWalker
+= 4;
819 if (StrStr(CommandLineWalker
, L
" 2> ") != NULL
) {
820 Status
= EFI_NOT_FOUND
;
824 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1> ")) != NULL
) {
825 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
826 SetMem16(CommandLineWalker
, 8, L
' ');
827 if (StdOutFileName
!= NULL
) {
828 Status
= EFI_INVALID_PARAMETER
;
830 StdOutFileName
= CommandLineWalker
+= 4;
833 if (StrStr(CommandLineWalker
, L
" 1> ") != NULL
) {
834 Status
= EFI_NOT_FOUND
;
838 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" > ")) != NULL
) {
839 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
840 SetMem16(CommandLineWalker
, 6, L
' ');
841 if (StdOutFileName
!= NULL
) {
842 Status
= EFI_INVALID_PARAMETER
;
844 StdOutFileName
= CommandLineWalker
+= 3;
847 if (StrStr(CommandLineWalker
, L
" > ") != NULL
) {
848 Status
= EFI_NOT_FOUND
;
852 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" < ")) != NULL
) {
853 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
854 SetMem16(CommandLineWalker
, 6, L
' ');
855 if (StdInFileName
!= NULL
) {
856 Status
= EFI_INVALID_PARAMETER
;
858 StdInFileName
= CommandLineWalker
+= 3;
860 if (StrStr(CommandLineWalker
, L
" < ") != NULL
) {
861 Status
= EFI_NOT_FOUND
;
864 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <a ")) != NULL
) {
865 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
866 SetMem16(CommandLineWalker
, 8, L
' ');
867 if (StdInFileName
!= NULL
) {
868 Status
= EFI_INVALID_PARAMETER
;
870 StdInFileName
= CommandLineWalker
+= 4;
873 if (StrStr(CommandLineWalker
, L
" <a ") != NULL
) {
874 Status
= EFI_NOT_FOUND
;
877 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <v ")) != NULL
) {
878 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
879 SetMem16(CommandLineWalker
, 8, L
' ');
880 if (StdInVarName
!= NULL
) {
881 Status
= EFI_INVALID_PARAMETER
;
883 StdInVarName
= CommandLineWalker
+= 4;
885 if (StrStr(CommandLineWalker
, L
" <v ") != NULL
) {
886 Status
= EFI_NOT_FOUND
;
891 // re-populate the string to support any filenames that were in quotes.
893 StrCpy(CommandLineCopy
, NewCommandLine
);
895 if (FirstLocation
!= CommandLineCopy
+ StrLen(CommandLineCopy
)
896 && ((UINTN
)(FirstLocation
- CommandLineCopy
) < StrLen(NewCommandLine
))
898 *(NewCommandLine
+ (UINTN
)(FirstLocation
- CommandLineCopy
)) = CHAR_NULL
;
901 if (!EFI_ERROR(Status
)) {
903 if (StdErrFileName
!= NULL
) {
904 if ((StdErrFileName
= FixFileName(StdErrFileName
)) == NULL
) {
905 Status
= EFI_INVALID_PARAMETER
;
908 if (StdOutFileName
!= NULL
) {
909 if ((StdOutFileName
= FixFileName(StdOutFileName
)) == NULL
) {
910 Status
= EFI_INVALID_PARAMETER
;
913 if (StdInFileName
!= NULL
) {
914 if ((StdInFileName
= FixFileName(StdInFileName
)) == NULL
) {
915 Status
= EFI_INVALID_PARAMETER
;
918 if (StdErrVarName
!= NULL
) {
919 if ((StdErrVarName
= FixFileName(StdErrVarName
)) == NULL
) {
920 Status
= EFI_INVALID_PARAMETER
;
923 if (StdOutVarName
!= NULL
) {
924 if ((StdOutVarName
= FixFileName(StdOutVarName
)) == NULL
) {
925 Status
= EFI_INVALID_PARAMETER
;
928 if (StdInVarName
!= NULL
) {
929 if ((StdInVarName
= FixFileName(StdInVarName
)) == NULL
) {
930 Status
= EFI_INVALID_PARAMETER
;
935 // Verify not the same and not duplicating something from a split
939 // Check that no 2 filenames are the same
941 (StdErrFileName
!= NULL
&& StdOutFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdOutFileName
) == 0)
942 ||(StdErrFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdInFileName
) == 0)
943 ||(StdOutFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdOutFileName
, &StdInFileName
) == 0)
945 // Check that no 2 variable names are the same
947 ||(StdErrVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdInVarName
) == 0)
948 ||(StdOutVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdOutVarName
, &StdInVarName
) == 0)
949 ||(StdErrVarName
!= NULL
&& StdOutVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdOutVarName
) == 0)
951 // When a split (using | operator) is in place some are not allowed
953 ||(Split
!= NULL
&& Split
->SplitStdIn
!= NULL
&& (StdInVarName
!= NULL
|| StdInFileName
!= NULL
))
954 ||(Split
!= NULL
&& Split
->SplitStdOut
!= NULL
&& (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
))
956 // Check that nothing is trying to be output to 2 locations.
958 ||(StdErrFileName
!= NULL
&& StdErrVarName
!= NULL
)
959 ||(StdOutFileName
!= NULL
&& StdOutVarName
!= NULL
)
960 ||(StdInFileName
!= NULL
&& StdInVarName
!= NULL
)
962 // Check for no volatile environment variables
964 ||(StdErrVarName
!= NULL
&& !IsVolatileEnv(StdErrVarName
))
965 ||(StdOutVarName
!= NULL
&& !IsVolatileEnv(StdOutVarName
))
967 // Cant redirect during a reconnect operation.
969 ||(StrStr(NewCommandLine
, L
"connect -r") != NULL
970 && (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
|| StdErrFileName
!= NULL
|| StdErrVarName
!= NULL
))
972 // Check that filetypes (Unicode/Ascii) do not change during an append
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
))))
976 ||(StdOutFileName
!= NULL
&& !OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
977 ||(StdErrFileName
!= NULL
&& !ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
979 Status
= EFI_INVALID_PARAMETER
;
980 ShellParameters
->StdIn
= *OldStdIn
;
981 ShellParameters
->StdOut
= *OldStdOut
;
982 ShellParameters
->StdErr
= *OldStdErr
;
983 } else if (!EFI_ERROR(Status
)){
985 // Open the Std<Whatever> and we should not have conflicts here...
991 if (StdErrFileName
!= NULL
) {
994 // delete existing file.
996 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdErrFileName
);
998 Status
= ShellOpenFileByName(StdErrFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
999 if (!ErrAppend
&& ErrUnicode
&& !EFI_ERROR(Status
)) {
1001 // Write out the gUnicodeFileTag
1003 Size
= sizeof(CHAR16
);
1004 TagBuffer
[0] = gUnicodeFileTag
;
1005 TagBuffer
[1] = CHAR_NULL
;
1006 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1008 if (!ErrUnicode
&& !EFI_ERROR(Status
)) {
1009 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1010 ASSERT(TempHandle
!= NULL
);
1012 if (!EFI_ERROR(Status
)) {
1013 ShellParameters
->StdErr
= TempHandle
;
1014 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1021 if (!EFI_ERROR(Status
) && StdOutFileName
!= NULL
) {
1024 // delete existing file.
1026 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdOutFileName
);
1028 Status
= ShellOpenFileByName(StdOutFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
1029 if (TempHandle
== NULL
) {
1030 Status
= EFI_INVALID_PARAMETER
;
1032 if (StrStr(StdOutFileName
, L
"NUL")==StdOutFileName
) {
1034 } else if (!OutAppend
&& OutUnicode
&& !EFI_ERROR(Status
)) {
1036 // Write out the gUnicodeFileTag
1038 Size
= sizeof(CHAR16
);
1039 TagBuffer
[0] = gUnicodeFileTag
;
1040 TagBuffer
[1] = CHAR_NULL
;
1041 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1042 } else if (OutAppend
) {
1044 // Move to end of file
1046 Status
= ShellInfoObject
.NewEfiShellProtocol
->GetFileSize(TempHandle
, &FileSize
);
1047 if (!EFI_ERROR(Status
)) {
1048 Status
= ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition(TempHandle
, FileSize
);
1051 if (!OutUnicode
&& !EFI_ERROR(Status
)) {
1052 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1053 ASSERT(TempHandle
!= NULL
);
1055 if (!EFI_ERROR(Status
)) {
1056 ShellParameters
->StdOut
= TempHandle
;
1057 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1065 if (!EFI_ERROR(Status
) && StdOutVarName
!= NULL
) {
1068 // delete existing variable.
1070 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName
, 0, L
"");
1072 TempHandle
= CreateFileInterfaceEnv(StdOutVarName
);
1073 ASSERT(TempHandle
!= NULL
);
1074 ShellParameters
->StdOut
= TempHandle
;
1075 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1081 if (!EFI_ERROR(Status
) && StdErrVarName
!= NULL
) {
1084 // delete existing variable.
1086 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName
, 0, L
"");
1088 TempHandle
= CreateFileInterfaceEnv(StdErrVarName
);
1089 ASSERT(TempHandle
!= NULL
);
1090 ShellParameters
->StdErr
= TempHandle
;
1091 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1097 if (!EFI_ERROR(Status
) && StdInVarName
!= NULL
) {
1098 TempHandle
= CreateFileInterfaceEnv(StdInVarName
);
1099 if (TempHandle
== NULL
) {
1100 Status
= EFI_OUT_OF_RESOURCES
;
1103 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1106 if (TempHandle
== NULL
|| ((EFI_FILE_PROTOCOL
*)TempHandle
)->Read(TempHandle
, &Size
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
1107 Status
= EFI_INVALID_PARAMETER
;
1109 ShellParameters
->StdIn
= TempHandle
;
1110 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1116 // StdIn from a file
1118 if (!EFI_ERROR(Status
) && StdInFileName
!= NULL
) {
1119 Status
= ShellOpenFileByName(
1124 if (!InUnicode
&& !EFI_ERROR(Status
)) {
1125 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1127 if (!EFI_ERROR(Status
)) {
1128 ShellParameters
->StdIn
= TempHandle
;
1129 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1134 FreePool(CommandLineCopy
);
1136 CalculateEfiHdrCrc(&gST
->Hdr
);
1138 if (gST
->ConIn
== NULL
||gST
->ConOut
== NULL
) {
1139 return (EFI_OUT_OF_RESOURCES
);
1145 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1146 structure with StdIn and StdOut. The current values are de-allocated.
1148 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1149 @param[in] OldStdIn Pointer to old StdIn.
1150 @param[in] OldStdOut Pointer to old StdOut.
1151 @param[in] OldStdErr Pointer to old StdErr.
1152 @param[in] SystemTableInfo Pointer to old system table information.
1156 RestoreStdInStdOutStdErr (
1157 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1158 IN SHELL_FILE_HANDLE
*OldStdIn
,
1159 IN SHELL_FILE_HANDLE
*OldStdOut
,
1160 IN SHELL_FILE_HANDLE
*OldStdErr
,
1161 IN SYSTEM_TABLE_INFO
*SystemTableInfo
1166 if (ShellParameters
== NULL
1170 ||SystemTableInfo
== NULL
) {
1171 return (EFI_INVALID_PARAMETER
);
1173 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1174 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1178 if (ShellParameters
->StdIn
!= *OldStdIn
) {
1179 if ((Split
!= NULL
&& Split
->SplitStdIn
!= ShellParameters
->StdIn
) || Split
== NULL
) {
1180 gEfiShellProtocol
->CloseFile(ShellParameters
->StdIn
);
1182 ShellParameters
->StdIn
= *OldStdIn
;
1184 if (ShellParameters
->StdOut
!= *OldStdOut
) {
1185 if ((Split
!= NULL
&& Split
->SplitStdOut
!= ShellParameters
->StdOut
) || Split
== NULL
) {
1186 gEfiShellProtocol
->CloseFile(ShellParameters
->StdOut
);
1188 ShellParameters
->StdOut
= *OldStdOut
;
1190 if (ShellParameters
->StdErr
!= *OldStdErr
) {
1191 gEfiShellProtocol
->CloseFile(ShellParameters
->StdErr
);
1192 ShellParameters
->StdErr
= *OldStdErr
;
1195 if (gST
->ConIn
!= SystemTableInfo
->ConIn
) {
1196 CloseSimpleTextInOnFile(gST
->ConIn
);
1197 gST
->ConIn
= SystemTableInfo
->ConIn
;
1198 gST
->ConsoleInHandle
= SystemTableInfo
->ConInHandle
;
1200 if (gST
->ConOut
!= SystemTableInfo
->ConOut
) {
1201 CloseSimpleTextOutOnFile(gST
->ConOut
);
1202 gST
->ConOut
= SystemTableInfo
->ConOut
;
1203 gST
->ConsoleOutHandle
= SystemTableInfo
->ConOutHandle
;
1205 if (gST
->StdErr
!= SystemTableInfo
->ErrOut
) {
1206 CloseSimpleTextOutOnFile(gST
->StdErr
);
1207 gST
->StdErr
= SystemTableInfo
->ErrOut
;
1208 gST
->StandardErrorHandle
= SystemTableInfo
->ErrOutHandle
;
1211 CalculateEfiHdrCrc(&gST
->Hdr
);
1213 return (EFI_SUCCESS
);
1216 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1217 structure by parsing NewCommandLine. The current values are returned to the
1220 If OldArgv or OldArgc is NULL then that value is not returned.
1222 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1223 @param[in] NewCommandLine The new command line to parse and use.
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 OUT CHAR16
***OldArgv OPTIONAL
,
1236 OUT UINTN
*OldArgc OPTIONAL
1239 ASSERT(ShellParameters
!= NULL
);
1241 if (OldArgc
!= NULL
) {
1242 *OldArgc
= ShellParameters
->Argc
;
1244 if (OldArgc
!= NULL
) {
1245 *OldArgv
= ShellParameters
->Argv
;
1248 return (ParseCommandLineToArgs(NewCommandLine
, &(ShellParameters
->Argv
), &(ShellParameters
->Argc
)));
1252 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1253 structure with Argv and Argc. The current values are de-allocated and the
1254 OldArgv must not be deallocated by the caller.
1256 @param[in, out] ShellParameters pointer to parameter structure to modify
1257 @param[in] OldArgv pointer to old list of parameters
1258 @param[in] OldArgc pointer to old number of items in Argv list
1263 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1264 IN CHAR16
***OldArgv
,
1269 ASSERT(ShellParameters
!= NULL
);
1270 ASSERT(OldArgv
!= NULL
);
1271 ASSERT(OldArgc
!= NULL
);
1273 if (ShellParameters
->Argv
!= NULL
) {
1274 for ( LoopCounter
= 0
1275 ; LoopCounter
< ShellParameters
->Argc
1278 FreePool(ShellParameters
->Argv
[LoopCounter
]);
1280 FreePool(ShellParameters
->Argv
);
1282 ShellParameters
->Argv
= *OldArgv
;
1284 ShellParameters
->Argc
= *OldArgc
;