/** @file | |
Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation, | |
manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL. | |
(C) Copyright 2016 Hewlett Packard Enterprise Development LP<BR> | |
Copyright (C) 2014, Red Hat, Inc. | |
(C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR> | |
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR> | |
SPDX-License-Identifier: BSD-2-Clause-Patent | |
**/ | |
#include "Shell.h" | |
BOOLEAN AsciiRedirection = FALSE; | |
/** | |
Return the next parameter's end from a command line string. | |
@param[in] String the string to parse | |
**/ | |
CONST CHAR16 * | |
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 | |
remaining command line on return | |
@param[in, out] TempParameter pointer to string of command line item extracted. | |
@param[in] Length buffer size of TempParameter. | |
@param[in] StripQuotation if TRUE then strip the quotation marks surrounding | |
the parameters. | |
@return EFI_INVALID_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 | |
GetNextParameter ( | |
IN OUT CHAR16 **Walker, | |
IN OUT CHAR16 **TempParameter, | |
IN CONST UINTN Length, | |
IN BOOLEAN StripQuotation | |
) | |
{ | |
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); | |
} | |
StrnCpyS (*TempParameter, Length / sizeof (CHAR16), (*Walker), NextDelim - *Walker); | |
// | |
// Add a CHAR_NULL if we didn't 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 | |
// | |
if (StripQuotation) { | |
CopyMem ((CHAR16 *)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); | |
} else { | |
NextDelim++; | |
} | |
} | |
} | |
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] StripQuotation if TRUE then strip the quotation marks surrounding | |
the parameters. | |
@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 successful | |
@return EFI_INVALID_PARAMETER some parameters are invalid | |
@return EFI_OUT_OF_RESOURCES a memory allocation failed. | |
**/ | |
EFI_STATUS | |
ParseCommandLineToArgs ( | |
IN CONST CHAR16 *CommandLine, | |
IN BOOLEAN StripQuotation, | |
IN OUT CHAR16 ***Argv, | |
IN OUT UINTN *Argc | |
) | |
{ | |
UINTN Count; | |
CHAR16 *TempParameter; | |
CHAR16 *Walker; | |
CHAR16 *NewParam; | |
CHAR16 *NewCommandLine; | |
UINTN Size; | |
EFI_STATUS Status; | |
ASSERT (Argc != NULL); | |
ASSERT (Argv != NULL); | |
if ((CommandLine == NULL) || (StrLen (CommandLine) == 0)) { | |
(*Argc) = 0; | |
(*Argv) = NULL; | |
return (EFI_SUCCESS); | |
} | |
NewCommandLine = AllocateCopyPool (StrSize (CommandLine), CommandLine); | |
if (NewCommandLine == NULL) { | |
return (EFI_OUT_OF_RESOURCES); | |
} | |
TrimSpaces (&NewCommandLine); | |
Size = StrSize (NewCommandLine); | |
TempParameter = AllocateZeroPool (Size); | |
if (TempParameter == NULL) { | |
SHELL_FREE_NON_NULL (NewCommandLine); | |
return (EFI_OUT_OF_RESOURCES); | |
} | |
for ( Count = 0, | |
Walker = (CHAR16 *)NewCommandLine | |
; Walker != NULL && *Walker != CHAR_NULL | |
; Count++ | |
) | |
{ | |
if (EFI_ERROR (GetNextParameter (&Walker, &TempParameter, Size, TRUE))) { | |
break; | |
} | |
} | |
// | |
// lets allocate the pointer array | |
// | |
(*Argv) = AllocateZeroPool ((Count)*sizeof (CHAR16 *)); | |
if (*Argv == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Done; | |
} | |
*Argc = 0; | |
Walker = (CHAR16 *)NewCommandLine; | |
while (Walker != NULL && *Walker != CHAR_NULL) { | |
SetMem16 (TempParameter, Size, CHAR_NULL); | |
if (EFI_ERROR (GetNextParameter (&Walker, &TempParameter, Size, StripQuotation))) { | |
Status = EFI_INVALID_PARAMETER; | |
goto Done; | |
} | |
NewParam = AllocateCopyPool (StrSize (TempParameter), TempParameter); | |
if (NewParam == NULL) { | |
Status = EFI_OUT_OF_RESOURCES; | |
goto Done; | |
} | |
((CHAR16 **)(*Argv))[(*Argc)] = NewParam; | |
(*Argc)++; | |
} | |
ASSERT (Count >= (*Argc)); | |
Status = EFI_SUCCESS; | |
Done: | |
SHELL_FREE_NON_NULL (TempParameter); | |
SHELL_FREE_NON_NULL (NewCommandLine); | |
return (Status); | |
} | |
/** | |
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 | |
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, | |
TRUE, | |
&(*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 creation 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 | |
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); | |
} | |
/** | |
Determine 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 | |
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 | |
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' '; | |
} | |
} | |
} | |
/** | |
Calculate 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 * | |
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 * | |
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)); | |
} | |
/** | |
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; | |
} | |
/** | |
Function 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 successful, Argv and Argc are valid. | |
@retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
**/ | |
EFI_STATUS | |
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; | |
BOOLEAN Volatile; | |
OutUnicode = TRUE; | |
InUnicode = TRUE; | |
AsciiRedirection = FALSE; | |
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; | |
AsciiRedirection = TRUE; | |
} | |
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. | |
// | |
StrnCpyS (CommandLineCopy, StrSize (CommandLineCopy)/sizeof (CHAR16), NewCommandLine, StrLen (NewCommandLine)); | |
if ( (FirstLocation != CommandLineCopy + StrLen (CommandLineCopy)) | |
&& (((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof (CHAR16) < StrLen (NewCommandLine)) | |
) | |
{ | |
*(NewCommandLine + ((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof (CHAR16)) = 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) && !EFI_ERROR (IsVolatileEnv (StdErrVarName, &Volatile)) && !Volatile) | |
|| ((StdOutVarName != NULL) && !EFI_ERROR (IsVolatileEnv (StdOutVarName, &Volatile)) && !Volatile) | |
// | |
// 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 (gUnicodeCollation->MetaiMatch (gUnicodeCollation, StdOutFileName, L"NUL")) { | |
// 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 (!EFI_ERROR (Status)) { | |
if (!InUnicode) { | |
// | |
// Create the ASCII->Unicode conversion layer | |
// | |
TempHandle = CreateFileInterfaceFile (TempHandle, FALSE); | |
} | |
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); | |
} | |
/** | |
Function 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 | |
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); | |
} | |
/** | |
Function 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[in] Type The type of operation. | |
@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 successful, Argv and Argc are valid. | |
@return EFI_INVALID_PARAMETER Some parameters are invalid. | |
@retval EFI_OUT_OF_RESOURCES A memory allocation failed. | |
**/ | |
EFI_STATUS | |
UpdateArgcArgv ( | |
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, | |
IN CONST CHAR16 *NewCommandLine, | |
IN SHELL_OPERATION_TYPES Type, | |
OUT CHAR16 ***OldArgv OPTIONAL, | |
OUT UINTN *OldArgc OPTIONAL | |
) | |
{ | |
BOOLEAN StripParamQuotation; | |
ASSERT (ShellParameters != NULL); | |
StripParamQuotation = TRUE; | |
if (OldArgc != NULL) { | |
*OldArgc = ShellParameters->Argc; | |
} | |
if (OldArgc != NULL) { | |
*OldArgv = ShellParameters->Argv; | |
} | |
if (Type == Script_File_Name) { | |
StripParamQuotation = FALSE; | |
} | |
return ParseCommandLineToArgs ( | |
NewCommandLine, | |
StripParamQuotation, | |
&(ShellParameters->Argv), | |
&(ShellParameters->Argc) | |
); | |
} | |
/** | |
Function 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 | |
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; | |
} |