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
'^' && *(TempLoc
+1) == L
'\"') {
76 } else if (*TempLoc
== L
'\"') {
82 if (NextDelim
- ((*Walker
)+1) == 0) {
86 StrCpy(*TempParameter
, L
"");
87 *Walker
= NextDelim
+ 1;
88 } else if (NextDelim
!= NULL
) {
89 StrnCpy(*TempParameter
, (*Walker
)+1, NextDelim
- ((*Walker
)+1));
90 *Walker
= NextDelim
+ 1;
93 // last one... someone forgot the training quote!
95 StrCpy(*TempParameter
, *Walker
);
98 for (TempLoc
= *TempParameter
; TempLoc
!= NULL
&& *TempLoc
!= CHAR_NULL
; TempLoc
++) {
99 if ((*TempLoc
== L
'^' && *(TempLoc
+1) == L
'^')
100 || (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'|')
101 || (*TempLoc
== L
'^' && *(TempLoc
+1) == L
'\"')
103 CopyMem(TempLoc
, TempLoc
+1, StrSize(TempLoc
) - sizeof(TempLoc
[0]));
108 // we have a regular parameter (no quote) OR
109 // we have the final parameter (no trailing space)
111 NextDelim
= StrStr((*Walker
), L
" ");
112 if (NextDelim
!= NULL
) {
113 StrnCpy(*TempParameter
, *Walker
, NextDelim
- (*Walker
));
114 (*TempParameter
)[NextDelim
- (*Walker
)] = CHAR_NULL
;
115 *Walker
= NextDelim
+1;
120 StrCpy(*TempParameter
, *Walker
);
123 for (NextDelim
= *TempParameter
; NextDelim
!= NULL
&& *NextDelim
!= CHAR_NULL
; NextDelim
++) {
124 if (*NextDelim
== L
'^' && *(NextDelim
+1) == L
'^') {
125 CopyMem(NextDelim
, NextDelim
+1, StrSize(NextDelim
) - sizeof(NextDelim
[0]));
126 }/* else if (*NextDelim == L'^') {
130 while ((*TempParameter
)[StrLen(*TempParameter
)-1] == L
' ') {
131 (*TempParameter
)[StrLen(*TempParameter
)-1] = CHAR_NULL
;
133 while ((*TempParameter
)[0] == L
' ') {
134 CopyMem(*TempParameter
, (*TempParameter
)+1, StrSize(*TempParameter
) - sizeof((*TempParameter
)[0]));
141 Function to populate Argc and Argv.
143 This function parses the CommandLine and divides it into standard C style Argc/Argv
144 parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
145 delimited and quote surrounded parameter definition.
147 @param[in] CommandLine String of command line to parse
148 @param[in,out] Argv pointer to array of strings; one for each parameter
149 @param[in,out] Argc pointer to number of strings in Argv array
151 @return EFI_SUCCESS the operation was sucessful
152 @return EFI_OUT_OF_RESOURCES a memory allocation failed.
156 ParseCommandLineToArgs(
157 IN CONST CHAR16
*CommandLine
,
158 IN OUT CHAR16
***Argv
,
163 CHAR16
*TempParameter
;
168 ASSERT(Argc
!= NULL
);
169 ASSERT(Argv
!= NULL
);
171 if (CommandLine
== NULL
|| StrLen(CommandLine
)==0) {
174 return (EFI_SUCCESS
);
177 Size
= StrSize(CommandLine
);
178 TempParameter
= AllocateZeroPool(Size
);
179 if (TempParameter
== NULL
) {
180 return (EFI_OUT_OF_RESOURCES
);
184 , Walker
= (CHAR16
*)CommandLine
185 ; Walker
!= NULL
&& *Walker
!= CHAR_NULL
186 ; GetNextParameter(&Walker
, &TempParameter
)
191 Walker = (CHAR16*)CommandLine;
192 while(Walker != NULL) {
193 GetNextParameter(&Walker, &TempParameter);
198 // lets allocate the pointer array
200 (*Argv
) = AllocateZeroPool((Count
)*sizeof(CHAR16
*));
202 return (EFI_OUT_OF_RESOURCES
);
206 Walker
= (CHAR16
*)CommandLine
;
207 while(Walker
!= NULL
&& *Walker
!= CHAR_NULL
) {
208 SetMem16(TempParameter
, Size
, CHAR_NULL
);
209 GetNextParameter(&Walker
, &TempParameter
);
210 NewParam
= AllocateZeroPool(StrSize(TempParameter
));
211 ASSERT(NewParam
!= NULL
);
212 StrCpy(NewParam
, TempParameter
);
213 ((CHAR16
**)(*Argv
))[(*Argc
)] = NewParam
;
216 ASSERT(Count
>= (*Argc
));
217 return (EFI_SUCCESS
);
221 creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
222 installs it on our handle and if there is an existing version of the protocol
223 that one is cached for removal later.
225 @param[in,out] NewShellParameters on a successful return, a pointer to pointer
226 to the newly installed interface.
227 @param[in,out] RootShellInstance on a successful return, pointer to boolean.
228 TRUE if this is the root shell instance.
230 @retval EFI_SUCCESS the operation completed successfully.
231 @return other the operation failed.
232 @sa ReinstallProtocolInterface
233 @sa InstallProtocolInterface
234 @sa ParseCommandLineToArgs
238 CreatePopulateInstallShellParametersProtocol (
239 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
**NewShellParameters
,
240 IN OUT BOOLEAN
*RootShellInstance
244 EFI_LOADED_IMAGE_PROTOCOL
*LoadedImage
;
245 CHAR16
*FullCommandLine
;
249 FullCommandLine
= NULL
;
253 // Assert for valid parameters
255 ASSERT(NewShellParameters
!= NULL
);
256 ASSERT(RootShellInstance
!= NULL
);
259 // See if we have a shell parameters placed on us
261 Status
= gBS
->OpenProtocol (
263 &gEfiShellParametersProtocolGuid
,
264 (VOID
**) &ShellInfoObject
.OldShellParameters
,
267 EFI_OPEN_PROTOCOL_GET_PROTOCOL
270 // if we don't then we must be the root shell (error is expected)
272 if (EFI_ERROR (Status
)) {
273 *RootShellInstance
= TRUE
;
277 // Allocate the new structure
279 *NewShellParameters
= AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL
));
280 if ((*NewShellParameters
) == NULL
) {
281 return (EFI_OUT_OF_RESOURCES
);
285 // get loaded image protocol
287 Status
= gBS
->OpenProtocol (
289 &gEfiLoadedImageProtocolGuid
,
290 (VOID
**) &LoadedImage
,
293 EFI_OPEN_PROTOCOL_GET_PROTOCOL
295 ASSERT_EFI_ERROR(Status
);
297 // Build the full command line
299 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
300 if (Status
== EFI_BUFFER_TOO_SMALL
) {
301 FullCommandLine
= AllocateZeroPool(Size
+ LoadedImage
->LoadOptionsSize
);
302 Status
= SHELL_GET_ENVIRONMENT_VARIABLE(L
"ShellOpt", &Size
, &FullCommandLine
);
304 if (Status
== EFI_NOT_FOUND
) {
306 // no parameters via environment... ok
309 if (EFI_ERROR(Status
)) {
313 if (Size
== 0 && LoadedImage
->LoadOptionsSize
!= 0) {
314 ASSERT(FullCommandLine
== NULL
);
316 // Now we need to include a NULL terminator in the size.
318 Size
= LoadedImage
->LoadOptionsSize
+ sizeof(FullCommandLine
[0]);
319 FullCommandLine
= AllocateZeroPool(Size
);
321 if (FullCommandLine
!= NULL
) {
322 if (LoadedImage
->LoadOptionsSize
!= 0){
323 StrCpy(FullCommandLine
, LoadedImage
->LoadOptions
);
326 // Populate Argc and Argv
328 Status
= ParseCommandLineToArgs(FullCommandLine
,
329 &(*NewShellParameters
)->Argv
,
330 &(*NewShellParameters
)->Argc
);
332 FreePool(FullCommandLine
);
334 ASSERT_EFI_ERROR(Status
);
336 (*NewShellParameters
)->Argv
= NULL
;
337 (*NewShellParameters
)->Argc
= 0;
341 // Populate the 3 faked file systems...
343 if (*RootShellInstance
) {
344 (*NewShellParameters
)->StdIn
= &FileInterfaceStdIn
;
345 (*NewShellParameters
)->StdOut
= &FileInterfaceStdOut
;
346 (*NewShellParameters
)->StdErr
= &FileInterfaceStdErr
;
347 Status
= gBS
->InstallProtocolInterface(&gImageHandle
,
348 &gEfiShellParametersProtocolGuid
,
349 EFI_NATIVE_INTERFACE
,
350 (VOID
*)(*NewShellParameters
));
353 // copy from the existing ones
355 (*NewShellParameters
)->StdIn
= ShellInfoObject
.OldShellParameters
->StdIn
;
356 (*NewShellParameters
)->StdOut
= ShellInfoObject
.OldShellParameters
->StdOut
;
357 (*NewShellParameters
)->StdErr
= ShellInfoObject
.OldShellParameters
->StdErr
;
358 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
359 &gEfiShellParametersProtocolGuid
,
360 (VOID
*)ShellInfoObject
.OldShellParameters
,
361 (VOID
*)(*NewShellParameters
));
368 frees all memory used by createion and installation of shell parameters protocol
369 and if there was an old version installed it will restore that one.
371 @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
374 @retval EFI_SUCCESS the cleanup was successful
375 @return other the cleanup failed
376 @sa ReinstallProtocolInterface
377 @sa UninstallProtocolInterface
381 CleanUpShellParametersProtocol (
382 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*NewShellParameters
389 // If the old exists we need to restore it
391 if (ShellInfoObject
.OldShellParameters
!= NULL
) {
392 Status
= gBS
->ReinstallProtocolInterface(gImageHandle
,
393 &gEfiShellParametersProtocolGuid
,
394 (VOID
*)NewShellParameters
,
395 (VOID
*)ShellInfoObject
.OldShellParameters
);
396 DEBUG_CODE(ShellInfoObject
.OldShellParameters
= NULL
;);
399 // No old one, just uninstall us...
401 Status
= gBS
->UninstallProtocolInterface(gImageHandle
,
402 &gEfiShellParametersProtocolGuid
,
403 (VOID
*)NewShellParameters
);
405 if (NewShellParameters
->Argv
!= NULL
) {
406 for ( LoopCounter
= 0
407 ; LoopCounter
< NewShellParameters
->Argc
410 FreePool(NewShellParameters
->Argv
[LoopCounter
]);
412 FreePool(NewShellParameters
->Argv
);
414 FreePool(NewShellParameters
);
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.
454 IN OUT CHAR16
*TheString
459 for (RemoveNow
= FALSE
; TheString
!= NULL
&& *TheString
!= CHAR_NULL
; TheString
++) {
460 if (*TheString
== L
'^' && *(TheString
+ 1) == L
'\"') {
462 } else if (*TheString
== L
'\"') {
463 RemoveNow
= (BOOLEAN
)!RemoveNow
;
464 } else if (RemoveNow
) {
471 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
472 structure by parsing NewCommandLine. The current values are returned to the
475 This will also update the system table.
477 @param[in,out] ShellParameters Pointer to parameter structure to modify.
478 @param[in] NewCommandLine The new command line to parse and use.
479 @param[out] OldStdIn Pointer to old StdIn.
480 @param[out] OldStdOut Pointer to old StdOut.
481 @param[out] OldStdErr Pointer to old StdErr.
482 @param[out] SystemTableInfo Pointer to old system table information.
484 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
485 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
489 UpdateStdInStdOutStdErr(
490 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
491 IN CHAR16
*NewCommandLine
,
492 OUT SHELL_FILE_HANDLE
*OldStdIn
,
493 OUT SHELL_FILE_HANDLE
*OldStdOut
,
494 OUT SHELL_FILE_HANDLE
*OldStdErr
,
495 OUT SYSTEM_TABLE_INFO
*SystemTableInfo
498 CHAR16
*CommandLineCopy
;
499 CHAR16
*CommandLineWalker
;
500 CHAR16
*StdErrFileName
;
501 CHAR16
*StdOutFileName
;
502 CHAR16
*StdInFileName
;
503 CHAR16
*StdInVarName
;
504 CHAR16
*StdOutVarName
;
505 CHAR16
*StdErrVarName
;
507 SHELL_FILE_HANDLE TempHandle
;
517 CHAR16
*FirstLocation
;
523 StdOutVarName
= NULL
;
524 StdErrVarName
= NULL
;
525 StdErrFileName
= NULL
;
526 StdInFileName
= NULL
;
527 StdOutFileName
= NULL
;
530 CommandLineCopy
= NULL
;
531 FirstLocation
= (CHAR16
*)(-1);
533 if (ShellParameters
== NULL
|| SystemTableInfo
== NULL
|| OldStdIn
== NULL
|| OldStdOut
== NULL
|| OldStdErr
== NULL
) {
534 return (EFI_INVALID_PARAMETER
);
537 SystemTableInfo
->ConIn
= gST
->ConIn
;
538 SystemTableInfo
->ConInHandle
= gST
->ConsoleInHandle
;
539 SystemTableInfo
->ConOut
= gST
->ConOut
;
540 SystemTableInfo
->ConOutHandle
= gST
->ConsoleOutHandle
;
541 SystemTableInfo
->ConErr
= gST
->StdErr
;
542 SystemTableInfo
->ConErrHandle
= gST
->StandardErrorHandle
;
543 *OldStdIn
= ShellParameters
->StdIn
;
544 *OldStdOut
= ShellParameters
->StdOut
;
545 *OldStdErr
= ShellParameters
->StdErr
;
547 if (NewCommandLine
== NULL
) {
548 return (EFI_SUCCESS
);
551 CommandLineCopy
= StrnCatGrow(&CommandLineCopy
, NULL
, NewCommandLine
, 0);
552 Status
= EFI_SUCCESS
;
555 StripQuotes(CommandLineCopy
);
557 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
558 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
559 if (Split
!= NULL
&& Split
->SplitStdIn
!= NULL
) {
560 ShellParameters
->StdIn
= Split
->SplitStdIn
;
562 if (Split
!= NULL
&& Split
->SplitStdOut
!= NULL
) {
563 ShellParameters
->StdOut
= Split
->SplitStdOut
;
567 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>>v ")) != NULL
) {
568 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
569 SetMem16(CommandLineWalker
, 12, L
' ');
570 StdErrVarName
= CommandLineWalker
+= 6;
572 if (StrStr(CommandLineWalker
, L
" 2>>v ") != NULL
) {
573 Status
= EFI_NOT_FOUND
;
576 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>v ")) != NULL
) {
577 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
578 SetMem16(CommandLineWalker
, 12, L
' ');
579 StdOutVarName
= CommandLineWalker
+= 6;
581 if (StrStr(CommandLineWalker
, L
" 1>>v ") != NULL
) {
582 Status
= EFI_NOT_FOUND
;
584 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>v ")) != NULL
) {
585 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
586 SetMem16(CommandLineWalker
, 10, L
' ');
587 StdOutVarName
= CommandLineWalker
+= 5;
589 if (StrStr(CommandLineWalker
, L
" >>v ") != NULL
) {
590 Status
= EFI_NOT_FOUND
;
592 } else if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >v ")) != NULL
) {
593 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
594 SetMem16(CommandLineWalker
, 8, L
' ');
595 StdOutVarName
= CommandLineWalker
+= 4;
597 if (StrStr(CommandLineWalker
, L
" >v ") != NULL
) {
598 Status
= EFI_NOT_FOUND
;
601 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>>a ")) != NULL
) {
602 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
603 SetMem16(CommandLineWalker
, 12, L
' ');
604 StdOutFileName
= CommandLineWalker
+= 6;
607 if (StrStr(CommandLineWalker
, L
" 1>>a ") != NULL
) {
608 Status
= EFI_NOT_FOUND
;
611 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>> ")) != NULL
) {
612 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
613 SetMem16(CommandLineWalker
, 10, L
' ');
614 if (StdOutFileName
!= NULL
) {
615 Status
= EFI_INVALID_PARAMETER
;
617 StdOutFileName
= CommandLineWalker
+= 5;
620 if (StrStr(CommandLineWalker
, L
" 1>> ") != NULL
) {
621 Status
= EFI_NOT_FOUND
;
624 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >> ")) != NULL
) {
625 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
626 SetMem16(CommandLineWalker
, 8, L
' ');
627 if (StdOutFileName
!= NULL
) {
628 Status
= EFI_INVALID_PARAMETER
;
630 StdOutFileName
= CommandLineWalker
+= 4;
633 if (StrStr(CommandLineWalker
, L
" >> ") != NULL
) {
634 Status
= EFI_NOT_FOUND
;
637 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >>a ")) != NULL
) {
638 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
639 SetMem16(CommandLineWalker
, 10, L
' ');
640 if (StdOutFileName
!= NULL
) {
641 Status
= EFI_INVALID_PARAMETER
;
643 StdOutFileName
= CommandLineWalker
+= 5;
647 if (StrStr(CommandLineWalker
, L
" >>a ") != NULL
) {
648 Status
= EFI_NOT_FOUND
;
651 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>a ")) != NULL
) {
652 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
653 SetMem16(CommandLineWalker
, 10, L
' ');
654 if (StdOutFileName
!= NULL
) {
655 Status
= EFI_INVALID_PARAMETER
;
657 StdOutFileName
= CommandLineWalker
+= 5;
661 if (StrStr(CommandLineWalker
, L
" 1>a ") != NULL
) {
662 Status
= EFI_NOT_FOUND
;
665 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" >a ")) != NULL
) {
666 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
667 SetMem16(CommandLineWalker
, 8, L
' ');
668 if (StdOutFileName
!= NULL
) {
669 Status
= EFI_INVALID_PARAMETER
;
671 StdOutFileName
= CommandLineWalker
+= 4;
675 if (StrStr(CommandLineWalker
, L
" >a ") != NULL
) {
676 Status
= EFI_NOT_FOUND
;
679 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>> ")) != NULL
) {
680 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
681 SetMem16(CommandLineWalker
, 10, L
' ');
682 if (StdErrFileName
!= NULL
) {
683 Status
= EFI_INVALID_PARAMETER
;
685 StdErrFileName
= CommandLineWalker
+= 5;
688 if (StrStr(CommandLineWalker
, L
" 2>> ") != NULL
) {
689 Status
= EFI_NOT_FOUND
;
693 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>v ")) != NULL
) {
694 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
695 SetMem16(CommandLineWalker
, 10, L
' ');
696 if (StdErrVarName
!= NULL
) {
697 Status
= EFI_INVALID_PARAMETER
;
699 StdErrVarName
= CommandLineWalker
+= 5;
702 if (StrStr(CommandLineWalker
, L
" 2>v ") != NULL
) {
703 Status
= EFI_NOT_FOUND
;
706 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1>v ")) != NULL
) {
707 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
708 SetMem16(CommandLineWalker
, 10, L
' ');
709 if (StdOutVarName
!= NULL
) {
710 Status
= EFI_INVALID_PARAMETER
;
712 StdOutVarName
= CommandLineWalker
+= 5;
715 if (StrStr(CommandLineWalker
, L
" 1>v ") != NULL
) {
716 Status
= EFI_NOT_FOUND
;
719 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2>a ")) != NULL
) {
720 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
721 SetMem16(CommandLineWalker
, 10, L
' ');
722 if (StdErrFileName
!= NULL
) {
723 Status
= EFI_INVALID_PARAMETER
;
725 StdErrFileName
= CommandLineWalker
+= 5;
729 if (StrStr(CommandLineWalker
, L
" 2>a ") != NULL
) {
730 Status
= EFI_NOT_FOUND
;
733 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 2> ")) != NULL
) {
734 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
735 SetMem16(CommandLineWalker
, 8, L
' ');
736 if (StdErrFileName
!= NULL
) {
737 Status
= EFI_INVALID_PARAMETER
;
739 StdErrFileName
= CommandLineWalker
+= 4;
742 if (StrStr(CommandLineWalker
, L
" 2> ") != NULL
) {
743 Status
= EFI_NOT_FOUND
;
747 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" 1> ")) != NULL
) {
748 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
749 SetMem16(CommandLineWalker
, 8, L
' ');
750 if (StdOutFileName
!= NULL
) {
751 Status
= EFI_INVALID_PARAMETER
;
753 StdOutFileName
= CommandLineWalker
+= 4;
756 if (StrStr(CommandLineWalker
, L
" 1> ") != NULL
) {
757 Status
= EFI_NOT_FOUND
;
761 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" > ")) != NULL
) {
762 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
763 SetMem16(CommandLineWalker
, 6, L
' ');
764 if (StdOutFileName
!= NULL
) {
765 Status
= EFI_INVALID_PARAMETER
;
767 StdOutFileName
= CommandLineWalker
+= 3;
770 if (StrStr(CommandLineWalker
, L
" > ") != NULL
) {
771 Status
= EFI_NOT_FOUND
;
775 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" < ")) != NULL
) {
776 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
777 SetMem16(CommandLineWalker
, 6, L
' ');
778 if (StdInFileName
!= NULL
) {
779 Status
= EFI_INVALID_PARAMETER
;
781 StdInFileName
= CommandLineWalker
+= 3;
783 if (StrStr(CommandLineWalker
, L
" < ") != NULL
) {
784 Status
= EFI_NOT_FOUND
;
787 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <a ")) != NULL
) {
788 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
789 SetMem16(CommandLineWalker
, 8, L
' ');
790 if (StdInFileName
!= NULL
) {
791 Status
= EFI_INVALID_PARAMETER
;
793 StdInFileName
= CommandLineWalker
+= 4;
796 if (StrStr(CommandLineWalker
, L
" <a ") != NULL
) {
797 Status
= EFI_NOT_FOUND
;
800 if (!EFI_ERROR(Status
) && (CommandLineWalker
= StrStr(CommandLineCopy
, L
" <v ")) != NULL
) {
801 FirstLocation
= MIN(CommandLineWalker
, FirstLocation
);
802 SetMem16(CommandLineWalker
, 8, L
' ');
803 if (StdInVarName
!= NULL
) {
804 Status
= EFI_INVALID_PARAMETER
;
806 StdInVarName
= CommandLineWalker
+= 4;
808 if (StrStr(CommandLineWalker
, L
" <v ") != NULL
) {
809 Status
= EFI_NOT_FOUND
;
813 if (FirstLocation
!= (CHAR16
*)(-1)
814 && ((UINTN
)(FirstLocation
- CommandLineCopy
) < StrLen(NewCommandLine
))
816 *(NewCommandLine
+ (UINTN
)(FirstLocation
- CommandLineCopy
)) = CHAR_NULL
;
819 if (!EFI_ERROR(Status
)) {
820 if (StdErrFileName
!= NULL
&& (CommandLineWalker
= StrStr(StdErrFileName
, L
" ")) != NULL
) {
821 CommandLineWalker
[0] = CHAR_NULL
;
823 if (StdOutFileName
!= NULL
&& (CommandLineWalker
= StrStr(StdOutFileName
, L
" ")) != NULL
) {
824 CommandLineWalker
[0] = CHAR_NULL
;
826 if (StdInFileName
!= NULL
&& (CommandLineWalker
= StrStr(StdInFileName
, L
" ")) != NULL
) {
827 CommandLineWalker
[0] = CHAR_NULL
;
829 if (StdErrVarName
!= NULL
&& (CommandLineWalker
= StrStr(StdErrVarName
, L
" ")) != NULL
) {
830 CommandLineWalker
[0] = CHAR_NULL
;
832 if (StdOutVarName
!= NULL
&& (CommandLineWalker
= StrStr(StdOutVarName
, L
" ")) != NULL
) {
833 CommandLineWalker
[0] = CHAR_NULL
;
835 if (StdInVarName
!= NULL
&& (CommandLineWalker
= StrStr(StdInVarName
, L
" ")) != NULL
) {
836 CommandLineWalker
[0] = CHAR_NULL
;
841 // Check that no 2 filenames are the same
843 (StdErrFileName
!= NULL
&& StdOutFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdOutFileName
) == 0)
844 ||(StdErrFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdErrFileName
, &StdInFileName
) == 0)
845 ||(StdOutFileName
!= NULL
&& StdInFileName
!= NULL
&& StringNoCaseCompare(&StdOutFileName
, &StdInFileName
) == 0)
847 // Check that no 2 variable names are the same
849 ||(StdErrVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdInVarName
) == 0)
850 ||(StdOutVarName
!= NULL
&& StdInVarName
!= NULL
&& StringNoCaseCompare(&StdOutVarName
, &StdInVarName
) == 0)
851 ||(StdErrVarName
!= NULL
&& StdOutVarName
!= NULL
&& StringNoCaseCompare(&StdErrVarName
, &StdOutVarName
) == 0)
853 // When a split (using | operator) is in place some are not allowed
855 ||(Split
!= NULL
&& Split
->SplitStdIn
!= NULL
&& (StdInVarName
!= NULL
|| StdInFileName
!= NULL
))
856 ||(Split
!= NULL
&& Split
->SplitStdOut
!= NULL
&& (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
))
858 // Check that nothing is trying to be output to 2 locations.
860 ||(StdErrFileName
!= NULL
&& StdErrVarName
!= NULL
)
861 ||(StdOutFileName
!= NULL
&& StdOutVarName
!= NULL
)
862 ||(StdInFileName
!= NULL
&& StdInVarName
!= NULL
)
864 // Check for no volatile environment variables
866 ||(StdErrVarName
!= NULL
&& !IsVolatileEnv(StdErrVarName
))
867 ||(StdOutVarName
!= NULL
&& !IsVolatileEnv(StdOutVarName
))
869 // Cant redirect during a reconnect operation.
871 ||(StrStr(NewCommandLine
, L
"connect -r") != NULL
872 && (StdOutVarName
!= NULL
|| StdOutFileName
!= NULL
|| StdErrFileName
!= NULL
|| StdErrVarName
!= NULL
))
874 // Check that filetypes (Unicode/Ascii) do not change during an append
876 ||(StdOutFileName
!= NULL
&& OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
877 ||(StdErrFileName
!= NULL
&& ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
878 ||(StdOutFileName
!= NULL
&& !OutUnicode
&& OutAppend
&& (!EFI_ERROR(ShellFileExists(StdOutFileName
)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName
))))
879 ||(StdErrFileName
!= NULL
&& !ErrUnicode
&& ErrAppend
&& (!EFI_ERROR(ShellFileExists(StdErrFileName
)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName
))))
881 Status
= EFI_INVALID_PARAMETER
;
882 } else if (!EFI_ERROR(Status
)){
884 // Open the Std<Whatever> and we should not have conflicts here...
890 if (StdErrFileName
!= NULL
) {
893 // delete existing file.
895 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdErrFileName
);
897 Status
= ShellOpenFileByName(StdErrFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
898 if (!ErrAppend
&& ErrUnicode
&& !EFI_ERROR(Status
)) {
900 // Write out the gUnicodeFileTag
902 Size
= sizeof(CHAR16
);
903 TagBuffer
[0] = gUnicodeFileTag
;
904 TagBuffer
[1] = CHAR_NULL
;
905 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
907 if (!ErrUnicode
&& !EFI_ERROR(Status
)) {
908 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
909 ASSERT(TempHandle
!= NULL
);
911 if (!EFI_ERROR(Status
)) {
912 ShellParameters
->StdErr
= TempHandle
;
913 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
920 if (!EFI_ERROR(Status
) && StdOutFileName
!= NULL
) {
923 // delete existing file.
925 ShellInfoObject
.NewEfiShellProtocol
->DeleteFileByName(StdOutFileName
);
927 Status
= ShellOpenFileByName(StdOutFileName
, &TempHandle
, EFI_FILE_MODE_WRITE
|EFI_FILE_MODE_READ
|EFI_FILE_MODE_CREATE
,0);
928 if (TempHandle
== NULL
) {
929 Status
= EFI_INVALID_PARAMETER
;
931 if (StrStr(StdOutFileName
, L
"NUL")==StdOutFileName
) {
933 } else if (!OutAppend
&& OutUnicode
&& !EFI_ERROR(Status
)) {
935 // Write out the gUnicodeFileTag
937 Size
= sizeof(CHAR16
);
938 TagBuffer
[0] = gUnicodeFileTag
;
939 TagBuffer
[1] = CHAR_NULL
;
940 ShellInfoObject
.NewEfiShellProtocol
->WriteFile(TempHandle
, &Size
, TagBuffer
);
941 } else if (OutAppend
) {
943 // Move to end of file
945 Status
= ShellInfoObject
.NewEfiShellProtocol
->GetFileSize(TempHandle
, &FileSize
);
946 if (!EFI_ERROR(Status
)) {
947 Status
= ShellInfoObject
.NewEfiShellProtocol
->SetFilePosition(TempHandle
, FileSize
);
950 if (!OutUnicode
&& !EFI_ERROR(Status
)) {
951 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
952 ASSERT(TempHandle
!= NULL
);
954 if (!EFI_ERROR(Status
)) {
955 ShellParameters
->StdOut
= TempHandle
;
956 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
964 if (!EFI_ERROR(Status
) && StdOutVarName
!= NULL
) {
967 // delete existing variable.
969 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName
, 0, L
"");
971 TempHandle
= CreateFileInterfaceEnv(StdOutVarName
);
972 ASSERT(TempHandle
!= NULL
);
973 ShellParameters
->StdOut
= TempHandle
;
974 gST
->ConOut
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->ConsoleOutHandle
);
980 if (!EFI_ERROR(Status
) && StdErrVarName
!= NULL
) {
983 // delete existing variable.
985 SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName
, 0, L
"");
987 TempHandle
= CreateFileInterfaceEnv(StdErrVarName
);
988 ASSERT(TempHandle
!= NULL
);
989 ShellParameters
->StdErr
= TempHandle
;
990 gST
->StdErr
= CreateSimpleTextOutOnFile(TempHandle
, &gST
->StandardErrorHandle
);
996 if (!EFI_ERROR(Status
) && StdInVarName
!= NULL
) {
997 TempHandle
= CreateFileInterfaceEnv(StdInVarName
);
999 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1002 ASSERT(TempHandle
!= NULL
);
1003 if (((EFI_FILE_PROTOCOL
*)TempHandle
)->Read(TempHandle
, &Size
, NULL
) != EFI_BUFFER_TOO_SMALL
) {
1004 Status
= EFI_INVALID_PARAMETER
;
1006 ShellParameters
->StdIn
= TempHandle
;
1007 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1012 // StdIn from a file
1014 if (!EFI_ERROR(Status
) && StdInFileName
!= NULL
) {
1015 Status
= ShellOpenFileByName(
1020 if (!InUnicode
&& !EFI_ERROR(Status
)) {
1021 TempHandle
= CreateFileInterfaceFile(TempHandle
, FALSE
);
1023 if (!EFI_ERROR(Status
)) {
1024 ShellParameters
->StdIn
= TempHandle
;
1025 gST
->ConIn
= CreateSimpleTextInOnFile(TempHandle
, &gST
->ConsoleInHandle
);
1030 FreePool(CommandLineCopy
);
1032 if (gST
->ConIn
== NULL
||gST
->ConOut
== NULL
) {
1033 return (EFI_OUT_OF_RESOURCES
);
1039 Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
1040 structure with StdIn and StdOut. The current values are de-allocated.
1042 @param[in,out] ShellParameters Pointer to parameter structure to modify.
1043 @param[in] OldStdIn Pointer to old StdIn.
1044 @param[in] OldStdOut Pointer to old StdOut.
1045 @param[in] OldStdErr Pointer to old StdErr.
1046 @param[in] SystemTableInfo Pointer to old system table information.
1050 RestoreStdInStdOutStdErr (
1051 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1052 IN SHELL_FILE_HANDLE
*OldStdIn
,
1053 IN SHELL_FILE_HANDLE
*OldStdOut
,
1054 IN SHELL_FILE_HANDLE
*OldStdErr
,
1055 IN SYSTEM_TABLE_INFO
*SystemTableInfo
1060 if (ShellParameters
== NULL
1064 ||SystemTableInfo
== NULL
) {
1065 return (EFI_INVALID_PARAMETER
);
1067 if (!IsListEmpty(&ShellInfoObject
.SplitList
.Link
)) {
1068 Split
= (SPLIT_LIST
*)GetFirstNode(&ShellInfoObject
.SplitList
.Link
);
1072 if (ShellParameters
->StdIn
!= *OldStdIn
) {
1073 if ((Split
!= NULL
&& Split
->SplitStdIn
!= ShellParameters
->StdIn
) || Split
== NULL
) {
1074 gEfiShellProtocol
->CloseFile(ShellParameters
->StdIn
);
1076 ShellParameters
->StdIn
= *OldStdIn
;
1078 if (ShellParameters
->StdOut
!= *OldStdOut
) {
1079 if ((Split
!= NULL
&& Split
->SplitStdOut
!= ShellParameters
->StdOut
) || Split
== NULL
) {
1080 gEfiShellProtocol
->CloseFile(ShellParameters
->StdOut
);
1082 ShellParameters
->StdOut
= *OldStdOut
;
1084 if (ShellParameters
->StdErr
!= *OldStdErr
) {
1085 gEfiShellProtocol
->CloseFile(ShellParameters
->StdErr
);
1086 ShellParameters
->StdErr
= *OldStdErr
;
1089 if (gST
->ConIn
!= SystemTableInfo
->ConIn
) {
1090 CloseSimpleTextInOnFile(gST
->ConIn
);
1091 gST
->ConIn
= SystemTableInfo
->ConIn
;
1092 gST
->ConsoleInHandle
= SystemTableInfo
->ConInHandle
;
1094 if (gST
->ConOut
!= SystemTableInfo
->ConOut
) {
1095 CloseSimpleTextOutOnFile(gST
->ConOut
);
1096 gST
->ConOut
= SystemTableInfo
->ConOut
;
1097 gST
->ConsoleOutHandle
= SystemTableInfo
->ConOutHandle
;
1099 if (gST
->StdErr
!= SystemTableInfo
->ConErr
) {
1100 CloseSimpleTextOutOnFile(gST
->StdErr
);
1101 gST
->StdErr
= SystemTableInfo
->ConErr
;
1102 gST
->StandardErrorHandle
= SystemTableInfo
->ConErrHandle
;
1105 return (EFI_SUCCESS
);
1108 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1109 structure by parsing NewCommandLine. The current values are returned to the
1112 If OldArgv or OldArgc is NULL then that value is not returned.
1114 @param[in,out] ShellParameters Pointer to parameter structure to modify.
1115 @param[in] NewCommandLine The new command line to parse and use.
1116 @param[out] OldArgv Pointer to old list of parameters.
1117 @param[out] OldArgc Pointer to old number of items in Argv list.
1119 @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
1120 @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
1125 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1126 IN CONST CHAR16
*NewCommandLine
,
1127 OUT CHAR16
***OldArgv OPTIONAL
,
1128 OUT UINTN
*OldArgc OPTIONAL
1131 ASSERT(ShellParameters
!= NULL
);
1133 if (OldArgc
!= NULL
) {
1134 *OldArgc
= ShellParameters
->Argc
;
1136 if (OldArgc
!= NULL
) {
1137 *OldArgv
= ShellParameters
->Argv
;
1140 return (ParseCommandLineToArgs(NewCommandLine
, &(ShellParameters
->Argv
), &(ShellParameters
->Argc
)));
1144 Funcion will replace the current Argc and Argv in the ShellParameters protocol
1145 structure with Argv and Argc. The current values are de-allocated and the
1146 OldArgv must not be deallocated by the caller.
1148 @param[in,out] ShellParameters pointer to parameter structure to modify
1149 @param[in] OldArgv pointer to old list of parameters
1150 @param[in] OldArgc pointer to old number of items in Argv list
1155 IN OUT EFI_SHELL_PARAMETERS_PROTOCOL
*ShellParameters
,
1156 IN CHAR16
***OldArgv
,
1161 ASSERT(ShellParameters
!= NULL
);
1162 ASSERT(OldArgv
!= NULL
);
1163 ASSERT(OldArgc
!= NULL
);
1165 if (ShellParameters
->Argv
!= NULL
) {
1166 for ( LoopCounter
= 0
1167 ; LoopCounter
< ShellParameters
->Argc
1170 FreePool(ShellParameters
->Argv
[LoopCounter
]);
1172 FreePool(ShellParameters
->Argv
);
1174 ShellParameters
->Argv
= *OldArgv
;
1176 ShellParameters
->Argc
= *OldArgc
;