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 - 2011, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "ShellParametersProtocol.h"
17 #include "ConsoleWrappers.h"
20 return the next parameter from a command line string;
22 This function moves the next parameter from Walker into TempParameter and moves
23 Walker up past that parameter for recursive calling. When the final parameter
24 is moved *Walker will be set to NULL;
26 Temp Parameter must be large enough to hold the parameter before calling this
29 @param[in,out] Walker pointer to string of command line. Adjusted to
30 reminaing command line on return
31 @param[in,out] TempParameter pointer to string of command line item extracted.
38 CHAR16
**TempParameter
44 ASSERT(Walker
!= NULL
);
45 ASSERT(*Walker
!= NULL
);
46 ASSERT(TempParameter
!= NULL
);
47 ASSERT(*TempParameter
!= NULL
);
50 // make sure we dont have any leading spaces
52 while ((*Walker
)[0] == L
' ') {
57 // make sure we still have some params now...
59 if (StrLen(*Walker
) == 0) {
60 ASSERT((*Walker
)[0] == CHAR_NULL
);
66 // we have a quoted parameter
67 // could be the last parameter, but SHOULD have a trailing quote
69 if ((*Walker
)[0] == L
'\"') {
71 for (TempLoc
= *Walker
+ 1 ; TempLoc
!= NULL
&& *TempLoc
!= CHAR_NULL
; TempLoc
++) {
72 if (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'\"') {
74 } else if (*TempLoc
== L
'\"') {
80 if (NextDelim
- ((*Walker
)+1) == 0) {
84 StrCpy(*TempParameter
, L
"");
85 *Walker
= NextDelim
+ 1;
86 } else if (NextDelim
!= NULL
) {
87 StrnCpy(*TempParameter
, (*Walker
)+1, NextDelim
- ((*Walker
)+1));
88 *Walker
= NextDelim
+ 1;
91 // last one... someone forgot the training quote!
93 StrCpy(*TempParameter
, *Walker
);
96 for (TempLoc
= *TempParameter
; TempLoc
!= NULL
&& *TempLoc
!= CHAR_NULL
; TempLoc
++) {
97 if (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'\"') {
98 CopyMem(TempLoc
, TempLoc
+1, StrSize(TempLoc
) - sizeof(TempLoc
[0]));
103 // we have a regular parameter (no quote) OR
104 // we have the final parameter (no trailing space)
106 NextDelim
= StrStr((*Walker
), L
" ");
107 if (NextDelim
!= NULL
) {
108 StrnCpy(*TempParameter
, *Walker
, NextDelim
- (*Walker
));
109 (*TempParameter
)[NextDelim
- (*Walker
)] = CHAR_NULL
;
110 *Walker
= NextDelim
+1;
115 StrCpy(*TempParameter
, *Walker
);
118 for (NextDelim
= *TempParameter
; NextDelim
!= NULL
&& *NextDelim
!= CHAR_NULL
; NextDelim
++) {
119 if (*NextDelim
== L
'^' && *(NextDelim
+1) == L
'^') {
120 CopyMem(NextDelim
, NextDelim
+1, StrSize(NextDelim
) - sizeof(NextDelim
[0]));
123 while ((*TempParameter
)[StrLen(*TempParameter
)-1] == L
' ') {
124 (*TempParameter
)[StrLen(*TempParameter
)-1] = CHAR_NULL
;
126 while ((*TempParameter
)[0] == L
' ') {
127 CopyMem(*TempParameter
, (*TempParameter
)+1, StrSize(*TempParameter
) - sizeof((*TempParameter
)[0]));
134 Function to populate Argc and Argv.
136 This function parses the CommandLine and divides it into standard C style Argc/Argv
137 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
138 delimited and quote surrounded parameter definition.
140 @param[in] CommandLine String of command line to parse
141 @param[in,out] Argv pointer to array of strings; one for each parameter
142 @param[in,out] Argc pointer to number of strings in Argv array
144 @return EFI_SUCCESS the operation was sucessful
145 @return EFI_OUT_OF_RESOURCES a memory allocation failed.
149 ParseCommandLineToArgs(
150 IN CONST CHAR16
*CommandLine
,
151 IN OUT CHAR16
***Argv
,
156 CHAR16
*TempParameter
;
161 ASSERT(Argc
!= NULL
);
162 ASSERT(Argv
!= NULL
);
164 if (CommandLine
== NULL
|| StrLen(CommandLine
)==0) {
167 return (EFI_SUCCESS
);
170 Size
= StrSize(CommandLine
);
171 TempParameter
= AllocateZeroPool(Size
);
172 if (TempParameter
== NULL
) {
173 return (EFI_OUT_OF_RESOURCES
);
177 , Walker
= (CHAR16
*)CommandLine
178 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
179 ; GetNextParameter(&Walker
, &TempParameter
)
184 Walker = (CHAR16*)CommandLine;
185 while(Walker != NULL) {
186 GetNextParameter(&Walker, &TempParameter);
191 // lets allocate the pointer array
193 (*Argv
) = AllocateZeroPool((Count
)*sizeof(CHAR16
*));
195 return (EFI_OUT_OF_RESOURCES
);
199 Walker
= (CHAR16
*)CommandLine
;
200 while(Walker
!= NULL
&& *Walker
!= CHAR_NULL
) {
201 SetMem16(TempParameter
, Size
, CHAR_NULL
);
202 GetNextParameter(&Walker
, &TempParameter
);
203 NewParam
= AllocateZeroPool(StrSize(TempParameter
));
204 ASSERT(NewParam
!= NULL
);
205 StrCpy(NewParam
, TempParameter
);
206 ((CHAR16
**)(*Argv
))[(*Argc
)] = NewParam
;
209 ASSERT(Count
>= (*Argc
));
210 return (EFI_SUCCESS
);
214 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
215 installs it on our handle and if there is an existing version of the protocol
216 that one is cached for removal later.
218 @param[in,out] NewShellParameters on a successful return, a pointer to pointer
219 to the newly installed interface.
220 @param[in,out] RootShellInstance on a successful return, pointer to boolean.
221 TRUE if this is the root shell instance.
223 @retval EFI_SUCCESS the operation completed successfully.
224 @return other the operation failed.
225 @sa ReinstallProtocolInterface
226 @sa InstallProtocolInterface
227 @sa ParseCommandLineToArgs
231 CreatePopulateInstallShellParametersProtocol (
232 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
**NewShellParameters
,
233 IN OUT BOOLEAN
*RootShellInstance
237 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
238 CHAR16
*FullCommandLine
;
242 FullCommandLine
= NULL
;
246 // Assert for valid parameters
248 ASSERT(NewShellParameters
!= NULL
);
249 ASSERT(RootShellInstance
!= NULL
);
252 // See if we have a shell parameters placed on us
254 Status
= gBS
->OpenProtocol (
256 &gEfiShellParametersProtocolGuid
,
257 (VOID
**) &ShellInfoObject
.OldShellParameters
,
260 EFI_OPEN_PROTOCOL_GET_PROTOCOL
263 // if we don't then we must be the root shell (error is expected)
265 if (EFI_ERROR (Status
)) {
266 *RootShellInstance
= TRUE
;
270 // Allocate the new structure
272 *NewShellParameters
= AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL
));
273 if ((*NewShellParameters
) == NULL
) {
274 return (EFI_OUT_OF_RESOURCES
);
278 // get loaded image protocol
280 Status
= gBS
->OpenProtocol (
282 &gEfiLoadedImageProtocolGuid
,
283 (VOID
**) &LoadedImage
,
286 EFI_OPEN_PROTOCOL_GET_PROTOCOL
288 ASSERT_EFI_ERROR(Status
);
290 // Build the full command line
292 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
293 if (Status
== EFI_BUFFER_TOO_SMALL
) {
294 FullCommandLine
= AllocateZeroPool(Size
+ LoadedImage
->LoadOptionsSize
);
295 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
297 if (Status
== EFI_NOT_FOUND
) {
299 // no parameters via environment... ok
302 if (EFI_ERROR(Status
)) {
306 if (Size
== 0 && LoadedImage
->LoadOptionsSize
!= 0) {
307 ASSERT(FullCommandLine
== NULL
);
309 // Now we need to include a NULL terminator in the size.
311 Size
= LoadedImage
->LoadOptionsSize
+ sizeof(FullCommandLine
[0]);
312 FullCommandLine
= AllocateZeroPool(Size
);
314 if (FullCommandLine
!= NULL
) {
315 if (LoadedImage
->LoadOptionsSize
!= 0){
316 StrCpy(FullCommandLine
, LoadedImage
->LoadOptions
);
319 // Populate Argc and Argv
321 Status
= ParseCommandLineToArgs(FullCommandLine
,
322 &(*NewShellParameters
)->Argv
,
323 &(*NewShellParameters
)->Argc
);
325 FreePool(FullCommandLine
);
327 ASSERT_EFI_ERROR(Status
);
329 (*NewShellParameters
)->Argv
= NULL
;
330 (*NewShellParameters
)->Argc
= 0;
334 // Populate the 3 faked file systems...
336 if (*RootShellInstance
) {
337 (*NewShellParameters
)->StdIn
= &FileInterfaceStdIn
;
338 (*NewShellParameters
)->StdOut
= &FileInterfaceStdOut
;
339 (*NewShellParameters
)->StdErr
= &FileInterfaceStdErr
;
340 Status
= gBS
->InstallProtocolInterface(&gImageHandle
,
341 &gEfiShellParametersProtocolGuid
,
342 EFI_NATIVE_INTERFACE
,
343 (VOID
*)(*NewShellParameters
));
346 // copy from the existing ones
348 (*NewShellParameters
)->StdIn
= ShellInfoObject
.OldShellParameters
->StdIn
;
349 (*NewShellParameters
)->StdOut
= ShellInfoObject
.OldShellParameters
->StdOut
;
350 (*NewShellParameters
)->StdErr
= ShellInfoObject
.OldShellParameters
->StdErr
;
351 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
352 &gEfiShellParametersProtocolGuid
,
353 (VOID
*)ShellInfoObject
.OldShellParameters
,
354 (VOID
*)(*NewShellParameters
));
361 frees all memory used by createion and installation of shell parameters protocol
362 and if there was an old version installed it will restore that one.
364 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
367 @retval EFI_SUCCESS the cleanup was successful
368 @return other the cleanup failed
369 @sa ReinstallProtocolInterface
370 @sa UninstallProtocolInterface
374 CleanUpShellParametersProtocol (
375 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*NewShellParameters
382 // If the old exists we need to restore it
384 if (ShellInfoObject
.OldShellParameters
!= NULL
) {
385 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
386 &gEfiShellParametersProtocolGuid
,
387 (VOID
*)NewShellParameters
,
388 (VOID
*)ShellInfoObject
.OldShellParameters
);
389 DEBUG_CODE(ShellInfoObject
.OldShellParameters
= NULL
;);
392 // No old one, just uninstall us...
394 Status
= gBS
->UninstallProtocolInterface(gImageHandle
,
395 &gEfiShellParametersProtocolGuid
,
396 (VOID
*)NewShellParameters
);
398 if (NewShellParameters
->Argv
!= NULL
) {
399 for ( LoopCounter
= 0
400 ; LoopCounter
< NewShellParameters
->Argc
403 FreePool(NewShellParameters
->Argv
[LoopCounter
]);
405 FreePool(NewShellParameters
->Argv
);
407 FreePool(NewShellParameters
);
412 Determin if a file name represents a unicode file.
414 @param[in] FileName Pointer to the filename to open.
416 @retval EFI_SUCCESS The file is a unicode file.
417 @return An error upon failure.
422 IN CONST CHAR16
*FileName
425 SHELL_FILE_HANDLE Handle
;
427 UINT64 OriginalFilePosition
;
431 Status
= gEfiShellProtocol
->OpenFileByName(FileName
, &Handle
, EFI_FILE_MODE_READ
);
432 if (EFI_ERROR(Status
)) {
435 gEfiShellProtocol
->GetFilePosition(Handle
, &OriginalFilePosition
);
436 gEfiShellProtocol
->SetFilePosition(Handle
, 0);
437 CharSize
= sizeof(CHAR16
);
438 Status
= gEfiShellProtocol
->ReadFile(Handle
, &CharSize
, &CharBuffer
);
439 if (EFI_ERROR(Status
) || CharBuffer
!= gUnicodeFileTag
) {
440 Status
= EFI_BUFFER_TOO_SMALL
;
442 gEfiShellProtocol
->SetFilePosition(Handle
, OriginalFilePosition
);
443 gEfiShellProtocol
->CloseFile(Handle
);
448 Strips out quotes sections of a string.
450 All of the characters between quotes is replaced with spaces.
452 @param[in,out] TheString A pointer to the string to update.
457 IN OUT CHAR16
*TheString
462 for (RemoveNow
= FALSE
; TheString
!= NULL
&& *TheString
!= CHAR_NULL
; TheString
++) {
463 if (*TheString
== L
'^' && *(TheString
+ 1) == L
'\"') {
465 } else if (*TheString
== L
'\"') {
466 RemoveNow
= (BOOLEAN
)!RemoveNow
;
467 } else if (RemoveNow
) {
474 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
475 structure by parsing NewCommandLine. The current values are returned to the
478 This will also update the system table.
480 @param[in,out] ShellParameters Pointer to parameter structure to modify.
481 @param[in] NewCommandLine The new command line to parse and use.
482 @param[out] OldStdIn Pointer to old StdIn.
483 @param[out] OldStdOut Pointer to old StdOut.
484 @param[out] OldStdErr Pointer to old StdErr.
485 @param[out] SystemTableInfo Pointer to old system table information.
487 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
488 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
492 UpdateStdInStdOutStdErr(
493 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
494 IN CHAR16
*NewCommandLine
,
495 OUT SHELL_FILE_HANDLE
*OldStdIn
,
496 OUT SHELL_FILE_HANDLE
*OldStdOut
,
497 OUT SHELL_FILE_HANDLE
*OldStdErr
,
498 OUT SYSTEM_TABLE_INFO
*SystemTableInfo
501 CHAR16
*CommandLineCopy
;
502 CHAR16
*CommandLineWalker
;
503 CHAR16
*StdErrFileName
;
504 CHAR16
*StdOutFileName
;
505 CHAR16
*StdInFileName
;
506 CHAR16
*StdInVarName
;
507 CHAR16
*StdOutVarName
;
508 CHAR16
*StdErrVarName
;
510 SHELL_FILE_HANDLE TempHandle
;
520 CHAR16
*FirstLocation
;
526 StdOutVarName
= NULL
;
527 StdErrVarName
= NULL
;
528 StdErrFileName
= NULL
;
529 StdInFileName
= NULL
;
530 StdOutFileName
= NULL
;
533 CommandLineCopy
= NULL
;
534 FirstLocation
= NULL
;
536 if (ShellParameters
== NULL
|| SystemTableInfo
== NULL
|| OldStdIn
== NULL
|| OldStdOut
== NULL
|| OldStdErr
== NULL
) {
537 return (EFI_INVALID_PARAMETER
);
540 SystemTableInfo
->ConIn
= gST
->ConIn
;
541 SystemTableInfo
->ConInHandle
= gST
->ConsoleInHandle
;
542 SystemTableInfo
->ConOut
= gST
->ConOut
;
543 SystemTableInfo
->ConOutHandle
= gST
->ConsoleOutHandle
;
544 SystemTableInfo
->ConErr
= gST
->StdErr
;
545 SystemTableInfo
->ConErrHandle
= gST
->StandardErrorHandle
;
546 *OldStdIn
= ShellParameters
->StdIn
;
547 *OldStdOut
= ShellParameters
->StdOut
;
548 *OldStdErr
= ShellParameters
->StdErr
;
550 if (NewCommandLine
== NULL
) {
551 return (EFI_SUCCESS
);
554 CommandLineCopy
= StrnCatGrow(&CommandLineCopy
, NULL
, NewCommandLine
, 0);
555 Status
= EFI_SUCCESS
;
557 FirstLocation
= CommandLineCopy
+ StrLen(CommandLineCopy
);
559 StripQuotes(CommandLineCopy
);
561 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
562 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
563 if (Split
!= NULL
&& Split
->SplitStdIn
!= NULL
) {
564 ShellParameters
->StdIn
= Split
->SplitStdIn
;
566 if (Split
!= NULL
&& Split
->SplitStdOut
!= NULL
) {
567 ShellParameters
->StdOut
= Split
->SplitStdOut
;
571 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>>v ")) != NULL
) {
572 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
573 SetMem16(CommandLineWalker
, 12, L
' ');
574 StdErrVarName
= CommandLineWalker
+= 6;
576 if (StrStr(CommandLineWalker
, L
" 2>>v ") != NULL
) {
577 Status
= EFI_NOT_FOUND
;
580 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>v ")) != NULL
) {
581 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
582 SetMem16(CommandLineWalker
, 12, L
' ');
583 StdOutVarName
= CommandLineWalker
+= 6;
585 if (StrStr(CommandLineWalker
, L
" 1>>v ") != NULL
) {
586 Status
= EFI_NOT_FOUND
;
588 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>v ")) != NULL
) {
589 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
590 SetMem16(CommandLineWalker
, 10, L
' ');
591 StdOutVarName
= CommandLineWalker
+= 5;
593 if (StrStr(CommandLineWalker
, L
" >>v ") != NULL
) {
594 Status
= EFI_NOT_FOUND
;
596 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >v ")) != NULL
) {
597 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
598 SetMem16(CommandLineWalker
, 8, L
' ');
599 StdOutVarName
= CommandLineWalker
+= 4;
601 if (StrStr(CommandLineWalker
, L
" >v ") != NULL
) {
602 Status
= EFI_NOT_FOUND
;
605 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>a ")) != NULL
) {
606 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
607 SetMem16(CommandLineWalker
, 12, L
' ');
608 StdOutFileName
= CommandLineWalker
+= 6;
611 if (StrStr(CommandLineWalker
, L
" 1>>a ") != NULL
) {
612 Status
= EFI_NOT_FOUND
;
615 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>> ")) != NULL
) {
616 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
617 SetMem16(CommandLineWalker
, 10, L
' ');
618 if (StdOutFileName
!= NULL
) {
619 Status
= EFI_INVALID_PARAMETER
;
621 StdOutFileName
= CommandLineWalker
+= 5;
624 if (StrStr(CommandLineWalker
, L
" 1>> ") != NULL
) {
625 Status
= EFI_NOT_FOUND
;
628 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >> ")) != NULL
) {
629 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
630 SetMem16(CommandLineWalker
, 8, L
' ');
631 if (StdOutFileName
!= NULL
) {
632 Status
= EFI_INVALID_PARAMETER
;
634 StdOutFileName
= CommandLineWalker
+= 4;
637 if (StrStr(CommandLineWalker
, L
" >> ") != NULL
) {
638 Status
= EFI_NOT_FOUND
;
641 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>a ")) != NULL
) {
642 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
643 SetMem16(CommandLineWalker
, 10, L
' ');
644 if (StdOutFileName
!= NULL
) {
645 Status
= EFI_INVALID_PARAMETER
;
647 StdOutFileName
= CommandLineWalker
+= 5;
651 if (StrStr(CommandLineWalker
, L
" >>a ") != NULL
) {
652 Status
= EFI_NOT_FOUND
;
655 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>a ")) != NULL
) {
656 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
657 SetMem16(CommandLineWalker
, 10, L
' ');
658 if (StdOutFileName
!= NULL
) {
659 Status
= EFI_INVALID_PARAMETER
;
661 StdOutFileName
= CommandLineWalker
+= 5;
665 if (StrStr(CommandLineWalker
, L
" 1>a ") != NULL
) {
666 Status
= EFI_NOT_FOUND
;
669 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >a ")) != NULL
) {
670 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
671 SetMem16(CommandLineWalker
, 8, L
' ');
672 if (StdOutFileName
!= NULL
) {
673 Status
= EFI_INVALID_PARAMETER
;
675 StdOutFileName
= CommandLineWalker
+= 4;
679 if (StrStr(CommandLineWalker
, L
" >a ") != NULL
) {
680 Status
= EFI_NOT_FOUND
;
683 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>> ")) != NULL
) {
684 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
685 SetMem16(CommandLineWalker
, 10, L
' ');
686 if (StdErrFileName
!= NULL
) {
687 Status
= EFI_INVALID_PARAMETER
;
689 StdErrFileName
= CommandLineWalker
+= 5;
692 if (StrStr(CommandLineWalker
, L
" 2>> ") != NULL
) {
693 Status
= EFI_NOT_FOUND
;
697 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>v ")) != NULL
) {
698 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
699 SetMem16(CommandLineWalker
, 10, L
' ');
700 if (StdErrVarName
!= NULL
) {
701 Status
= EFI_INVALID_PARAMETER
;
703 StdErrVarName
= CommandLineWalker
+= 5;
706 if (StrStr(CommandLineWalker
, L
" 2>v ") != NULL
) {
707 Status
= EFI_NOT_FOUND
;
710 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>v ")) != NULL
) {
711 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
712 SetMem16(CommandLineWalker
, 10, L
' ');
713 if (StdOutVarName
!= NULL
) {
714 Status
= EFI_INVALID_PARAMETER
;
716 StdOutVarName
= CommandLineWalker
+= 5;
719 if (StrStr(CommandLineWalker
, L
" 1>v ") != NULL
) {
720 Status
= EFI_NOT_FOUND
;
723 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>a ")) != NULL
) {
724 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
725 SetMem16(CommandLineWalker
, 10, L
' ');
726 if (StdErrFileName
!= NULL
) {
727 Status
= EFI_INVALID_PARAMETER
;
729 StdErrFileName
= CommandLineWalker
+= 5;
733 if (StrStr(CommandLineWalker
, L
" 2>a ") != NULL
) {
734 Status
= EFI_NOT_FOUND
;
737 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2> ")) != NULL
) {
738 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
739 SetMem16(CommandLineWalker
, 8, L
' ');
740 if (StdErrFileName
!= NULL
) {
741 Status
= EFI_INVALID_PARAMETER
;
743 StdErrFileName
= CommandLineWalker
+= 4;
746 if (StrStr(CommandLineWalker
, L
" 2> ") != NULL
) {
747 Status
= EFI_NOT_FOUND
;
751 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1> ")) != NULL
) {
752 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
753 SetMem16(CommandLineWalker
, 8, L
' ');
754 if (StdOutFileName
!= NULL
) {
755 Status
= EFI_INVALID_PARAMETER
;
757 StdOutFileName
= CommandLineWalker
+= 4;
760 if (StrStr(CommandLineWalker
, L
" 1> ") != NULL
) {
761 Status
= EFI_NOT_FOUND
;
765 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" > ")) != NULL
) {
766 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
767 SetMem16(CommandLineWalker
, 6, L
' ');
768 if (StdOutFileName
!= NULL
) {
769 Status
= EFI_INVALID_PARAMETER
;
771 StdOutFileName
= CommandLineWalker
+= 3;
774 if (StrStr(CommandLineWalker
, L
" > ") != NULL
) {
775 Status
= EFI_NOT_FOUND
;
779 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" < ")) != NULL
) {
780 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
781 SetMem16(CommandLineWalker
, 6, L
' ');
782 if (StdInFileName
!= NULL
) {
783 Status
= EFI_INVALID_PARAMETER
;
785 StdInFileName
= CommandLineWalker
+= 3;
787 if (StrStr(CommandLineWalker
, L
" < ") != NULL
) {
788 Status
= EFI_NOT_FOUND
;
791 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <a ")) != NULL
) {
792 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
793 SetMem16(CommandLineWalker
, 8, L
' ');
794 if (StdInFileName
!= NULL
) {
795 Status
= EFI_INVALID_PARAMETER
;
797 StdInFileName
= CommandLineWalker
+= 4;
800 if (StrStr(CommandLineWalker
, L
" <a ") != NULL
) {
801 Status
= EFI_NOT_FOUND
;
804 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <v ")) != NULL
) {
805 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
806 SetMem16(CommandLineWalker
, 8, L
' ');
807 if (StdInVarName
!= NULL
) {
808 Status
= EFI_INVALID_PARAMETER
;
810 StdInVarName
= CommandLineWalker
+= 4;
812 if (StrStr(CommandLineWalker
, L
" <v ") != NULL
) {
813 Status
= EFI_NOT_FOUND
;
817 if (FirstLocation
!= CommandLineCopy
+ StrLen(CommandLineCopy
)
818 && ((UINTN
)(FirstLocation
- CommandLineCopy
) < StrLen(NewCommandLine
))
820 *(NewCommandLine
+ (UINTN
)(FirstLocation
- CommandLineCopy
)) = CHAR_NULL
;
823 if (!EFI_ERROR(Status
)) {
824 if (StdErrFileName
!= NULL
&& (CommandLineWalker
= StrStr(StdErrFileName
, L
" ")) != NULL
) {
825 CommandLineWalker
[0] = CHAR_NULL
;
827 if (StdOutFileName
!= NULL
&& (CommandLineWalker
= StrStr(StdOutFileName
, L
" ")) != NULL
) {
828 CommandLineWalker
[0] = CHAR_NULL
;
830 if (StdInFileName
!= NULL
&& (CommandLineWalker
= StrStr(StdInFileName
, L
" ")) != NULL
) {
831 CommandLineWalker
[0] = CHAR_NULL
;
833 if (StdErrVarName
!= NULL
&& (CommandLineWalker
= StrStr(StdErrVarName
, L
" ")) != NULL
) {
834 CommandLineWalker
[0] = CHAR_NULL
;
836 if (StdOutVarName
!= NULL
&& (CommandLineWalker
= StrStr(StdOutVarName
, L
" ")) != NULL
) {
837 CommandLineWalker
[0] = CHAR_NULL
;
839 if (StdInVarName
!= NULL
&& (CommandLineWalker
= StrStr(StdInVarName
, L
" ")) != NULL
) {
840 CommandLineWalker
[0] = CHAR_NULL
;
844 // Verify not the same and not duplicating something from a split
848 // Check that no 2 filenames are the same
850 (StdErrFileName
!= NULL
&& StdOutFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdOutFileName
) == 0)
851 ||(StdErrFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdInFileName
) == 0)
852 ||(StdOutFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdOutFileName
, &StdInFileName
) == 0)
854 // Check that no 2 variable names are the same
856 ||(StdErrVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdInVarName
) == 0)
857 ||(StdOutVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdOutVarName
, &StdInVarName
) == 0)
858 ||(StdErrVarName
!= NULL
&& StdOutVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdOutVarName
) == 0)
860 // When a split (using | operator) is in place some are not allowed
862 ||(Split
!= NULL
&& Split
->SplitStdIn
!= NULL
&& (StdInVarName
!= NULL
|| StdInFileName
!= NULL
))
863 ||(Split
!= NULL
&& Split
->SplitStdOut
!= NULL
&& (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
))
865 // Check that nothing is trying to be output to 2 locations.
867 ||(StdErrFileName
!= NULL
&& StdErrVarName
!= NULL
)
868 ||(StdOutFileName
!= NULL
&& StdOutVarName
!= NULL
)
869 ||(StdInFileName
!= NULL
&& StdInVarName
!= NULL
)
871 // Check for no volatile environment variables
873 ||(StdErrVarName
!= NULL
&& !IsVolatileEnv(StdErrVarName
))
874 ||(StdOutVarName
!= NULL
&& !IsVolatileEnv(StdOutVarName
))
876 // Cant redirect during a reconnect operation.
878 ||(StrStr(NewCommandLine
, L
"connect -r") != NULL
879 && (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
|| StdErrFileName
!= NULL
|| StdErrVarName
!= NULL
))
881 // Check that filetypes (Unicode/Ascii) do not change during an append
883 ||(StdOutFileName
!= NULL
&& OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
884 ||(StdErrFileName
!= NULL
&& ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
885 ||(StdOutFileName
!= NULL
&& !OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
886 ||(StdErrFileName
!= NULL
&& !ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
888 Status
= EFI_INVALID_PARAMETER
;
889 } else if (!EFI_ERROR(Status
)){
891 // Open the Std<Whatever> and we should not have conflicts here...
897 if (StdErrFileName
!= NULL
) {
900 // delete existing file.
902 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdErrFileName
);
904 Status
= ShellOpenFileByName(StdErrFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
905 if (!ErrAppend
&& ErrUnicode
&& !EFI_ERROR(Status
)) {
907 // Write out the gUnicodeFileTag
909 Size
= sizeof(CHAR16
);
910 TagBuffer
[0] = gUnicodeFileTag
;
911 TagBuffer
[1] = CHAR_NULL
;
912 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
914 if (!ErrUnicode
&& !EFI_ERROR(Status
)) {
915 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
916 ASSERT(TempHandle
!= NULL
);
918 if (!EFI_ERROR(Status
)) {
919 ShellParameters
->StdErr
= TempHandle
;
920 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
927 if (!EFI_ERROR(Status
) && StdOutFileName
!= NULL
) {
930 // delete existing file.
932 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdOutFileName
);
934 Status
= ShellOpenFileByName(StdOutFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
935 if (TempHandle
== NULL
) {
936 Status
= EFI_INVALID_PARAMETER
;
938 if (StrStr(StdOutFileName
, L
"NUL")==StdOutFileName
) {
940 } else if (!OutAppend
&& OutUnicode
&& !EFI_ERROR(Status
)) {
942 // Write out the gUnicodeFileTag
944 Size
= sizeof(CHAR16
);
945 TagBuffer
[0] = gUnicodeFileTag
;
946 TagBuffer
[1] = CHAR_NULL
;
947 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
948 } else if (OutAppend
) {
950 // Move to end of file
952 Status
= ShellInfoObject
.NewEfiShellProtocol
->GetFileSize(TempHandle
, &FileSize
);
953 if (!EFI_ERROR(Status
)) {
954 Status
= ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition(TempHandle
, FileSize
);
957 if (!OutUnicode
&& !EFI_ERROR(Status
)) {
958 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
959 ASSERT(TempHandle
!= NULL
);
961 if (!EFI_ERROR(Status
)) {
962 ShellParameters
->StdOut
= TempHandle
;
963 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
971 if (!EFI_ERROR(Status
) && StdOutVarName
!= NULL
) {
974 // delete existing variable.
976 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName
, 0, L
"");
978 TempHandle
= CreateFileInterfaceEnv(StdOutVarName
);
979 ASSERT(TempHandle
!= NULL
);
980 ShellParameters
->StdOut
= TempHandle
;
981 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
987 if (!EFI_ERROR(Status
) && StdErrVarName
!= NULL
) {
990 // delete existing variable.
992 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName
, 0, L
"");
994 TempHandle
= CreateFileInterfaceEnv(StdErrVarName
);
995 ASSERT(TempHandle
!= NULL
);
996 ShellParameters
->StdErr
= TempHandle
;
997 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
1003 if (!EFI_ERROR(Status
) && StdInVarName
!= NULL
) {
1004 TempHandle
= CreateFileInterfaceEnv(StdInVarName
);
1006 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1009 ASSERT(TempHandle
!= NULL
);
1010 if (((EFI_FILE_PROTOCOL
*)TempHandle
)->Read(TempHandle
, &Size
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
1011 Status
= EFI_INVALID_PARAMETER
;
1013 ShellParameters
->StdIn
= TempHandle
;
1014 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1019 // StdIn from a file
1021 if (!EFI_ERROR(Status
) && StdInFileName
!= NULL
) {
1022 Status
= ShellOpenFileByName(
1027 if (!InUnicode
&& !EFI_ERROR(Status
)) {
1028 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1030 if (!EFI_ERROR(Status
)) {
1031 ShellParameters
->StdIn
= TempHandle
;
1032 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1037 FreePool(CommandLineCopy
);
1039 if (gST
->ConIn
== NULL
||gST
->ConOut
== NULL
) {
1040 return (EFI_OUT_OF_RESOURCES
);
1046 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1047 structure with StdIn and StdOut. The current values are de-allocated.
1049 @param[in,out] ShellParameters Pointer to parameter structure to modify.
1050 @param[in] OldStdIn Pointer to old StdIn.
1051 @param[in] OldStdOut Pointer to old StdOut.
1052 @param[in] OldStdErr Pointer to old StdErr.
1053 @param[in] SystemTableInfo Pointer to old system table information.
1057 RestoreStdInStdOutStdErr (
1058 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1059 IN SHELL_FILE_HANDLE
*OldStdIn
,
1060 IN SHELL_FILE_HANDLE
*OldStdOut
,
1061 IN SHELL_FILE_HANDLE
*OldStdErr
,
1062 IN SYSTEM_TABLE_INFO
*SystemTableInfo
1067 if (ShellParameters
== NULL
1071 ||SystemTableInfo
== NULL
) {
1072 return (EFI_INVALID_PARAMETER
);
1074 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1075 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1079 if (ShellParameters
->StdIn
!= *OldStdIn
) {
1080 if ((Split
!= NULL
&& Split
->SplitStdIn
!= ShellParameters
->StdIn
) || Split
== NULL
) {
1081 gEfiShellProtocol
->CloseFile(ShellParameters
->StdIn
);
1083 ShellParameters
->StdIn
= *OldStdIn
;
1085 if (ShellParameters
->StdOut
!= *OldStdOut
) {
1086 if ((Split
!= NULL
&& Split
->SplitStdOut
!= ShellParameters
->StdOut
) || Split
== NULL
) {
1087 gEfiShellProtocol
->CloseFile(ShellParameters
->StdOut
);
1089 ShellParameters
->StdOut
= *OldStdOut
;
1091 if (ShellParameters
->StdErr
!= *OldStdErr
) {
1092 gEfiShellProtocol
->CloseFile(ShellParameters
->StdErr
);
1093 ShellParameters
->StdErr
= *OldStdErr
;
1096 if (gST
->ConIn
!= SystemTableInfo
->ConIn
) {
1097 CloseSimpleTextInOnFile(gST
->ConIn
);
1098 gST
->ConIn
= SystemTableInfo
->ConIn
;
1099 gST
->ConsoleInHandle
= SystemTableInfo
->ConInHandle
;
1101 if (gST
->ConOut
!= SystemTableInfo
->ConOut
) {
1102 CloseSimpleTextOutOnFile(gST
->ConOut
);
1103 gST
->ConOut
= SystemTableInfo
->ConOut
;
1104 gST
->ConsoleOutHandle
= SystemTableInfo
->ConOutHandle
;
1106 if (gST
->StdErr
!= SystemTableInfo
->ConErr
) {
1107 CloseSimpleTextOutOnFile(gST
->StdErr
);
1108 gST
->StdErr
= SystemTableInfo
->ConErr
;
1109 gST
->StandardErrorHandle
= SystemTableInfo
->ConErrHandle
;
1112 return (EFI_SUCCESS
);
1115 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1116 structure by parsing NewCommandLine. The current values are returned to the
1119 If OldArgv or OldArgc is NULL then that value is not returned.
1121 @param[in,out] ShellParameters Pointer to parameter structure to modify.
1122 @param[in] NewCommandLine The new command line to parse and use.
1123 @param[out] OldArgv Pointer to old list of parameters.
1124 @param[out] OldArgc Pointer to old number of items in Argv list.
1126 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
1127 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1132 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1133 IN CONST CHAR16
*NewCommandLine
,
1134 OUT CHAR16
***OldArgv OPTIONAL
,
1135 OUT UINTN
*OldArgc OPTIONAL
1138 ASSERT(ShellParameters
!= NULL
);
1140 if (OldArgc
!= NULL
) {
1141 *OldArgc
= ShellParameters
->Argc
;
1143 if (OldArgc
!= NULL
) {
1144 *OldArgv
= ShellParameters
->Argv
;
1147 return (ParseCommandLineToArgs(NewCommandLine
, &(ShellParameters
->Argv
), &(ShellParameters
->Argc
)));
1151 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1152 structure with Argv and Argc. The current values are de-allocated and the
1153 OldArgv must not be deallocated by the caller.
1155 @param[in,out] ShellParameters pointer to parameter structure to modify
1156 @param[in] OldArgv pointer to old list of parameters
1157 @param[in] OldArgc pointer to old number of items in Argv list
1162 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1163 IN CHAR16
***OldArgv
,
1168 ASSERT(ShellParameters
!= NULL
);
1169 ASSERT(OldArgv
!= NULL
);
1170 ASSERT(OldArgc
!= NULL
);
1172 if (ShellParameters
->Argv
!= NULL
) {
1173 for ( LoopCounter
= 0
1174 ; LoopCounter
< ShellParameters
->Argc
1177 FreePool(ShellParameters
->Argv
[LoopCounter
]);
1179 FreePool(ShellParameters
->Argv
);
1181 ShellParameters
->Argv
= *OldArgv
;
1183 ShellParameters
->Argc
= *OldArgc
;