mirror of https://github.com/acidanthera/audk.git
ShellPkg: Fix 'EfiShellExecute' doesn't get command status correctly.
1. Add a new function 'RunShellCommand' to return command status, thus 'EfiShellExecute' can get the command return status of 'CommandLine'. 2. Refine the code logic of 'EfiShellExecute' to make the new image of shell be loaded only if 'Environment' isn't NULL. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Qiu Shumin <shumin.qiu@intel.com> Signed-off-by: Jin Eric <eric.jin@intel.com> Signed-off-by: Jaben Carsey <jaben.carsey@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18664 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
c2305a4af8
commit
490ce43d92
|
@ -1053,6 +1053,7 @@ DoStartupScript(
|
|||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_STATUS CalleeStatus;
|
||||
UINTN Delay;
|
||||
EFI_INPUT_KEY Key;
|
||||
SHELL_FILE_HANDLE FileHandle;
|
||||
|
@ -1084,7 +1085,10 @@ DoStartupScript(
|
|||
StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
|
||||
StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);
|
||||
}
|
||||
Status = RunCommand(FileStringPath);
|
||||
Status = RunShellCommand(FileStringPath, &CalleeStatus);
|
||||
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) {
|
||||
ShellCommandRegisterExit(gEfiShellProtocol->BatchIsActive(), (CONST UINT64)CalleeStatus);
|
||||
}
|
||||
FreePool(FileStringPath);
|
||||
return (Status);
|
||||
|
||||
|
@ -2133,6 +2137,7 @@ ProcessCommandLineToFinal(
|
|||
@param[in] CmdLine the command line to run.
|
||||
@param[in] FirstParameter the first parameter on the command line
|
||||
@param[in] ParamProtocol the shell parameters protocol pointer
|
||||
@param[out] CommandStatus the status from the command line.
|
||||
|
||||
@retval EFI_SUCCESS The command was completed.
|
||||
@retval EFI_ABORTED The command's operation was aborted.
|
||||
|
@ -2142,7 +2147,8 @@ EFIAPI
|
|||
RunInternalCommand(
|
||||
IN CONST CHAR16 *CmdLine,
|
||||
IN CHAR16 *FirstParameter,
|
||||
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
|
||||
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
|
||||
OUT EFI_STATUS *CommandStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -2175,6 +2181,14 @@ RunInternalCommand(
|
|||
Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError);
|
||||
|
||||
if (!EFI_ERROR(Status)) {
|
||||
if (CommandStatus != NULL) {
|
||||
if (CommandReturnedStatus != SHELL_SUCCESS) {
|
||||
*CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT);
|
||||
} else {
|
||||
*CommandStatus = EFI_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Update last error status.
|
||||
// some commands do not update last error.
|
||||
|
@ -2236,6 +2250,7 @@ RunInternalCommand(
|
|||
@param[in] CmdLine the command line to run.
|
||||
@param[in] FirstParameter the first parameter on the command line
|
||||
@param[in] ParamProtocol the shell parameters protocol pointer
|
||||
@param[out] CommandStatus the status from the command line.
|
||||
|
||||
@retval EFI_SUCCESS The command was completed.
|
||||
@retval EFI_ABORTED The command's operation was aborted.
|
||||
|
@ -2246,7 +2261,8 @@ RunCommandOrFile(
|
|||
IN SHELL_OPERATION_TYPES Type,
|
||||
IN CONST CHAR16 *CmdLine,
|
||||
IN CHAR16 *FirstParameter,
|
||||
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
|
||||
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
|
||||
OUT EFI_STATUS *CommandStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -2262,7 +2278,7 @@ RunCommandOrFile(
|
|||
|
||||
switch (Type) {
|
||||
case Internal_Command:
|
||||
Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol);
|
||||
Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol, CommandStatus);
|
||||
break;
|
||||
case Script_File_Name:
|
||||
case Efi_Application:
|
||||
|
@ -2328,6 +2344,10 @@ RunCommandOrFile(
|
|||
CalleeExitStatus = (SHELL_STATUS) StartStatus;
|
||||
}
|
||||
|
||||
if (CommandStatus != NULL) {
|
||||
*CommandStatus = CalleeExitStatus;
|
||||
}
|
||||
|
||||
//
|
||||
// Update last error status.
|
||||
//
|
||||
|
@ -2360,6 +2380,7 @@ RunCommandOrFile(
|
|||
@param[in] CmdLine the command line to run.
|
||||
@param[in] FirstParameter the first parameter on the command line.
|
||||
@param[in] ParamProtocol the shell parameters protocol pointer
|
||||
@param[out] CommandStatus the status from the command line.
|
||||
|
||||
@retval EFI_SUCCESS The command was completed.
|
||||
@retval EFI_ABORTED The command's operation was aborted.
|
||||
|
@ -2367,10 +2388,11 @@ RunCommandOrFile(
|
|||
EFI_STATUS
|
||||
EFIAPI
|
||||
SetupAndRunCommandOrFile(
|
||||
IN SHELL_OPERATION_TYPES Type,
|
||||
IN CHAR16 *CmdLine,
|
||||
IN CHAR16 *FirstParameter,
|
||||
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol
|
||||
IN SHELL_OPERATION_TYPES Type,
|
||||
IN CHAR16 *CmdLine,
|
||||
IN CHAR16 *FirstParameter,
|
||||
IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,
|
||||
OUT EFI_STATUS *CommandStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -2390,7 +2412,7 @@ SetupAndRunCommandOrFile(
|
|||
//
|
||||
if (!EFI_ERROR(Status)) {
|
||||
TrimSpaces(&CmdLine);
|
||||
Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol);
|
||||
Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -2415,14 +2437,16 @@ SetupAndRunCommandOrFile(
|
|||
command or dispatch an external application.
|
||||
|
||||
@param[in] CmdLine The command line to parse.
|
||||
@param[out] CommandStatus The status from the command line.
|
||||
|
||||
@retval EFI_SUCCESS The command was completed.
|
||||
@retval EFI_ABORTED The command's operation was aborted.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RunCommand(
|
||||
IN CONST CHAR16 *CmdLine
|
||||
RunShellCommand(
|
||||
IN CONST CHAR16 *CmdLine,
|
||||
OUT EFI_STATUS *CommandStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
@ -2507,7 +2531,7 @@ RunCommand(
|
|||
case Internal_Command:
|
||||
case Script_File_Name:
|
||||
case Efi_Application:
|
||||
Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol);
|
||||
Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus);
|
||||
break;
|
||||
default:
|
||||
//
|
||||
|
@ -2528,6 +2552,27 @@ RunCommand(
|
|||
return (Status);
|
||||
}
|
||||
|
||||
/**
|
||||
Function will process and run a command line.
|
||||
|
||||
This will determine if the command line represents an internal shell
|
||||
command or dispatch an external application.
|
||||
|
||||
@param[in] CmdLine The command line to parse.
|
||||
|
||||
@retval EFI_SUCCESS The command was completed.
|
||||
@retval EFI_ABORTED The command's operation was aborted.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RunCommand(
|
||||
IN CONST CHAR16 *CmdLine
|
||||
)
|
||||
{
|
||||
return (RunShellCommand(CmdLine, NULL));
|
||||
}
|
||||
|
||||
|
||||
STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};
|
||||
/**
|
||||
Function determines if the CommandName COULD be a valid command. It does not determine whether
|
||||
|
|
|
@ -293,6 +293,25 @@ RunCommand(
|
|||
IN CONST CHAR16 *CmdLine
|
||||
);
|
||||
|
||||
/**
|
||||
Function will process and run a command line.
|
||||
|
||||
This will determine if the command line represents an internal shell
|
||||
command or dispatch an external application.
|
||||
|
||||
@param[in] CmdLine The command line to parse.
|
||||
@param[out] CommandStatus The status from the command line.
|
||||
|
||||
@retval EFI_SUCCESS The command was completed.
|
||||
@retval EFI_ABORTED The command's operation was aborted.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
RunShellCommand(
|
||||
IN CONST CHAR16 *CmdLine,
|
||||
OUT EFI_STATUS *CommandStatus
|
||||
);
|
||||
|
||||
/**
|
||||
Function determines if the CommandName COULD be a valid command. It does not determine whether
|
||||
this is a valid command. It only checks for invalid characters.
|
||||
|
|
|
@ -339,9 +339,10 @@ SetEnvironmentVariables(
|
|||
//
|
||||
// Copy the string into the Key, leaving the last character allocated as NULL to terminate
|
||||
//
|
||||
StrCpyS( Node->Key,
|
||||
StrnCpyS( Node->Key,
|
||||
StrStr(CurrentString, L"=") - CurrentString + 1,
|
||||
CurrentString
|
||||
CurrentString,
|
||||
StrStr(CurrentString, L"=") - CurrentString
|
||||
);
|
||||
|
||||
//
|
||||
|
|
|
@ -1631,40 +1631,60 @@ EfiShellExecute(
|
|||
CHAR16 *Temp;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevPath;
|
||||
UINTN Size;
|
||||
|
||||
EFI_STATUS CalleeStatusCode;
|
||||
|
||||
if ((PcdGet8(PcdShellSupportLevel) < 1)) {
|
||||
return (EFI_UNSUPPORTED);
|
||||
}
|
||||
|
||||
DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
|
||||
if (Environment != NULL) {
|
||||
// If Environment isn't null, load a new image of the shell with its own
|
||||
// environment
|
||||
DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);
|
||||
|
||||
DEBUG_CODE_BEGIN();
|
||||
Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);
|
||||
FreePool(Temp);
|
||||
Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);
|
||||
FreePool(Temp);
|
||||
Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);
|
||||
FreePool(Temp);
|
||||
DEBUG_CODE_END();
|
||||
|
||||
DEBUG_CODE_BEGIN();
|
||||
Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);
|
||||
FreePool(Temp);
|
||||
Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);
|
||||
FreePool(Temp);
|
||||
Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);
|
||||
FreePool(Temp);
|
||||
DEBUG_CODE_END();
|
||||
Temp = NULL;
|
||||
Size = 0;
|
||||
ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));
|
||||
StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);
|
||||
StrnCatGrow(&Temp, &Size, CommandLine, 0);
|
||||
|
||||
Temp = NULL;
|
||||
Size = 0;
|
||||
ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));
|
||||
StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);
|
||||
StrnCatGrow(&Temp, &Size, CommandLine, 0);
|
||||
Status = InternalShellExecuteDevicePath(
|
||||
ParentImageHandle,
|
||||
DevPath,
|
||||
Temp,
|
||||
(CONST CHAR16**)Environment,
|
||||
StatusCode);
|
||||
|
||||
Status = InternalShellExecuteDevicePath(
|
||||
ParentImageHandle,
|
||||
DevPath,
|
||||
Temp,
|
||||
(CONST CHAR16**)Environment,
|
||||
StatusCode);
|
||||
//
|
||||
// de-allocate and return
|
||||
//
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// de-allocate and return
|
||||
//
|
||||
FreePool(DevPath);
|
||||
FreePool(Temp);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue