summaryrefslogtreecommitdiff
path: root/Core/ShellPkg/Application/Shell/ShellParametersProtocol.c
diff options
context:
space:
mode:
Diffstat (limited to 'Core/ShellPkg/Application/Shell/ShellParametersProtocol.c')
-rw-r--r--Core/ShellPkg/Application/Shell/ShellParametersProtocol.c1298
1 files changed, 1298 insertions, 0 deletions
diff --git a/Core/ShellPkg/Application/Shell/ShellParametersProtocol.c b/Core/ShellPkg/Application/Shell/ShellParametersProtocol.c
new file mode 100644
index 0000000000..0785902b16
--- /dev/null
+++ b/Core/ShellPkg/Application/Shell/ShellParametersProtocol.c
@@ -0,0 +1,1298 @@
+/** @file
+ Member functions of EFI_SHELL_PARAMETERS_PROTOCOL and functions for creation,
+ manipulation, and initialization of EFI_SHELL_PARAMETERS_PROTOCOL.
+
+ Copyright (C) 2014, Red Hat, Inc.
+ (C) Copyright 2013 Hewlett-Packard Development Company, L.P.<BR>
+ Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
+ This program and the accompanying materials
+ are licensed and made available under the terms and conditions of the BSD License
+ which accompanies this distribution. The full text of the license may be found at
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#include "Shell.h"
+
+BOOLEAN AsciiRedirection = FALSE;
+
+/**
+ 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 sucessful
+ @return EFI_OUT_OF_RESOURCES a memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+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 (ShellGetNextParameter (&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 (ShellGetNextParameter (&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
+EFIAPI
+CreatePopulateInstallShellParametersProtocol (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL **NewShellParameters,
+ IN OUT BOOLEAN *RootShellInstance
+ )
+{
+ EFI_STATUS Status;
+ EFI_LOADED_IMAGE_PROTOCOL *LoadedImage;
+ CHAR16 *FullCommandLine;
+ UINTN Size;
+
+ Size = 0;
+ FullCommandLine = NULL;
+ LoadedImage = NULL;
+
+ //
+ // Assert for valid parameters
+ //
+ ASSERT(NewShellParameters != NULL);
+ ASSERT(RootShellInstance != NULL);
+
+ //
+ // See if we have a shell parameters placed on us
+ //
+ Status = gBS->OpenProtocol (
+ gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID **) &ShellInfoObject.OldShellParameters,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ //
+ // if we don't then we must be the root shell (error is expected)
+ //
+ if (EFI_ERROR (Status)) {
+ *RootShellInstance = TRUE;
+ }
+
+ //
+ // Allocate the new structure
+ //
+ *NewShellParameters = AllocateZeroPool(sizeof(EFI_SHELL_PARAMETERS_PROTOCOL));
+ if ((*NewShellParameters) == NULL) {
+ return (EFI_OUT_OF_RESOURCES);
+ }
+
+ //
+ // get loaded image protocol
+ //
+ Status = gBS->OpenProtocol (
+ gImageHandle,
+ &gEfiLoadedImageProtocolGuid,
+ (VOID **) &LoadedImage,
+ gImageHandle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL
+ );
+ ASSERT_EFI_ERROR(Status);
+ //
+ // Build the full command line
+ //
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);
+ if (Status == EFI_BUFFER_TOO_SMALL) {
+ FullCommandLine = AllocateZeroPool(Size + LoadedImage->LoadOptionsSize);
+ Status = SHELL_GET_ENVIRONMENT_VARIABLE(L"ShellOpt", &Size, FullCommandLine);
+ }
+ if (Status == EFI_NOT_FOUND) {
+ //
+ // no parameters via environment... ok
+ //
+ } else {
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ }
+ if (Size == 0 && LoadedImage->LoadOptionsSize != 0) {
+ ASSERT(FullCommandLine == NULL);
+ //
+ // Now we need to include a NULL terminator in the size.
+ //
+ Size = LoadedImage->LoadOptionsSize + sizeof(FullCommandLine[0]);
+ FullCommandLine = AllocateZeroPool(Size);
+ }
+ if (FullCommandLine != NULL) {
+ CopyMem (FullCommandLine, LoadedImage->LoadOptions, LoadedImage->LoadOptionsSize);
+ //
+ // Populate Argc and Argv
+ //
+ Status = ParseCommandLineToArgs(FullCommandLine,
+ 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 createion and installation of shell parameters protocol
+ and if there was an old version installed it will restore that one.
+
+ @param NewShellParameters the interface of EFI_SHELL_PARAMETERS_PROTOCOL that is
+ being cleaned up.
+
+ @retval EFI_SUCCESS the cleanup was successful
+ @return other the cleanup failed
+ @sa ReinstallProtocolInterface
+ @sa UninstallProtocolInterface
+**/
+EFI_STATUS
+EFIAPI
+CleanUpShellParametersProtocol (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *NewShellParameters
+ )
+{
+ EFI_STATUS Status;
+ UINTN LoopCounter;
+
+ //
+ // If the old exists we need to restore it
+ //
+ if (ShellInfoObject.OldShellParameters != NULL) {
+ Status = gBS->ReinstallProtocolInterface(gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID*)NewShellParameters,
+ (VOID*)ShellInfoObject.OldShellParameters);
+ DEBUG_CODE(ShellInfoObject.OldShellParameters = NULL;);
+ } else {
+ //
+ // No old one, just uninstall us...
+ //
+ Status = gBS->UninstallProtocolInterface(gImageHandle,
+ &gEfiShellParametersProtocolGuid,
+ (VOID*)NewShellParameters);
+ }
+ if (NewShellParameters->Argv != NULL) {
+ for ( LoopCounter = 0
+ ; LoopCounter < NewShellParameters->Argc
+ ; LoopCounter++
+ ){
+ FreePool(NewShellParameters->Argv[LoopCounter]);
+ }
+ FreePool(NewShellParameters->Argv);
+ }
+ FreePool(NewShellParameters);
+ return (Status);
+}
+
+/**
+ Determin if a file name represents a unicode file.
+
+ @param[in] FileName Pointer to the filename to open.
+
+ @retval EFI_SUCCESS The file is a unicode file.
+ @return An error upon failure.
+**/
+EFI_STATUS
+EFIAPI
+IsUnicodeFile(
+ IN CONST CHAR16 *FileName
+ )
+{
+ SHELL_FILE_HANDLE Handle;
+ EFI_STATUS Status;
+ UINT64 OriginalFilePosition;
+ UINTN CharSize;
+ CHAR16 CharBuffer;
+
+ Status = gEfiShellProtocol->OpenFileByName(FileName, &Handle, EFI_FILE_MODE_READ);
+ if (EFI_ERROR(Status)) {
+ return (Status);
+ }
+ gEfiShellProtocol->GetFilePosition(Handle, &OriginalFilePosition);
+ gEfiShellProtocol->SetFilePosition(Handle, 0);
+ CharSize = sizeof(CHAR16);
+ Status = gEfiShellProtocol->ReadFile(Handle, &CharSize, &CharBuffer);
+ if (EFI_ERROR(Status) || CharBuffer != gUnicodeFileTag) {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+ gEfiShellProtocol->SetFilePosition(Handle, OriginalFilePosition);
+ gEfiShellProtocol->CloseFile(Handle);
+ return (Status);
+}
+
+/**
+ Strips out quotes sections of a string.
+
+ All of the characters between quotes is replaced with spaces.
+
+ @param[in, out] TheString A pointer to the string to update.
+**/
+VOID
+EFIAPI
+StripQuotes (
+ IN OUT CHAR16 *TheString
+ )
+{
+ BOOLEAN RemoveNow;
+
+ for (RemoveNow = FALSE ; TheString != NULL && *TheString != CHAR_NULL ; TheString++) {
+ if (*TheString == L'^' && *(TheString + 1) == L'\"') {
+ TheString++;
+ } else if (*TheString == L'\"') {
+ RemoveNow = (BOOLEAN)!RemoveNow;
+ } else if (RemoveNow) {
+ *TheString = L' ';
+ }
+ }
+}
+
+/**
+ Calcualte the 32-bit CRC in a EFI table using the service provided by the
+ gRuntime service.
+
+ @param Hdr Pointer to an EFI standard header
+
+**/
+VOID
+CalculateEfiHdrCrc (
+ IN OUT EFI_TABLE_HEADER *Hdr
+ )
+{
+ UINT32 Crc;
+
+ Hdr->CRC32 = 0;
+
+ //
+ // If gBS->CalculateCrce32 () == CoreEfiNotAvailableYet () then
+ // Crc will come back as zero if we set it to zero here
+ //
+ Crc = 0;
+ gBS->CalculateCrc32 ((UINT8 *)Hdr, Hdr->HeaderSize, &Crc);
+ Hdr->CRC32 = Crc;
+}
+
+/**
+ Fix a string to only have the file name, removing starting at the first space of whatever is quoted.
+
+ @param[in] FileName The filename to start with.
+
+ @retval NULL FileName was invalid.
+ @return The modified FileName.
+**/
+CHAR16*
+EFIAPI
+FixFileName (
+ IN CHAR16 *FileName
+ )
+{
+ CHAR16 *Copy;
+ CHAR16 *TempLocation;
+
+ if (FileName == NULL) {
+ return (NULL);
+ }
+
+ if (FileName[0] == L'\"') {
+ Copy = FileName+1;
+ if ((TempLocation = StrStr(Copy , L"\"")) != NULL) {
+ TempLocation[0] = CHAR_NULL;
+ }
+ } else {
+ Copy = FileName;
+ while(Copy[0] == L' ') {
+ Copy++;
+ }
+ if ((TempLocation = StrStr(Copy , L" ")) != NULL) {
+ TempLocation[0] = CHAR_NULL;
+ }
+ }
+
+ if (Copy[0] == CHAR_NULL) {
+ return (NULL);
+ }
+
+ return (Copy);
+}
+
+/**
+ Fix a string to only have the environment variable name, removing starting at the first space of whatever is quoted and removing the leading and trailing %.
+
+ @param[in] FileName The filename to start with.
+
+ @retval NULL FileName was invalid.
+ @return The modified FileName.
+**/
+CHAR16*
+EFIAPI
+FixVarName (
+ IN CHAR16 *FileName
+ )
+{
+ CHAR16 *Copy;
+ CHAR16 *TempLocation;
+
+ Copy = FileName;
+
+ if (FileName[0] == L'%') {
+ Copy = FileName+1;
+ if ((TempLocation = StrStr(Copy , L"%")) != NULL) {
+ TempLocation[0] = CHAR_NULL;
+ }
+ }
+
+ return (FixFileName(Copy));
+}
+
+/**
+ Remove the unicode file tag from the begining of the file buffer since that will not be
+ used by StdIn.
+
+ @param[in] Handle Pointer to the handle of the file to be processed.
+
+ @retval EFI_SUCCESS The unicode file tag has been moved successfully.
+**/
+EFI_STATUS
+EFIAPI
+RemoveFileTag(
+ IN SHELL_FILE_HANDLE *Handle
+ )
+{
+ UINTN CharSize;
+ CHAR16 CharBuffer;
+
+ CharSize = sizeof(CHAR16);
+ CharBuffer = 0;
+ gEfiShellProtocol->ReadFile(*Handle, &CharSize, &CharBuffer);
+ if (CharBuffer != gUnicodeFileTag) {
+ gEfiShellProtocol->SetFilePosition(*Handle, 0);
+ }
+ return (EFI_SUCCESS);
+}
+
+/**
+ Write the unicode file tag to the specified file.
+
+ It is the caller's responsibility to ensure that
+ ShellInfoObject.NewEfiShellProtocol has been initialized before calling this
+ function.
+
+ @param[in] FileHandle The file to write the unicode file tag to.
+
+ @return Status code from ShellInfoObject.NewEfiShellProtocol->WriteFile.
+**/
+EFI_STATUS
+WriteFileTag (
+ IN SHELL_FILE_HANDLE FileHandle
+ )
+{
+ CHAR16 FileTag;
+ UINTN Size;
+ EFI_STATUS Status;
+
+ FileTag = gUnicodeFileTag;
+ Size = sizeof FileTag;
+ Status = ShellInfoObject.NewEfiShellProtocol->WriteFile (FileHandle, &Size,
+ &FileTag);
+ ASSERT (EFI_ERROR (Status) || Size == sizeof FileTag);
+ return Status;
+}
+
+
+/**
+ Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
+ structure by parsing NewCommandLine. The current values are returned to the
+ user.
+
+ This will also update the system table.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] NewCommandLine The new command line to parse and use.
+ @param[out] OldStdIn Pointer to old StdIn.
+ @param[out] OldStdOut Pointer to old StdOut.
+ @param[out] OldStdErr Pointer to old StdErr.
+ @param[out] SystemTableInfo Pointer to old system table information.
+
+ @retval EFI_SUCCESS Operation was sucessful, Argv and Argc are valid.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateStdInStdOutStdErr(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CHAR16 *NewCommandLine,
+ OUT SHELL_FILE_HANDLE *OldStdIn,
+ OUT SHELL_FILE_HANDLE *OldStdOut,
+ OUT SHELL_FILE_HANDLE *OldStdErr,
+ OUT SYSTEM_TABLE_INFO *SystemTableInfo
+ )
+{
+ CHAR16 *CommandLineCopy;
+ CHAR16 *CommandLineWalker;
+ CHAR16 *StdErrFileName;
+ CHAR16 *StdOutFileName;
+ CHAR16 *StdInFileName;
+ CHAR16 *StdInVarName;
+ CHAR16 *StdOutVarName;
+ CHAR16 *StdErrVarName;
+ EFI_STATUS Status;
+ SHELL_FILE_HANDLE TempHandle;
+ UINT64 FileSize;
+ BOOLEAN OutUnicode;
+ BOOLEAN InUnicode;
+ BOOLEAN ErrUnicode;
+ BOOLEAN OutAppend;
+ BOOLEAN ErrAppend;
+ UINTN Size;
+ SPLIT_LIST *Split;
+ CHAR16 *FirstLocation;
+ 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 - CommandLineCopy) < StrLen(NewCommandLine))
+ ){
+ *(NewCommandLine + (UINTN)(FirstLocation - CommandLineCopy)) = CHAR_NULL;
+ }
+
+ if (!EFI_ERROR(Status)) {
+
+ if (StdErrFileName != NULL) {
+ if ((StdErrFileName = FixFileName(StdErrFileName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdOutFileName != NULL) {
+ if ((StdOutFileName = FixFileName(StdOutFileName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdInFileName != NULL) {
+ if ((StdInFileName = FixFileName(StdInFileName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdErrVarName != NULL) {
+ if ((StdErrVarName = FixVarName(StdErrVarName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdOutVarName != NULL) {
+ if ((StdOutVarName = FixVarName(StdOutVarName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+ if (StdInVarName != NULL) {
+ if ((StdInVarName = FixVarName(StdInVarName)) == NULL) {
+ Status = EFI_INVALID_PARAMETER;
+ }
+ }
+
+ //
+ // Verify not the same and not duplicating something from a split
+ //
+ if (
+ //
+ // Check that no 2 filenames are the same
+ //
+ (StdErrFileName != NULL && StdOutFileName!= NULL && StringNoCaseCompare(&StdErrFileName, &StdOutFileName) == 0)
+ ||(StdErrFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdErrFileName, &StdInFileName ) == 0)
+ ||(StdOutFileName != NULL && StdInFileName != NULL && StringNoCaseCompare(&StdOutFileName, &StdInFileName ) == 0)
+ //
+ // Check that no 2 variable names are the same
+ //
+ ||(StdErrVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdInVarName ) == 0)
+ ||(StdOutVarName != NULL && StdInVarName != NULL && StringNoCaseCompare(&StdOutVarName , &StdInVarName ) == 0)
+ ||(StdErrVarName != NULL && StdOutVarName != NULL && StringNoCaseCompare(&StdErrVarName , &StdOutVarName ) == 0)
+ //
+ // When a split (using | operator) is in place some are not allowed
+ //
+ ||(Split != NULL && Split->SplitStdIn != NULL && (StdInVarName != NULL || StdInFileName != NULL))
+ ||(Split != NULL && Split->SplitStdOut != NULL && (StdOutVarName != NULL || StdOutFileName != NULL))
+ //
+ // Check that nothing is trying to be output to 2 locations.
+ //
+ ||(StdErrFileName != NULL && StdErrVarName != NULL)
+ ||(StdOutFileName != NULL && StdOutVarName != NULL)
+ ||(StdInFileName != NULL && StdInVarName != NULL)
+ //
+ // Check for no volatile environment variables
+ //
+ ||(StdErrVarName != NULL && !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 (StrStr(StdOutFileName, L"NUL")==StdOutFileName) {
+ //no-op
+ } else if (!OutAppend && OutUnicode && !EFI_ERROR(Status)) {
+ Status = WriteFileTag (TempHandle);
+ } else if (OutAppend) {
+ Status = ShellInfoObject.NewEfiShellProtocol->GetFileSize(TempHandle, &FileSize);
+ if (!EFI_ERROR(Status)) {
+ //
+ // When appending to a new unicode file, write the file tag.
+ // Otherwise (ie. when appending to a new ASCII file, or an
+ // existent file with any encoding), just seek to the end.
+ //
+ Status = (FileSize == 0 && OutUnicode) ?
+ WriteFileTag (TempHandle) :
+ ShellInfoObject.NewEfiShellProtocol->SetFilePosition (
+ TempHandle,
+ FileSize);
+ }
+ }
+ if (!OutUnicode && !EFI_ERROR(Status)) {
+ TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
+ ASSERT(TempHandle != NULL);
+ }
+ if (!EFI_ERROR(Status)) {
+ ShellParameters->StdOut = TempHandle;
+ gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
+ }
+ }
+ }
+
+ //
+ // StdOut to a var
+ //
+ if (!EFI_ERROR(Status) && StdOutVarName != NULL) {
+ if (!OutAppend) {
+ //
+ // delete existing variable.
+ //
+ SHELL_SET_ENVIRONMENT_VARIABLE_V(StdOutVarName, 0, L"");
+ }
+ TempHandle = CreateFileInterfaceEnv(StdOutVarName);
+ ASSERT(TempHandle != NULL);
+ ShellParameters->StdOut = TempHandle;
+ gST->ConOut = CreateSimpleTextOutOnFile(TempHandle, &gST->ConsoleOutHandle, gST->ConOut);
+ }
+
+ //
+ // StdErr to a var
+ //
+ if (!EFI_ERROR(Status) && StdErrVarName != NULL) {
+ if (!ErrAppend) {
+ //
+ // delete existing variable.
+ //
+ SHELL_SET_ENVIRONMENT_VARIABLE_V(StdErrVarName, 0, L"");
+ }
+ TempHandle = CreateFileInterfaceEnv(StdErrVarName);
+ ASSERT(TempHandle != NULL);
+ ShellParameters->StdErr = TempHandle;
+ gST->StdErr = CreateSimpleTextOutOnFile(TempHandle, &gST->StandardErrorHandle, gST->StdErr);
+ }
+
+ //
+ // StdIn from a var
+ //
+ if (!EFI_ERROR(Status) && StdInVarName != NULL) {
+ TempHandle = CreateFileInterfaceEnv(StdInVarName);
+ if (TempHandle == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ } else {
+ if (!InUnicode) {
+ TempHandle = CreateFileInterfaceFile(TempHandle, FALSE);
+ }
+ Size = 0;
+ if (TempHandle == NULL || ((EFI_FILE_PROTOCOL*)TempHandle)->Read(TempHandle, &Size, NULL) != EFI_BUFFER_TOO_SMALL) {
+ Status = EFI_INVALID_PARAMETER;
+ } else {
+ ShellParameters->StdIn = TempHandle;
+ gST->ConIn = CreateSimpleTextInOnFile(TempHandle, &gST->ConsoleInHandle);
+ }
+ }
+ }
+
+ //
+ // StdIn from a file
+ //
+ if (!EFI_ERROR(Status) && StdInFileName != NULL) {
+ Status = ShellOpenFileByName(
+ StdInFileName,
+ &TempHandle,
+ EFI_FILE_MODE_READ,
+ 0);
+ if (!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);
+}
+
+/**
+ Funcion will replace the current StdIn and StdOut in the ShellParameters protocol
+ structure with StdIn and StdOut. The current values are de-allocated.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] OldStdIn Pointer to old StdIn.
+ @param[in] OldStdOut Pointer to old StdOut.
+ @param[in] OldStdErr Pointer to old StdErr.
+ @param[in] SystemTableInfo Pointer to old system table information.
+**/
+EFI_STATUS
+EFIAPI
+RestoreStdInStdOutStdErr (
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN SHELL_FILE_HANDLE *OldStdIn,
+ IN SHELL_FILE_HANDLE *OldStdOut,
+ IN SHELL_FILE_HANDLE *OldStdErr,
+ IN SYSTEM_TABLE_INFO *SystemTableInfo
+ )
+{
+ SPLIT_LIST *Split;
+
+ if (ShellParameters == NULL
+ ||OldStdIn == NULL
+ ||OldStdOut == NULL
+ ||OldStdErr == NULL
+ ||SystemTableInfo == NULL) {
+ return (EFI_INVALID_PARAMETER);
+ }
+ if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {
+ Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);
+ } else {
+ Split = NULL;
+ }
+ if (ShellParameters->StdIn != *OldStdIn) {
+ if ((Split != NULL && Split->SplitStdIn != ShellParameters->StdIn) || Split == NULL) {
+ gEfiShellProtocol->CloseFile(ShellParameters->StdIn);
+ }
+ ShellParameters->StdIn = *OldStdIn;
+ }
+ if (ShellParameters->StdOut != *OldStdOut) {
+ if ((Split != NULL && Split->SplitStdOut != ShellParameters->StdOut) || Split == NULL) {
+ gEfiShellProtocol->CloseFile(ShellParameters->StdOut);
+ }
+ ShellParameters->StdOut = *OldStdOut;
+ }
+ if (ShellParameters->StdErr != *OldStdErr) {
+ gEfiShellProtocol->CloseFile(ShellParameters->StdErr);
+ ShellParameters->StdErr = *OldStdErr;
+ }
+
+ if (gST->ConIn != SystemTableInfo->ConIn) {
+ CloseSimpleTextInOnFile(gST->ConIn);
+ gST->ConIn = SystemTableInfo->ConIn;
+ gST->ConsoleInHandle = SystemTableInfo->ConInHandle;
+ }
+ if (gST->ConOut != SystemTableInfo->ConOut) {
+ CloseSimpleTextOutOnFile(gST->ConOut);
+ gST->ConOut = SystemTableInfo->ConOut;
+ gST->ConsoleOutHandle = SystemTableInfo->ConOutHandle;
+ }
+ if (gST->StdErr != SystemTableInfo->ErrOut) {
+ CloseSimpleTextOutOnFile(gST->StdErr);
+ gST->StdErr = SystemTableInfo->ErrOut;
+ gST->StandardErrorHandle = SystemTableInfo->ErrOutHandle;
+ }
+
+ CalculateEfiHdrCrc(&gST->Hdr);
+
+ return (EFI_SUCCESS);
+}
+/**
+ Funcion will replace the current Argc and Argv in the ShellParameters protocol
+ structure by parsing NewCommandLine. The current values are returned to the
+ user.
+
+ If OldArgv or OldArgc is NULL then that value is not returned.
+
+ @param[in, out] ShellParameters Pointer to parameter structure to modify.
+ @param[in] NewCommandLine The new command line to parse and use.
+ @param[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 sucessful, Argv and Argc are valid.
+ @retval EFI_OUT_OF_RESOURCES A memory allocation failed.
+**/
+EFI_STATUS
+EFIAPI
+UpdateArgcArgv(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CONST CHAR16 *NewCommandLine,
+ 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)
+ );
+}
+
+/**
+ Funcion will replace the current Argc and Argv in the ShellParameters protocol
+ structure with Argv and Argc. The current values are de-allocated and the
+ OldArgv must not be deallocated by the caller.
+
+ @param[in, out] ShellParameters pointer to parameter structure to modify
+ @param[in] OldArgv pointer to old list of parameters
+ @param[in] OldArgc pointer to old number of items in Argv list
+**/
+VOID
+EFIAPI
+RestoreArgcArgv(
+ IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
+ IN CHAR16 ***OldArgv,
+ IN UINTN *OldArgc
+ )
+{
+ UINTN LoopCounter;
+ ASSERT(ShellParameters != NULL);
+ ASSERT(OldArgv != NULL);
+ ASSERT(OldArgc != NULL);
+
+ if (ShellParameters->Argv != NULL) {
+ for ( LoopCounter = 0
+ ; LoopCounter < ShellParameters->Argc
+ ; LoopCounter++
+ ){
+ FreePool(ShellParameters->Argv[LoopCounter]);
+ }
+ FreePool(ShellParameters->Argv);
+ }
+ ShellParameters->Argv = *OldArgv;
+ *OldArgv = NULL;
+ ShellParameters->Argc = *OldArgc;
+ *OldArgc = 0;
+}