Revision: 19397
          http://sourceforge.net/p/edk2/code/19397
Author:   vanjeff
Date:     2015-12-18 07:31:38 +0000 (Fri, 18 Dec 2015)
Log Message:
-----------
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.

(Sync patch r18664 from main trunk.)

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Qiu Shumin <[email protected]>
Signed-off-by: Jin Eric <[email protected]>
Signed-off-by: Jaben Carsey <[email protected]>
Reviewed-by: Ruiyu Ni <[email protected]>

Revision Links:
--------------
    http://sourceforge.net/p/edk2/code/18664

Modified Paths:
--------------
    branches/UDK2015/ShellPkg/Application/Shell/Shell.c
    branches/UDK2015/ShellPkg/Application/Shell/Shell.h
    branches/UDK2015/ShellPkg/Application/Shell/ShellEnvVar.c
    branches/UDK2015/ShellPkg/Application/Shell/ShellProtocol.c

Modified: branches/UDK2015/ShellPkg/Application/Shell/Shell.c
===================================================================
--- branches/UDK2015/ShellPkg/Application/Shell/Shell.c 2015-12-18 07:30:58 UTC 
(rev 19396)
+++ branches/UDK2015/ShellPkg/Application/Shell/Shell.c 2015-12-18 07:31:38 UTC 
(rev 19397)
@@ -1053,6 +1053,7 @@
   )
 {
   EFI_STATUS                    Status;
+  EFI_STATUS                    CalleeStatus;
   UINTN                         Delay;
   EFI_INPUT_KEY                 Key;
   SHELL_FILE_HANDLE             FileHandle;
@@ -1084,7 +1085,10 @@
       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 @@
   @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 @@
 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 @@
     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 @@
   @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 @@
   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 @@
 
   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 @@
             CalleeExitStatus = (SHELL_STATUS) StartStatus;
           }
 
+          if (CommandStatus != NULL) {
+            *CommandStatus = CalleeExitStatus;
+          }
+
           //
           // Update last error status.
           //
@@ -2360,6 +2380,7 @@
   @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 @@
 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 @@
   //
   if (!EFI_ERROR(Status)) {
     TrimSpaces(&CmdLine);
-    Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol);
+    Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, 
CommandStatus);
   }
 
   //
@@ -2415,14 +2437,16 @@
   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 @@
       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 @@
   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

Modified: branches/UDK2015/ShellPkg/Application/Shell/Shell.h
===================================================================
--- branches/UDK2015/ShellPkg/Application/Shell/Shell.h 2015-12-18 07:30:58 UTC 
(rev 19396)
+++ branches/UDK2015/ShellPkg/Application/Shell/Shell.h 2015-12-18 07:31:38 UTC 
(rev 19397)
@@ -294,6 +294,25 @@
   );
 
 /**
+  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.
 

Modified: branches/UDK2015/ShellPkg/Application/Shell/ShellEnvVar.c
===================================================================
--- branches/UDK2015/ShellPkg/Application/Shell/ShellEnvVar.c   2015-12-18 
07:30:58 UTC (rev 19396)
+++ branches/UDK2015/ShellPkg/Application/Shell/ShellEnvVar.c   2015-12-18 
07:31:38 UTC (rev 19397)
@@ -339,9 +339,10 @@
     //
     // 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
               );
 
     //

Modified: branches/UDK2015/ShellPkg/Application/Shell/ShellProtocol.c
===================================================================
--- branches/UDK2015/ShellPkg/Application/Shell/ShellProtocol.c 2015-12-18 
07:30:58 UTC (rev 19396)
+++ branches/UDK2015/ShellPkg/Application/Shell/ShellProtocol.c 2015-12-18 
07:31:38 UTC (rev 19397)
@@ -1631,40 +1631,60 @@
   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.
 
-  //
-  // de-allocate and return
-  //
-  FreePool(DevPath);
-  FreePool(Temp);
+    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;
+    }
+  }
+
   return(Status);
 }
 


------------------------------------------------------------------------------
_______________________________________________
edk2-commits mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/edk2-commits

Reply via email to