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:
@ -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 {
|
||||
//
|
||||
|
Reference in New Issue
Block a user