mirror of https://github.com/acidanthera/audk.git
ShellPkg: Per UEFI Shell 2.2 SPEC to make Shell supports 'NoNesting'.
This patch makes Shell support -nonesting invocation option. This option specifies that EFI_SHELL_PROTOCOL.Execute API nesting of a new Shell instance is optional and dependent on the 'nonesting' Shell environment variable. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-by: Qiu Shumin <shumin.qiu@intel.com> Reviewed-by: Jim Dailey <Jim_Dailey@Dell.com>
This commit is contained in:
parent
7537258100
commit
dcbdb8bfb0
|
@ -1,7 +1,7 @@
|
|||
/** @file
|
||||
This is THE shell (application)
|
||||
|
||||
Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>
|
||||
(C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
|
@ -33,6 +33,7 @@ SHELL_INFO ShellInfoObject = {
|
|||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
}},
|
||||
0,
|
||||
|
@ -69,6 +70,9 @@ SHELL_INFO ShellInfoObject = {
|
|||
STATIC CONST CHAR16 mScriptExtension[] = L".NSH";
|
||||
STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";
|
||||
STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";
|
||||
CONST CHAR16 mNoNestingEnvVarName[] = L"nonesting";
|
||||
CONST CHAR16 mNoNestingTrue[] = L"True";
|
||||
CONST CHAR16 mNoNestingFalse[] = L"False";
|
||||
|
||||
/**
|
||||
Cleans off leading and trailing spaces and tabs.
|
||||
|
@ -456,6 +460,29 @@ UefiMain (
|
|||
Status = ShellCommandCreateInitialMappingsAndPaths();
|
||||
}
|
||||
|
||||
//
|
||||
// Set the environment variable for nesting support
|
||||
//
|
||||
Size = 0;
|
||||
TempString = NULL;
|
||||
if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {
|
||||
//
|
||||
// No change. require nesting in Shell Protocol Execute()
|
||||
//
|
||||
StrnCatGrow(&TempString,
|
||||
&Size,
|
||||
L"False",
|
||||
0);
|
||||
} else {
|
||||
StrnCatGrow(&TempString,
|
||||
&Size,
|
||||
mNoNestingTrue,
|
||||
0);
|
||||
}
|
||||
Status = InternalEfiShellSetEnv(mNoNestingEnvVarName, TempString, TRUE);
|
||||
SHELL_FREE_NON_NULL(TempString);
|
||||
Size = 0;
|
||||
|
||||
//
|
||||
// save the device path for the loaded image and the device path for the filepath (under loaded image)
|
||||
// These are where to look for the startup.nsh file
|
||||
|
@ -891,6 +918,7 @@ ProcessCommandLine(
|
|||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = FALSE;
|
||||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = FALSE;
|
||||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = FALSE;
|
||||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = FALSE;
|
||||
ShellInfoObject.ShellInitSettings.Delay = 5;
|
||||
|
||||
//
|
||||
|
@ -950,6 +978,13 @@ ProcessCommandLine(
|
|||
) == 0) {
|
||||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = TRUE;
|
||||
}
|
||||
else if (UnicodeCollation->StriColl (
|
||||
UnicodeCollation,
|
||||
L"-nonest",
|
||||
CurrentArg
|
||||
) == 0) {
|
||||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest = TRUE;
|
||||
}
|
||||
else if (UnicodeCollation->StriColl (
|
||||
UnicodeCollation,
|
||||
L"-delay",
|
||||
|
@ -1324,7 +1359,7 @@ AddLineToCommandHistory(
|
|||
BUFFER_LIST *Walker;
|
||||
UINT16 MaxHistoryCmdCount;
|
||||
UINT16 Count;
|
||||
|
||||
|
||||
Count = 0;
|
||||
MaxHistoryCmdCount = PcdGet16(PcdShellMaxHistoryCommandCount);
|
||||
|
||||
|
@ -2452,7 +2487,7 @@ SetupAndRunCommandOrFile(
|
|||
IN CHAR16 *CmdLine,
|
||||
IN CHAR16 *FirstParameter,
|
||||
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
|
||||
OUT EFI_STATUS *CommandStatus
|
||||
OUT EFI_STATUS *CommandStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
|
|
@ -58,6 +58,10 @@
|
|||
#include "ConsoleWrappers.h"
|
||||
#include "FileHandleWrappers.h"
|
||||
|
||||
extern CONST CHAR16 mNoNestingEnvVarName[];
|
||||
extern CONST CHAR16 mNoNestingTrue[];
|
||||
extern CONST CHAR16 mNoNestingFalse[];
|
||||
|
||||
typedef struct {
|
||||
LIST_ENTRY Link; ///< Standard linked list handler.
|
||||
SHELL_FILE_HANDLE *SplitStdOut; ///< ConsoleOut for use in the split.
|
||||
|
@ -73,7 +77,8 @@ typedef struct {
|
|||
UINT32 NoMap:1; ///< Was "-nomap" found on command line.
|
||||
UINT32 NoVersion:1; ///< Was "-noversion" found on command line.
|
||||
UINT32 Delay:1; ///< Was "-delay[:n] found on command line
|
||||
UINT32 Exit:1; ///< Was "-_exit" found on command line
|
||||
UINT32 Exit:1; ///< Was "-_exit" found on command line
|
||||
UINT32 NoNest:1; ///< Was "-nonest" found on command line
|
||||
UINT32 Reserved:7; ///< Extra bits
|
||||
} SHELL_BITS;
|
||||
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
manipulation, and initialization of EFI_SHELL_PROTOCOL.
|
||||
|
||||
(C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
|
||||
Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<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
|
||||
|
@ -1588,6 +1588,109 @@ FreeAlloc:
|
|||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/**
|
||||
internal worker function to load and run an image in the current shell.
|
||||
|
||||
@param CommandLine Points to the NULL-terminated UCS-2 encoded string
|
||||
containing the command line. If NULL then the command-
|
||||
line will be empty.
|
||||
@param Environment Points to a NULL-terminated array of environment
|
||||
variables with the format 'x=y', where x is the
|
||||
environment variable name and y is the value. If this
|
||||
is NULL, then the current shell environment is used.
|
||||
|
||||
@param[out] StartImageStatus Returned status from the command line.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully. The status code
|
||||
returned by the command is pointed to by StatusCode.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES Out of resources.
|
||||
@retval EFI_UNSUPPORTED Nested shell invocations are not allowed.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InternalShellExecute(
|
||||
IN CONST CHAR16 *CommandLine OPTIONAL,
|
||||
IN CONST CHAR16 **Environment OPTIONAL,
|
||||
OUT EFI_STATUS *StartImageStatus OPTIONAL
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS CleanupStatus;
|
||||
LIST_ENTRY OrigEnvs;
|
||||
|
||||
InitializeListHead(&OrigEnvs);
|
||||
|
||||
//
|
||||
// Save our current environment settings for later restoration if necessary
|
||||
//
|
||||
if (Environment != NULL) {
|
||||
Status = GetEnvironmentVariableList(&OrigEnvs);
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = SetEnvironmentVariables(Environment);
|
||||
} else {
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
Status = RunShellCommand(CommandLine, StartImageStatus);
|
||||
|
||||
// Restore environment variables
|
||||
if (!IsListEmpty(&OrigEnvs)) {
|
||||
CleanupStatus = SetEnvironmentVariableList(&OrigEnvs);
|
||||
ASSERT_EFI_ERROR (CleanupStatus);
|
||||
}
|
||||
|
||||
return(Status);
|
||||
}
|
||||
|
||||
/**
|
||||
Determine if the UEFI Shell is currently running with nesting enabled or disabled.
|
||||
|
||||
@retval FALSE nesting is required
|
||||
@retval other nesting is enabled
|
||||
**/
|
||||
STATIC
|
||||
BOOLEAN
|
||||
EFIAPI
|
||||
NestingEnabled(
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
CHAR16 *Temp;
|
||||
CHAR16 *Temp2;
|
||||
UINTN TempSize;
|
||||
BOOLEAN RetVal;
|
||||
|
||||
RetVal = TRUE;
|
||||
Temp = NULL;
|
||||
Temp2 = NULL;
|
||||
|
||||
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {
|
||||
TempSize = 0;
|
||||
Temp = NULL;
|
||||
Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);
|
||||
if (Status == EFI_BUFFER_TOO_SMALL) {
|
||||
Temp = AllocateZeroPool(TempSize + sizeof(CHAR16));
|
||||
if (Temp != NULL) {
|
||||
Status = SHELL_GET_ENVIRONMENT_VARIABLE(mNoNestingEnvVarName, &TempSize, Temp);
|
||||
}
|
||||
}
|
||||
Temp2 = StrnCatGrow(&Temp2, NULL, mNoNestingTrue, 0);
|
||||
if (Temp != NULL && Temp2 != NULL && StringNoCaseCompare(&Temp, &Temp2) == 0) {
|
||||
//
|
||||
// Use the no nesting method.
|
||||
//
|
||||
RetVal = FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
SHELL_FREE_NON_NULL(Temp);
|
||||
SHELL_FREE_NON_NULL(Temp2);
|
||||
return (RetVal);
|
||||
}
|
||||
|
||||
/**
|
||||
Execute the command line.
|
||||
|
||||
|
@ -1611,7 +1714,7 @@ FreeAlloc:
|
|||
variables with the format 'x=y', where x is the
|
||||
environment variable name and y is the value. If this
|
||||
is NULL, then the current shell environment is used.
|
||||
@param StatusCode Points to the status code returned by the command.
|
||||
@param StatusCode Points to the status code returned by the CommandLine.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully. The status code
|
||||
returned by the command is pointed to by StatusCode.
|
||||
|
@ -1643,11 +1746,9 @@ EfiShellExecute(
|
|||
return (EFI_UNSUPPORTED);
|
||||
}
|
||||
|
||||
if (Environment != NULL) {
|
||||
// If Environment isn't null, load a new image of the shell with its own
|
||||
// environment
|
||||
if (NestingEnabled()) {
|
||||
DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
|
||||
|
||||
|
||||
DEBUG_CODE_BEGIN();
|
||||
Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);
|
||||
FreePool(Temp);
|
||||
|
@ -1676,19 +1777,10 @@ EfiShellExecute(
|
|||
FreePool(DevPath);
|
||||
FreePool(Temp);
|
||||
} else {
|
||||
// If Environment is NULL, we are free to use and mutate the current shell
|
||||
// environment. This is much faster as uses much less memory.
|
||||
|
||||
if (CommandLine == NULL) {
|
||||
CommandLine = L"";
|
||||
}
|
||||
|
||||
Status = RunShellCommand (CommandLine, &CalleeStatusCode);
|
||||
|
||||
// Pass up the command's exit code if the caller wants it
|
||||
if (StatusCode != NULL) {
|
||||
*StatusCode = (EFI_STATUS) CalleeStatusCode;
|
||||
}
|
||||
Status = InternalShellExecute(
|
||||
(CONST CHAR16*)CommandLine,
|
||||
(CONST CHAR16**)Environment,
|
||||
StatusCode);
|
||||
}
|
||||
|
||||
return(Status);
|
||||
|
@ -2814,6 +2906,11 @@ EfiShellSetEnv(
|
|||
gUnicodeCollation,
|
||||
(CHAR16*)Name,
|
||||
L"uefiversion") == 0
|
||||
||(!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest &&
|
||||
gUnicodeCollation->StriColl(
|
||||
gUnicodeCollation,
|
||||
(CHAR16*)Name,
|
||||
(CHAR16*)mNoNestingEnvVarName) == 0)
|
||||
){
|
||||
return (EFI_INVALID_PARAMETER);
|
||||
}
|
||||
|
@ -2827,7 +2924,7 @@ EfiShellSetEnv(
|
|||
FileSystemMapping is not NULL, it returns the current directory associated with the
|
||||
FileSystemMapping. In both cases, the returned name includes the file system
|
||||
mapping (i.e. fs0:\current-dir).
|
||||
|
||||
|
||||
Note that the current directory string should exclude the tailing backslash character.
|
||||
|
||||
@param FileSystemMapping A pointer to the file system mapping. If NULL,
|
||||
|
@ -2981,7 +3078,7 @@ EfiShellSetCurDir(
|
|||
ASSERT((MapListItem->CurrentDirectoryPath == NULL && Size == 0) || (MapListItem->CurrentDirectoryPath != NULL));
|
||||
if (MapListItem->CurrentDirectoryPath != NULL) {
|
||||
MapListItem->CurrentDirectoryPath[StrLen(MapListItem->CurrentDirectoryPath)-1] = CHAR_NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
//
|
||||
|
|
Loading…
Reference in New Issue