]> git.proxmox.com Git - mirror_edk2.git/commitdiff
ShellPkg: Fix 'EfiShellExecute' doesn't get command status correctly.
authorQiu Shumin <shumin.qiu@intel.com>
Mon, 26 Oct 2015 13:28:01 +0000 (13:28 +0000)
committershenshushi <shenshushi@Edk2>
Mon, 26 Oct 2015 13:28:01 +0000 (13:28 +0000)
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

ShellPkg/Application/Shell/Shell.c
ShellPkg/Application/Shell/Shell.h
ShellPkg/Application/Shell/ShellEnvVar.c
ShellPkg/Application/Shell/ShellProtocol.c

index 03f5e4f05fe8756ad922fdd5e2537f3b53121d9b..cb9d969441506981e1587a66b16be3261bb9a3e8 100644 (file)
@@ -1053,6 +1053,7 @@ DoStartupScript(
   )\r
 {\r
   EFI_STATUS                    Status;\r
+  EFI_STATUS                    CalleeStatus;\r
   UINTN                         Delay;\r
   EFI_INPUT_KEY                 Key;\r
   SHELL_FILE_HANDLE             FileHandle;\r
@@ -1084,7 +1085,10 @@ DoStartupScript(
       StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
       StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
     }\r
-    Status = RunCommand(FileStringPath);\r
+    Status = RunShellCommand(FileStringPath, &CalleeStatus);\r
+    if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) {\r
+      ShellCommandRegisterExit(gEfiShellProtocol->BatchIsActive(), (CONST UINT64)CalleeStatus);\r
+    }\r
     FreePool(FileStringPath);\r
     return (Status);\r
 \r
@@ -2133,6 +2137,7 @@ ProcessCommandLineToFinal(
   @param[in] CmdLine          the command line to run.\r
   @param[in] FirstParameter   the first parameter on the command line\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
+  @param[out] CommandStatus   the status from the command line.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
@@ -2142,7 +2147,8 @@ EFIAPI
 RunInternalCommand(\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
+  OUT EFI_STATUS                    *CommandStatus\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2175,6 +2181,14 @@ RunInternalCommand(
     Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError);\r
 \r
     if (!EFI_ERROR(Status)) {\r
+      if (CommandStatus != NULL) {\r
+        if (CommandReturnedStatus != SHELL_SUCCESS) {\r
+          *CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT);\r
+        } else {\r
+          *CommandStatus = EFI_SUCCESS;\r
+        }\r
+      }\r
+\r
       //\r
       // Update last error status.\r
       // some commands do not update last error.\r
@@ -2236,6 +2250,7 @@ RunInternalCommand(
   @param[in] CmdLine          the command line to run.\r
   @param[in] FirstParameter   the first parameter on the command line\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
+  @param[out] CommandStatus   the status from the command line.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
@@ -2246,7 +2261,8 @@ RunCommandOrFile(
   IN       SHELL_OPERATION_TYPES    Type,\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
+  OUT EFI_STATUS                    *CommandStatus\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2262,7 +2278,7 @@ RunCommandOrFile(
 \r
   switch (Type) {\r
     case   Internal_Command:\r
-      Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol);\r
+      Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol, CommandStatus);\r
       break;\r
     case   Script_File_Name:\r
     case   Efi_Application:\r
@@ -2328,6 +2344,10 @@ RunCommandOrFile(
             CalleeExitStatus = (SHELL_STATUS) StartStatus;\r
           }\r
 \r
+          if (CommandStatus != NULL) {\r
+            *CommandStatus = CalleeExitStatus;\r
+          }\r
+\r
           //\r
           // Update last error status.\r
           //\r
@@ -2360,6 +2380,7 @@ RunCommandOrFile(
   @param[in] CmdLine          the command line to run.\r
   @param[in] FirstParameter   the first parameter on the command line.\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
+  @param[out] CommandStatus   the status from the command line.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
@@ -2367,10 +2388,11 @@ RunCommandOrFile(
 EFI_STATUS\r
 EFIAPI\r
 SetupAndRunCommandOrFile(\r
-  IN SHELL_OPERATION_TYPES          Type,\r
-  IN CHAR16                         *CmdLine,\r
-  IN CHAR16                         *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
+  IN   SHELL_OPERATION_TYPES          Type,\r
+  IN   CHAR16                         *CmdLine,\r
+  IN   CHAR16                         *FirstParameter,\r
+  IN   EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
+  OUT EFI_STATUS                    *CommandStatus\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2390,7 +2412,7 @@ SetupAndRunCommandOrFile(
   //\r
   if (!EFI_ERROR(Status)) {\r
     TrimSpaces(&CmdLine);\r
-    Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol);\r
+    Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus);\r
   }\r
 \r
   //\r
@@ -2415,14 +2437,16 @@ SetupAndRunCommandOrFile(
   command or dispatch an external application.\r
 \r
   @param[in] CmdLine      The command line to parse.\r
+  @param[out] CommandStatus   The status from the command line.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-RunCommand(\r
-  IN CONST CHAR16   *CmdLine\r
+RunShellCommand(\r
+  IN CONST CHAR16   *CmdLine,\r
+  OUT EFI_STATUS    *CommandStatus\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2507,7 +2531,7 @@ RunCommand(
       case   Internal_Command:\r
       case   Script_File_Name:\r
       case   Efi_Application:\r
-        Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol);\r
+        Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus);\r
         break;\r
       default:\r
         //\r
@@ -2528,6 +2552,27 @@ RunCommand(
   return (Status);\r
 }\r
 \r
+/**\r
+  Function will process and run a command line.\r
+\r
+  This will determine if the command line represents an internal shell \r
+  command or dispatch an external application.\r
+\r
+  @param[in] CmdLine      The command line to parse.\r
+\r
+  @retval EFI_SUCCESS     The command was completed.\r
+  @retval EFI_ABORTED     The command's operation was aborted.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunCommand(\r
+  IN CONST CHAR16   *CmdLine\r
+  )\r
+{\r
+  return (RunShellCommand(CmdLine, NULL));\r
+}\r
+\r
+\r
 STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};\r
 /**\r
   Function determines if the CommandName COULD be a valid command.  It does not determine whether\r
index b6686256aac3aa49cdebff06b54c13e078ce2446..7c876510dd29f5d80ee08c9b3b361597414a251f 100644 (file)
@@ -293,6 +293,25 @@ RunCommand(
   IN CONST CHAR16   *CmdLine\r
   );\r
 \r
+/**\r
+  Function will process and run a command line.\r
+\r
+  This will determine if the command line represents an internal shell \r
+  command or dispatch an external application.\r
+\r
+  @param[in] CmdLine      The command line to parse.\r
+  @param[out] CommandStatus   The status from the command line.\r
+\r
+  @retval EFI_SUCCESS     The command was completed.\r
+  @retval EFI_ABORTED     The command's operation was aborted.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunShellCommand(\r
+  IN CONST CHAR16   *CmdLine,\r
+  OUT EFI_STATUS    *CommandStatus\r
+  );\r
+\r
 /**\r
   Function determines if the CommandName COULD be a valid command.  It does not determine whether\r
   this is a valid command.  It only checks for invalid characters.\r
index 8ed14b34a2f48992c0ae3a2b29c53f54d18615af..a8f177e6adae3dd7cc8100e589a6eb5bebbc3fe9 100644 (file)
@@ -339,9 +339,10 @@ SetEnvironmentVariables(
     //\r
     // Copy the string into the Key, leaving the last character allocated as NULL to terminate\r
     //\r
-    StrCpyS( Node->Key, \r
+    StrnCpyS( Node->Key, \r
               StrStr(CurrentString, L"=") - CurrentString + 1, \r
-              CurrentString\r
+              CurrentString,\r
+              StrStr(CurrentString, L"=") - CurrentString\r
               );\r
 \r
     //\r
index 3a963849f29aef8220004befe43f188cb61726a5..af00fe401d9c49eba3bc656b2e1a6aa5a8e01b97 100644 (file)
@@ -1631,40 +1631,60 @@ EfiShellExecute(
   CHAR16                    *Temp;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   UINTN                     Size;\r
-\r
+  EFI_STATUS                CalleeStatusCode;\r
+  \r
   if ((PcdGet8(PcdShellSupportLevel) < 1)) {\r
     return (EFI_UNSUPPORTED);\r
   }\r
 \r
-  DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
+  if (Environment != NULL) {\r
+    // If Environment isn't null, load a new image of the shell with its own\r
+    // environment\r
+    DevPath = AppendDevicePath (ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
\r
+    DEBUG_CODE_BEGIN();\r
+    Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
+    FreePool(Temp);\r
+    DEBUG_CODE_END();\r
+\r
+    Temp = NULL;\r
+    Size = 0;\r
+    ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));\r
+    StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);\r
+    StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
 \r
-  DEBUG_CODE_BEGIN();\r
-  Temp = ConvertDevicePathToText(ShellInfoObject.FileDevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  Temp = ConvertDevicePathToText(ShellInfoObject.ImageDevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  Temp = ConvertDevicePathToText(DevPath, TRUE, TRUE);\r
-  FreePool(Temp);\r
-  DEBUG_CODE_END();\r
+    Status = InternalShellExecuteDevicePath(\r
+      ParentImageHandle,\r
+      DevPath,\r
+      Temp,\r
+      (CONST CHAR16**)Environment,\r
+      StatusCode);\r
 \r
-  Temp = NULL;\r
-  Size = 0;\r
-  ASSERT((Temp == NULL && Size == 0) || (Temp != NULL));\r
-  StrnCatGrow(&Temp, &Size, L"Shell.efi -_exit ", 0);\r
-  StrnCatGrow(&Temp, &Size, CommandLine, 0);\r
+    //\r
+    // de-allocate and return\r
+    //\r
+    FreePool(DevPath);\r
+    FreePool(Temp);\r
+  } else {\r
+    // If Environment is NULL, we are free to use and mutate the current shell\r
+    // environment. This is much faster as uses much less memory.\r
 \r
-  Status = InternalShellExecuteDevicePath(\r
-    ParentImageHandle,\r
-    DevPath,\r
-    Temp,\r
-    (CONST CHAR16**)Environment,\r
-    StatusCode);\r
+    if (CommandLine == NULL) {\r
+      CommandLine = L"";\r
+    }\r
+\r
+    Status = RunShellCommand (CommandLine, &CalleeStatusCode);\r
+\r
+    // Pass up the command's exit code if the caller wants it\r
+    if (StatusCode != NULL) {\r
+      *StatusCode = (EFI_STATUS) CalleeStatusCode;\r
+    }\r
+  }\r
 \r
-  //\r
-  // de-allocate and return\r
-  //\r
-  FreePool(DevPath);\r
-  FreePool(Temp);\r
   return(Status);\r
 }\r
 \r