summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ShellPkg/Application/Shell/Shell.c69
-rw-r--r--ShellPkg/Application/Shell/Shell.h19
-rw-r--r--ShellPkg/Application/Shell/ShellEnvVar.c5
-rw-r--r--ShellPkg/Application/Shell/ShellProtocol.c72
4 files changed, 125 insertions, 40 deletions
diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c
index 03f5e4f05f..cb9d969441 100644
--- a/ShellPkg/Application/Shell/Shell.c
+++ b/ShellPkg/Application/Shell/Shell.c
@@ -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
diff --git a/ShellPkg/Application/Shell/Shell.h b/ShellPkg/Application/Shell/Shell.h
index b6686256aa..7c876510dd 100644
--- a/ShellPkg/Application/Shell/Shell.h
+++ b/ShellPkg/Application/Shell/Shell.h
@@ -294,6 +294,25 @@ RunCommand(
);
/**
+ 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.
diff --git a/ShellPkg/Application/Shell/ShellEnvVar.c b/ShellPkg/Application/Shell/ShellEnvVar.c
index 8ed14b34a2..a8f177e6ad 100644
--- a/ShellPkg/Application/Shell/ShellEnvVar.c
+++ b/ShellPkg/Application/Shell/ShellEnvVar.c
@@ -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
);
//
diff --git a/ShellPkg/Application/Shell/ShellProtocol.c b/ShellPkg/Application/Shell/ShellProtocol.c
index 3a963849f2..af00fe401d 100644
--- a/ShellPkg/Application/Shell/ShellProtocol.c
+++ b/ShellPkg/Application/Shell/ShellProtocol.c
@@ -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();
+
+ Temp = NULL;
+ Size = 0;
+ ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));
+ StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);
+ StrnCatGrow(&Temp, &Size, CommandLine, 0);
- 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();
+ Status = InternalShellExecuteDevicePath(
+ ParentImageHandle,
+ DevPath,
+ Temp,
+ (CONST CHAR16**)Environment,
+ StatusCode);
- Temp = NULL;
- Size = 0;
- ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));
- StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);
- StrnCatGrow(&Temp, &Size, CommandLine, 0);
+ //
+ // 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.
- Status = InternalShellExecuteDevicePath(
- ParentImageHandle,
- DevPath,
- Temp,
- (CONST CHAR16**)Environment,
- StatusCode);
+ 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);
}