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 - 2013, 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.
19 return the next parameter from a command line string;
21 This function moves the next parameter from Walker into TempParameter and moves
22 Walker up past that parameter for recursive calling. When the final parameter
23 is moved *Walker will be set to NULL;
25 Temp Parameter must be large enough to hold the parameter before calling this
28 @param[in, out] Walker pointer to string of command line. Adjusted to
29 reminaing command line on return
30 @param[in, out] TempParameter pointer to string of command line item extracted.
37 CHAR16
**TempParameter
43 ASSERT(Walker
!= NULL
);
44 ASSERT(*Walker
!= NULL
);
45 ASSERT(TempParameter
!= NULL
);
46 ASSERT(*TempParameter
!= NULL
);
49 // make sure we dont have any leading spaces
51 while ((*Walker
)[0] == L
' ') {
56 // make sure we still have some params now...
58 if (StrLen(*Walker
) == 0) {
59 ASSERT((*Walker
)[0] == CHAR_NULL
);
65 // we have a quoted parameter
66 // could be the last parameter, but SHOULD have a trailing quote
68 if ((*Walker
)[0] == L
'\"') {
70 for (TempLoc
= *Walker
+ 1 ; TempLoc
!= NULL
&& *TempLoc
!= CHAR_NULL
; TempLoc
++) {
71 if (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'\"') {
73 } else if (*TempLoc
== L
'\"') {
79 if (NextDelim
- ((*Walker
)+1) == 0) {
83 StrCpy(*TempParameter
, L
"");
84 *Walker
= NextDelim
+ 1;
85 } else if (NextDelim
!= NULL
) {
86 StrnCpy(*TempParameter
, (*Walker
)+1, NextDelim
- ((*Walker
)+1));
87 *Walker
= NextDelim
+ 1;
90 // last one... someone forgot the training quote!
92 StrCpy(*TempParameter
, *Walker
);
95 for (TempLoc
= *TempParameter
; TempLoc
!= NULL
&& *TempLoc
!= CHAR_NULL
; TempLoc
++) {
96 if (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'\"') {
97 CopyMem(TempLoc
, TempLoc
+1, StrSize(TempLoc
) - sizeof(TempLoc
[0]));
102 // we have a regular parameter (no quote) OR
103 // we have the final parameter (no trailing space)
105 NextDelim
= StrStr((*Walker
), L
" ");
106 if (NextDelim
!= NULL
) {
107 StrnCpy(*TempParameter
, *Walker
, NextDelim
- (*Walker
));
108 (*TempParameter
)[NextDelim
- (*Walker
)] = CHAR_NULL
;
109 *Walker
= NextDelim
+1;
114 StrCpy(*TempParameter
, *Walker
);
117 for (NextDelim
= *TempParameter
; NextDelim
!= NULL
&& *NextDelim
!= CHAR_NULL
; NextDelim
++) {
118 if (*NextDelim
== L
'^' && *(NextDelim
+1) == L
'^') {
119 CopyMem(NextDelim
, NextDelim
+1, StrSize(NextDelim
) - sizeof(NextDelim
[0]));
122 while ((*TempParameter
)[StrLen(*TempParameter
)-1] == L
' ') {
123 (*TempParameter
)[StrLen(*TempParameter
)-1] = CHAR_NULL
;
125 while ((*TempParameter
)[0] == L
' ') {
126 CopyMem(*TempParameter
, (*TempParameter
)+1, StrSize(*TempParameter
) - sizeof((*TempParameter
)[0]));
133 Function to populate Argc and Argv.
135 This function parses the CommandLine and divides it into standard C style Argc/Argv
136 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
137 delimited and quote surrounded parameter definition.
139 @param[in] CommandLine String of command line to parse
140 @param[in, out] Argv pointer to array of strings; one for each parameter
141 @param[in, out] Argc pointer to number of strings in Argv array
143 @return EFI_SUCCESS the operation was sucessful
144 @return EFI_OUT_OF_RESOURCES a memory allocation failed.
148 ParseCommandLineToArgs(
149 IN CONST CHAR16
*CommandLine
,
150 IN OUT CHAR16
***Argv
,
155 CHAR16
*TempParameter
;
160 ASSERT(Argc
!= NULL
);
161 ASSERT(Argv
!= NULL
);
163 if (CommandLine
== NULL
|| StrLen(CommandLine
)==0) {
166 return (EFI_SUCCESS
);
169 Size
= StrSize(CommandLine
);
170 TempParameter
= AllocateZeroPool(Size
);
171 if (TempParameter
== NULL
) {
172 return (EFI_OUT_OF_RESOURCES
);
176 , Walker
= (CHAR16
*)CommandLine
177 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
178 ; GetNextParameter(&Walker
, &TempParameter
)
183 Walker = (CHAR16*)CommandLine;
184 while(Walker != NULL) {
185 GetNextParameter(&Walker, &TempParameter);
190 // lets allocate the pointer array
192 (*Argv
) = AllocateZeroPool((Count
)*sizeof(CHAR16
*));
194 SHELL_FREE_NON_NULL(TempParameter
);
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 SHELL_FREE_NON_NULL(TempParameter
);
211 return (EFI_SUCCESS
);
215 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
216 installs it on our handle and if there is an existing version of the protocol
217 that one is cached for removal later.
219 @param[in, out] NewShellParameters on a successful return, a pointer to pointer
220 to the newly installed interface.
221 @param[in, out] RootShellInstance on a successful return, pointer to boolean.
222 TRUE if this is the root shell instance.
224 @retval EFI_SUCCESS the operation completed successfully.
225 @return other the operation failed.
226 @sa ReinstallProtocolInterface
227 @sa InstallProtocolInterface
228 @sa ParseCommandLineToArgs
232 CreatePopulateInstallShellParametersProtocol (
233 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
**NewShellParameters
,
234 IN OUT BOOLEAN
*RootShellInstance
238 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
239 CHAR16
*FullCommandLine
;
243 FullCommandLine
= NULL
;
247 // Assert for valid parameters
249 ASSERT(NewShellParameters
!= NULL
);
250 ASSERT(RootShellInstance
!= NULL
);
253 // See if we have a shell parameters placed on us
255 Status
= gBS
->OpenProtocol (
257 &gEfiShellParametersProtocolGuid
,
258 (VOID
**) &ShellInfoObject
.OldShellParameters
,
261 EFI_OPEN_PROTOCOL_GET_PROTOCOL
264 // if we don't then we must be the root shell (error is expected)
266 if (EFI_ERROR (Status
)) {
267 *RootShellInstance
= TRUE
;
271 // Allocate the new structure
273 *NewShellParameters
= AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL
));
274 if ((*NewShellParameters
) == NULL
) {
275 return (EFI_OUT_OF_RESOURCES
);
279 // get loaded image protocol
281 Status
= gBS
->OpenProtocol (
283 &gEfiLoadedImageProtocolGuid
,
284 (VOID
**) &LoadedImage
,
287 EFI_OPEN_PROTOCOL_GET_PROTOCOL
289 ASSERT_EFI_ERROR(Status
);
291 // Build the full command line
293 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, FullCommandLine
);
294 if (Status
== EFI_BUFFER_TOO_SMALL
) {
295 FullCommandLine
= AllocateZeroPool(Size
+ LoadedImage
->LoadOptionsSize
);
296 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, FullCommandLine
);
298 if (Status
== EFI_NOT_FOUND
) {
300 // no parameters via environment... ok
303 if (EFI_ERROR(Status
)) {
307 if (Size
== 0 && LoadedImage
->LoadOptionsSize
!= 0) {
308 ASSERT(FullCommandLine
== NULL
);
310 // Now we need to include a NULL terminator in the size.
312 Size
= LoadedImage
->LoadOptionsSize
+ sizeof(FullCommandLine
[0]);
313 FullCommandLine
= AllocateZeroPool(Size
);
315 if (FullCommandLine
!= NULL
) {
316 CopyMem (FullCommandLine
, LoadedImage
->LoadOptions
, LoadedImage
->LoadOptionsSize
);
318 // Populate Argc and Argv
320 Status
= ParseCommandLineToArgs(FullCommandLine
,
321 &(*NewShellParameters
)->Argv
,
322 &(*NewShellParameters
)->Argc
);
324 FreePool(FullCommandLine
);
326 ASSERT_EFI_ERROR(Status
);
328 (*NewShellParameters
)->Argv
= NULL
;
329 (*NewShellParameters
)->Argc
= 0;
333 // Populate the 3 faked file systems...
335 if (*RootShellInstance
) {
336 (*NewShellParameters
)->StdIn
= &FileInterfaceStdIn
;
337 (*NewShellParameters
)->StdOut
= &FileInterfaceStdOut
;
338 (*NewShellParameters
)->StdErr
= &FileInterfaceStdErr
;
339 Status
= gBS
->InstallProtocolInterface(&gImageHandle
,
340 &gEfiShellParametersProtocolGuid
,
341 EFI_NATIVE_INTERFACE
,
342 (VOID
*)(*NewShellParameters
));
345 // copy from the existing ones
347 (*NewShellParameters
)->StdIn
= ShellInfoObject
.OldShellParameters
->StdIn
;
348 (*NewShellParameters
)->StdOut
= ShellInfoObject
.OldShellParameters
->StdOut
;
349 (*NewShellParameters
)->StdErr
= ShellInfoObject
.OldShellParameters
->StdErr
;
350 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
351 &gEfiShellParametersProtocolGuid
,
352 (VOID
*)ShellInfoObject
.OldShellParameters
,
353 (VOID
*)(*NewShellParameters
));
360 frees all memory used by createion and installation of shell parameters protocol
361 and if there was an old version installed it will restore that one.
363 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
366 @retval EFI_SUCCESS the cleanup was successful
367 @return other the cleanup failed
368 @sa ReinstallProtocolInterface
369 @sa UninstallProtocolInterface
373 CleanUpShellParametersProtocol (
374 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*NewShellParameters
381 // If the old exists we need to restore it
383 if (ShellInfoObject
.OldShellParameters
!= NULL
) {
384 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
385 &gEfiShellParametersProtocolGuid
,
386 (VOID
*)NewShellParameters
,
387 (VOID
*)ShellInfoObject
.OldShellParameters
);
388 DEBUG_CODE(ShellInfoObject
.OldShellParameters
= NULL
;);
391 // No old one, just uninstall us...
393 Status
= gBS
->UninstallProtocolInterface(gImageHandle
,
394 &gEfiShellParametersProtocolGuid
,
395 (VOID
*)NewShellParameters
);
397 if (NewShellParameters
->Argv
!= NULL
) {
398 for ( LoopCounter
= 0
399 ; LoopCounter
< NewShellParameters
->Argc
402 FreePool(NewShellParameters
->Argv
[LoopCounter
]);
404 FreePool(NewShellParameters
->Argv
);
406 FreePool(NewShellParameters
);
411 Determin if a file name represents a unicode file.
413 @param[in] FileName Pointer to the filename to open.
415 @retval EFI_SUCCESS The file is a unicode file.
416 @return An error upon failure.
421 IN CONST CHAR16
*FileName
424 SHELL_FILE_HANDLE Handle
;
426 UINT64 OriginalFilePosition
;
430 Status
= gEfiShellProtocol
->OpenFileByName(FileName
, &Handle
, EFI_FILE_MODE_READ
);
431 if (EFI_ERROR(Status
)) {
434 gEfiShellProtocol
->GetFilePosition(Handle
, &OriginalFilePosition
);
435 gEfiShellProtocol
->SetFilePosition(Handle
, 0);
436 CharSize
= sizeof(CHAR16
);
437 Status
= gEfiShellProtocol
->ReadFile(Handle
, &CharSize
, &CharBuffer
);
438 if (EFI_ERROR(Status
) || CharBuffer
!= gUnicodeFileTag
) {
439 Status
= EFI_BUFFER_TOO_SMALL
;
441 gEfiShellProtocol
->SetFilePosition(Handle
, OriginalFilePosition
);
442 gEfiShellProtocol
->CloseFile(Handle
);
447 Strips out quotes sections of a string.
449 All of the characters between quotes is replaced with spaces.
451 @param[in, out] TheString A pointer to the string to update.
456 IN OUT CHAR16
*TheString
461 for (RemoveNow
= FALSE
; TheString
!= NULL
&& *TheString
!= CHAR_NULL
; TheString
++) {
462 if (*TheString
== L
'^' && *(TheString
+ 1) == L
'\"') {
464 } else if (*TheString
== L
'\"') {
465 RemoveNow
= (BOOLEAN
)!RemoveNow
;
466 } else if (RemoveNow
) {
473 Calcualte the 32-bit CRC in a EFI table using the service provided by the
476 @param Hdr Pointer to an EFI standard header
481 IN OUT EFI_TABLE_HEADER
*Hdr
489 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
490 // Crc will come back as zero if we set it to zero here
493 gBS
->CalculateCrc32 ((UINT8
*)Hdr
, Hdr
->HeaderSize
, &Crc
);
498 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.
500 @param[in] FileName The filename to start with.
502 @retval NULL FileName was invalid.
503 @return The modified FileName.
512 CHAR16
*TempLocation
;
514 if (FileName
== NULL
) {
518 if (FileName
[0] == L
'\"') {
520 if ((TempLocation
= StrStr(Copy
, L
"\"")) != NULL
) {
521 TempLocation
[0] = CHAR_NULL
;
525 while(Copy
[0] == L
' ') {
528 if ((TempLocation
= StrStr(Copy
, L
" ")) != NULL
) {
529 TempLocation
[0] = CHAR_NULL
;
533 if (Copy
[0] == CHAR_NULL
) {
541 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
542 structure by parsing NewCommandLine. The current values are returned to the
545 This will also update the system table.
547 @param[in, out] ShellParameters Pointer to parameter structure to modify.
548 @param[in] NewCommandLine The new command line to parse and use.
549 @param[out] OldStdIn Pointer to old StdIn.
550 @param[out] OldStdOut Pointer to old StdOut.
551 @param[out] OldStdErr Pointer to old StdErr.
552 @param[out] SystemTableInfo Pointer to old system table information.
554 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
555 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
559 UpdateStdInStdOutStdErr(
560 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
561 IN CHAR16
*NewCommandLine
,
562 OUT SHELL_FILE_HANDLE
*OldStdIn
,
563 OUT SHELL_FILE_HANDLE
*OldStdOut
,
564 OUT SHELL_FILE_HANDLE
*OldStdErr
,
565 OUT SYSTEM_TABLE_INFO
*SystemTableInfo
568 CHAR16
*CommandLineCopy
;
569 CHAR16
*CommandLineWalker
;
570 CHAR16
*StdErrFileName
;
571 CHAR16
*StdOutFileName
;
572 CHAR16
*StdInFileName
;
573 CHAR16
*StdInVarName
;
574 CHAR16
*StdOutVarName
;
575 CHAR16
*StdErrVarName
;
577 SHELL_FILE_HANDLE TempHandle
;
587 CHAR16
*FirstLocation
;
593 StdOutVarName
= NULL
;
594 StdErrVarName
= NULL
;
595 StdErrFileName
= NULL
;
596 StdInFileName
= NULL
;
597 StdOutFileName
= NULL
;
600 CommandLineCopy
= NULL
;
601 FirstLocation
= NULL
;
603 if (ShellParameters
== NULL
|| SystemTableInfo
== NULL
|| OldStdIn
== NULL
|| OldStdOut
== NULL
|| OldStdErr
== NULL
) {
604 return (EFI_INVALID_PARAMETER
);
607 SystemTableInfo
->ConIn
= gST
->ConIn
;
608 SystemTableInfo
->ConInHandle
= gST
->ConsoleInHandle
;
609 SystemTableInfo
->ConOut
= gST
->ConOut
;
610 SystemTableInfo
->ConOutHandle
= gST
->ConsoleOutHandle
;
611 SystemTableInfo
->ErrOut
= gST
->StdErr
;
612 SystemTableInfo
->ErrOutHandle
= gST
->StandardErrorHandle
;
613 *OldStdIn
= ShellParameters
->StdIn
;
614 *OldStdOut
= ShellParameters
->StdOut
;
615 *OldStdErr
= ShellParameters
->StdErr
;
617 if (NewCommandLine
== NULL
) {
618 return (EFI_SUCCESS
);
621 CommandLineCopy
= StrnCatGrow(&CommandLineCopy
, NULL
, NewCommandLine
, 0);
622 if (CommandLineCopy
== NULL
) {
623 return (EFI_OUT_OF_RESOURCES
);
625 Status
= EFI_SUCCESS
;
627 FirstLocation
= CommandLineCopy
+ StrLen(CommandLineCopy
);
629 StripQuotes(CommandLineCopy
);
631 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
632 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
633 if (Split
!= NULL
&& Split
->SplitStdIn
!= NULL
) {
634 ShellParameters
->StdIn
= Split
->SplitStdIn
;
636 if (Split
!= NULL
&& Split
->SplitStdOut
!= NULL
) {
637 ShellParameters
->StdOut
= Split
->SplitStdOut
;
641 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>>v ")) != NULL
) {
642 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
643 SetMem16(CommandLineWalker
, 12, L
' ');
644 StdErrVarName
= CommandLineWalker
+= 6;
646 if (StrStr(CommandLineWalker
, L
" 2>>v ") != NULL
) {
647 Status
= EFI_NOT_FOUND
;
650 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>v ")) != NULL
) {
651 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
652 SetMem16(CommandLineWalker
, 12, L
' ');
653 StdOutVarName
= CommandLineWalker
+= 6;
655 if (StrStr(CommandLineWalker
, L
" 1>>v ") != NULL
) {
656 Status
= EFI_NOT_FOUND
;
658 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>v ")) != NULL
) {
659 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
660 SetMem16(CommandLineWalker
, 10, L
' ');
661 StdOutVarName
= CommandLineWalker
+= 5;
663 if (StrStr(CommandLineWalker
, L
" >>v ") != NULL
) {
664 Status
= EFI_NOT_FOUND
;
666 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >v ")) != NULL
) {
667 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
668 SetMem16(CommandLineWalker
, 8, L
' ');
669 StdOutVarName
= CommandLineWalker
+= 4;
671 if (StrStr(CommandLineWalker
, L
" >v ") != NULL
) {
672 Status
= EFI_NOT_FOUND
;
675 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>a ")) != NULL
) {
676 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
677 SetMem16(CommandLineWalker
, 12, L
' ');
678 StdOutFileName
= CommandLineWalker
+= 6;
681 if (StrStr(CommandLineWalker
, L
" 1>>a ") != NULL
) {
682 Status
= EFI_NOT_FOUND
;
685 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>> ")) != NULL
) {
686 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
687 SetMem16(CommandLineWalker
, 10, L
' ');
688 if (StdOutFileName
!= NULL
) {
689 Status
= EFI_INVALID_PARAMETER
;
691 StdOutFileName
= CommandLineWalker
+= 5;
694 if (StrStr(CommandLineWalker
, L
" 1>> ") != NULL
) {
695 Status
= EFI_NOT_FOUND
;
698 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >> ")) != NULL
) {
699 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
700 SetMem16(CommandLineWalker
, 8, L
' ');
701 if (StdOutFileName
!= NULL
) {
702 Status
= EFI_INVALID_PARAMETER
;
704 StdOutFileName
= CommandLineWalker
+= 4;
707 if (StrStr(CommandLineWalker
, L
" >> ") != NULL
) {
708 Status
= EFI_NOT_FOUND
;
711 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>a ")) != NULL
) {
712 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
713 SetMem16(CommandLineWalker
, 10, L
' ');
714 if (StdOutFileName
!= NULL
) {
715 Status
= EFI_INVALID_PARAMETER
;
717 StdOutFileName
= CommandLineWalker
+= 5;
721 if (StrStr(CommandLineWalker
, L
" >>a ") != NULL
) {
722 Status
= EFI_NOT_FOUND
;
725 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>a ")) != NULL
) {
726 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
727 SetMem16(CommandLineWalker
, 10, L
' ');
728 if (StdOutFileName
!= NULL
) {
729 Status
= EFI_INVALID_PARAMETER
;
731 StdOutFileName
= CommandLineWalker
+= 5;
735 if (StrStr(CommandLineWalker
, L
" 1>a ") != NULL
) {
736 Status
= EFI_NOT_FOUND
;
739 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >a ")) != NULL
) {
740 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
741 SetMem16(CommandLineWalker
, 8, L
' ');
742 if (StdOutFileName
!= NULL
) {
743 Status
= EFI_INVALID_PARAMETER
;
745 StdOutFileName
= CommandLineWalker
+= 4;
749 if (StrStr(CommandLineWalker
, L
" >a ") != NULL
) {
750 Status
= EFI_NOT_FOUND
;
753 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>> ")) != NULL
) {
754 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
755 SetMem16(CommandLineWalker
, 10, L
' ');
756 if (StdErrFileName
!= NULL
) {
757 Status
= EFI_INVALID_PARAMETER
;
759 StdErrFileName
= CommandLineWalker
+= 5;
762 if (StrStr(CommandLineWalker
, L
" 2>> ") != NULL
) {
763 Status
= EFI_NOT_FOUND
;
767 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>v ")) != NULL
) {
768 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
769 SetMem16(CommandLineWalker
, 10, L
' ');
770 if (StdErrVarName
!= NULL
) {
771 Status
= EFI_INVALID_PARAMETER
;
773 StdErrVarName
= CommandLineWalker
+= 5;
776 if (StrStr(CommandLineWalker
, L
" 2>v ") != NULL
) {
777 Status
= EFI_NOT_FOUND
;
780 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>v ")) != NULL
) {
781 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
782 SetMem16(CommandLineWalker
, 10, L
' ');
783 if (StdOutVarName
!= NULL
) {
784 Status
= EFI_INVALID_PARAMETER
;
786 StdOutVarName
= CommandLineWalker
+= 5;
789 if (StrStr(CommandLineWalker
, L
" 1>v ") != NULL
) {
790 Status
= EFI_NOT_FOUND
;
793 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>a ")) != NULL
) {
794 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
795 SetMem16(CommandLineWalker
, 10, L
' ');
796 if (StdErrFileName
!= NULL
) {
797 Status
= EFI_INVALID_PARAMETER
;
799 StdErrFileName
= CommandLineWalker
+= 5;
803 if (StrStr(CommandLineWalker
, L
" 2>a ") != NULL
) {
804 Status
= EFI_NOT_FOUND
;
807 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2> ")) != NULL
) {
808 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
809 SetMem16(CommandLineWalker
, 8, L
' ');
810 if (StdErrFileName
!= NULL
) {
811 Status
= EFI_INVALID_PARAMETER
;
813 StdErrFileName
= CommandLineWalker
+= 4;
816 if (StrStr(CommandLineWalker
, L
" 2> ") != NULL
) {
817 Status
= EFI_NOT_FOUND
;
821 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1> ")) != NULL
) {
822 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
823 SetMem16(CommandLineWalker
, 8, L
' ');
824 if (StdOutFileName
!= NULL
) {
825 Status
= EFI_INVALID_PARAMETER
;
827 StdOutFileName
= CommandLineWalker
+= 4;
830 if (StrStr(CommandLineWalker
, L
" 1> ") != NULL
) {
831 Status
= EFI_NOT_FOUND
;
835 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" > ")) != NULL
) {
836 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
837 SetMem16(CommandLineWalker
, 6, L
' ');
838 if (StdOutFileName
!= NULL
) {
839 Status
= EFI_INVALID_PARAMETER
;
841 StdOutFileName
= CommandLineWalker
+= 3;
844 if (StrStr(CommandLineWalker
, L
" > ") != NULL
) {
845 Status
= EFI_NOT_FOUND
;
849 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" < ")) != NULL
) {
850 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
851 SetMem16(CommandLineWalker
, 6, L
' ');
852 if (StdInFileName
!= NULL
) {
853 Status
= EFI_INVALID_PARAMETER
;
855 StdInFileName
= CommandLineWalker
+= 3;
857 if (StrStr(CommandLineWalker
, L
" < ") != NULL
) {
858 Status
= EFI_NOT_FOUND
;
861 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <a ")) != NULL
) {
862 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
863 SetMem16(CommandLineWalker
, 8, L
' ');
864 if (StdInFileName
!= NULL
) {
865 Status
= EFI_INVALID_PARAMETER
;
867 StdInFileName
= CommandLineWalker
+= 4;
870 if (StrStr(CommandLineWalker
, L
" <a ") != NULL
) {
871 Status
= EFI_NOT_FOUND
;
874 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <v ")) != NULL
) {
875 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
876 SetMem16(CommandLineWalker
, 8, L
' ');
877 if (StdInVarName
!= NULL
) {
878 Status
= EFI_INVALID_PARAMETER
;
880 StdInVarName
= CommandLineWalker
+= 4;
882 if (StrStr(CommandLineWalker
, L
" <v ") != NULL
) {
883 Status
= EFI_NOT_FOUND
;
888 // re-populate the string to support any filenames that were in quotes.
890 StrCpy(CommandLineCopy
, NewCommandLine
);
892 if (FirstLocation
!= CommandLineCopy
+ StrLen(CommandLineCopy
)
893 && ((UINTN
)(FirstLocation
- CommandLineCopy
) < StrLen(NewCommandLine
))
895 *(NewCommandLine
+ (UINTN
)(FirstLocation
- CommandLineCopy
)) = CHAR_NULL
;
898 if (!EFI_ERROR(Status
)) {
900 if (StdErrFileName
!= NULL
) {
901 if ((StdErrFileName
= FixFileName(StdErrFileName
)) == NULL
) {
902 Status
= EFI_INVALID_PARAMETER
;
905 if (StdOutFileName
!= NULL
) {
906 if ((StdOutFileName
= FixFileName(StdOutFileName
)) == NULL
) {
907 Status
= EFI_INVALID_PARAMETER
;
910 if (StdInFileName
!= NULL
) {
911 if ((StdInFileName
= FixFileName(StdInFileName
)) == NULL
) {
912 Status
= EFI_INVALID_PARAMETER
;
915 if (StdErrVarName
!= NULL
) {
916 if ((StdErrVarName
= FixFileName(StdErrVarName
)) == NULL
) {
917 Status
= EFI_INVALID_PARAMETER
;
920 if (StdOutVarName
!= NULL
) {
921 if ((StdOutVarName
= FixFileName(StdOutVarName
)) == NULL
) {
922 Status
= EFI_INVALID_PARAMETER
;
925 if (StdInVarName
!= NULL
) {
926 if ((StdInVarName
= FixFileName(StdInVarName
)) == NULL
) {
927 Status
= EFI_INVALID_PARAMETER
;
932 // Verify not the same and not duplicating something from a split
936 // Check that no 2 filenames are the same
938 (StdErrFileName
!= NULL
&& StdOutFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdOutFileName
) == 0)
939 ||(StdErrFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdInFileName
) == 0)
940 ||(StdOutFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdOutFileName
, &StdInFileName
) == 0)
942 // Check that no 2 variable names are the same
944 ||(StdErrVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdInVarName
) == 0)
945 ||(StdOutVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdOutVarName
, &StdInVarName
) == 0)
946 ||(StdErrVarName
!= NULL
&& StdOutVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdOutVarName
) == 0)
948 // When a split (using | operator) is in place some are not allowed
950 ||(Split
!= NULL
&& Split
->SplitStdIn
!= NULL
&& (StdInVarName
!= NULL
|| StdInFileName
!= NULL
))
951 ||(Split
!= NULL
&& Split
->SplitStdOut
!= NULL
&& (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
))
953 // Check that nothing is trying to be output to 2 locations.
955 ||(StdErrFileName
!= NULL
&& StdErrVarName
!= NULL
)
956 ||(StdOutFileName
!= NULL
&& StdOutVarName
!= NULL
)
957 ||(StdInFileName
!= NULL
&& StdInVarName
!= NULL
)
959 // Check for no volatile environment variables
961 ||(StdErrVarName
!= NULL
&& !IsVolatileEnv(StdErrVarName
))
962 ||(StdOutVarName
!= NULL
&& !IsVolatileEnv(StdOutVarName
))
964 // Cant redirect during a reconnect operation.
966 ||(StrStr(NewCommandLine
, L
"connect -r") != NULL
967 && (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
|| StdErrFileName
!= NULL
|| StdErrVarName
!= NULL
))
969 // Check that filetypes (Unicode/Ascii) do not change during an append
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
))))
973 ||(StdOutFileName
!= NULL
&& !OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
974 ||(StdErrFileName
!= NULL
&& !ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
976 Status
= EFI_INVALID_PARAMETER
;
977 ShellParameters
->StdIn
= *OldStdIn
;
978 ShellParameters
->StdOut
= *OldStdOut
;
979 ShellParameters
->StdErr
= *OldStdErr
;
980 } else if (!EFI_ERROR(Status
)){
982 // Open the Std<Whatever> and we should not have conflicts here...
988 if (StdErrFileName
!= NULL
) {
991 // delete existing file.
993 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdErrFileName
);
995 Status
= ShellOpenFileByName(StdErrFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
996 if (!ErrAppend
&& ErrUnicode
&& !EFI_ERROR(Status
)) {
998 // Write out the gUnicodeFileTag
1000 Size
= sizeof(CHAR16
);
1001 TagBuffer
[0] = gUnicodeFileTag
;
1002 TagBuffer
[1] = CHAR_NULL
;
1003 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1005 if (!ErrUnicode
&& !EFI_ERROR(Status
)) {
1006 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1007 ASSERT(TempHandle
!= NULL
);
1009 if (!EFI_ERROR(Status
)) {
1010 ShellParameters
->StdErr
= TempHandle
;
1011 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1018 if (!EFI_ERROR(Status
) && StdOutFileName
!= NULL
) {
1021 // delete existing file.
1023 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdOutFileName
);
1025 Status
= ShellOpenFileByName(StdOutFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
1026 if (TempHandle
== NULL
) {
1027 Status
= EFI_INVALID_PARAMETER
;
1029 if (StrStr(StdOutFileName
, L
"NUL")==StdOutFileName
) {
1031 } else if (!OutAppend
&& OutUnicode
&& !EFI_ERROR(Status
)) {
1033 // Write out the gUnicodeFileTag
1035 Size
= sizeof(CHAR16
);
1036 TagBuffer
[0] = gUnicodeFileTag
;
1037 TagBuffer
[1] = CHAR_NULL
;
1038 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1039 } else if (OutAppend
) {
1041 // Move to end of file
1043 Status
= ShellInfoObject
.NewEfiShellProtocol
->GetFileSize(TempHandle
, &FileSize
);
1044 if (!EFI_ERROR(Status
)) {
1045 Status
= ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition(TempHandle
, FileSize
);
1048 if (!OutUnicode
&& !EFI_ERROR(Status
)) {
1049 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1050 ASSERT(TempHandle
!= NULL
);
1052 if (!EFI_ERROR(Status
)) {
1053 ShellParameters
->StdOut
= TempHandle
;
1054 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1062 if (!EFI_ERROR(Status
) && StdOutVarName
!= NULL
) {
1065 // delete existing variable.
1067 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName
, 0, L
"");
1069 TempHandle
= CreateFileInterfaceEnv(StdOutVarName
);
1070 ASSERT(TempHandle
!= NULL
);
1071 ShellParameters
->StdOut
= TempHandle
;
1072 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1078 if (!EFI_ERROR(Status
) && StdErrVarName
!= NULL
) {
1081 // delete existing variable.
1083 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName
, 0, L
"");
1085 TempHandle
= CreateFileInterfaceEnv(StdErrVarName
);
1086 ASSERT(TempHandle
!= NULL
);
1087 ShellParameters
->StdErr
= TempHandle
;
1088 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1094 if (!EFI_ERROR(Status
) && StdInVarName
!= NULL
) {
1095 TempHandle
= CreateFileInterfaceEnv(StdInVarName
);
1096 if (TempHandle
== NULL
) {
1097 Status
= EFI_OUT_OF_RESOURCES
;
1100 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1103 if (TempHandle
== NULL
|| ((EFI_FILE_PROTOCOL
*)TempHandle
)->Read(TempHandle
, &Size
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
1104 Status
= EFI_INVALID_PARAMETER
;
1106 ShellParameters
->StdIn
= TempHandle
;
1107 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1113 // StdIn from a file
1115 if (!EFI_ERROR(Status
) && StdInFileName
!= NULL
) {
1116 Status
= ShellOpenFileByName(
1121 if (!InUnicode
&& !EFI_ERROR(Status
)) {
1122 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1124 if (!EFI_ERROR(Status
)) {
1125 ShellParameters
->StdIn
= TempHandle
;
1126 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1131 FreePool(CommandLineCopy
);
1133 CalculateEfiHdrCrc(&gST
->Hdr
);
1135 if (gST
->ConIn
== NULL
||gST
->ConOut
== NULL
) {
1136 return (EFI_OUT_OF_RESOURCES
);
1142 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1143 structure with StdIn and StdOut. The current values are de-allocated.
1145 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1146 @param[in] OldStdIn Pointer to old StdIn.
1147 @param[in] OldStdOut Pointer to old StdOut.
1148 @param[in] OldStdErr Pointer to old StdErr.
1149 @param[in] SystemTableInfo Pointer to old system table information.
1153 RestoreStdInStdOutStdErr (
1154 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1155 IN SHELL_FILE_HANDLE
*OldStdIn
,
1156 IN SHELL_FILE_HANDLE
*OldStdOut
,
1157 IN SHELL_FILE_HANDLE
*OldStdErr
,
1158 IN SYSTEM_TABLE_INFO
*SystemTableInfo
1163 if (ShellParameters
== NULL
1167 ||SystemTableInfo
== NULL
) {
1168 return (EFI_INVALID_PARAMETER
);
1170 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1171 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1175 if (ShellParameters
->StdIn
!= *OldStdIn
) {
1176 if ((Split
!= NULL
&& Split
->SplitStdIn
!= ShellParameters
->StdIn
) || Split
== NULL
) {
1177 gEfiShellProtocol
->CloseFile(ShellParameters
->StdIn
);
1179 ShellParameters
->StdIn
= *OldStdIn
;
1181 if (ShellParameters
->StdOut
!= *OldStdOut
) {
1182 if ((Split
!= NULL
&& Split
->SplitStdOut
!= ShellParameters
->StdOut
) || Split
== NULL
) {
1183 gEfiShellProtocol
->CloseFile(ShellParameters
->StdOut
);
1185 ShellParameters
->StdOut
= *OldStdOut
;
1187 if (ShellParameters
->StdErr
!= *OldStdErr
) {
1188 gEfiShellProtocol
->CloseFile(ShellParameters
->StdErr
);
1189 ShellParameters
->StdErr
= *OldStdErr
;
1192 if (gST
->ConIn
!= SystemTableInfo
->ConIn
) {
1193 CloseSimpleTextInOnFile(gST
->ConIn
);
1194 gST
->ConIn
= SystemTableInfo
->ConIn
;
1195 gST
->ConsoleInHandle
= SystemTableInfo
->ConInHandle
;
1197 if (gST
->ConOut
!= SystemTableInfo
->ConOut
) {
1198 CloseSimpleTextOutOnFile(gST
->ConOut
);
1199 gST
->ConOut
= SystemTableInfo
->ConOut
;
1200 gST
->ConsoleOutHandle
= SystemTableInfo
->ConOutHandle
;
1202 if (gST
->StdErr
!= SystemTableInfo
->ErrOut
) {
1203 CloseSimpleTextOutOnFile(gST
->StdErr
);
1204 gST
->StdErr
= SystemTableInfo
->ErrOut
;
1205 gST
->StandardErrorHandle
= SystemTableInfo
->ErrOutHandle
;
1208 CalculateEfiHdrCrc(&gST
->Hdr
);
1210 return (EFI_SUCCESS
);
1213 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1214 structure by parsing NewCommandLine. The current values are returned to the
1217 If OldArgv or OldArgc is NULL then that value is not returned.
1219 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1220 @param[in] NewCommandLine The new command line to parse and use.
1221 @param[out] OldArgv Pointer to old list of parameters.
1222 @param[out] OldArgc Pointer to old number of items in Argv list.
1224 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
1225 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1230 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1231 IN CONST CHAR16
*NewCommandLine
,
1232 OUT CHAR16
***OldArgv OPTIONAL
,
1233 OUT UINTN
*OldArgc OPTIONAL
1236 ASSERT(ShellParameters
!= NULL
);
1238 if (OldArgc
!= NULL
) {
1239 *OldArgc
= ShellParameters
->Argc
;
1241 if (OldArgc
!= NULL
) {
1242 *OldArgv
= ShellParameters
->Argv
;
1245 return (ParseCommandLineToArgs(NewCommandLine
, &(ShellParameters
->Argv
), &(ShellParameters
->Argc
)));
1249 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1250 structure with Argv and Argc. The current values are de-allocated and the
1251 OldArgv must not be deallocated by the caller.
1253 @param[in, out] ShellParameters pointer to parameter structure to modify
1254 @param[in] OldArgv pointer to old list of parameters
1255 @param[in] OldArgc pointer to old number of items in Argv list
1260 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1261 IN CHAR16
***OldArgv
,
1266 ASSERT(ShellParameters
!= NULL
);
1267 ASSERT(OldArgv
!= NULL
);
1268 ASSERT(OldArgc
!= NULL
);
1270 if (ShellParameters
->Argv
!= NULL
) {
1271 for ( LoopCounter
= 0
1272 ; LoopCounter
< ShellParameters
->Argc
1275 FreePool(ShellParameters
->Argv
[LoopCounter
]);
1277 FreePool(ShellParameters
->Argv
);
1279 ShellParameters
->Argv
= *OldArgv
;
1281 ShellParameters
->Argc
= *OldArgc
;