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.
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 if (LoadedImage
->LoadOptionsSize
!= 0){
317 StrCpy(FullCommandLine
, LoadedImage
->LoadOptions
);
320 // Populate Argc and Argv
322 Status
= ParseCommandLineToArgs(FullCommandLine
,
323 &(*NewShellParameters
)->Argv
,
324 &(*NewShellParameters
)->Argc
);
326 FreePool(FullCommandLine
);
328 ASSERT_EFI_ERROR(Status
);
330 (*NewShellParameters
)->Argv
= NULL
;
331 (*NewShellParameters
)->Argc
= 0;
335 // Populate the 3 faked file systems...
337 if (*RootShellInstance
) {
338 (*NewShellParameters
)->StdIn
= &FileInterfaceStdIn
;
339 (*NewShellParameters
)->StdOut
= &FileInterfaceStdOut
;
340 (*NewShellParameters
)->StdErr
= &FileInterfaceStdErr
;
341 Status
= gBS
->InstallProtocolInterface(&gImageHandle
,
342 &gEfiShellParametersProtocolGuid
,
343 EFI_NATIVE_INTERFACE
,
344 (VOID
*)(*NewShellParameters
));
347 // copy from the existing ones
349 (*NewShellParameters
)->StdIn
= ShellInfoObject
.OldShellParameters
->StdIn
;
350 (*NewShellParameters
)->StdOut
= ShellInfoObject
.OldShellParameters
->StdOut
;
351 (*NewShellParameters
)->StdErr
= ShellInfoObject
.OldShellParameters
->StdErr
;
352 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
353 &gEfiShellParametersProtocolGuid
,
354 (VOID
*)ShellInfoObject
.OldShellParameters
,
355 (VOID
*)(*NewShellParameters
));
362 frees all memory used by createion and installation of shell parameters protocol
363 and if there was an old version installed it will restore that one.
365 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
368 @retval EFI_SUCCESS the cleanup was successful
369 @return other the cleanup failed
370 @sa ReinstallProtocolInterface
371 @sa UninstallProtocolInterface
375 CleanUpShellParametersProtocol (
376 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*NewShellParameters
383 // If the old exists we need to restore it
385 if (ShellInfoObject
.OldShellParameters
!= NULL
) {
386 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
387 &gEfiShellParametersProtocolGuid
,
388 (VOID
*)NewShellParameters
,
389 (VOID
*)ShellInfoObject
.OldShellParameters
);
390 DEBUG_CODE(ShellInfoObject
.OldShellParameters
= NULL
;);
393 // No old one, just uninstall us...
395 Status
= gBS
->UninstallProtocolInterface(gImageHandle
,
396 &gEfiShellParametersProtocolGuid
,
397 (VOID
*)NewShellParameters
);
399 if (NewShellParameters
->Argv
!= NULL
) {
400 for ( LoopCounter
= 0
401 ; LoopCounter
< NewShellParameters
->Argc
404 FreePool(NewShellParameters
->Argv
[LoopCounter
]);
406 FreePool(NewShellParameters
->Argv
);
408 FreePool(NewShellParameters
);
413 Determin if a file name represents a unicode file.
415 @param[in] FileName Pointer to the filename to open.
417 @retval EFI_SUCCESS The file is a unicode file.
418 @return An error upon failure.
423 IN CONST CHAR16
*FileName
426 SHELL_FILE_HANDLE Handle
;
428 UINT64 OriginalFilePosition
;
432 Status
= gEfiShellProtocol
->OpenFileByName(FileName
, &Handle
, EFI_FILE_MODE_READ
);
433 if (EFI_ERROR(Status
)) {
436 gEfiShellProtocol
->GetFilePosition(Handle
, &OriginalFilePosition
);
437 gEfiShellProtocol
->SetFilePosition(Handle
, 0);
438 CharSize
= sizeof(CHAR16
);
439 Status
= gEfiShellProtocol
->ReadFile(Handle
, &CharSize
, &CharBuffer
);
440 if (EFI_ERROR(Status
) || CharBuffer
!= gUnicodeFileTag
) {
441 Status
= EFI_BUFFER_TOO_SMALL
;
443 gEfiShellProtocol
->SetFilePosition(Handle
, OriginalFilePosition
);
444 gEfiShellProtocol
->CloseFile(Handle
);
449 Strips out quotes sections of a string.
451 All of the characters between quotes is replaced with spaces.
453 @param[in, out] TheString A pointer to the string to update.
458 IN OUT CHAR16
*TheString
463 for (RemoveNow
= FALSE
; TheString
!= NULL
&& *TheString
!= CHAR_NULL
; TheString
++) {
464 if (*TheString
== L
'^' && *(TheString
+ 1) == L
'\"') {
466 } else if (*TheString
== L
'\"') {
467 RemoveNow
= (BOOLEAN
)!RemoveNow
;
468 } else if (RemoveNow
) {
475 Calcualte the 32-bit CRC in a EFI table using the service provided by the
478 @param Hdr Pointer to an EFI standard header
483 IN OUT EFI_TABLE_HEADER
*Hdr
491 // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
492 // Crc will come back as zero if we set it to zero here
495 gBS
->CalculateCrc32 ((UINT8
*)Hdr
, Hdr
->HeaderSize
, &Crc
);
500 Fix a string to only have the file name, removing starting at the first space of whatever is quoted.
502 @param[in] FileName The filename to start with.
504 @retval NULL FileName was invalid.
505 @return The modified FileName.
514 CHAR16
*TempLocation
;
516 if (FileName
== NULL
) {
520 if (FileName
[0] == L
'\"') {
522 if ((TempLocation
= StrStr(Copy
, L
"\"")) != NULL
) {
523 TempLocation
[0] = CHAR_NULL
;
527 while(Copy
[0] == L
' ') {
530 if ((TempLocation
= StrStr(Copy
, L
" ")) != NULL
) {
531 TempLocation
[0] = CHAR_NULL
;
535 if (Copy
[0] == CHAR_NULL
) {
543 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
544 structure by parsing NewCommandLine. The current values are returned to the
547 This will also update the system table.
549 @param[in, out] ShellParameters Pointer to parameter structure to modify.
550 @param[in] NewCommandLine The new command line to parse and use.
551 @param[out] OldStdIn Pointer to old StdIn.
552 @param[out] OldStdOut Pointer to old StdOut.
553 @param[out] OldStdErr Pointer to old StdErr.
554 @param[out] SystemTableInfo Pointer to old system table information.
556 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
557 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
561 UpdateStdInStdOutStdErr(
562 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
563 IN CHAR16
*NewCommandLine
,
564 OUT SHELL_FILE_HANDLE
*OldStdIn
,
565 OUT SHELL_FILE_HANDLE
*OldStdOut
,
566 OUT SHELL_FILE_HANDLE
*OldStdErr
,
567 OUT SYSTEM_TABLE_INFO
*SystemTableInfo
570 CHAR16
*CommandLineCopy
;
571 CHAR16
*CommandLineWalker
;
572 CHAR16
*StdErrFileName
;
573 CHAR16
*StdOutFileName
;
574 CHAR16
*StdInFileName
;
575 CHAR16
*StdInVarName
;
576 CHAR16
*StdOutVarName
;
577 CHAR16
*StdErrVarName
;
579 SHELL_FILE_HANDLE TempHandle
;
589 CHAR16
*FirstLocation
;
595 StdOutVarName
= NULL
;
596 StdErrVarName
= NULL
;
597 StdErrFileName
= NULL
;
598 StdInFileName
= NULL
;
599 StdOutFileName
= NULL
;
602 CommandLineCopy
= NULL
;
603 FirstLocation
= NULL
;
605 if (ShellParameters
== NULL
|| SystemTableInfo
== NULL
|| OldStdIn
== NULL
|| OldStdOut
== NULL
|| OldStdErr
== NULL
) {
606 return (EFI_INVALID_PARAMETER
);
609 SystemTableInfo
->ConIn
= gST
->ConIn
;
610 SystemTableInfo
->ConInHandle
= gST
->ConsoleInHandle
;
611 SystemTableInfo
->ConOut
= gST
->ConOut
;
612 SystemTableInfo
->ConOutHandle
= gST
->ConsoleOutHandle
;
613 SystemTableInfo
->ErrOut
= gST
->StdErr
;
614 SystemTableInfo
->ErrOutHandle
= gST
->StandardErrorHandle
;
615 *OldStdIn
= ShellParameters
->StdIn
;
616 *OldStdOut
= ShellParameters
->StdOut
;
617 *OldStdErr
= ShellParameters
->StdErr
;
619 if (NewCommandLine
== NULL
) {
620 return (EFI_SUCCESS
);
623 CommandLineCopy
= StrnCatGrow(&CommandLineCopy
, NULL
, NewCommandLine
, 0);
624 if (CommandLineCopy
== NULL
) {
625 return (EFI_OUT_OF_RESOURCES
);
627 Status
= EFI_SUCCESS
;
629 FirstLocation
= CommandLineCopy
+ StrLen(CommandLineCopy
);
631 StripQuotes(CommandLineCopy
);
633 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
634 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
635 if (Split
!= NULL
&& Split
->SplitStdIn
!= NULL
) {
636 ShellParameters
->StdIn
= Split
->SplitStdIn
;
638 if (Split
!= NULL
&& Split
->SplitStdOut
!= NULL
) {
639 ShellParameters
->StdOut
= Split
->SplitStdOut
;
643 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>>v ")) != NULL
) {
644 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
645 SetMem16(CommandLineWalker
, 12, L
' ');
646 StdErrVarName
= CommandLineWalker
+= 6;
648 if (StrStr(CommandLineWalker
, L
" 2>>v ") != NULL
) {
649 Status
= EFI_NOT_FOUND
;
652 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>v ")) != NULL
) {
653 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
654 SetMem16(CommandLineWalker
, 12, L
' ');
655 StdOutVarName
= CommandLineWalker
+= 6;
657 if (StrStr(CommandLineWalker
, L
" 1>>v ") != NULL
) {
658 Status
= EFI_NOT_FOUND
;
660 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>v ")) != NULL
) {
661 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
662 SetMem16(CommandLineWalker
, 10, L
' ');
663 StdOutVarName
= CommandLineWalker
+= 5;
665 if (StrStr(CommandLineWalker
, L
" >>v ") != NULL
) {
666 Status
= EFI_NOT_FOUND
;
668 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >v ")) != NULL
) {
669 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
670 SetMem16(CommandLineWalker
, 8, L
' ');
671 StdOutVarName
= CommandLineWalker
+= 4;
673 if (StrStr(CommandLineWalker
, L
" >v ") != NULL
) {
674 Status
= EFI_NOT_FOUND
;
677 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>a ")) != NULL
) {
678 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
679 SetMem16(CommandLineWalker
, 12, L
' ');
680 StdOutFileName
= CommandLineWalker
+= 6;
683 if (StrStr(CommandLineWalker
, L
" 1>>a ") != NULL
) {
684 Status
= EFI_NOT_FOUND
;
687 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>> ")) != NULL
) {
688 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
689 SetMem16(CommandLineWalker
, 10, L
' ');
690 if (StdOutFileName
!= NULL
) {
691 Status
= EFI_INVALID_PARAMETER
;
693 StdOutFileName
= CommandLineWalker
+= 5;
696 if (StrStr(CommandLineWalker
, L
" 1>> ") != NULL
) {
697 Status
= EFI_NOT_FOUND
;
700 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >> ")) != NULL
) {
701 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
702 SetMem16(CommandLineWalker
, 8, L
' ');
703 if (StdOutFileName
!= NULL
) {
704 Status
= EFI_INVALID_PARAMETER
;
706 StdOutFileName
= CommandLineWalker
+= 4;
709 if (StrStr(CommandLineWalker
, L
" >> ") != NULL
) {
710 Status
= EFI_NOT_FOUND
;
713 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>a ")) != NULL
) {
714 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
715 SetMem16(CommandLineWalker
, 10, L
' ');
716 if (StdOutFileName
!= NULL
) {
717 Status
= EFI_INVALID_PARAMETER
;
719 StdOutFileName
= CommandLineWalker
+= 5;
723 if (StrStr(CommandLineWalker
, L
" >>a ") != NULL
) {
724 Status
= EFI_NOT_FOUND
;
727 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>a ")) != NULL
) {
728 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
729 SetMem16(CommandLineWalker
, 10, L
' ');
730 if (StdOutFileName
!= NULL
) {
731 Status
= EFI_INVALID_PARAMETER
;
733 StdOutFileName
= CommandLineWalker
+= 5;
737 if (StrStr(CommandLineWalker
, L
" 1>a ") != NULL
) {
738 Status
= EFI_NOT_FOUND
;
741 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >a ")) != NULL
) {
742 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
743 SetMem16(CommandLineWalker
, 8, L
' ');
744 if (StdOutFileName
!= NULL
) {
745 Status
= EFI_INVALID_PARAMETER
;
747 StdOutFileName
= CommandLineWalker
+= 4;
751 if (StrStr(CommandLineWalker
, L
" >a ") != NULL
) {
752 Status
= EFI_NOT_FOUND
;
755 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>> ")) != NULL
) {
756 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
757 SetMem16(CommandLineWalker
, 10, L
' ');
758 if (StdErrFileName
!= NULL
) {
759 Status
= EFI_INVALID_PARAMETER
;
761 StdErrFileName
= CommandLineWalker
+= 5;
764 if (StrStr(CommandLineWalker
, L
" 2>> ") != NULL
) {
765 Status
= EFI_NOT_FOUND
;
769 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>v ")) != NULL
) {
770 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
771 SetMem16(CommandLineWalker
, 10, L
' ');
772 if (StdErrVarName
!= NULL
) {
773 Status
= EFI_INVALID_PARAMETER
;
775 StdErrVarName
= CommandLineWalker
+= 5;
778 if (StrStr(CommandLineWalker
, L
" 2>v ") != NULL
) {
779 Status
= EFI_NOT_FOUND
;
782 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>v ")) != NULL
) {
783 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
784 SetMem16(CommandLineWalker
, 10, L
' ');
785 if (StdOutVarName
!= NULL
) {
786 Status
= EFI_INVALID_PARAMETER
;
788 StdOutVarName
= CommandLineWalker
+= 5;
791 if (StrStr(CommandLineWalker
, L
" 1>v ") != NULL
) {
792 Status
= EFI_NOT_FOUND
;
795 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>a ")) != NULL
) {
796 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
797 SetMem16(CommandLineWalker
, 10, L
' ');
798 if (StdErrFileName
!= NULL
) {
799 Status
= EFI_INVALID_PARAMETER
;
801 StdErrFileName
= CommandLineWalker
+= 5;
805 if (StrStr(CommandLineWalker
, L
" 2>a ") != NULL
) {
806 Status
= EFI_NOT_FOUND
;
809 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2> ")) != NULL
) {
810 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
811 SetMem16(CommandLineWalker
, 8, L
' ');
812 if (StdErrFileName
!= NULL
) {
813 Status
= EFI_INVALID_PARAMETER
;
815 StdErrFileName
= CommandLineWalker
+= 4;
818 if (StrStr(CommandLineWalker
, L
" 2> ") != NULL
) {
819 Status
= EFI_NOT_FOUND
;
823 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1> ")) != NULL
) {
824 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
825 SetMem16(CommandLineWalker
, 8, L
' ');
826 if (StdOutFileName
!= NULL
) {
827 Status
= EFI_INVALID_PARAMETER
;
829 StdOutFileName
= CommandLineWalker
+= 4;
832 if (StrStr(CommandLineWalker
, L
" 1> ") != NULL
) {
833 Status
= EFI_NOT_FOUND
;
837 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" > ")) != NULL
) {
838 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
839 SetMem16(CommandLineWalker
, 6, L
' ');
840 if (StdOutFileName
!= NULL
) {
841 Status
= EFI_INVALID_PARAMETER
;
843 StdOutFileName
= CommandLineWalker
+= 3;
846 if (StrStr(CommandLineWalker
, L
" > ") != NULL
) {
847 Status
= EFI_NOT_FOUND
;
851 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" < ")) != NULL
) {
852 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
853 SetMem16(CommandLineWalker
, 6, L
' ');
854 if (StdInFileName
!= NULL
) {
855 Status
= EFI_INVALID_PARAMETER
;
857 StdInFileName
= CommandLineWalker
+= 3;
859 if (StrStr(CommandLineWalker
, L
" < ") != NULL
) {
860 Status
= EFI_NOT_FOUND
;
863 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <a ")) != NULL
) {
864 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
865 SetMem16(CommandLineWalker
, 8, L
' ');
866 if (StdInFileName
!= NULL
) {
867 Status
= EFI_INVALID_PARAMETER
;
869 StdInFileName
= CommandLineWalker
+= 4;
872 if (StrStr(CommandLineWalker
, L
" <a ") != NULL
) {
873 Status
= EFI_NOT_FOUND
;
876 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <v ")) != NULL
) {
877 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
878 SetMem16(CommandLineWalker
, 8, L
' ');
879 if (StdInVarName
!= NULL
) {
880 Status
= EFI_INVALID_PARAMETER
;
882 StdInVarName
= CommandLineWalker
+= 4;
884 if (StrStr(CommandLineWalker
, L
" <v ") != NULL
) {
885 Status
= EFI_NOT_FOUND
;
890 // re-populate the string to support any filenames that were in quotes.
892 StrCpy(CommandLineCopy
, NewCommandLine
);
894 if (FirstLocation
!= CommandLineCopy
+ StrLen(CommandLineCopy
)
895 && ((UINTN
)(FirstLocation
- CommandLineCopy
) < StrLen(NewCommandLine
))
897 *(NewCommandLine
+ (UINTN
)(FirstLocation
- CommandLineCopy
)) = CHAR_NULL
;
900 if (!EFI_ERROR(Status
)) {
902 if (StdErrFileName
!= NULL
) {
903 if ((StdErrFileName
= FixFileName(StdErrFileName
)) == NULL
) {
904 Status
= EFI_INVALID_PARAMETER
;
907 if (StdOutFileName
!= NULL
) {
908 if ((StdOutFileName
= FixFileName(StdOutFileName
)) == NULL
) {
909 Status
= EFI_INVALID_PARAMETER
;
912 if (StdInFileName
!= NULL
) {
913 if ((StdInFileName
= FixFileName(StdInFileName
)) == NULL
) {
914 Status
= EFI_INVALID_PARAMETER
;
917 if (StdErrVarName
!= NULL
) {
918 if ((StdErrVarName
= FixFileName(StdErrVarName
)) == NULL
) {
919 Status
= EFI_INVALID_PARAMETER
;
922 if (StdOutVarName
!= NULL
) {
923 if ((StdOutVarName
= FixFileName(StdOutVarName
)) == NULL
) {
924 Status
= EFI_INVALID_PARAMETER
;
927 if (StdInVarName
!= NULL
) {
928 if ((StdInVarName
= FixFileName(StdInVarName
)) == NULL
) {
929 Status
= EFI_INVALID_PARAMETER
;
934 // Verify not the same and not duplicating something from a split
938 // Check that no 2 filenames are the same
940 (StdErrFileName
!= NULL
&& StdOutFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdOutFileName
) == 0)
941 ||(StdErrFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdInFileName
) == 0)
942 ||(StdOutFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdOutFileName
, &StdInFileName
) == 0)
944 // Check that no 2 variable names are the same
946 ||(StdErrVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdInVarName
) == 0)
947 ||(StdOutVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdOutVarName
, &StdInVarName
) == 0)
948 ||(StdErrVarName
!= NULL
&& StdOutVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdOutVarName
) == 0)
950 // When a split (using | operator) is in place some are not allowed
952 ||(Split
!= NULL
&& Split
->SplitStdIn
!= NULL
&& (StdInVarName
!= NULL
|| StdInFileName
!= NULL
))
953 ||(Split
!= NULL
&& Split
->SplitStdOut
!= NULL
&& (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
))
955 // Check that nothing is trying to be output to 2 locations.
957 ||(StdErrFileName
!= NULL
&& StdErrVarName
!= NULL
)
958 ||(StdOutFileName
!= NULL
&& StdOutVarName
!= NULL
)
959 ||(StdInFileName
!= NULL
&& StdInVarName
!= NULL
)
961 // Check for no volatile environment variables
963 ||(StdErrVarName
!= NULL
&& !IsVolatileEnv(StdErrVarName
))
964 ||(StdOutVarName
!= NULL
&& !IsVolatileEnv(StdOutVarName
))
966 // Cant redirect during a reconnect operation.
968 ||(StrStr(NewCommandLine
, L
"connect -r") != NULL
969 && (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
|| StdErrFileName
!= NULL
|| StdErrVarName
!= NULL
))
971 // Check that filetypes (Unicode/Ascii) do not change during an append
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
))))
975 ||(StdOutFileName
!= NULL
&& !OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
976 ||(StdErrFileName
!= NULL
&& !ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
978 Status
= EFI_INVALID_PARAMETER
;
979 ShellParameters
->StdIn
= *OldStdIn
;
980 ShellParameters
->StdOut
= *OldStdOut
;
981 ShellParameters
->StdErr
= *OldStdErr
;
982 } else if (!EFI_ERROR(Status
)){
984 // Open the Std<Whatever> and we should not have conflicts here...
990 if (StdErrFileName
!= NULL
) {
993 // delete existing file.
995 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdErrFileName
);
997 Status
= ShellOpenFileByName(StdErrFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
998 if (!ErrAppend
&& ErrUnicode
&& !EFI_ERROR(Status
)) {
1000 // Write out the gUnicodeFileTag
1002 Size
= sizeof(CHAR16
);
1003 TagBuffer
[0] = gUnicodeFileTag
;
1004 TagBuffer
[1] = CHAR_NULL
;
1005 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1007 if (!ErrUnicode
&& !EFI_ERROR(Status
)) {
1008 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1009 ASSERT(TempHandle
!= NULL
);
1011 if (!EFI_ERROR(Status
)) {
1012 ShellParameters
->StdErr
= TempHandle
;
1013 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1020 if (!EFI_ERROR(Status
) && StdOutFileName
!= NULL
) {
1023 // delete existing file.
1025 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdOutFileName
);
1027 Status
= ShellOpenFileByName(StdOutFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
1028 if (TempHandle
== NULL
) {
1029 Status
= EFI_INVALID_PARAMETER
;
1031 if (StrStr(StdOutFileName
, L
"NUL")==StdOutFileName
) {
1033 } else if (!OutAppend
&& OutUnicode
&& !EFI_ERROR(Status
)) {
1035 // Write out the gUnicodeFileTag
1037 Size
= sizeof(CHAR16
);
1038 TagBuffer
[0] = gUnicodeFileTag
;
1039 TagBuffer
[1] = CHAR_NULL
;
1040 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
1041 } else if (OutAppend
) {
1043 // Move to end of file
1045 Status
= ShellInfoObject
.NewEfiShellProtocol
->GetFileSize(TempHandle
, &FileSize
);
1046 if (!EFI_ERROR(Status
)) {
1047 Status
= ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition(TempHandle
, FileSize
);
1050 if (!OutUnicode
&& !EFI_ERROR(Status
)) {
1051 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1052 ASSERT(TempHandle
!= NULL
);
1054 if (!EFI_ERROR(Status
)) {
1055 ShellParameters
->StdOut
= TempHandle
;
1056 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1064 if (!EFI_ERROR(Status
) && StdOutVarName
!= NULL
) {
1067 // delete existing variable.
1069 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName
, 0, L
"");
1071 TempHandle
= CreateFileInterfaceEnv(StdOutVarName
);
1072 ASSERT(TempHandle
!= NULL
);
1073 ShellParameters
->StdOut
= TempHandle
;
1074 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
1080 if (!EFI_ERROR(Status
) && StdErrVarName
!= NULL
) {
1083 // delete existing variable.
1085 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName
, 0, L
"");
1087 TempHandle
= CreateFileInterfaceEnv(StdErrVarName
);
1088 ASSERT(TempHandle
!= NULL
);
1089 ShellParameters
->StdErr
= TempHandle
;
1090 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1096 if (!EFI_ERROR(Status
) && StdInVarName
!= NULL
) {
1097 TempHandle
= CreateFileInterfaceEnv(StdInVarName
);
1098 if (TempHandle
== NULL
) {
1099 Status
= EFI_OUT_OF_RESOURCES
;
1102 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1105 if (TempHandle
== NULL
|| ((EFI_FILE_PROTOCOL
*)TempHandle
)->Read(TempHandle
, &Size
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
1106 Status
= EFI_INVALID_PARAMETER
;
1108 ShellParameters
->StdIn
= TempHandle
;
1109 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1115 // StdIn from a file
1117 if (!EFI_ERROR(Status
) && StdInFileName
!= NULL
) {
1118 Status
= ShellOpenFileByName(
1123 if (!InUnicode
&& !EFI_ERROR(Status
)) {
1124 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1126 if (!EFI_ERROR(Status
)) {
1127 ShellParameters
->StdIn
= TempHandle
;
1128 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1133 FreePool(CommandLineCopy
);
1135 CalculateEfiHdrCrc(&gST
->Hdr
);
1137 if (gST
->ConIn
== NULL
||gST
->ConOut
== NULL
) {
1138 return (EFI_OUT_OF_RESOURCES
);
1144 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1145 structure with StdIn and StdOut. The current values are de-allocated.
1147 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1148 @param[in] OldStdIn Pointer to old StdIn.
1149 @param[in] OldStdOut Pointer to old StdOut.
1150 @param[in] OldStdErr Pointer to old StdErr.
1151 @param[in] SystemTableInfo Pointer to old system table information.
1155 RestoreStdInStdOutStdErr (
1156 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1157 IN SHELL_FILE_HANDLE
*OldStdIn
,
1158 IN SHELL_FILE_HANDLE
*OldStdOut
,
1159 IN SHELL_FILE_HANDLE
*OldStdErr
,
1160 IN SYSTEM_TABLE_INFO
*SystemTableInfo
1165 if (ShellParameters
== NULL
1169 ||SystemTableInfo
== NULL
) {
1170 return (EFI_INVALID_PARAMETER
);
1172 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1173 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1177 if (ShellParameters
->StdIn
!= *OldStdIn
) {
1178 if ((Split
!= NULL
&& Split
->SplitStdIn
!= ShellParameters
->StdIn
) || Split
== NULL
) {
1179 gEfiShellProtocol
->CloseFile(ShellParameters
->StdIn
);
1181 ShellParameters
->StdIn
= *OldStdIn
;
1183 if (ShellParameters
->StdOut
!= *OldStdOut
) {
1184 if ((Split
!= NULL
&& Split
->SplitStdOut
!= ShellParameters
->StdOut
) || Split
== NULL
) {
1185 gEfiShellProtocol
->CloseFile(ShellParameters
->StdOut
);
1187 ShellParameters
->StdOut
= *OldStdOut
;
1189 if (ShellParameters
->StdErr
!= *OldStdErr
) {
1190 gEfiShellProtocol
->CloseFile(ShellParameters
->StdErr
);
1191 ShellParameters
->StdErr
= *OldStdErr
;
1194 if (gST
->ConIn
!= SystemTableInfo
->ConIn
) {
1195 CloseSimpleTextInOnFile(gST
->ConIn
);
1196 gST
->ConIn
= SystemTableInfo
->ConIn
;
1197 gST
->ConsoleInHandle
= SystemTableInfo
->ConInHandle
;
1199 if (gST
->ConOut
!= SystemTableInfo
->ConOut
) {
1200 CloseSimpleTextOutOnFile(gST
->ConOut
);
1201 gST
->ConOut
= SystemTableInfo
->ConOut
;
1202 gST
->ConsoleOutHandle
= SystemTableInfo
->ConOutHandle
;
1204 if (gST
->StdErr
!= SystemTableInfo
->ErrOut
) {
1205 CloseSimpleTextOutOnFile(gST
->StdErr
);
1206 gST
->StdErr
= SystemTableInfo
->ErrOut
;
1207 gST
->StandardErrorHandle
= SystemTableInfo
->ErrOutHandle
;
1210 CalculateEfiHdrCrc(&gST
->Hdr
);
1212 return (EFI_SUCCESS
);
1215 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1216 structure by parsing NewCommandLine. The current values are returned to the
1219 If OldArgv or OldArgc is NULL then that value is not returned.
1221 @param[in, out] ShellParameters Pointer to parameter structure to modify.
1222 @param[in] NewCommandLine The new command line to parse and use.
1223 @param[out] OldArgv Pointer to old list of parameters.
1224 @param[out] OldArgc Pointer to old number of items in Argv list.
1226 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
1227 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1232 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1233 IN CONST CHAR16
*NewCommandLine
,
1234 OUT CHAR16
***OldArgv OPTIONAL
,
1235 OUT UINTN
*OldArgc OPTIONAL
1238 ASSERT(ShellParameters
!= NULL
);
1240 if (OldArgc
!= NULL
) {
1241 *OldArgc
= ShellParameters
->Argc
;
1243 if (OldArgc
!= NULL
) {
1244 *OldArgv
= ShellParameters
->Argv
;
1247 return (ParseCommandLineToArgs(NewCommandLine
, &(ShellParameters
->Argv
), &(ShellParameters
->Argc
)));
1251 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1252 structure with Argv and Argc. The current values are de-allocated and the
1253 OldArgv must not be deallocated by the caller.
1255 @param[in, out] ShellParameters pointer to parameter structure to modify
1256 @param[in] OldArgv pointer to old list of parameters
1257 @param[in] OldArgc pointer to old number of items in Argv list
1262 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1263 IN CHAR16
***OldArgv
,
1268 ASSERT(ShellParameters
!= NULL
);
1269 ASSERT(OldArgv
!= NULL
);
1270 ASSERT(OldArgc
!= NULL
);
1272 if (ShellParameters
->Argv
!= NULL
) {
1273 for ( LoopCounter
= 0
1274 ; LoopCounter
< ShellParameters
->Argc
1277 FreePool(ShellParameters
->Argv
[LoopCounter
]);
1279 FreePool(ShellParameters
->Argv
);
1281 ShellParameters
->Argv
= *OldArgv
;
1283 ShellParameters
->Argc
= *OldArgc
;