Files

Ignoring revisions in .git-blame-ignore-revs. Click here to bypass and see the normal blame view.

1528 lines
48 KiB
C
Raw Permalink Normal View History

2010-09-14 05:18:09 +00:00
/** @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>
2018-06-27 21:13:38 +08:00
Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
SPDX-License-Identifier: BSD-2-Clause-Patent
2010-09-14 05:18:09 +00:00
**/
2012-11-13 22:39:09 +00:00
#include "Shell.h"
2010-09-14 05:18:09 +00:00
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
2020-02-07 02:08:20 +01:00
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.
2020-02-07 02:08:20 +01:00
@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);
//
2020-02-07 02:08:20 +01:00
// 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
//
2018-06-27 21:13:38 +08:00
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));
2018-06-27 21:13:38 +08:00
} else {
NextDelim++;
2018-06-27 21:13:38 +08:00
}
}
}
return EFI_SUCCESS;
}
2010-09-14 05:18:09 +00:00
/**
Function to populate Argc and Argv.
2010-09-14 05:18:09 +00:00
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.
2018-06-27 21:13:38 +08:00
All special character processing (alias, environment variable, redirection,
2015-01-27 18:56:36 +00:00
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
2010-09-14 05:18:09 +00:00
2020-02-07 02:08:20 +01:00
@return EFI_SUCCESS the operation was successful
@return EFI_INVALID_PARAMETER some parameters are invalid
2010-09-14 05:18:09 +00:00
@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
2010-09-14 05:18:09 +00:00
)
{
UINTN Count;
CHAR16 *TempParameter;
CHAR16 *Walker;
CHAR16 *NewParam;
CHAR16 *NewCommandLine;
2010-09-14 05:18:09 +00:00
UINTN Size;
EFI_STATUS Status;
2010-09-14 05:18:09 +00:00
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);
2010-09-14 05:18:09 +00:00
TempParameter = AllocateZeroPool (Size);
if (TempParameter == NULL) {
SHELL_FREE_NON_NULL (NewCommandLine);
2010-09-14 05:18:09 +00:00
return (EFI_OUT_OF_RESOURCES);
}
for ( Count = 0,
Walker = (CHAR16 *)NewCommandLine
2010-09-14 05:18:09 +00:00
; Walker != NULL && *Walker != CHAR_NULL
2015-01-27 18:56:36 +00:00
; Count++
)
{
if (EFI_ERROR (GetNextParameter (&Walker, &TempParameter, Size, TRUE))) {
2015-01-27 18:56:36 +00:00
break;
}
}
2010-09-14 05:18:09 +00:00
//
// lets allocate the pointer array
//
(*Argv) = AllocateZeroPool ((Count)*sizeof (CHAR16 *));
if (*Argv == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
2010-09-14 05:18:09 +00:00
}
*Argc = 0;
Walker = (CHAR16 *)NewCommandLine;
2010-09-14 05:18:09 +00:00
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;
2015-01-27 18:56:36 +00:00
}
2014-09-02 20:17:38 +00:00
NewParam = AllocateCopyPool (StrSize (TempParameter), TempParameter);
if (NewParam == NULL) {
Status = EFI_OUT_OF_RESOURCES;
goto Done;
2014-09-02 20:17:38 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
((CHAR16 **)(*Argv))[(*Argc)] = NewParam;
(*Argc)++;
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
ASSERT (Count >= (*Argc));
Status = EFI_SUCCESS;
2018-06-27 21:13:38 +08:00
Done:
SHELL_FREE_NON_NULL (TempParameter);
SHELL_FREE_NON_NULL (NewCommandLine);
return (Status);
2010-09-14 05:18:09 +00:00
}
/**
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.
2011-09-02 08:05:34 +00:00
@param[in, out] NewShellParameters on a successful return, a pointer to pointer
2010-09-14 05:18:09 +00:00
to the newly installed interface.
2011-09-02 08:05:34 +00:00
@param[in, out] RootShellInstance on a successful return, pointer to boolean.
2010-09-14 05:18:09 +00:00
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);
}
2010-09-14 05:18:09 +00:00
//
// 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);
2010-09-14 05:18:09 +00:00
if (Status == EFI_BUFFER_TOO_SMALL) {
FullCommandLine = AllocateZeroPool (Size + LoadedImage->LoadOptionsSize);
2024-10-03 10:30:15 -07:00
if (FullCommandLine == NULL) {
return EFI_OUT_OF_RESOURCES;
}
Status = SHELL_GET_ENVIRONMENT_VARIABLE (L"ShellOpt", &Size, FullCommandLine);
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (Status == EFI_NOT_FOUND) {
//
// no parameters via environment... ok
//
} else {
if (EFI_ERROR (Status)) {
return (Status);
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if ((Size == 0) && (LoadedImage->LoadOptionsSize != 0)) {
ASSERT (FullCommandLine == NULL);
2010-09-14 05:18:09 +00:00
//
// Now we need to include a NULL terminator in the size.
//
Size = LoadedImage->LoadOptionsSize + sizeof (FullCommandLine[0]);
FullCommandLine = AllocateZeroPool (Size);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (FullCommandLine != NULL) {
2013-10-22 01:14:54 +00:00
CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);
2010-09-14 05:18:09 +00:00
//
// Populate Argc and Argv
//
Status = ParseCommandLineToArgs (
FullCommandLine,
TRUE,
2010-09-14 05:18:09 +00:00
&(*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);
}
/**
2020-02-07 02:08:20 +01:00
frees all memory used by creation and installation of shell parameters protocol
2010-09-14 05:18:09 +00:00
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
);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (NewShellParameters->Argv != NULL) {
for ( LoopCounter = 0
; LoopCounter < NewShellParameters->Argc
; LoopCounter++
)
{
FreePool (NewShellParameters->Argv[LoopCounter]);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
FreePool (NewShellParameters->Argv);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
FreePool (NewShellParameters);
return (Status);
}
2011-04-01 22:16:01 +00:00
/**
2020-02-07 02:08:20 +01:00
Determine if a file name represents a unicode file.
2011-04-01 22:16:01 +00:00
@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);
}
2021-12-05 14:54:13 -08:00
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;
}
2021-12-05 14:54:13 -08:00
gEfiShellProtocol->SetFilePosition (Handle, OriginalFilePosition);
gEfiShellProtocol->CloseFile (Handle);
2018-06-27 21:13:38 +08:00
return (Status);
}
/**
Strips out quotes sections of a string.
All of the characters between quotes is replaced with spaces.
2011-09-02 08:05:34 +00:00
@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' ';
}
}
}
/**
2020-02-07 02:08:20 +01:00
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;
2018-06-27 21:13:38 +08:00
}
} else {
Copy = FileName;
while (Copy[0] == L' ') {
Copy++;
}
2021-12-05 14:54:13 -08:00
if ((TempLocation = StrStr (Copy, L" ")) != NULL) {
TempLocation[0] = CHAR_NULL;
2018-06-27 21:13:38 +08:00
}
}
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;
2018-06-27 21:13:38 +08:00
}
}
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;
}
2010-09-14 05:18:09 +00:00
/**
2020-02-07 02:08:20 +01:00
Function will replace the current StdIn and StdOut in the ShellParameters protocol
2010-09-14 05:18:09 +00:00
structure by parsing NewCommandLine. The current values are returned to the
user.
This will also update the system table.
2010-09-14 05:18:09 +00:00
2011-09-02 08:05:34 +00:00
@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.
2010-09-14 05:18:09 +00:00
2020-02-07 02:08:20 +01:00
@retval EFI_SUCCESS Operation was successful, Argv and Argc are valid.
2010-09-14 05:18:09 +00:00
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.
**/
EFI_STATUS
UpdateStdInStdOutStdErr (
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
IN CHAR16 *NewCommandLine,
2010-09-14 05:18:09 +00:00
OUT SHELL_FILE_HANDLE *OldStdIn,
OUT SHELL_FILE_HANDLE *OldStdOut,
OUT SHELL_FILE_HANDLE *OldStdErr,
OUT SYSTEM_TABLE_INFO *SystemTableInfo
2010-09-14 05:18:09 +00:00
)
{
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;
2010-09-14 05:18:09 +00:00
OutUnicode = TRUE;
InUnicode = TRUE;
AsciiRedirection = FALSE;
2010-09-14 05:18:09 +00:00
ErrUnicode = TRUE;
StdInVarName = NULL;
StdOutVarName = NULL;
StdErrVarName = NULL;
StdErrFileName = NULL;
StdInFileName = NULL;
StdOutFileName = NULL;
ErrAppend = FALSE;
OutAppend = FALSE;
CommandLineCopy = NULL;
2011-04-01 16:11:59 +00:00
FirstLocation = NULL;
2024-10-03 10:30:15 -07:00
TempHandle = NULL;
2010-09-14 05:18:09 +00:00
if ((ShellParameters == NULL) || (SystemTableInfo == NULL) || (OldStdIn == NULL) || (OldStdOut == NULL) || (OldStdErr == NULL)) {
return (EFI_INVALID_PARAMETER);
2010-09-14 05:18:09 +00:00
}
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;
2010-09-14 05:18:09 +00:00
if (NewCommandLine == NULL) {
return (EFI_SUCCESS);
}
CommandLineCopy = StrnCatGrow (&CommandLineCopy, NULL, NewCommandLine, 0);
if (CommandLineCopy == NULL) {
return (EFI_OUT_OF_RESOURCES);
}
2010-09-14 05:18:09 +00:00
Status = EFI_SUCCESS;
2010-09-14 05:18:09 +00:00
Split = NULL;
FirstLocation = CommandLineCopy + StrLen (CommandLineCopy);
2011-04-01 16:11:59 +00:00
StripQuotes (CommandLineCopy);
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!IsListEmpty (&ShellInfoObject.SplitList.Link)) {
Split = (SPLIT_LIST *)GetFirstNode (&ShellInfoObject.SplitList.Link);
if ((Split != NULL) && (Split->SplitStdIn != NULL)) {
ShellParameters->StdIn = Split->SplitStdIn;
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
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' ');
2010-09-14 05:18:09 +00:00
StdErrVarName = CommandLineWalker += 6;
ErrAppend = TRUE;
if (StrStr (CommandLineWalker, L" 2>>v ") != NULL) {
Status = EFI_NOT_FOUND;
}
2010-09-14 05:18:09 +00:00
}
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 1>>v ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 12, L' ');
2010-09-14 05:18:09 +00:00
StdOutVarName = CommandLineWalker += 6;
OutAppend = TRUE;
if (StrStr (CommandLineWalker, L" 1>>v ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
} else if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" >>v ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
StdOutVarName = CommandLineWalker += 5;
OutAppend = TRUE;
if (StrStr (CommandLineWalker, L" >>v ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
} else if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" >v ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 8, L' ');
2010-09-14 05:18:09 +00:00
StdOutVarName = CommandLineWalker += 4;
OutAppend = FALSE;
if (StrStr (CommandLineWalker, L" >v ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 1>>a ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 12, L' ');
2010-09-14 05:18:09 +00:00
StdOutFileName = CommandLineWalker += 6;
OutAppend = TRUE;
OutUnicode = FALSE;
if (StrStr (CommandLineWalker, L" 1>>a ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 1>> ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
2021-12-05 14:54:13 -08:00
} else {
2010-09-14 05:18:09 +00:00
StdOutFileName = CommandLineWalker += 5;
OutAppend = TRUE;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
if (StrStr (CommandLineWalker, L" 1>> ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" >> ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 8, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
2021-12-05 14:54:13 -08:00
} else {
2010-09-14 05:18:09 +00:00
StdOutFileName = CommandLineWalker += 4;
OutAppend = TRUE;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
if (StrStr (CommandLineWalker, L" >> ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" >>a ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
2021-12-05 14:54:13 -08:00
} else {
2010-09-14 05:18:09 +00:00
StdOutFileName = CommandLineWalker += 5;
OutAppend = TRUE;
OutUnicode = FALSE;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
if (StrStr (CommandLineWalker, L" >>a ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 1>a ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
2021-12-05 14:54:13 -08:00
} else {
2010-09-14 05:18:09 +00:00
StdOutFileName = CommandLineWalker += 5;
OutAppend = FALSE;
OutUnicode = FALSE;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
if (StrStr (CommandLineWalker, L" 1>a ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" >a ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 8, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
2021-12-05 14:54:13 -08:00
} else {
2010-09-14 05:18:09 +00:00
StdOutFileName = CommandLineWalker += 4;
OutAppend = FALSE;
OutUnicode = FALSE;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
if (StrStr (CommandLineWalker, L" >a ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 2>> ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
if (StdErrFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
2021-12-05 14:54:13 -08:00
} else {
2010-09-14 05:18:09 +00:00
StdErrFileName = CommandLineWalker += 5;
ErrAppend = TRUE;
2021-12-05 14:54:13 -08:00
}
2010-09-14 05:18:09 +00:00
if (StrStr (CommandLineWalker, L" 2>> ") != NULL) {
Status = EFI_NOT_FOUND;
2021-12-05 14:54:13 -08:00
}
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 2>v ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
if (StdErrVarName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdErrVarName = CommandLineWalker += 5;
ErrAppend = FALSE;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" 2>v ") != NULL) {
Status = EFI_NOT_FOUND;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 1>v ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutVarName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdOutVarName = CommandLineWalker += 5;
OutAppend = FALSE;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" 1>v ") != NULL) {
Status = EFI_NOT_FOUND;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 2>a ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 10, L' ');
2010-09-14 05:18:09 +00:00
if (StdErrFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdErrFileName = CommandLineWalker += 5;
ErrAppend = FALSE;
ErrUnicode = FALSE;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" 2>a ") != NULL) {
Status = EFI_NOT_FOUND;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 2> ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 8, L' ');
2010-09-14 05:18:09 +00:00
if (StdErrFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdErrFileName = CommandLineWalker += 4;
ErrAppend = FALSE;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" 2> ") != NULL) {
Status = EFI_NOT_FOUND;
}
2010-09-14 05:18:09 +00:00
}
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" 1> ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 8, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdOutFileName = CommandLineWalker += 4;
OutAppend = FALSE;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" 1> ") != NULL) {
Status = EFI_NOT_FOUND;
}
2010-09-14 05:18:09 +00:00
}
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" > ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 6, L' ');
2010-09-14 05:18:09 +00:00
if (StdOutFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdOutFileName = CommandLineWalker += 3;
OutAppend = FALSE;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" > ") != NULL) {
Status = EFI_NOT_FOUND;
}
2010-09-14 05:18:09 +00:00
}
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" < ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 6, L' ');
2010-09-14 05:18:09 +00:00
if (StdInFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdInFileName = CommandLineWalker += 3;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" < ") != NULL) {
Status = EFI_NOT_FOUND;
2010-09-14 05:18:09 +00:00
}
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" <a ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 8, L' ');
2010-09-14 05:18:09 +00:00
if (StdInFileName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdInFileName = CommandLineWalker += 4;
InUnicode = FALSE;
AsciiRedirection = TRUE;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" <a ") != NULL) {
Status = EFI_NOT_FOUND;
2010-09-14 05:18:09 +00:00
}
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status) && ((CommandLineWalker = StrStr (CommandLineCopy, L" <v ")) != NULL)) {
FirstLocation = MIN (CommandLineWalker, FirstLocation);
SetMem16 (CommandLineWalker, 8, L' ');
2010-09-14 05:18:09 +00:00
if (StdInVarName != NULL) {
Status = EFI_INVALID_PARAMETER;
} else {
StdInVarName = CommandLineWalker += 4;
}
2021-12-05 14:54:13 -08:00
if (StrStr (CommandLineWalker, L" <v ") != NULL) {
Status = EFI_NOT_FOUND;
2010-09-14 05:18:09 +00:00
}
}
//
// re-populate the string to support any filenames that were in quotes.
//
StrnCpyS (CommandLineCopy, StrSize (CommandLineCopy)/sizeof (CHAR16), NewCommandLine, StrLen (NewCommandLine));
2011-04-01 16:11:59 +00:00
if ( (FirstLocation != CommandLineCopy + StrLen (CommandLineCopy))
&& (((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof (CHAR16) < StrLen (NewCommandLine))
)
{
*(NewCommandLine + ((UINTN)FirstLocation - (UINTN)CommandLineCopy)/sizeof (CHAR16)) = CHAR_NULL;
}
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status)) {
if (StdErrFileName != NULL) {
if ((StdErrFileName = FixFileName (StdErrFileName)) == NULL) {
Status = EFI_INVALID_PARAMETER;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
if (StdOutFileName != NULL) {
if ((StdOutFileName = FixFileName (StdOutFileName)) == NULL) {
Status = EFI_INVALID_PARAMETER;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
if (StdInFileName != NULL) {
if ((StdInFileName = FixFileName (StdInFileName)) == NULL) {
Status = EFI_INVALID_PARAMETER;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
if (StdErrVarName != NULL) {
if ((StdErrVarName = FixVarName (StdErrVarName)) == NULL) {
Status = EFI_INVALID_PARAMETER;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
if (StdOutVarName != NULL) {
if ((StdOutVarName = FixVarName (StdOutVarName)) == NULL) {
Status = EFI_INVALID_PARAMETER;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
if (StdInVarName != NULL) {
if ((StdInVarName = FixVarName (StdInVarName)) == NULL) {
Status = EFI_INVALID_PARAMETER;
}
2010-09-14 05:18:09 +00:00
}
2011-03-30 21:05:25 +00:00
//
// 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))
2010-09-14 05:18:09 +00:00
|| ((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
//
2010-09-14 05:18:09 +00:00
|| ((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
//
2010-09-14 05:18:09 +00:00
|| ((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.
//
2010-09-14 05:18:09 +00:00
|| ((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.
//
2018-06-27 21:13:38 +08:00
|| ( (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))))
2010-09-14 05:18:09 +00:00
)
{
Status = EFI_INVALID_PARAMETER;
ShellParameters->StdIn = *OldStdIn;
ShellParameters->StdOut = *OldStdOut;
ShellParameters->StdErr = *OldStdErr;
} else if (!EFI_ERROR (Status)) {
2010-09-14 05:18:09 +00:00
//
// 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);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
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);
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!ErrUnicode && !EFI_ERROR (Status)) {
TempHandle = CreateFileInterfaceFile (TempHandle, FALSE);
2024-10-03 10:30:15 -07:00
if (TempHandle == NULL) {
ASSERT (TempHandle != NULL);
Status = EFI_OUT_OF_RESOURCES;
}
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status)) {
ShellParameters->StdErr = TempHandle;
gST->StdErr = CreateSimpleTextOutOnFile (TempHandle, &gST->StandardErrorHandle, gST->StdErr);
2010-09-14 05:18:09 +00:00
}
}
//
// StdOut to a file
//
if (!EFI_ERROR (Status) && (StdOutFileName != NULL)) {
if (!OutAppend) {
//
// delete existing file.
//
ShellInfoObject.NewEfiShellProtocol->DeleteFileByName (StdOutFileName);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
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
);
}
}
2021-12-05 14:54:13 -08:00
if (!OutUnicode && !EFI_ERROR (Status)) {
TempHandle = CreateFileInterfaceFile (TempHandle, FALSE);
2024-10-03 10:30:15 -07:00
if (TempHandle == NULL) {
ASSERT (TempHandle != NULL);
Status = EFI_OUT_OF_RESOURCES;
}
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!EFI_ERROR (Status)) {
ShellParameters->StdOut = TempHandle;
gST->ConOut = CreateSimpleTextOutOnFile (TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
2010-09-14 05:18:09 +00:00
}
}
}
//
// StdOut to a var
//
if (!EFI_ERROR (Status) && (StdOutVarName != NULL)) {
if (!OutAppend) {
//
// delete existing variable.
//
SHELL_SET_ENVIRONMENT_VARIABLE_V (StdOutVarName, 0, L"");
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
TempHandle = CreateFileInterfaceEnv (StdOutVarName);
2024-10-03 10:30:15 -07:00
if (TempHandle == NULL) {
ASSERT (TempHandle != NULL);
Status = EFI_OUT_OF_RESOURCES;
} else {
ShellParameters->StdOut = TempHandle;
gST->ConOut = CreateSimpleTextOutOnFile (TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
}
2010-09-14 05:18:09 +00:00
}
//
// StdErr to a var
//
if (!EFI_ERROR (Status) && (StdErrVarName != NULL)) {
if (!ErrAppend) {
//
// delete existing variable.
//
SHELL_SET_ENVIRONMENT_VARIABLE_V (StdErrVarName, 0, L"");
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
TempHandle = CreateFileInterfaceEnv (StdErrVarName);
2024-10-03 10:30:15 -07:00
if (TempHandle == NULL) {
ASSERT (TempHandle != NULL);
Status = EFI_OUT_OF_RESOURCES;
} else {
ShellParameters->StdErr = TempHandle;
gST->StdErr = CreateSimpleTextOutOnFile (TempHandle, &gST->StandardErrorHandle, gST->StdErr);
}
2010-09-14 05:18:09 +00:00
}
//
// StdIn from a var
//
if (!EFI_ERROR (Status) && (StdInVarName != NULL)) {
TempHandle = CreateFileInterfaceEnv (StdInVarName);
if (TempHandle == NULL) {
Status = EFI_OUT_OF_RESOURCES;
2010-09-14 05:18:09 +00:00
} else {
if (!InUnicode) {
TempHandle = CreateFileInterfaceFile (TempHandle, FALSE);
}
2021-12-05 14:54:13 -08:00
Size = 0;
2011-10-22 04:10:30 +00:00
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);
}
2010-09-14 05:18:09 +00:00
}
}
//
// StdIn from a file
//
if (!EFI_ERROR (Status) && (StdInFileName != NULL)) {
Status = ShellOpenFileByName (
StdInFileName,
&TempHandle,
EFI_FILE_MODE_READ,
0
);
if (!EFI_ERROR (Status)) {
2016-03-08 20:51:43 +08:00
if (!InUnicode) {
//
// Create the ASCII->Unicode conversion layer
//
TempHandle = CreateFileInterfaceFile (TempHandle, FALSE);
}
2021-12-05 14:54:13 -08:00
2024-10-03 10:30:15 -07:00
if (TempHandle == NULL) {
Status = EFI_OUT_OF_RESOURCES;
} else {
ShellParameters->StdIn = TempHandle;
gST->ConIn = CreateSimpleTextInOnFile (TempHandle, &gST->ConsoleInHandle);
}
2010-09-14 05:18:09 +00:00
}
}
}
}
FreePool (CommandLineCopy);
CalculateEfiHdrCrc (&gST->Hdr);
2021-12-05 14:54:13 -08:00
if ((gST->ConIn == NULL) || (gST->ConOut == NULL)) {
2013-12-13 23:53:59 +00:00
Status = EFI_OUT_OF_RESOURCES;
}
2013-12-13 23:53:59 +00:00
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);
}
2010-09-14 05:18:09 +00:00
return (Status);
}
/**
2020-02-07 02:08:20 +01:00
Function will replace the current StdIn and StdOut in the ShellParameters protocol
2010-09-14 05:18:09 +00:00
structure with StdIn and StdOut. The current values are de-allocated.
2011-09-02 08:05:34 +00:00
@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.
2010-09-14 05:18:09 +00:00
**/
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
2010-09-14 05:18:09 +00:00
)
{
SPLIT_LIST *Split;
2018-06-27 21:13:38 +08:00
if ( (ShellParameters == NULL)
|| (OldStdIn == NULL)
|| (OldStdOut == NULL)
|| (OldStdErr == NULL)
|| (SystemTableInfo == NULL))
{
return (EFI_INVALID_PARAMETER);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
if (!IsListEmpty (&ShellInfoObject.SplitList.Link)) {
Split = (SPLIT_LIST *)GetFirstNode (&ShellInfoObject.SplitList.Link);
} else {
Split = NULL;
}
2021-12-05 14:54:13 -08:00
if (ShellParameters->StdIn != *OldStdIn) {
2010-09-14 05:18:09 +00:00
if (((Split != NULL) && (Split->SplitStdIn != ShellParameters->StdIn)) || (Split == NULL)) {
gEfiShellProtocol->CloseFile (ShellParameters->StdIn);
}
2021-12-05 14:54:13 -08:00
ShellParameters->StdIn = *OldStdIn;
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
if (ShellParameters->StdOut != *OldStdOut) {
2010-09-14 05:18:09 +00:00
if (((Split != NULL) && (Split->SplitStdOut != ShellParameters->StdOut)) || (Split == NULL)) {
gEfiShellProtocol->CloseFile (ShellParameters->StdOut);
}
2021-12-05 14:54:13 -08:00
ShellParameters->StdOut = *OldStdOut;
2010-09-14 05:18:09 +00:00
}
2021-12-05 14:54:13 -08:00
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;
2021-12-05 14:54:13 -08:00
}
if (gST->StdErr != SystemTableInfo->ErrOut) {
CloseSimpleTextOutOnFile (gST->StdErr);
gST->StdErr = SystemTableInfo->ErrOut;
gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;
2021-12-05 14:54:13 -08:00
}
CalculateEfiHdrCrc (&gST->Hdr);
2010-09-14 05:18:09 +00:00
return (EFI_SUCCESS);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
/**
2020-02-07 02:08:20 +01:00
Function will replace the current Argc and Argv in the ShellParameters protocol
2010-09-14 05:18:09 +00:00
structure by parsing NewCommandLine. The current values are returned to the
user.
If OldArgv or OldArgc is NULL then that value is not returned.
2011-09-02 08:05:34 +00:00
@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.
2011-09-02 08:05:34 +00:00
@param[out] OldArgv Pointer to old list of parameters.
@param[out] OldArgc Pointer to old number of items in Argv list.
2010-09-14 05:18:09 +00:00
2020-02-07 02:08:20 +01:00
@retval EFI_SUCCESS Operation was successful, Argv and Argc are valid.
@return EFI_INVALID_PARAMETER Some parameters are invalid.
2010-09-14 05:18:09 +00:00
@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,
2010-09-14 05:18:09 +00:00
OUT CHAR16 ***OldArgv OPTIONAL,
OUT UINTN *OldArgc OPTIONAL
)
{
BOOLEAN StripParamQuotation;
2018-06-27 21:13:38 +08:00
2010-09-14 05:18:09 +00:00
ASSERT (ShellParameters != NULL);
StripParamQuotation = TRUE;
2010-09-14 05:18:09 +00:00
if (OldArgc != NULL) {
*OldArgc = ShellParameters->Argc;
}
2021-12-05 14:54:13 -08:00
if (OldArgv != NULL) {
2010-09-14 05:18:09 +00:00
*OldArgv = ShellParameters->Argv;
}
if (Type == Script_File_Name) {
StripParamQuotation = FALSE;
}
2018-06-27 21:13:38 +08:00
return ParseCommandLineToArgs (
NewCommandLine,
StripParamQuotation,
&(ShellParameters->Argv),
&(ShellParameters->Argc)
);
2010-09-14 05:18:09 +00:00
}
/**
2020-02-07 02:08:20 +01:00
Function will replace the current Argc and Argv in the ShellParameters protocol
2010-09-14 05:18:09 +00:00
structure with Argv and Argc. The current values are de-allocated and the
OldArgv must not be deallocated by the caller.
2011-09-02 08:05:34 +00:00
@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
2010-09-14 05:18:09 +00:00
**/
VOID
RestoreArgcArgv (
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
IN CHAR16 ***OldArgv,
IN UINTN *OldArgc
)
{
UINTN LoopCounter;
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
ASSERT (ShellParameters != NULL);
ASSERT (OldArgv != NULL);
ASSERT (OldArgc != NULL);
if (ShellParameters->Argv != NULL) {
for ( LoopCounter = 0
; LoopCounter < ShellParameters->Argc
; LoopCounter++
)
{
FreePool (ShellParameters->Argv[LoopCounter]);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
FreePool (ShellParameters->Argv);
}
2021-12-05 14:54:13 -08:00
2010-09-14 05:18:09 +00:00
ShellParameters->Argv = *OldArgv;
*OldArgv = NULL;
ShellParameters->Argc = *OldArgc;
*OldArgc = 0;
}