diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /ShellPkg/Application/Shell/ShellParametersProtocol.c | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'ShellPkg/Application/Shell/ShellParametersProtocol.c')
| -rw-r--r-- | ShellPkg/Application/Shell/ShellParametersProtocol.c | 3008 |
1 files changed, 1504 insertions, 1504 deletions
diff --git a/ShellPkg/Application/Shell/ShellParametersProtocol.c b/ShellPkg/Application/Shell/ShellParametersProtocol.c index 64d67d9f13..7cd2f9088b 100644 --- a/ShellPkg/Application/Shell/ShellParametersProtocol.c +++ b/ShellPkg/Application/Shell/ShellParametersProtocol.c @@ -1,1504 +1,1504 @@ -/** @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;
-}
+/** @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; +} |
