/** @file | |
Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation, | |
manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL. | |
Copyright (C) 2014, Red Hat, Inc. | |
(C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR> | |
Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR> | |
This program and the accompanying materials | |
are licensed and made available under the terms and conditions of the BSD License | |
which accompanies this distribution. The full text of the license may be found at | |
http://opensource.org/licenses/bsd-license.php | |
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, | |
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. | |
**/ | |
#include "Shell.h" | |
/** | |
Return the next parameter's end from a command line string. | |
@param[in] String the string to parse | |
**/ | |
CONST CHAR16* | |
EFIAPI | |
FindEndOfParameter( | |
IN CONST CHAR16 *String | |
) | |
{ | |
CONST CHAR16 *First; | |
CONST CHAR16 *CloseQuote; | |
First = FindFirstCharacter(String, L" \"", L'^'); | |
// | |
// nothing, all one parameter remaining | |
// | |
if (*First == CHAR_NULL) { | |
return (First); | |
} | |
// | |
// If space before a quote (or neither found, i.e. both CHAR_NULL), | |
// then that's the end. | |
// | |
if (*First == L' ') { | |
return (First); | |
} | |
CloseQuote = FindFirstCharacter (First+1, L"\"", L'^'); | |
// | |
// We did not find a terminator... | |
// | |
if (*CloseQuote == CHAR_NULL) { | |
return (NULL); | |
} | |
return (FindEndOfParameter (CloseQuote+1)); | |
} | |
/** | |
Return the next parameter from a command line string. | |
This function moves the next parameter from Walker into TempParameter and moves | |
Walker up past that parameter for recursive calling. When the final parameter | |
is moved *Walker will be set to NULL; | |
Temp Parameter must be large enough to hold the parameter before calling this | |
function. | |
This will also remove all remaining ^ characters after processing. | |
@param[in, out] Walker pointer to string of command line. Adjusted to | |
reminaing command line on return | |
@param[in, out] TempParameter pointer to string of command line item extracted. | |
@param[in] Length buffer size of TempParameter. | |
@return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string. | |
@return EFI_NOT_FOUND A closing " could not be found on the specified string | |
**/ | |
EFI_STATUS | |
EFIAPI | |
GetNextParameter( | |
IN OUT CHAR16 **Walker, | |
IN OUT CHAR16 **TempParameter, | |
IN CONST UINTN Length | |
) | |
{ | |
CONST CHAR16 *NextDelim; | |
if (Walker == NULL | |
||*Walker == NULL | |
||TempParameter == NULL | |
||*TempParameter == NULL | |
){ | |
return (EFI_INVALID_PARAMETER); | |
} | |
// | |
// make sure we dont have any leading spaces | |
// | |
while ((*Walker)[0] == L' ') { | |
(*Walker)++; | |
} | |
// | |
// make sure we still have some params now... | |
// | |
if (StrLen(*Walker) == 0) { | |
DEBUG_CODE_BEGIN(); | |
*Walker = NULL; | |
DEBUG_CODE_END(); | |
return (EFI_INVALID_PARAMETER); | |
} | |
NextDelim = FindEndOfParameter(*Walker); | |
if (NextDelim == NULL){ | |
DEBUG_CODE_BEGIN(); | |
*Walker = NULL; | |
DEBUG_CODE_END(); | |
return (EFI_NOT_FOUND); | |
} | |
StrnCpy(*TempParameter, (*Walker), NextDelim - *Walker); | |
// | |
// Add a CHAR_NULL if we didnt get one via the copy | |
// | |
if (*NextDelim != CHAR_NULL) { | |
(*TempParameter)[NextDelim - *Walker] = CHAR_NULL; | |
} | |
// | |
// Update Walker for the next iteration through the function | |
// | |
*Walker = (CHAR16*)NextDelim; | |
// | |
// Remove any non-escaped quotes in the string | |
// Remove any remaining escape characters in the string | |
// | |
for (NextDelim = FindFirstCharacter(*TempParameter, L"\"^", CHAR_NULL) | |
; *NextDelim != CHAR_NULL | |
; NextDelim = FindFirstCharacter(NextDelim, L"\"^", CHAR_NULL) | |
) { | |
if (*NextDelim == L'^') { | |
// | |
// eliminate the escape ^ | |
// | |
CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); | |
NextDelim++; | |
} else if (*NextDelim == L'\"') { | |
// | |
// eliminate the unescaped quote | |
// | |
CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); | |
} | |
} | |
return EFI_SUCCESS; | |
} | |
/** | |
Function to populate Argc and Argv. | |
This function parses the CommandLine and divides it into standard C style Argc/Argv | |
parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space | |
delimited and quote surrounded parameter definition. | |
All special character processing (alias, environment variable, redirection, | |
etc... must be complete before calling this API. | |
@param[in] CommandLine String of command line to parse | |
@param[in, out] Argv pointer to array of strings; one for each parameter | |
@param[in, out] Argc pointer to number of strings in Argv array | |
@return EFI_SUCCESS the operation was sucessful | |
@return EFI_OUT_OF_RESOURCES a memory allocation failed. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
ParseCommandLineToArgs( | |
IN CONST CHAR16 *CommandLine, | |
IN OUT CHAR16 ***Argv, | |
IN OUT UINTN *Argc | |
) | |
{ | |
UINTN Count; | |
CHAR16 *TempParameter; | |
CHAR16 *Walker; | |
CHAR16 *NewParam; | |
UINTN Size; | |
ASSERT(Argc != NULL); | |
ASSERT(Argv != NULL); | |
if (CommandLine == NULL || StrLen(CommandLine)==0) { | |
(*Argc) = 0; | |
(*Argv) = NULL; | |
return (EFI_SUCCESS); | |
} | |
Size = StrSize(CommandLine); | |
TempParameter = AllocateZeroPool(Size); | |
if (TempParameter == NULL) { | |
return (EFI_OUT_OF_RESOURCES); | |
} | |
for ( Count = 0 | |
, Walker = (CHAR16*)CommandLine | |
; Walker != NULL && *Walker != CHAR_NULL | |
; Count++ | |
) { | |
if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) { | |
break; | |
} | |
} | |
// | |
// lets allocate the pointer array | |
// | |
(*Argv) = AllocateZeroPool((Count)*sizeof(CHAR16*)); | |
if (*Argv == NULL) { | |
SHELL_FREE_NON_NULL(TempParameter); | |
return (EFI_OUT_OF_RESOURCES); | |
} | |
*Argc = 0; | |
Walker = (CHAR16*)CommandLine; | |
while(Walker != NULL && *Walker != CHAR_NULL) { | |
SetMem16(TempParameter, Size, CHAR_NULL); | |
if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) { | |
SHELL_FREE_NON_NULL(TempParameter); | |
return (EFI_INVALID_PARAMETER); | |
} | |
NewParam = AllocateCopyPool(StrSize(TempParameter), TempParameter); | |
if (NewParam == NULL){ | |
SHELL_FREE_NON_NULL(TempParameter); | |
return (EFI_OUT_OF_RESOURCES); | |
} | |
((CHAR16**)(*Argv))[(*Argc)] = NewParam; | |
(*Argc)++; | |
} | |
ASSERT(Count >= (*Argc)); | |
SHELL_FREE_NON_NULL(TempParameter); | |
return (EFI_SUCCESS); | |
} | |
/** | |
creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then | |
installs it on our handle and if there is an existing version of the protocol | |
that one is cached for removal later. | |
@param[in, out] NewShellParameters on a successful return, a pointer to pointer | |
to the newly installed interface. | |
@param[in, out] RootShellInstance on a successful return, pointer to boolean. | |
TRUE if this is the root shell instance. | |
@retval EFI_SUCCESS the operation completed successfully. | |
@return other the operation failed. | |
@sa ReinstallProtocolInterface | |
@sa InstallProtocolInterface | |
@sa ParseCommandLineToArgs | |
**/ | |
EFI_STATUS | |
EFIAPI | |
CreatePopulateInstallShellParametersProtocol ( | |
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters, | |
IN OUT BOOLEAN *RootShellInstance | |
) | |
{ | |
EFI_STATUS Status; | |
EFI_LOADED_IMAGE_PROTOCOL *LoadedImage; | |
CHAR16 *FullCommandLine; | |
UINTN Size; | |
Size = 0; | |
FullCommandLine = NULL; | |
LoadedImage = NULL; | |
// | |
// Assert for valid parameters | |
// | |
ASSERT(NewShellParameters != NULL); | |
ASSERT(RootShellInstance != NULL); | |
// | |
// See if we have a shell parameters placed on us | |
// | |
Status = gBS->OpenProtocol ( | |
gImageHandle, | |
&gEfiShellParametersProtocolGuid, | |
(VOID **) &ShellInfoObject.OldShellParameters, | |
gImageHandle, | |
NULL, | |
EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
); | |
// | |
// if we don't then we must be the root shell (error is expected) | |
// | |
if (EFI_ERROR (Status)) { | |
*RootShellInstance = TRUE; | |
} | |
// | |
// Allocate the new structure | |
// | |
*NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL)); | |
if ((*NewShellParameters) == NULL) { | |
return (EFI_OUT_OF_RESOURCES); | |
} | |
// | |
// get loaded image protocol | |
// | |
Status = gBS->OpenProtocol ( | |
gImageHandle, | |
&gEfiLoadedImageProtocolGuid, | |
(VOID **) &LoadedImage, | |
gImageHandle, | |
NULL, | |
EFI_OPEN_PROTOCOL_GET_PROTOCOL | |
); | |
ASSERT_EFI_ERROR(Status); | |
// | |
// Build the full command line | |
// | |
Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine); | |
if (Status == EFI_BUFFER_TOO_SMALL) { | |
FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize); | |
Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine); | |
} | |
if (Status == EFI_NOT_FOUND) { | |
// | |
// no parameters via environment... ok | |
// | |
} else { | |
if (EFI_ERROR(Status)) { | |
return (Status); | |
} | |
} | |
if (Size == 0 && LoadedImage->LoadOptionsSize != 0) { | |
ASSERT(FullCommandLine == NULL); | |
// | |
// Now we need to include a NULL terminator in the size. | |
// | |
Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]); | |
FullCommandLine = AllocateZeroPool(Size); | |
} | |
if (FullCommandLine != NULL) { | |
CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize); | |
// | |
// Populate Argc and Argv | |
// | |
Status = ParseCommandLineToArgs(FullCommandLine, | |
&(*NewShellParameters)->Argv, | |
&(*NewShellParameters)->Argc); | |
FreePool(FullCommandLine); | |
ASSERT_EFI_ERROR(Status); | |
} else { | |
(*NewShellParameters)->Argv = NULL; | |
(*NewShellParameters)->Argc = 0; | |
} | |
// | |
// Populate the 3 faked file systems... | |
// | |
if (*RootShellInstance) { | |
(*NewShellParameters)->StdIn = &FileInterfaceStdIn; | |
(*NewShellParameters)->StdOut = &FileInterfaceStdOut; | |
(*NewShellParameters)->StdErr = &FileInterfaceStdErr; | |
Status = gBS->InstallProtocolInterface(&gImageHandle, | |
&gEfiShellParametersProtocolGuid, | |
EFI_NATIVE_INTERFACE, | |
(VOID*)(*NewShellParameters)); | |
} else { | |
// | |
// copy from the existing ones | |
// | |
(*NewShellParameters)->StdIn = ShellInfoObject.OldShellParameters->StdIn; | |
(*NewShellParameters)->StdOut = ShellInfoObject.OldShellParameters->StdOut; | |
(*NewShellParameters)->StdErr = ShellInfoObject.OldShellParameters->StdErr; | |
Status = gBS->ReinstallProtocolInterface(gImageHandle, | |
&gEfiShellParametersProtocolGuid, | |
(VOID*)ShellInfoObject.OldShellParameters, | |
(VOID*)(*NewShellParameters)); | |
} | |
return (Status); | |
} | |
/** | |
frees all memory used by createion and installation of shell parameters protocol | |
and if there was an old version installed it will restore that one. | |
@param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is | |
being cleaned up. | |
@retval EFI_SUCCESS the cleanup was successful | |
@return other the cleanup failed | |
@sa ReinstallProtocolInterface | |
@sa UninstallProtocolInterface | |
**/ | |
EFI_STATUS | |
EFIAPI | |
CleanUpShellParametersProtocol ( | |
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters | |
) | |
{ | |
EFI_STATUS Status; | |
UINTN LoopCounter; | |
// | |
// If the old exists we need to restore it | |
// | |
if (ShellInfoObject.OldShellParameters != NULL) { | |
Status = gBS->ReinstallProtocolInterface(gImageHandle, | |
&gEfiShellParametersProtocolGuid, | |
(VOID*)NewShellParameters, | |
(VOID*)ShellInfoObject.OldShellParameters); | |
DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;); | |
} else { | |
// | |
// No old one, just uninstall us... | |
// | |
Status = gBS->UninstallProtocolInterface(gImageHandle, | |
&gEfiShellParametersProtocolGuid, | |
(VOID*)NewShellParameters); | |
} | |
if (NewShellParameters->Argv != NULL) { | |
for ( LoopCounter = 0 | |
; LoopCounter < NewShellParameters->Argc | |
; LoopCounter++ | |
){ | |
FreePool(NewShellParameters->Argv[LoopCounter]); | |
} | |
FreePool(NewShellParameters->Argv); | |
} | |
FreePool(NewShellParameters); | |
return (Status); | |
} | |
/** | |
Determin if a file name represents a unicode file. | |
@param[in] FileName Pointer to the filename to open. | |
@retval EFI_SUCCESS The file is a unicode file. | |
@return An error upon failure. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
IsUnicodeFile( | |
IN CONST CHAR16 *FileName | |
) | |
{ | |
SHELL_FILE_HANDLE Handle; | |
EFI_STATUS Status; | |
UINT64 OriginalFilePosition; | |
UINTN CharSize; | |
CHAR16 CharBuffer; | |
Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ); | |
if (EFI_ERROR(Status)) { | |
return (Status); | |
} | |
gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition); | |
gEfiShellProtocol->SetFilePosition(Handle, 0); | |
CharSize = sizeof(CHAR16); | |
Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer); | |
if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) { | |
Status = EFI_BUFFER_TOO_SMALL; | |
} | |
gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition); | |
gEfiShellProtocol->CloseFile(Handle); | |
return (Status); | |
} | |
/** | |
Strips out quotes sections of a string. | |
All of the characters between quotes is replaced with spaces. | |
@param[in, out] TheString A pointer to the string to update. | |
**/ | |
VOID | |
EFIAPI | |
StripQuotes ( | |
IN OUT CHAR16 *TheString | |
) | |
{ | |
BOOLEAN RemoveNow; | |
for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) { | |
if (*TheString == L'^' && *(TheString + 1) == L'\"') { | |
TheString++; | |
} else if (*TheString == L'\"') { | |
RemoveNow = (BOOLEAN)!RemoveNow; | |
} else if (RemoveNow) { | |
*TheString = L' '; | |
} | |
} | |
} | |
/** | |
Calcualte the 32-bit CRC in a EFI table using the service provided by the | |
gRuntime service. | |
@param Hdr Pointer to an EFI standard header | |
**/ | |
VOID | |
CalculateEfiHdrCrc ( | |
IN OUT EFI_TABLE_HEADER *Hdr | |
) | |
{ | |
UINT32 Crc; | |
Hdr->CRC32 = 0; | |
// | |
// If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then | |
// Crc will come back as zero if we set it to zero here | |
// | |
Crc = 0; | |
gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc); | |
Hdr->CRC32 = Crc; | |
} | |
/** | |
Fix a string to only have the file name, removing starting at the first space of whatever is quoted. | |
@param[in] FileName The filename to start with. | |
@retval NULL FileName was invalid. | |
@return The modified FileName. | |
**/ | |
CHAR16* | |
EFIAPI | |
FixFileName ( | |
IN CHAR16 *FileName | |
) | |
{ | |
CHAR16 *Copy; | |
CHAR16 *TempLocation; | |
if (FileName == NULL) { | |
return (NULL); | |
} | |
if (FileName[0] == L'\"') { | |
Copy = FileName+1; | |
if ((TempLocation = StrStr(Copy , L"\"")) != NULL) { | |
TempLocation[0] = CHAR_NULL; | |
} | |
} else { | |
Copy = FileName; | |
while(Copy[0] == L' ') { | |
Copy++; | |
} | |
if ((TempLocation = StrStr(Copy , L" ")) != NULL) { | |
TempLocation[0] = CHAR_NULL; | |
} | |
} | |
if (Copy[0] == CHAR_NULL) { | |
return (NULL); | |
} | |
return (Copy); | |
} | |
/** | |
Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %. | |
@param[in] FileName The filename to start with. | |
@retval NULL FileName was invalid. | |
@return The modified FileName. | |
**/ | |
CHAR16* | |
EFIAPI | |
FixVarName ( | |
IN CHAR16 *FileName | |
) | |
{ | |
CHAR16 *Copy; | |
CHAR16 *TempLocation; | |
Copy = FileName; | |
if (FileName[0] == L'%') { | |
Copy = FileName+1; | |
if ((TempLocation = StrStr(Copy , L"%")) != NULL) { | |
TempLocation[0] = CHAR_NULL; | |
} | |
} | |
return (FixFileName(Copy)); | |
} | |
/** | |
Remove the unicode file tag from the begining of the file buffer since that will not be | |
used by StdIn. | |
@param[in] Handle Pointer to the handle of the file to be processed. | |
@retval EFI_SUCCESS The unicode file tag has been moved successfully. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
RemoveFileTag( | |
IN SHELL_FILE_HANDLE *Handle | |
) | |
{ | |
UINTN CharSize; | |
CHAR16 CharBuffer; | |
CharSize = sizeof(CHAR16); | |
CharBuffer = 0; | |
gEfiShellProtocol->ReadFile(*Handle, &CharSize, &CharBuffer); | |
if (CharBuffer != gUnicodeFileTag) { | |
gEfiShellProtocol->SetFilePosition(*Handle, 0); | |
} | |
return (EFI_SUCCESS); | |
} | |
/** | |
Write the unicode file tag to the specified file. | |
It is the caller's responsibility to ensure that | |
ShellInfoObject.NewEfiShellProtocol has been initialized before calling this | |
function. | |
@param[in] FileHandle The file to write the unicode file tag to. | |
@return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile. | |
**/ | |
EFI_STATUS | |
WriteFileTag ( | |
IN SHELL_FILE_HANDLE FileHandle | |
) | |
{ | |
CHAR16 FileTag; | |
UINTN Size; | |
EFI_STATUS Status; | |
FileTag = gUnicodeFileTag; | |
Size = sizeof FileTag; | |
Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size, | |
&FileTag); | |
ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag); | |
return Status; | |
} | |
/** | |
Funcion will replace the current StdIn and StdOut in the ShellParameters protocol | |
structure by parsing NewCommandLine. The current values are returned to the | |
user. | |
This will also update the system table. | |
@param[in, out] ShellParameters Pointer to parameter structure to modify. | |
@param[in] NewCommandLine The new command line to parse and use. | |
@param[out] OldStdIn Pointer to old StdIn. | |
@param[out] OldStdOut Pointer to old StdOut. | |
@param[out] OldStdErr Pointer to old StdErr. | |
@param[out] SystemTableInfo Pointer to old system table information. | |
@retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid. | |
@retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
UpdateStdInStdOutStdErr( | |
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, | |
IN CHAR16 *NewCommandLine, | |
OUT SHELL_FILE_HANDLE *OldStdIn, | |
OUT SHELL_FILE_HANDLE *OldStdOut, | |
OUT SHELL_FILE_HANDLE *OldStdErr, | |
OUT SYSTEM_TABLE_INFO *SystemTableInfo | |
) | |
{ | |
CHAR16 *CommandLineCopy; | |
CHAR16 *CommandLineWalker; | |
CHAR16 *StdErrFileName; | |
CHAR16 *StdOutFileName; | |
CHAR16 *StdInFileName; | |
CHAR16 *StdInVarName; | |
CHAR16 *StdOutVarName; | |
CHAR16 *StdErrVarName; | |
EFI_STATUS Status; | |
SHELL_FILE_HANDLE TempHandle; | |
UINT64 FileSize; | |
BOOLEAN OutUnicode; | |
BOOLEAN InUnicode; | |
BOOLEAN ErrUnicode; | |
BOOLEAN OutAppend; | |
BOOLEAN ErrAppend; | |
UINTN Size; | |
SPLIT_LIST *Split; | |
CHAR16 *FirstLocation; | |
OutUnicode = TRUE; | |
InUnicode = TRUE; | |
ErrUnicode = TRUE; | |
StdInVarName = NULL; | |
StdOutVarName = NULL; | |
StdErrVarName = NULL; | |
StdErrFileName = NULL; | |
StdInFileName = NULL; | |
StdOutFileName = NULL; | |
ErrAppend = FALSE; | |
OutAppend = FALSE; | |
CommandLineCopy = NULL; | |
FirstLocation = NULL; | |
if (ShellParameters == NULL || SystemTableInfo == NULL || OldStdIn == NULL || OldStdOut == NULL || OldStdErr == NULL) { | |
return (EFI_INVALID_PARAMETER); | |
} | |
SystemTableInfo->ConIn = gST->ConIn; | |
SystemTableInfo->ConInHandle = gST->ConsoleInHandle; | |
SystemTableInfo->ConOut = gST->ConOut; | |
SystemTableInfo->ConOutHandle = gST->ConsoleOutHandle; | |
SystemTableInfo->ErrOut = gST->StdErr; | |
SystemTableInfo->ErrOutHandle = gST->StandardErrorHandle; | |
*OldStdIn = ShellParameters->StdIn; | |
*OldStdOut = ShellParameters->StdOut; | |
*OldStdErr = ShellParameters->StdErr; | |
if (NewCommandLine == NULL) { | |
return (EFI_SUCCESS); | |
} | |
CommandLineCopy = StrnCatGrow(&CommandLineCopy, NULL, NewCommandLine, 0); | |
if (CommandLineCopy == NULL) { | |
return (EFI_OUT_OF_RESOURCES); | |
} | |
Status = EFI_SUCCESS; | |
Split = NULL; | |
FirstLocation = CommandLineCopy + StrLen(CommandLineCopy); | |
StripQuotes(CommandLineCopy); | |
if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) { | |
Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link); | |
if (Split != NULL && Split->SplitStdIn != NULL) { | |
ShellParameters->StdIn = Split->SplitStdIn; | |
} | |
if (Split != NULL && Split->SplitStdOut != NULL) { | |
ShellParameters->StdOut = Split->SplitStdOut; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>>v ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 12, L' '); | |
StdErrVarName = CommandLineWalker += 6; | |
ErrAppend = TRUE; | |
if (StrStr(CommandLineWalker, L" 2>>v ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>v ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 12, L' '); | |
StdOutVarName = CommandLineWalker += 6; | |
OutAppend = TRUE; | |
if (StrStr(CommandLineWalker, L" 1>>v ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>v ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
StdOutVarName = CommandLineWalker += 5; | |
OutAppend = TRUE; | |
if (StrStr(CommandLineWalker, L" >>v ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} else if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >v ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 8, L' '); | |
StdOutVarName = CommandLineWalker += 4; | |
OutAppend = FALSE; | |
if (StrStr(CommandLineWalker, L" >v ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>>a ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 12, L' '); | |
StdOutFileName = CommandLineWalker += 6; | |
OutAppend = TRUE; | |
OutUnicode = FALSE; | |
if (StrStr(CommandLineWalker, L" 1>>a ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>> ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
if (StdOutFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutFileName = CommandLineWalker += 5; | |
OutAppend = TRUE; | |
} | |
if (StrStr(CommandLineWalker, L" 1>> ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >> ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 8, L' '); | |
if (StdOutFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutFileName = CommandLineWalker += 4; | |
OutAppend = TRUE; | |
} | |
if (StrStr(CommandLineWalker, L" >> ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >>a ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
if (StdOutFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutFileName = CommandLineWalker += 5; | |
OutAppend = TRUE; | |
OutUnicode = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" >>a ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>a ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
if (StdOutFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutFileName = CommandLineWalker += 5; | |
OutAppend = FALSE; | |
OutUnicode = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" 1>a ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" >a ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 8, L' '); | |
if (StdOutFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutFileName = CommandLineWalker += 4; | |
OutAppend = FALSE; | |
OutUnicode = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" >a ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>> ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
if (StdErrFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdErrFileName = CommandLineWalker += 5; | |
ErrAppend = TRUE; | |
} | |
if (StrStr(CommandLineWalker, L" 2>> ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>v ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
if (StdErrVarName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdErrVarName = CommandLineWalker += 5; | |
ErrAppend = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" 2>v ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1>v ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
if (StdOutVarName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutVarName = CommandLineWalker += 5; | |
OutAppend = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" 1>v ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2>a ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 10, L' '); | |
if (StdErrFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdErrFileName = CommandLineWalker += 5; | |
ErrAppend = FALSE; | |
ErrUnicode = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" 2>a ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 2> ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 8, L' '); | |
if (StdErrFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdErrFileName = CommandLineWalker += 4; | |
ErrAppend = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" 2> ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" 1> ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 8, L' '); | |
if (StdOutFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutFileName = CommandLineWalker += 4; | |
OutAppend = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" 1> ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" > ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 6, L' '); | |
if (StdOutFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdOutFileName = CommandLineWalker += 3; | |
OutAppend = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" > ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" < ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 6, L' '); | |
if (StdInFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdInFileName = CommandLineWalker += 3; | |
} | |
if (StrStr(CommandLineWalker, L" < ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <a ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 8, L' '); | |
if (StdInFileName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdInFileName = CommandLineWalker += 4; | |
InUnicode = FALSE; | |
} | |
if (StrStr(CommandLineWalker, L" <a ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
if (!EFI_ERROR(Status) && (CommandLineWalker = StrStr(CommandLineCopy, L" <v ")) != NULL) { | |
FirstLocation = MIN(CommandLineWalker, FirstLocation); | |
SetMem16(CommandLineWalker, 8, L' '); | |
if (StdInVarName != NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
StdInVarName = CommandLineWalker += 4; | |
} | |
if (StrStr(CommandLineWalker, L" <v ") != NULL) { | |
Status = EFI_NOT_FOUND; | |
} | |
} | |
// | |
// re-populate the string to support any filenames that were in quotes. | |
// | |
StrnCpy(CommandLineCopy, NewCommandLine, StrLen(NewCommandLine)); | |
if (FirstLocation != CommandLineCopy + StrLen(CommandLineCopy) | |
&& ((UINTN)(FirstLocation - CommandLineCopy) < StrLen(NewCommandLine)) | |
){ | |
*(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL; | |
} | |
if (!EFI_ERROR(Status)) { | |
if (StdErrFileName != NULL) { | |
if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} | |
} | |
if (StdOutFileName != NULL) { | |
if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} | |
} | |
if (StdInFileName != NULL) { | |
if ((StdInFileName = FixFileName(StdInFileName)) == NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} | |
} | |
if (StdErrVarName != NULL) { | |
if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} | |
} | |
if (StdOutVarName != NULL) { | |
if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} | |
} | |
if (StdInVarName != NULL) { | |
if ((StdInVarName = FixVarName(StdInVarName)) == NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} | |
} | |
// | |
// Verify not the same and not duplicating something from a split | |
// | |
if ( | |
// | |
// Check that no 2 filenames are the same | |
// | |
(StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0) | |
||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0) | |
||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0) | |
// | |
// Check that no 2 variable names are the same | |
// | |
||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0) | |
||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0) | |
||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0) | |
// | |
// When a split (using | operator) is in place some are not allowed | |
// | |
||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL)) | |
||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL)) | |
// | |
// Check that nothing is trying to be output to 2 locations. | |
// | |
||(StdErrFileName != NULL && StdErrVarName != NULL) | |
||(StdOutFileName != NULL && StdOutVarName != NULL) | |
||(StdInFileName != NULL && StdInVarName != NULL) | |
// | |
// Check for no volatile environment variables | |
// | |
||(StdErrVarName != NULL && !IsVolatileEnv(StdErrVarName)) | |
||(StdOutVarName != NULL && !IsVolatileEnv(StdOutVarName)) | |
// | |
// Cant redirect during a reconnect operation. | |
// | |
||(StrStr(NewCommandLine, L"connect -r") != NULL | |
&& (StdOutVarName != NULL || StdOutFileName != NULL || StdErrFileName != NULL || StdErrVarName != NULL)) | |
// | |
// Check that filetypes (Unicode/Ascii) do not change during an append | |
// | |
||(StdOutFileName != NULL && OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && EFI_ERROR(IsUnicodeFile(StdOutFileName)))) | |
||(StdErrFileName != NULL && ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && EFI_ERROR(IsUnicodeFile(StdErrFileName)))) | |
||(StdOutFileName != NULL && !OutUnicode && OutAppend && (!EFI_ERROR(ShellFileExists(StdOutFileName)) && !EFI_ERROR(IsUnicodeFile(StdOutFileName)))) | |
||(StdErrFileName != NULL && !ErrUnicode && ErrAppend && (!EFI_ERROR(ShellFileExists(StdErrFileName)) && !EFI_ERROR(IsUnicodeFile(StdErrFileName)))) | |
){ | |
Status = EFI_INVALID_PARAMETER; | |
ShellParameters->StdIn = *OldStdIn; | |
ShellParameters->StdOut = *OldStdOut; | |
ShellParameters->StdErr = *OldStdErr; | |
} else if (!EFI_ERROR(Status)){ | |
// | |
// Open the Std<Whatever> and we should not have conflicts here... | |
// | |
// | |
// StdErr to a file | |
// | |
if (StdErrFileName != NULL) { | |
if (!ErrAppend) { | |
// | |
// delete existing file. | |
// | |
ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdErrFileName); | |
} | |
Status = ShellOpenFileByName(StdErrFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0); | |
if (!ErrAppend && ErrUnicode && !EFI_ERROR(Status)) { | |
Status = WriteFileTag (TempHandle); | |
} | |
if (!ErrUnicode && !EFI_ERROR(Status)) { | |
TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); | |
ASSERT(TempHandle != NULL); | |
} | |
if (!EFI_ERROR(Status)) { | |
ShellParameters->StdErr = TempHandle; | |
gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr); | |
} | |
} | |
// | |
// StdOut to a file | |
// | |
if (!EFI_ERROR(Status) && StdOutFileName != NULL) { | |
if (!OutAppend) { | |
// | |
// delete existing file. | |
// | |
ShellInfoObject.NewEfiShellProtocol->DeleteFileByName(StdOutFileName); | |
} | |
Status = ShellOpenFileByName(StdOutFileName, &TempHandle, EFI_FILE_MODE_WRITE|EFI_FILE_MODE_READ|EFI_FILE_MODE_CREATE,0); | |
if (TempHandle == NULL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
if (StrStr(StdOutFileName, L"NUL")==StdOutFileName) { | |
//no-op | |
} else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) { | |
Status = WriteFileTag (TempHandle); | |
} else if (OutAppend) { | |
Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize); | |
if (!EFI_ERROR(Status)) { | |
// | |
// When appending to a new unicode file, write the file tag. | |
// Otherwise (ie. when appending to a new ASCII file, or an | |
// existent file with any encoding), just seek to the end. | |
// | |
Status = (FileSize == 0 && OutUnicode) ? | |
WriteFileTag (TempHandle) : | |
ShellInfoObject.NewEfiShellProtocol->SetFilePosition ( | |
TempHandle, | |
FileSize); | |
} | |
} | |
if (!OutUnicode && !EFI_ERROR(Status)) { | |
TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); | |
ASSERT(TempHandle != NULL); | |
} | |
if (!EFI_ERROR(Status)) { | |
ShellParameters->StdOut = TempHandle; | |
gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut); | |
} | |
} | |
} | |
// | |
// StdOut to a var | |
// | |
if (!EFI_ERROR(Status) && StdOutVarName != NULL) { | |
if (!OutAppend) { | |
// | |
// delete existing variable. | |
// | |
SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L""); | |
} | |
TempHandle = CreateFileInterfaceEnv(StdOutVarName); | |
ASSERT(TempHandle != NULL); | |
ShellParameters->StdOut = TempHandle; | |
gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut); | |
} | |
// | |
// StdErr to a var | |
// | |
if (!EFI_ERROR(Status) && StdErrVarName != NULL) { | |
if (!ErrAppend) { | |
// | |
// delete existing variable. | |
// | |
SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L""); | |
} | |
TempHandle = CreateFileInterfaceEnv(StdErrVarName); | |
ASSERT(TempHandle != NULL); | |
ShellParameters->StdErr = TempHandle; | |
gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr); | |
} | |
// | |
// StdIn from a var | |
// | |
if (!EFI_ERROR(Status) && StdInVarName != NULL) { | |
TempHandle = CreateFileInterfaceEnv(StdInVarName); | |
if (TempHandle == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
} else { | |
if (!InUnicode) { | |
TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); | |
} | |
Size = 0; | |
if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) { | |
Status = EFI_INVALID_PARAMETER; | |
} else { | |
ShellParameters->StdIn = TempHandle; | |
gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle); | |
} | |
} | |
} | |
// | |
// StdIn from a file | |
// | |
if (!EFI_ERROR(Status) && StdInFileName != NULL) { | |
Status = ShellOpenFileByName( | |
StdInFileName, | |
&TempHandle, | |
EFI_FILE_MODE_READ, | |
0); | |
if (InUnicode) { | |
// | |
// Chop off the 0xFEFF if it's there... | |
// | |
RemoveFileTag(&TempHandle); | |
} else if (!EFI_ERROR(Status)) { | |
// | |
// Create the ASCII->Unicode conversion layer | |
// | |
TempHandle = CreateFileInterfaceFile(TempHandle, FALSE); | |
} | |
if (!EFI_ERROR(Status)) { | |
ShellParameters->StdIn = TempHandle; | |
gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle); | |
} | |
} | |
} | |
} | |
FreePool(CommandLineCopy); | |
CalculateEfiHdrCrc(&gST->Hdr); | |
if (gST->ConIn == NULL ||gST->ConOut == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
} | |
if (Status == EFI_NOT_FOUND) { | |
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle); | |
} else if (EFI_ERROR(Status)) { | |
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle); | |
} | |
return (Status); | |
} | |
/** | |
Funcion will replace the current StdIn and StdOut in the ShellParameters protocol | |
structure with StdIn and StdOut. The current values are de-allocated. | |
@param[in, out] ShellParameters Pointer to parameter structure to modify. | |
@param[in] OldStdIn Pointer to old StdIn. | |
@param[in] OldStdOut Pointer to old StdOut. | |
@param[in] OldStdErr Pointer to old StdErr. | |
@param[in] SystemTableInfo Pointer to old system table information. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
RestoreStdInStdOutStdErr ( | |
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, | |
IN SHELL_FILE_HANDLE *OldStdIn, | |
IN SHELL_FILE_HANDLE *OldStdOut, | |
IN SHELL_FILE_HANDLE *OldStdErr, | |
IN SYSTEM_TABLE_INFO *SystemTableInfo | |
) | |
{ | |
SPLIT_LIST *Split; | |
if (ShellParameters == NULL | |
||OldStdIn == NULL | |
||OldStdOut == NULL | |
||OldStdErr == NULL | |
||SystemTableInfo == NULL) { | |
return (EFI_INVALID_PARAMETER); | |
} | |
if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) { | |
Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link); | |
} else { | |
Split = NULL; | |
} | |
if (ShellParameters->StdIn != *OldStdIn) { | |
if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) { | |
gEfiShellProtocol->CloseFile(ShellParameters->StdIn); | |
} | |
ShellParameters->StdIn = *OldStdIn; | |
} | |
if (ShellParameters->StdOut != *OldStdOut) { | |
if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) { | |
gEfiShellProtocol->CloseFile(ShellParameters->StdOut); | |
} | |
ShellParameters->StdOut = *OldStdOut; | |
} | |
if (ShellParameters->StdErr != *OldStdErr) { | |
gEfiShellProtocol->CloseFile(ShellParameters->StdErr); | |
ShellParameters->StdErr = *OldStdErr; | |
} | |
if (gST->ConIn != SystemTableInfo->ConIn) { | |
CloseSimpleTextInOnFile(gST->ConIn); | |
gST->ConIn = SystemTableInfo->ConIn; | |
gST->ConsoleInHandle = SystemTableInfo->ConInHandle; | |
} | |
if (gST->ConOut != SystemTableInfo->ConOut) { | |
CloseSimpleTextOutOnFile(gST->ConOut); | |
gST->ConOut = SystemTableInfo->ConOut; | |
gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle; | |
} | |
if (gST->StdErr != SystemTableInfo->ErrOut) { | |
CloseSimpleTextOutOnFile(gST->StdErr); | |
gST->StdErr = SystemTableInfo->ErrOut; | |
gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle; | |
} | |
CalculateEfiHdrCrc(&gST->Hdr); | |
return (EFI_SUCCESS); | |
} | |
/** | |
Funcion will replace the current Argc and Argv in the ShellParameters protocol | |
structure by parsing NewCommandLine. The current values are returned to the | |
user. | |
If OldArgv or OldArgc is NULL then that value is not returned. | |
@param[in, out] ShellParameters Pointer to parameter structure to modify. | |
@param[in] NewCommandLine The new command line to parse and use. | |
@param[out] OldArgv Pointer to old list of parameters. | |
@param[out] OldArgc Pointer to old number of items in Argv list. | |
@retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid. | |
@retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
**/ | |
EFI_STATUS | |
EFIAPI | |
UpdateArgcArgv( | |
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, | |
IN CONST CHAR16 *NewCommandLine, | |
OUT CHAR16 ***OldArgv OPTIONAL, | |
OUT UINTN *OldArgc OPTIONAL | |
) | |
{ | |
ASSERT(ShellParameters != NULL); | |
if (OldArgc != NULL) { | |
*OldArgc = ShellParameters->Argc; | |
} | |
if (OldArgc != NULL) { | |
*OldArgv = ShellParameters->Argv; | |
} | |
return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc))); | |
} | |
/** | |
Funcion will replace the current Argc and Argv in the ShellParameters protocol | |
structure with Argv and Argc. The current values are de-allocated and the | |
OldArgv must not be deallocated by the caller. | |
@param[in, out] ShellParameters pointer to parameter structure to modify | |
@param[in] OldArgv pointer to old list of parameters | |
@param[in] OldArgc pointer to old number of items in Argv list | |
**/ | |
VOID | |
EFIAPI | |
RestoreArgcArgv( | |
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, | |
IN CHAR16 ***OldArgv, | |
IN UINTN *OldArgc | |
) | |
{ | |
UINTN LoopCounter; | |
ASSERT(ShellParameters != NULL); | |
ASSERT(OldArgv != NULL); | |
ASSERT(OldArgc != NULL); | |
if (ShellParameters->Argv != NULL) { | |
for ( LoopCounter = 0 | |
; LoopCounter < ShellParameters->Argc | |
; LoopCounter++ | |
){ | |
FreePool(ShellParameters->Argv[LoopCounter]); | |
} | |
FreePool(ShellParameters->Argv); | |
} | |
ShellParameters->Argv = *OldArgv; | |
*OldArgv = NULL; | |
ShellParameters->Argc = *OldArgc; | |
*OldArgc = 0; | |
} |