]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/Shell.c
ShellPkg: add array index check for shell delay option
[mirror_edk2.git] / ShellPkg / Application / Shell / Shell.c
index 03f5e4f05fe8756ad922fdd5e2537f3b53121d9b..ec344137d355e2dad689bc54f71c3839a896d7f5 100644 (file)
@@ -1,8 +1,9 @@
 /** @file\r
   This is THE shell (application)\r
 \r
 /** @file\r
   This is THE shell (application)\r
 \r
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
   (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>\r
   (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>\r
+  Copyright 2015-2018 Dell Technologies.<BR>\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
   This program and the accompanying materials\r
   are licensed and made available under the terms and conditions of the BSD License\r
   which accompanies this distribution.  The full text of the license may be found at\r
@@ -33,6 +34,7 @@ SHELL_INFO ShellInfoObject = {
       0,\r
       0,\r
       0,\r
       0,\r
       0,\r
       0,\r
+      0,\r
       0\r
     }},\r
     0,\r
       0\r
     }},\r
     0,\r
@@ -69,6 +71,9 @@ SHELL_INFO ShellInfoObject = {
 STATIC CONST CHAR16 mScriptExtension[]      = L".NSH";\r
 STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";\r
 STATIC CONST CHAR16 mStartupScript[]        = L"startup.nsh";\r
 STATIC CONST CHAR16 mScriptExtension[]      = L".NSH";\r
 STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";\r
 STATIC CONST CHAR16 mStartupScript[]        = L"startup.nsh";\r
+CONST CHAR16 mNoNestingEnvVarName[]         = L"nonesting";\r
+CONST CHAR16 mNoNestingTrue[]               = L"True";\r
+CONST CHAR16 mNoNestingFalse[]              = L"False";\r
 \r
 /**\r
   Cleans off leading and trailing spaces and tabs.\r
 \r
 /**\r
   Cleans off leading and trailing spaces and tabs.\r
@@ -76,7 +81,6 @@ STATIC CONST CHAR16 mStartupScript[]        = L"startup.nsh";
   @param[in] String pointer to the string to trim them off.\r
 **/\r
 EFI_STATUS\r
   @param[in] String pointer to the string to trim them off.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 TrimSpaces(\r
   IN CHAR16 **String\r
   )\r
 TrimSpaces(\r
   IN CHAR16 **String\r
   )\r
@@ -101,7 +105,7 @@ TrimSpaces(
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Parse for the next instance of one string within another string. Can optionally make sure that \r
+  Parse for the next instance of one string within another string. Can optionally make sure that\r
   the string was not escaped (^ character) per the shell specification.\r
 \r
   @param[in] SourceString             The string to search within\r
   the string was not escaped (^ character) per the shell specification.\r
 \r
   @param[in] SourceString             The string to search within\r
@@ -109,7 +113,6 @@ TrimSpaces(
   @param[in] CheckForEscapeCharacter  TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances\r
 **/\r
 CHAR16*\r
   @param[in] CheckForEscapeCharacter  TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances\r
 **/\r
 CHAR16*\r
-EFIAPI\r
 FindNextInstance(\r
   IN CONST CHAR16   *SourceString,\r
   IN CONST CHAR16   *FindString,\r
 FindNextInstance(\r
   IN CONST CHAR16   *SourceString,\r
   IN CONST CHAR16   *FindString,\r
@@ -158,13 +161,13 @@ IsValidEnvironmentVariableName(
   )\r
 {\r
   CONST CHAR16    *Walker;\r
   )\r
 {\r
   CONST CHAR16    *Walker;\r
-  \r
+\r
   Walker = NULL;\r
 \r
   ASSERT (BeginPercent != NULL);\r
   ASSERT (EndPercent != NULL);\r
   ASSERT (BeginPercent < EndPercent);\r
   Walker = NULL;\r
 \r
   ASSERT (BeginPercent != NULL);\r
   ASSERT (EndPercent != NULL);\r
   ASSERT (BeginPercent < EndPercent);\r
-  \r
+\r
   if ((BeginPercent + 1) == EndPercent) {\r
     return FALSE;\r
   }\r
   if ((BeginPercent + 1) == EndPercent) {\r
     return FALSE;\r
   }\r
@@ -198,7 +201,6 @@ IsValidEnvironmentVariableName(
   @retval FALSE           CmdLine does not have a valid split.\r
 **/\r
 BOOLEAN\r
   @retval FALSE           CmdLine does not have a valid split.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 ContainsSplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
 ContainsSplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -211,9 +213,9 @@ ContainsSplit(
   SecondQuote   = NULL;\r
   TempSpot      = FindFirstCharacter(CmdLine, L"|", L'^');\r
 \r
   SecondQuote   = NULL;\r
   TempSpot      = FindFirstCharacter(CmdLine, L"|", L'^');\r
 \r
-  if (FirstQuote == NULL    || \r
-      TempSpot == NULL      || \r
-      TempSpot == CHAR_NULL || \r
+  if (FirstQuote == NULL    ||\r
+      TempSpot == NULL      ||\r
+      TempSpot == CHAR_NULL ||\r
       FirstQuote > TempSpot\r
       ) {\r
     return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
       FirstQuote > TempSpot\r
       ) {\r
     return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
@@ -222,7 +224,7 @@ ContainsSplit(
   while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) {\r
     if (FirstQuote == NULL || FirstQuote > TempSpot) {\r
       break;\r
   while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) {\r
     if (FirstQuote == NULL || FirstQuote > TempSpot) {\r
       break;\r
-    }    \r
+    }\r
     SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE);\r
     if (SecondQuote == NULL) {\r
       break;\r
     SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE);\r
     if (SecondQuote == NULL) {\r
       break;\r
@@ -234,21 +236,20 @@ ContainsSplit(
       FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);\r
       TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^');\r
       continue;\r
       FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);\r
       TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^');\r
       continue;\r
-    } \r
+    }\r
   }\r
   }\r
-  \r
+\r
   return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
 }\r
 \r
 /**\r
   return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
 }\r
 \r
 /**\r
-  Function to start monitoring for CTRL-S using SimpleTextInputEx.  This \r
+  Function to start monitoring for CTRL-S using SimpleTextInputEx.  This\r
   feature's enabled state was not known when the shell initially launched.\r
 \r
   @retval EFI_SUCCESS           The feature is enabled.\r
   @retval EFI_OUT_OF_RESOURCES  There is not enough memory available.\r
 **/\r
 EFI_STATUS\r
   feature's enabled state was not known when the shell initially launched.\r
 \r
   @retval EFI_SUCCESS           The feature is enabled.\r
   @retval EFI_OUT_OF_RESOURCES  There is not enough memory available.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InternalEfiShellStartCtrlSMonitor(\r
   VOID\r
   )\r
 InternalEfiShellStartCtrlSMonitor(\r
   VOID\r
   )\r
@@ -266,8 +267,8 @@ InternalEfiShellStartCtrlSMonitor(
     EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
   if (EFI_ERROR(Status)) {\r
     ShellPrintHiiEx(\r
     EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
   if (EFI_ERROR(Status)) {\r
     ShellPrintHiiEx(\r
-      -1, \r
-      -1, \r
+      -1,\r
+      -1,\r
       NULL,\r
       STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
       ShellInfoObject.HiiHandle);\r
       NULL,\r
       STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
       ShellInfoObject.HiiHandle);\r
@@ -284,7 +285,7 @@ InternalEfiShellStartCtrlSMonitor(
     &KeyData,\r
     NotificationFunction,\r
     &ShellInfoObject.CtrlSNotifyHandle1);\r
     &KeyData,\r
     NotificationFunction,\r
     &ShellInfoObject.CtrlSNotifyHandle1);\r
-  \r
+\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
   if (!EFI_ERROR(Status)) {\r
     Status = SimpleEx->RegisterKeyNotify(\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
   if (!EFI_ERROR(Status)) {\r
     Status = SimpleEx->RegisterKeyNotify(\r
@@ -302,7 +303,7 @@ InternalEfiShellStartCtrlSMonitor(
       &KeyData,\r
       NotificationFunction,\r
       &ShellInfoObject.CtrlSNotifyHandle3);\r
       &KeyData,\r
       NotificationFunction,\r
       &ShellInfoObject.CtrlSNotifyHandle3);\r
-  }  \r
+  }\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
   if (!EFI_ERROR(Status)) {\r
     Status = SimpleEx->RegisterKeyNotify(\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
   if (!EFI_ERROR(Status)) {\r
     Status = SimpleEx->RegisterKeyNotify(\r
@@ -338,6 +339,7 @@ UefiMain (
   UINTN                           Size;\r
   EFI_HANDLE                      ConInHandle;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *OldConIn;\r
   UINTN                           Size;\r
   EFI_HANDLE                      ConInHandle;\r
   EFI_SIMPLE_TEXT_INPUT_PROTOCOL  *OldConIn;\r
+  SPLIT_LIST                      *Split;\r
 \r
   if (PcdGet8(PcdShellSupportLevel) > 3) {\r
     return (EFI_UNSUPPORTED);\r
 \r
   if (PcdGet8(PcdShellSupportLevel) > 3) {\r
     return (EFI_UNSUPPORTED);\r
@@ -441,6 +443,8 @@ UefiMain (
     Status = CommandInit();\r
     ASSERT_EFI_ERROR(Status);\r
 \r
     Status = CommandInit();\r
     ASSERT_EFI_ERROR(Status);\r
 \r
+    Status = ShellInitEnvVarList ();\r
+\r
     //\r
     // Check the command line\r
     //\r
     //\r
     // Check the command line\r
     //\r
@@ -456,6 +460,29 @@ UefiMain (
       Status = ShellCommandCreateInitialMappingsAndPaths();\r
     }\r
 \r
       Status = ShellCommandCreateInitialMappingsAndPaths();\r
     }\r
 \r
+    //\r
+    // Set the environment variable for nesting support\r
+    //\r
+    Size = 0;\r
+    TempString = NULL;\r
+    if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest) {\r
+      //\r
+      // No change.  require nesting in Shell Protocol Execute()\r
+      //\r
+      StrnCatGrow(&TempString,\r
+                  &Size,\r
+                  L"False",\r
+                  0);\r
+    } else {\r
+      StrnCatGrow(&TempString,\r
+                  &Size,\r
+                  mNoNestingTrue,\r
+                  0);\r
+    }\r
+    Status = InternalEfiShellSetEnv(mNoNestingEnvVarName, TempString, TRUE);\r
+    SHELL_FREE_NON_NULL(TempString);\r
+    Size = 0;\r
+\r
     //\r
     // save the device path for the loaded image and the device path for the filepath (under loaded image)\r
     // These are where to look for the startup.nsh file\r
     //\r
     // save the device path for the loaded image and the device path for the filepath (under loaded image)\r
     // These are where to look for the startup.nsh file\r
@@ -594,11 +621,6 @@ UefiMain (
           ShellInfoObject.ConsoleInfo->Enabled    = TRUE;\r
           ShellInfoObject.ConsoleInfo->RowCounter = 0;\r
 \r
           ShellInfoObject.ConsoleInfo->Enabled    = TRUE;\r
           ShellInfoObject.ConsoleInfo->RowCounter = 0;\r
 \r
-          //\r
-          // Reset the CTRL-C event (yes we ignore the return values)\r
-          //\r
-          Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);\r
-\r
           //\r
           // Display Prompt\r
           //\r
           //\r
           // Display Prompt\r
           //\r
@@ -637,7 +659,7 @@ FreeResources:
     if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){\r
       InternalEfiShellSetEnv(L"cwd", NULL, TRUE);\r
     }\r
     if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){\r
       InternalEfiShellSetEnv(L"cwd", NULL, TRUE);\r
     }\r
-    CleanUpShellProtocol(ShellInfoObject.NewEfiShellProtocol);\r
+    CleanUpShellEnvironment (ShellInfoObject.NewEfiShellProtocol);\r
     DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);\r
   }\r
 \r
     DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);\r
   }\r
 \r
@@ -646,7 +668,17 @@ FreeResources:
   }\r
 \r
   if (!IsListEmpty(&ShellInfoObject.SplitList.Link)){\r
   }\r
 \r
   if (!IsListEmpty(&ShellInfoObject.SplitList.Link)){\r
-    ASSERT(FALSE); ///@todo finish this de-allocation.\r
+    ASSERT(FALSE); ///@todo finish this de-allocation (free SplitStdIn/Out when needed).\r
+\r
+    for ( Split = (SPLIT_LIST*)GetFirstNode (&ShellInfoObject.SplitList.Link)\r
+        ; !IsNull (&ShellInfoObject.SplitList.Link, &Split->Link)\r
+        ; Split = (SPLIT_LIST *)GetNextNode (&ShellInfoObject.SplitList.Link, &Split->Link)\r
+     ) {\r
+      RemoveEntryList (&Split->Link);\r
+      FreePool (Split);\r
+    }\r
+\r
+    DEBUG_CODE (InitializeListHead (&ShellInfoObject.SplitList.Link););\r
   }\r
 \r
   if (ShellInfoObject.ShellInitSettings.FileName != NULL) {\r
   }\r
 \r
   if (ShellInfoObject.ShellInitSettings.FileName != NULL) {\r
@@ -675,6 +707,8 @@ FreeResources:
     DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);\r
   }\r
 \r
     DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);\r
   }\r
 \r
+  ShellFreeEnvVarList ();\r
+\r
   if (ShellCommandGetExit()) {\r
     return ((EFI_STATUS)ShellCommandGetExitCode());\r
   }\r
   if (ShellCommandGetExit()) {\r
     return ((EFI_STATUS)ShellCommandGetExitCode());\r
   }\r
@@ -687,8 +721,8 @@ FreeResources:
   @retval EFI_SUCCESS           all init commands were run successfully.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_SUCCESS           all init commands were run successfully.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 SetBuiltInAlias(\r
 SetBuiltInAlias(\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS          Status;\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -726,7 +760,6 @@ SetBuiltInAlias(
   @retval FALSE             The 2 command names are not the same.\r
 **/\r
 BOOLEAN\r
   @retval FALSE             The 2 command names are not the same.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 IsCommand(\r
   IN CONST CHAR16 *Command1,\r
   IN CONST CHAR16 *Command2\r
 IsCommand(\r
   IN CONST CHAR16 *Command1,\r
   IN CONST CHAR16 *Command2\r
@@ -747,7 +780,6 @@ IsCommand(
   @retval FALSE             The command is not a script only command.\r
 **/\r
 BOOLEAN\r
   @retval FALSE             The command is not a script only command.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 IsScriptOnlyCommand(\r
   IN CONST CHAR16 *CommandName\r
   )\r
 IsScriptOnlyCommand(\r
   IN CONST CHAR16 *CommandName\r
   )\r
@@ -778,7 +810,6 @@ IsScriptOnlyCommand(
   @sa HandleProtocol\r
 **/\r
 EFI_STATUS\r
   @sa HandleProtocol\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 GetDevicePathsForImageAndFile (\r
   IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath,\r
   IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath\r
 GetDevicePathsForImageAndFile (\r
   IN OUT EFI_DEVICE_PATH_PROTOCOL **DevPath,\r
   IN OUT EFI_DEVICE_PATH_PROTOCOL **FilePath\r
@@ -854,7 +885,6 @@ GetDevicePathsForImageAndFile (
   @retval EFI_SUCCESS           The variable is initialized.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_SUCCESS           The variable is initialized.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ProcessCommandLine(\r
   VOID\r
   )\r
 ProcessCommandLine(\r
   VOID\r
   )\r
@@ -873,12 +903,19 @@ ProcessCommandLine(
   // like a shell option (which is assumed to be `file-name`).\r
 \r
   Status = gBS->LocateProtocol (\r
   // like a shell option (which is assumed to be `file-name`).\r
 \r
   Status = gBS->LocateProtocol (\r
-                  &gEfiUnicodeCollationProtocolGuid,\r
+                  &gEfiUnicodeCollation2ProtocolGuid,\r
                   NULL,\r
                   (VOID **) &UnicodeCollation\r
                   );\r
   if (EFI_ERROR (Status)) {\r
                   NULL,\r
                   (VOID **) &UnicodeCollation\r
                   );\r
   if (EFI_ERROR (Status)) {\r
-    return Status;\r
+    Status = gBS->LocateProtocol (\r
+                    &gEfiUnicodeCollationProtocolGuid,\r
+                    NULL,\r
+                    (VOID **) &UnicodeCollation\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      return Status;\r
+    }\r
   }\r
 \r
   // Set default options\r
   }\r
 \r
   // Set default options\r
@@ -891,6 +928,7 @@ ProcessCommandLine(
   ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion    = FALSE;\r
   ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay        = FALSE;\r
   ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit         = FALSE;\r
   ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion    = FALSE;\r
   ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay        = FALSE;\r
   ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit         = FALSE;\r
+  ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest       = FALSE;\r
   ShellInfoObject.ShellInitSettings.Delay = 5;\r
 \r
   //\r
   ShellInfoObject.ShellInitSettings.Delay = 5;\r
 \r
   //\r
@@ -950,6 +988,13 @@ ProcessCommandLine(
                                  ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion    = TRUE;\r
     }\r
                                  ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion    = TRUE;\r
     }\r
+    else if (UnicodeCollation->StriColl (\r
+                                 UnicodeCollation,\r
+                                 L"-nonest",\r
+                                 CurrentArg\r
+                                 ) == 0) {\r
+      ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoNest       = TRUE;\r
+    }\r
     else if (UnicodeCollation->StriColl (\r
                                  UnicodeCollation,\r
                                  L"-delay",\r
     else if (UnicodeCollation->StriColl (\r
                                  UnicodeCollation,\r
                                  L"-delay",\r
@@ -957,7 +1002,11 @@ ProcessCommandLine(
                                  ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay        = TRUE;\r
       // Check for optional delay value following "-delay"\r
                                  ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay        = TRUE;\r
       // Check for optional delay value following "-delay"\r
-      DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1];\r
+      if ((LoopVar + 1) >= gEfiShellParametersProtocol->Argc) {\r
+        DelayValueStr = NULL;\r
+      } else {\r
+        DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1];\r
+      }\r
       if (DelayValueStr != NULL){\r
         if (*DelayValueStr == L':') {\r
           DelayValueStr++;\r
       if (DelayValueStr != NULL){\r
         if (*DelayValueStr == L':') {\r
           DelayValueStr++;\r
@@ -974,7 +1023,7 @@ ProcessCommandLine(
       }\r
     } else if (UnicodeCollation->StriColl (\r
                                    UnicodeCollation,\r
       }\r
     } else if (UnicodeCollation->StriColl (\r
                                    UnicodeCollation,\r
-                                   L"-_exit",\r
+                                   L"-exit",\r
                                    CurrentArg\r
                                    ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit         = TRUE;\r
                                    CurrentArg\r
                                    ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit         = TRUE;\r
@@ -994,11 +1043,31 @@ ProcessCommandLine(
         continue;\r
       }\r
 \r
         continue;\r
       }\r
 \r
-      ShellInfoObject.ShellInitSettings.FileName = AllocateCopyPool(StrSize(CurrentArg), CurrentArg);\r
+      ShellInfoObject.ShellInitSettings.FileName = NULL;\r
+      Size = 0;\r
+      //\r
+      // If first argument contains a space, then add double quotes before the argument\r
+      //\r
+      if (StrStr (CurrentArg, L" ") != NULL) {\r
+        StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0);\r
+        if (ShellInfoObject.ShellInitSettings.FileName == NULL) {\r
+          return (EFI_OUT_OF_RESOURCES);\r
+        }\r
+      }\r
+      StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, CurrentArg, 0);\r
       if (ShellInfoObject.ShellInitSettings.FileName == NULL) {\r
         return (EFI_OUT_OF_RESOURCES);\r
       }\r
       //\r
       if (ShellInfoObject.ShellInitSettings.FileName == NULL) {\r
         return (EFI_OUT_OF_RESOURCES);\r
       }\r
       //\r
+      // If first argument contains a space, then add double quotes after the argument\r
+      //\r
+      if (StrStr (CurrentArg, L" ") != NULL) {\r
+        StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileName, &Size, L"\"", 0);\r
+        if (ShellInfoObject.ShellInitSettings.FileName == NULL) {\r
+          return (EFI_OUT_OF_RESOURCES);\r
+        }\r
+      }\r
+      //\r
       // We found `file-name`.\r
       //\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1;\r
       // We found `file-name`.\r
       //\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1;\r
@@ -1007,13 +1076,28 @@ ProcessCommandLine(
       // Add `file-name-options`\r
       for (Size = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
         ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL));\r
       // Add `file-name-options`\r
       for (Size = 0 ; LoopVar < gEfiShellParametersProtocol->Argc ; LoopVar++) {\r
         ASSERT((ShellInfoObject.ShellInitSettings.FileOptions == NULL && Size == 0) || (ShellInfoObject.ShellInitSettings.FileOptions != NULL));\r
-        StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
-                    &Size,\r
-                    L" ",\r
-                    0);\r
-        if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {\r
-          SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
-          return (EFI_OUT_OF_RESOURCES);\r
+        //\r
+        // Add a space between arguments\r
+        //\r
+        if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {\r
+          StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions, &Size, L" ", 0);\r
+          if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {\r
+            SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
+            return (EFI_OUT_OF_RESOURCES);\r
+          }\r
+        }\r
+        //\r
+        // If an argumnent contains a space, then add double quotes before the argument\r
+        //\r
+        if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {\r
+          StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
+                      &Size,\r
+                      L"\"",\r
+                      0);\r
+          if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {\r
+            SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
+            return (EFI_OUT_OF_RESOURCES);\r
+          }\r
         }\r
         StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
                     &Size,\r
         }\r
         StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
                     &Size,\r
@@ -1023,6 +1107,19 @@ ProcessCommandLine(
           SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
           return (EFI_OUT_OF_RESOURCES);\r
         }\r
           SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
           return (EFI_OUT_OF_RESOURCES);\r
         }\r
+        //\r
+        // If an argumnent contains a space, then add double quotes after the argument\r
+        //\r
+        if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {\r
+          StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
+                      &Size,\r
+                      L"\"",\r
+                      0);\r
+          if (ShellInfoObject.ShellInitSettings.FileOptions == NULL) {\r
+            SHELL_FREE_NON_NULL(ShellInfoObject.ShellInitSettings.FileName);\r
+            return (EFI_OUT_OF_RESOURCES);\r
+          }\r
+        }\r
       }\r
     }\r
   }\r
       }\r
     }\r
   }\r
@@ -1035,6 +1132,66 @@ ProcessCommandLine(
   return EFI_SUCCESS;\r
 }\r
 \r
   return EFI_SUCCESS;\r
 }\r
 \r
+/**\r
+  Function try to find location of the Startup.nsh file.\r
+\r
+  The buffer is callee allocated and should be freed by the caller.\r
+\r
+  @param    ImageDevicePath       The path to the image for shell.  first place to look for the startup script\r
+  @param    FileDevicePath        The path to the file for shell.  second place to look for the startup script.\r
+\r
+  @retval   NULL                  No Startup.nsh file was found.\r
+  @return   !=NULL                Pointer to NULL-terminated path.\r
+**/\r
+CHAR16 *\r
+LocateStartupScript (\r
+  IN EFI_DEVICE_PATH_PROTOCOL *ImageDevicePath,\r
+  IN EFI_DEVICE_PATH_PROTOCOL *FileDevicePath\r
+  )\r
+{\r
+  CHAR16          *StartupScriptPath;\r
+  CHAR16          *TempSpot;\r
+  CONST CHAR16    *MapName;\r
+  UINTN           Size;\r
+\r
+  StartupScriptPath = NULL;\r
+  Size              = 0;\r
+\r
+  //\r
+  // Try to find 'Startup.nsh' in the directory where the shell itself was launched.\r
+  //\r
+  MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath (&ImageDevicePath);\r
+  if (MapName != NULL) {\r
+    StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, MapName, 0);\r
+    if (StartupScriptPath == NULL) {\r
+      //\r
+      // Do not locate the startup script in sys path when out of resource.\r
+      //\r
+      return NULL;\r
+    }\r
+    TempSpot = StrStr (StartupScriptPath, L";");\r
+    if (TempSpot != NULL) {\r
+      *TempSpot = CHAR_NULL;\r
+    }\r
+\r
+    InternalEfiShellSetEnv(L"homefilesystem", StartupScriptPath, TRUE);\r
+\r
+    StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, ((FILEPATH_DEVICE_PATH *)FileDevicePath)->PathName, 0);\r
+    PathRemoveLastItem (StartupScriptPath);\r
+    StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, mStartupScript, 0);\r
+  }\r
+\r
+  //\r
+  // Try to find 'Startup.nsh' in the execution path defined by the envrionment variable PATH.\r
+  //\r
+  if ((StartupScriptPath == NULL) || EFI_ERROR (ShellIsFile (StartupScriptPath))) {\r
+    SHELL_FREE_NON_NULL (StartupScriptPath);\r
+    StartupScriptPath = ShellFindFilePath (mStartupScript);\r
+  }\r
+\r
+  return StartupScriptPath;\r
+}\r
+\r
 /**\r
   Handles all interaction with the default startup script.\r
 \r
 /**\r
   Handles all interaction with the default startup script.\r
 \r
@@ -1046,26 +1203,21 @@ ProcessCommandLine(
   @retval EFI_SUCCESS           the variable is initialized.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_SUCCESS           the variable is initialized.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 DoStartupScript(\r
   IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,\r
   IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
 DoStartupScript(\r
   IN EFI_DEVICE_PATH_PROTOCOL *ImagePath,\r
   IN EFI_DEVICE_PATH_PROTOCOL *FilePath\r
   )\r
 {\r
   EFI_STATUS                    Status;\r
+  EFI_STATUS                    CalleeStatus;\r
   UINTN                         Delay;\r
   EFI_INPUT_KEY                 Key;\r
   UINTN                         Delay;\r
   EFI_INPUT_KEY                 Key;\r
-  SHELL_FILE_HANDLE             FileHandle;\r
-  EFI_DEVICE_PATH_PROTOCOL      *NewPath;\r
-  EFI_DEVICE_PATH_PROTOCOL      *NamePath;\r
   CHAR16                        *FileStringPath;\r
   CHAR16                        *FileStringPath;\r
-  CHAR16                        *TempSpot;\r
+  CHAR16                        *FullFileStringPath;\r
   UINTN                         NewSize;\r
   UINTN                         NewSize;\r
-  CONST CHAR16                  *MapName;\r
 \r
   Key.UnicodeChar = CHAR_NULL;\r
   Key.ScanCode    = 0;\r
 \r
   Key.UnicodeChar = CHAR_NULL;\r
   Key.ScanCode    = 0;\r
-  FileHandle      = NULL;\r
 \r
   if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup && ShellInfoObject.ShellInitSettings.FileName != NULL) {\r
     //\r
 \r
   if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Startup && ShellInfoObject.ShellInitSettings.FileName != NULL) {\r
     //\r
@@ -1084,7 +1236,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
       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(), (UINT64)CalleeStatus);\r
+    }\r
     FreePool(FileStringPath);\r
     return (Status);\r
 \r
     FreePool(FileStringPath);\r
     return (Status);\r
 \r
@@ -1124,60 +1279,23 @@ DoStartupScript(
     return (EFI_SUCCESS);\r
   }\r
 \r
     return (EFI_SUCCESS);\r
   }\r
 \r
-  //\r
-  // Try the first location (must be file system)\r
-  //\r
-  MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath(&ImagePath);\r
-  if (MapName != NULL) {\r
-    FileStringPath = NULL;\r
-    NewSize = 0;\r
-    FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, MapName, 0);\r
-    if (FileStringPath == NULL) {\r
-      Status = EFI_OUT_OF_RESOURCES;\r
+  FileStringPath = LocateStartupScript (ImagePath, FilePath);\r
+  if (FileStringPath != NULL) {\r
+    FullFileStringPath = FullyQualifyPath(FileStringPath);\r
+    if (FullFileStringPath == NULL) {\r
+      Status = RunScriptFile (FileStringPath, NULL, FileStringPath, ShellInfoObject.NewShellParametersProtocol);\r
     } else {\r
     } else {\r
-      TempSpot = StrStr(FileStringPath, L";");\r
-      if (TempSpot != NULL) {\r
-        *TempSpot = CHAR_NULL;\r
-      }\r
-      FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, ((FILEPATH_DEVICE_PATH*)FilePath)->PathName, 0);\r
-      PathRemoveLastItem(FileStringPath);\r
-      FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, mStartupScript, 0);\r
-      Status = ShellInfoObject.NewEfiShellProtocol->OpenFileByName(FileStringPath, &FileHandle, EFI_FILE_MODE_READ);\r
-      FreePool(FileStringPath);\r
+      Status = RunScriptFile (FullFileStringPath, NULL, FullFileStringPath, ShellInfoObject.NewShellParametersProtocol);\r
+      FreePool(FullFileStringPath);\r
     }\r
     }\r
-  }\r
-  if (EFI_ERROR(Status)) {\r
-    NamePath = FileDevicePath (NULL, mStartupScript);\r
-    NewPath = AppendDevicePathNode (ImagePath, NamePath);\r
-    FreePool(NamePath);\r
-\r
+    FreePool (FileStringPath);\r
+  } else {\r
     //\r
     //\r
-    // Try the location\r
+    // we return success since startup script is not mandatory.\r
     //\r
     //\r
-    Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
-    FreePool(NewPath);\r
-  }\r
-  //\r
-  // If we got a file, run it\r
-  //\r
-  if (!EFI_ERROR(Status) && FileHandle != NULL) {\r
-    Status = RunScriptFile (mStartupScript, FileHandle, L"", ShellInfoObject.NewShellParametersProtocol);\r
-    ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);\r
-  } else {\r
-    FileStringPath = ShellFindFilePath(mStartupScript);\r
-    if (FileStringPath == NULL) {\r
-      //\r
-      // we return success since we don't need to have a startup script\r
-      //\r
-      Status = EFI_SUCCESS;\r
-      ASSERT(FileHandle == NULL);\r
-    } else {\r
-      Status = RunScriptFile(FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);\r
-      FreePool(FileStringPath);\r
-    }\r
+    Status = EFI_SUCCESS;\r
   }\r
 \r
   }\r
 \r
-\r
   return (Status);\r
 }\r
 \r
   return (Status);\r
 }\r
 \r
@@ -1190,7 +1308,6 @@ DoStartupScript(
   @retval RETURN_ABORTED\r
 **/\r
 EFI_STATUS\r
   @retval RETURN_ABORTED\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 DoShellPrompt (\r
   VOID\r
   )\r
 DoShellPrompt (\r
   VOID\r
   )\r
@@ -1201,6 +1318,7 @@ DoShellPrompt (
   CONST CHAR16  *CurDir;\r
   UINTN         BufferSize;\r
   EFI_STATUS    Status;\r
   CONST CHAR16  *CurDir;\r
   UINTN         BufferSize;\r
   EFI_STATUS    Status;\r
+  LIST_ENTRY    OldBufferList;\r
 \r
   CurDir  = NULL;\r
 \r
 \r
   CurDir  = NULL;\r
 \r
@@ -1214,6 +1332,7 @@ DoShellPrompt (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  SaveBufferList(&OldBufferList);\r
   CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
 \r
   //\r
   CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
 \r
   //\r
@@ -1236,13 +1355,19 @@ DoShellPrompt (
   // Null terminate the string and parse it\r
   //\r
   if (!EFI_ERROR (Status)) {\r
   // Null terminate the string and parse it\r
   //\r
   if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Reset the CTRL-C event just before running the command (yes we ignore the return values)\r
+    //\r
+    Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);\r
+\r
     CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;\r
     Status = RunCommand(CmdLine);\r
     CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;\r
     Status = RunCommand(CmdLine);\r
-    }\r
+  }\r
 \r
   //\r
   // Done with this command\r
   //\r
 \r
   //\r
   // Done with this command\r
   //\r
+  RestoreBufferList(&OldBufferList);\r
   FreePool (CmdLine);\r
   return Status;\r
 }\r
   FreePool (CmdLine);\r
   return Status;\r
 }\r
@@ -1254,8 +1379,7 @@ DoShellPrompt (
   @param Buffer   Something to pass to FreePool when the shell is exiting.\r
 **/\r
 VOID*\r
   @param Buffer   Something to pass to FreePool when the shell is exiting.\r
 **/\r
 VOID*\r
-EFIAPI\r
-AddBufferToFreeList(\r
+AddBufferToFreeList (\r
   VOID *Buffer\r
   )\r
 {\r
   VOID *Buffer\r
   )\r
 {\r
@@ -1265,32 +1389,97 @@ AddBufferToFreeList(
     return (NULL);\r
   }\r
 \r
     return (NULL);\r
   }\r
 \r
-  BufferListEntry = AllocateZeroPool(sizeof(BUFFER_LIST));\r
-  ASSERT(BufferListEntry != NULL);\r
+  BufferListEntry = AllocateZeroPool (sizeof (BUFFER_LIST));\r
+  if (BufferListEntry == NULL) {\r
+    return NULL;\r
+  }\r
+\r
   BufferListEntry->Buffer = Buffer;\r
   BufferListEntry->Buffer = Buffer;\r
-  InsertTailList(&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);\r
+  InsertTailList (&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);\r
   return (Buffer);\r
 }\r
 \r
   return (Buffer);\r
 }\r
 \r
+\r
+/**\r
+  Create a new buffer list and stores the old one to OldBufferList\r
+\r
+  @param OldBufferList   The temporary list head used to store the nodes in BufferToFreeList.\r
+**/\r
+VOID\r
+SaveBufferList (\r
+  OUT LIST_ENTRY     *OldBufferList\r
+  )\r
+{\r
+  CopyMem (OldBufferList, &ShellInfoObject.BufferToFreeList.Link, sizeof (LIST_ENTRY));\r
+  InitializeListHead (&ShellInfoObject.BufferToFreeList.Link);\r
+}\r
+\r
+/**\r
+  Restore previous nodes into BufferToFreeList .\r
+\r
+  @param OldBufferList   The temporary list head used to store the nodes in BufferToFreeList.\r
+**/\r
+VOID\r
+RestoreBufferList (\r
+  IN OUT LIST_ENTRY     *OldBufferList\r
+  )\r
+{\r
+  FreeBufferList (&ShellInfoObject.BufferToFreeList);\r
+  CopyMem (&ShellInfoObject.BufferToFreeList.Link, OldBufferList, sizeof (LIST_ENTRY));\r
+}\r
+\r
+\r
 /**\r
   Add a buffer to the Line History List\r
 \r
   @param Buffer     The line buffer to add.\r
 **/\r
 VOID\r
 /**\r
   Add a buffer to the Line History List\r
 \r
   @param Buffer     The line buffer to add.\r
 **/\r
 VOID\r
-EFIAPI\r
 AddLineToCommandHistory(\r
   IN CONST CHAR16 *Buffer\r
   )\r
 {\r
   BUFFER_LIST *Node;\r
 AddLineToCommandHistory(\r
   IN CONST CHAR16 *Buffer\r
   )\r
 {\r
   BUFFER_LIST *Node;\r
+  BUFFER_LIST *Walker;\r
+  UINT16       MaxHistoryCmdCount;\r
+  UINT16       Count;\r
+\r
+  Count = 0;\r
+  MaxHistoryCmdCount = PcdGet16(PcdShellMaxHistoryCommandCount);\r
+\r
+  if (MaxHistoryCmdCount == 0) {\r
+    return ;\r
+  }\r
+\r
 \r
   Node = AllocateZeroPool(sizeof(BUFFER_LIST));\r
 \r
   Node = AllocateZeroPool(sizeof(BUFFER_LIST));\r
-  ASSERT(Node != NULL);\r
-  Node->Buffer = AllocateCopyPool(StrSize(Buffer), Buffer);\r
-  ASSERT(Node->Buffer != NULL);\r
+  if (Node == NULL) {\r
+    return;\r
+  }\r
+\r
+  Node->Buffer = AllocateCopyPool (StrSize (Buffer), Buffer);\r
+  if (Node->Buffer == NULL) {\r
+    FreePool (Node);\r
+    return;\r
+  }\r
 \r
 \r
-  InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);\r
+  for ( Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)\r
+      ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)\r
+      ; Walker = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)\r
+   ){\r
+    Count++;\r
+  }\r
+  if (Count < MaxHistoryCmdCount){\r
+    InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);\r
+  } else {\r
+    Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link);\r
+    RemoveEntryList(&Walker->Link);\r
+    if (Walker->Buffer != NULL) {\r
+      FreePool(Walker->Buffer);\r
+    }\r
+    FreePool(Walker);\r
+    InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);\r
+  }\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -1307,7 +1496,6 @@ AddLineToCommandHistory(
   @retval EFI_OUT_OF_RESOURCES    A memory allocation failed.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_OUT_OF_RESOURCES    A memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellConvertAlias(\r
   IN OUT CHAR16 **CommandString\r
   )\r
 ShellConvertAlias(\r
   IN OUT CHAR16 **CommandString\r
   )\r
@@ -1332,7 +1520,6 @@ ShellConvertAlias(
   @param[in,out] CmdLine   The command line to update.\r
 **/\r
 EFI_STATUS\r
   @param[in,out] CmdLine   The command line to update.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 StripUnreplacedEnvironmentVariables(\r
   IN OUT CHAR16 *CmdLine\r
   )\r
 StripUnreplacedEnvironmentVariables(\r
   IN OUT CHAR16 *CmdLine\r
   )\r
@@ -1373,7 +1560,7 @@ StripUnreplacedEnvironmentVariables(
       }\r
       continue;\r
     }\r
       }\r
       continue;\r
     }\r
-    \r
+\r
     if (FirstQuote == NULL || SecondPercent < FirstQuote) {\r
       if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) {\r
         //\r
     if (FirstQuote == NULL || SecondPercent < FirstQuote) {\r
       if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) {\r
         //\r
@@ -1405,7 +1592,6 @@ StripUnreplacedEnvironmentVariables(
   @return                           The new command line with no environment variables present.\r
 **/\r
 CHAR16*\r
   @return                           The new command line with no environment variables present.\r
 **/\r
 CHAR16*\r
-EFIAPI\r
 ShellConvertVariables (\r
   IN CONST CHAR16 *OriginalCommandLine\r
   )\r
 ShellConvertVariables (\r
   IN CONST CHAR16 *OriginalCommandLine\r
   )\r
@@ -1475,7 +1661,7 @@ ShellConvertVariables (
   //\r
   // now do the replacements...\r
   //\r
   //\r
   // now do the replacements...\r
   //\r
-  NewCommandLine1 = AllocateCopyPool(NewSize, OriginalCommandLine);\r
+  NewCommandLine1 = AllocateZeroPool (NewSize);\r
   NewCommandLine2 = AllocateZeroPool(NewSize);\r
   ItemTemp        = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16)));\r
   if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) {\r
   NewCommandLine2 = AllocateZeroPool(NewSize);\r
   ItemTemp        = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16)));\r
   if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) {\r
@@ -1484,20 +1670,22 @@ ShellConvertVariables (
     SHELL_FREE_NON_NULL(ItemTemp);\r
     return (NULL);\r
   }\r
     SHELL_FREE_NON_NULL(ItemTemp);\r
     return (NULL);\r
   }\r
+  CopyMem (NewCommandLine1, OriginalCommandLine, StrSize (OriginalCommandLine));\r
+\r
   for (MasterEnvList = EfiShellGetEnv(NULL)\r
     ;  MasterEnvList != NULL && *MasterEnvList != CHAR_NULL\r
     ;  MasterEnvList += StrLen(MasterEnvList) + 1\r
    ){\r
   for (MasterEnvList = EfiShellGetEnv(NULL)\r
     ;  MasterEnvList != NULL && *MasterEnvList != CHAR_NULL\r
     ;  MasterEnvList += StrLen(MasterEnvList) + 1\r
    ){\r
-    StrCpyS( ItemTemp, \r
-              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+    StrCpyS( ItemTemp,\r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),\r
               L"%"\r
               );\r
               L"%"\r
               );\r
-    StrCatS( ItemTemp, \r
-              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+    StrCatS( ItemTemp,\r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),\r
               MasterEnvList\r
               );\r
               MasterEnvList\r
               );\r
-    StrCatS( ItemTemp, \r
-              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+    StrCatS( ItemTemp,\r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),\r
               L"%"\r
               );\r
     ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);\r
               L"%"\r
               );\r
     ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);\r
@@ -1523,7 +1711,7 @@ ShellConvertVariables (
   //\r
   ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);\r
   StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
   //\r
   ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);\r
   StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
-  \r
+\r
   FreePool(NewCommandLine2);\r
   FreePool(ItemTemp);\r
 \r
   FreePool(NewCommandLine2);\r
   FreePool(ItemTemp);\r
 \r
@@ -1541,11 +1729,10 @@ ShellConvertVariables (
   @retval other             Some error occurs when executing the split command.\r
 **/\r
 EFI_STATUS\r
   @retval other             Some error occurs when executing the split command.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 RunSplitCommand(\r
   IN CONST CHAR16             *CmdLine,\r
 RunSplitCommand(\r
   IN CONST CHAR16             *CmdLine,\r
-  IN       SHELL_FILE_HANDLE  *StdIn,\r
-  IN       SHELL_FILE_HANDLE  *StdOut\r
+  IN       SHELL_FILE_HANDLE  StdIn,\r
+  IN       SHELL_FILE_HANDLE  StdOut\r
   )\r
 {\r
   EFI_STATUS        Status;\r
   )\r
 {\r
   EFI_STATUS        Status;\r
@@ -1554,7 +1741,7 @@ RunSplitCommand(
   UINTN             Size1;\r
   UINTN             Size2;\r
   SPLIT_LIST        *Split;\r
   UINTN             Size1;\r
   UINTN             Size2;\r
   SPLIT_LIST        *Split;\r
-  SHELL_FILE_HANDLE *TempFileHandle;\r
+  SHELL_FILE_HANDLE TempFileHandle;\r
   BOOLEAN           Unicode;\r
 \r
   ASSERT(StdOut == NULL);\r
   BOOLEAN           Unicode;\r
 \r
   ASSERT(StdOut == NULL);\r
@@ -1600,7 +1787,9 @@ RunSplitCommand(
   // make a SPLIT_LIST item and add to list\r
   //\r
   Split = AllocateZeroPool(sizeof(SPLIT_LIST));\r
   // make a SPLIT_LIST item and add to list\r
   //\r
   Split = AllocateZeroPool(sizeof(SPLIT_LIST));\r
-  ASSERT(Split != NULL);\r
+  if (Split == NULL) {\r
+    return EFI_OUT_OF_RESOURCES;\r
+  }\r
   Split->SplitStdIn   = StdIn;\r
   Split->SplitStdOut  = ConvertEfiFileProtocolToShellHandle(CreateFileInterfaceMem(Unicode), NULL);\r
   ASSERT(Split->SplitStdOut != NULL);\r
   Split->SplitStdIn   = StdIn;\r
   Split->SplitStdOut  = ConvertEfiFileProtocolToShellHandle(CreateFileInterfaceMem(Unicode), NULL);\r
   ASSERT(Split->SplitStdOut != NULL);\r
@@ -1618,7 +1807,7 @@ RunSplitCommand(
     Split->SplitStdOut  = Split->SplitStdIn;\r
   }\r
   Split->SplitStdIn   = TempFileHandle;\r
     Split->SplitStdOut  = Split->SplitStdIn;\r
   }\r
   Split->SplitStdIn   = TempFileHandle;\r
-  ShellInfoObject.NewEfiShellProtocol->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn), 0);\r
+  ShellInfoObject.NewEfiShellProtocol->SetFilePosition (Split->SplitStdIn, 0);\r
 \r
   if (!EFI_ERROR(Status)) {\r
     Status = RunCommand(NextCommandLine);\r
 \r
   if (!EFI_ERROR(Status)) {\r
     Status = RunCommand(NextCommandLine);\r
@@ -1633,11 +1822,11 @@ RunSplitCommand(
   //\r
   // Note that the original StdIn is now the StdOut...\r
   //\r
   //\r
   // Note that the original StdIn is now the StdOut...\r
   //\r
-  if (Split->SplitStdOut != NULL && Split->SplitStdOut != StdIn) {\r
-    ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdOut));\r
+  if (Split->SplitStdOut != NULL) {\r
+    ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdOut);\r
   }\r
   if (Split->SplitStdIn != NULL) {\r
   }\r
   if (Split->SplitStdIn != NULL) {\r
-    ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn));\r
+    ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdIn);\r
   }\r
 \r
   FreePool(Split);\r
   }\r
 \r
   FreePool(Split);\r
@@ -1648,7 +1837,7 @@ RunSplitCommand(
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Take the original command line, substitute any variables, free \r
+  Take the original command line, substitute any variables, free\r
   the original string, return the modified copy.\r
 \r
   @param[in] CmdLine  pointer to the command line to update.\r
   the original string, return the modified copy.\r
 \r
   @param[in] CmdLine  pointer to the command line to update.\r
@@ -1657,7 +1846,6 @@ RunSplitCommand(
   @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellSubstituteVariables(\r
   IN CHAR16 **CmdLine\r
   )\r
 ShellSubstituteVariables(\r
   IN CHAR16 **CmdLine\r
   )\r
@@ -1673,7 +1861,7 @@ ShellSubstituteVariables(
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
-  Take the original command line, substitute any alias in the first group of space delimited characters, free \r
+  Take the original command line, substitute any alias in the first group of space delimited characters, free\r
   the original string, return the modified copy.\r
 \r
   @param[in] CmdLine  pointer to the command line to update.\r
   the original string, return the modified copy.\r
 \r
   @param[in] CmdLine  pointer to the command line to update.\r
@@ -1682,7 +1870,6 @@ ShellSubstituteVariables(
   @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellSubstituteAliases(\r
   IN CHAR16 **CmdLine\r
   )\r
 ShellSubstituteAliases(\r
   IN CHAR16 **CmdLine\r
   )\r
@@ -1733,7 +1920,7 @@ ShellSubstituteAliases(
 \r
   SHELL_FREE_NON_NULL(*CmdLine);\r
   SHELL_FREE_NON_NULL(CommandName);\r
 \r
   SHELL_FREE_NON_NULL(*CmdLine);\r
   SHELL_FREE_NON_NULL(CommandName);\r
\r
+\r
   //\r
   // re-assign the passed in double pointer to point to our newly allocated buffer\r
   //\r
   //\r
   // re-assign the passed in double pointer to point to our newly allocated buffer\r
   //\r
@@ -1746,7 +1933,7 @@ ShellSubstituteAliases(
   Takes the Argv[0] part of the command line and determine the meaning of it.\r
 \r
   @param[in] CmdName  pointer to the command line to update.\r
   Takes the Argv[0] part of the command line and determine the meaning of it.\r
 \r
   @param[in] CmdName  pointer to the command line to update.\r
-  \r
+\r
   @retval Internal_Command    The name is an internal command.\r
   @retval File_Sys_Change     the name is a file system change.\r
   @retval Script_File_Name    the name is a NSH script file.\r
   @retval Internal_Command    The name is an internal command.\r
   @retval File_Sys_Change     the name is a file system change.\r
   @retval Script_File_Name    the name is a NSH script file.\r
@@ -1754,7 +1941,6 @@ ShellSubstituteAliases(
   @retval Efi_Application     the name is an application (.EFI).\r
 **/\r
 SHELL_OPERATION_TYPES\r
   @retval Efi_Application     the name is an application (.EFI).\r
 **/\r
 SHELL_OPERATION_TYPES\r
-EFIAPI\r
 GetOperationType(\r
   IN CONST CHAR16 *CmdName\r
   )\r
 GetOperationType(\r
   IN CONST CHAR16 *CmdName\r
   )\r
@@ -1775,7 +1961,7 @@ GetOperationType(
   // Test for file system change request.  anything ending with first : and cant have spaces.\r
   //\r
   if (CmdName[(StrLen(CmdName)-1)] == L':') {\r
   // Test for file system change request.  anything ending with first : and cant have spaces.\r
   //\r
   if (CmdName[(StrLen(CmdName)-1)] == L':') {\r
-    if ( StrStr(CmdName, L" ") != NULL \r
+    if ( StrStr(CmdName, L" ") != NULL\r
       || StrLen(StrStr(CmdName, L":")) > 1\r
       ) {\r
       return (Unknown_Invalid);\r
       || StrLen(StrStr(CmdName, L":")) > 1\r
       ) {\r
       return (Unknown_Invalid);\r
@@ -1805,7 +1991,7 @@ GetOperationType(
     SHELL_FREE_NON_NULL(FileWithPath);\r
     return (Efi_Application);\r
   }\r
     SHELL_FREE_NON_NULL(FileWithPath);\r
     return (Efi_Application);\r
   }\r
-  \r
+\r
   SHELL_FREE_NON_NULL(FileWithPath);\r
   //\r
   // No clue what this is... return invalid flag...\r
   SHELL_FREE_NON_NULL(FileWithPath);\r
   //\r
   // No clue what this is... return invalid flag...\r
@@ -1822,8 +2008,7 @@ GetOperationType(
   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
   @retval EFI_NOT_FOUND         The operation type is unknown or invalid.\r
 **/\r
   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
   @retval EFI_NOT_FOUND         The operation type is unknown or invalid.\r
 **/\r
-EFI_STATUS \r
-EFIAPI\r
+EFI_STATUS\r
 IsValidSplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
 IsValidSplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -1859,7 +2044,7 @@ IsValidSplit(
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
     TempWalker = (CHAR16*)Temp;\r
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
     TempWalker = (CHAR16*)Temp;\r
-    if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine)))) {\r
+    if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine), TRUE))) {\r
       if (GetOperationType(FirstParameter) == Unknown_Invalid) {\r
         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
         SetLastError(SHELL_NOT_FOUND);\r
       if (GetOperationType(FirstParameter) == Unknown_Invalid) {\r
         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
         SetLastError(SHELL_NOT_FOUND);\r
@@ -1882,7 +2067,6 @@ IsValidSplit(
   @retval EFI_ABORTED     CmdLine has at least one invalid command or application.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_ABORTED     CmdLine has at least one invalid command or application.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 VerifySplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
 VerifySplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -1909,13 +2093,13 @@ VerifySplit(
   // recurse to verify the next item\r
   //\r
   TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;\r
   // recurse to verify the next item\r
   //\r
   TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;\r
-  if (*TempSpot == L'a' && \r
+  if (*TempSpot == L'a' &&\r
       (*(TempSpot + 1) == L' ' || *(TempSpot + 1) == CHAR_NULL)\r
      ) {\r
     // If it's an ASCII pipe '|a'\r
     TempSpot += 1;\r
   }\r
       (*(TempSpot + 1) == L' ' || *(TempSpot + 1) == CHAR_NULL)\r
      ) {\r
     // If it's an ASCII pipe '|a'\r
     TempSpot += 1;\r
   }\r
-  \r
+\r
   return (VerifySplit(TempSpot));\r
 }\r
 \r
   return (VerifySplit(TempSpot));\r
 }\r
 \r
@@ -1928,7 +2112,6 @@ VerifySplit(
   @return               an error occurred.\r
 **/\r
 EFI_STATUS\r
   @return               an error occurred.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ProcessNewSplitCommandLine(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
 ProcessNewSplitCommandLine(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -1969,7 +2152,6 @@ ProcessNewSplitCommandLine(
   @retval EFI_SUCCESS The operation was successful.\r
 **/\r
 EFI_STATUS\r
   @retval EFI_SUCCESS The operation was successful.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ChangeMappedDrive(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
 ChangeMappedDrive(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -1981,7 +2163,7 @@ ChangeMappedDrive(
   // make sure we are the right operation\r
   //\r
   ASSERT(CmdLine[(StrLen(CmdLine)-1)] == L':' && StrStr(CmdLine, L" ") == NULL);\r
   // make sure we are the right operation\r
   //\r
   ASSERT(CmdLine[(StrLen(CmdLine)-1)] == L':' && StrStr(CmdLine, L" ") == NULL);\r
-  \r
+\r
   //\r
   // Call the protocol API to do the work\r
   //\r
   //\r
   // Call the protocol API to do the work\r
   //\r
@@ -2005,7 +2187,6 @@ ChangeMappedDrive(
   @param[in,out] CmdLine        pointer to the command line to update\r
 **/\r
 EFI_STATUS\r
   @param[in,out] CmdLine        pointer to the command line to update\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 DoHelpUpdate(\r
   IN OUT CHAR16 **CmdLine\r
   )\r
 DoHelpUpdate(\r
   IN OUT CHAR16 **CmdLine\r
   )\r
@@ -2025,7 +2206,7 @@ DoHelpUpdate(
 \r
   Walker = *CmdLine;\r
   while(Walker != NULL && *Walker != CHAR_NULL) {\r
 \r
   Walker = *CmdLine;\r
   while(Walker != NULL && *Walker != CHAR_NULL) {\r
-    if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine)))) {\r
+    if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine), TRUE))) {\r
       if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {\r
         CurrentParameter[0] = L' ';\r
         CurrentParameter[1] = L' ';\r
       if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {\r
         CurrentParameter[0] = L' ';\r
         CurrentParameter[1] = L' ';\r
@@ -2059,7 +2240,6 @@ DoHelpUpdate(
   @param[in] ErrorCode      the error code to put into lasterror.\r
 **/\r
 EFI_STATUS\r
   @param[in] ErrorCode      the error code to put into lasterror.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 SetLastError(\r
   IN CONST SHELL_STATUS   ErrorCode\r
   )\r
 SetLastError(\r
   IN CONST SHELL_STATUS   ErrorCode\r
   )\r
@@ -2086,7 +2266,6 @@ SetLastError(
   @return                       some other error occurred\r
 **/\r
 EFI_STATUS\r
   @return                       some other error occurred\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ProcessCommandLineToFinal(\r
   IN OUT CHAR16 **CmdLine\r
   )\r
 ProcessCommandLineToFinal(\r
   IN OUT CHAR16 **CmdLine\r
   )\r
@@ -2129,20 +2308,21 @@ ProcessCommandLineToFinal(
   Run an internal shell command.\r
 \r
   This API will update the shell's environment since these commands are libraries.\r
   Run an internal shell command.\r
 \r
   This API will update the shell's environment since these commands are libraries.\r
-  \r
+\r
   @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[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
 **/\r
 EFI_STATUS\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
 RunInternalCommand(\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
 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
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2151,7 +2331,7 @@ RunInternalCommand(
   SHELL_STATUS              CommandReturnedStatus;\r
   BOOLEAN                   LastError;\r
   CHAR16                    *Walker;\r
   SHELL_STATUS              CommandReturnedStatus;\r
   BOOLEAN                   LastError;\r
   CHAR16                    *Walker;\r
-  CHAR16                    *NewCmdLine;  \r
+  CHAR16                    *NewCmdLine;\r
 \r
   NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine);\r
   if (NewCmdLine == NULL) {\r
 \r
   NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine);\r
   if (NewCmdLine == NULL) {\r
@@ -2167,7 +2347,7 @@ RunInternalCommand(
   //\r
   // get the argc and argv updated for internal commands\r
   //\r
   //\r
   // get the argc and argv updated for internal commands\r
   //\r
-  Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, &Argv, &Argc);\r
+  Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, Internal_Command, &Argv, &Argc);\r
   if (!EFI_ERROR(Status)) {\r
     //\r
     // Run the internal command.\r
   if (!EFI_ERROR(Status)) {\r
     //\r
     // Run the internal command.\r
@@ -2175,6 +2355,14 @@ RunInternalCommand(
     Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError);\r
 \r
     if (!EFI_ERROR(Status)) {\r
     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
       //\r
       // Update last error status.\r
       // some commands do not update last error.\r
@@ -2236,22 +2424,24 @@ 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[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
 **/\r
 EFI_STATUS\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
 RunCommandOrFile(\r
   IN       SHELL_OPERATION_TYPES    Type,\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
 RunCommandOrFile(\r
   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
   EFI_STATUS                StartStatus;\r
   CHAR16                    *CommandWithPath;\r
 )\r
 {\r
   EFI_STATUS                Status;\r
   EFI_STATUS                StartStatus;\r
   CHAR16                    *CommandWithPath;\r
+  CHAR16                    *FullCommandWithPath;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   SHELL_STATUS              CalleeExitStatus;\r
 \r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   SHELL_STATUS              CalleeExitStatus;\r
 \r
@@ -2262,7 +2452,7 @@ RunCommandOrFile(
 \r
   switch (Type) {\r
     case   Internal_Command:\r
 \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
       break;\r
     case   Script_File_Name:\r
     case   Efi_Application:\r
@@ -2297,7 +2487,13 @@ RunCommandOrFile(
       }\r
       switch (Type) {\r
         case   Script_File_Name:\r
       }\r
       switch (Type) {\r
         case   Script_File_Name:\r
-          Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);\r
+          FullCommandWithPath = FullyQualifyPath(CommandWithPath);\r
+          if (FullCommandWithPath == NULL) {\r
+            Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);\r
+          } else {\r
+            Status = RunScriptFile (FullCommandWithPath, NULL, CmdLine, ParamProtocol);\r
+            FreePool(FullCommandWithPath);\r
+          }\r
           break;\r
         case   Efi_Application:\r
           //\r
           break;\r
         case   Efi_Application:\r
           //\r
@@ -2328,6 +2524,10 @@ RunCommandOrFile(
             CalleeExitStatus = (SHELL_STATUS) StartStatus;\r
           }\r
 \r
             CalleeExitStatus = (SHELL_STATUS) StartStatus;\r
           }\r
 \r
+          if (CommandStatus != NULL) {\r
+            *CommandStatus = CalleeExitStatus;\r
+          }\r
+\r
           //\r
           // Update last error status.\r
           //\r
           //\r
           // Update last error status.\r
           //\r
@@ -2360,17 +2560,18 @@ 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[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
 **/\r
 EFI_STATUS\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
 SetupAndRunCommandOrFile(\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
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2378,6 +2579,7 @@ SetupAndRunCommandOrFile(
   SHELL_FILE_HANDLE         OriginalStdOut;\r
   SHELL_FILE_HANDLE         OriginalStdErr;\r
   SYSTEM_TABLE_INFO         OriginalSystemTableInfo;\r
   SHELL_FILE_HANDLE         OriginalStdOut;\r
   SHELL_FILE_HANDLE         OriginalStdErr;\r
   SYSTEM_TABLE_INFO         OriginalSystemTableInfo;\r
+  CONST SCRIPT_FILE         *ConstScriptFile;\r
 \r
   //\r
   // Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII\r
 \r
   //\r
   // Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII\r
@@ -2390,14 +2592,19 @@ SetupAndRunCommandOrFile(
   //\r
   if (!EFI_ERROR(Status)) {\r
     TrimSpaces(&CmdLine);\r
   //\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
   // Now print errors\r
   //\r
   if (EFI_ERROR(Status)) {\r
   }\r
 \r
   //\r
   // Now print errors\r
   //\r
   if (EFI_ERROR(Status)) {\r
-    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status));\r
+    ConstScriptFile = ShellCommandGetCurrentScriptFile();\r
+    if (ConstScriptFile == NULL || ConstScriptFile->CurrentCommand == NULL) {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status));\r
+    } else {\r
+      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR_SCRIPT), ShellInfoObject.HiiHandle, (VOID*)(Status), ConstScriptFile->CurrentCommand->Line);\r
+    }\r
   }\r
 \r
   //\r
   }\r
 \r
   //\r
@@ -2411,18 +2618,19 @@ SetupAndRunCommandOrFile(
 /**\r
   Function will process and run a command line.\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
+  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
   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
 \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
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2430,6 +2638,7 @@ RunCommand(
   CHAR16                    *FirstParameter;\r
   CHAR16                    *TempWalker;\r
   SHELL_OPERATION_TYPES     Type;\r
   CHAR16                    *FirstParameter;\r
   CHAR16                    *TempWalker;\r
   SHELL_OPERATION_TYPES     Type;\r
+  CONST CHAR16              *CurDir;\r
 \r
   ASSERT(CmdLine != NULL);\r
   if (StrLen(CmdLine) == 0) {\r
 \r
   ASSERT(CmdLine != NULL);\r
   if (StrLen(CmdLine) == 0) {\r
@@ -2485,7 +2694,7 @@ RunCommand(
     Status = ProcessNewSplitCommandLine(CleanOriginal);\r
     SHELL_FREE_NON_NULL(CleanOriginal);\r
     return (Status);\r
     Status = ProcessNewSplitCommandLine(CleanOriginal);\r
     SHELL_FREE_NON_NULL(CleanOriginal);\r
     return (Status);\r
-  } \r
+  }\r
 \r
   //\r
   // We need the first parameter information so we can determine the operation type\r
 \r
   //\r
   // We need the first parameter information so we can determine the operation type\r
@@ -2496,7 +2705,7 @@ RunCommand(
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
   TempWalker = CleanOriginal;\r
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
   TempWalker = CleanOriginal;\r
-  if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal)))) {\r
+  if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal), TRUE))) {\r
     //\r
     // Depending on the first parameter we change the behavior\r
     //\r
     //\r
     // Depending on the first parameter we change the behavior\r
     //\r
@@ -2507,7 +2716,7 @@ RunCommand(
       case   Internal_Command:\r
       case   Script_File_Name:\r
       case   Efi_Application:\r
       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
         break;\r
       default:\r
         //\r
@@ -2521,43 +2730,45 @@ RunCommand(
     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
     SetLastError(SHELL_NOT_FOUND);\r
   }\r
     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
     SetLastError(SHELL_NOT_FOUND);\r
   }\r
\r
+  //\r
+  // Check whether the current file system still exists. If not exist, we need update "cwd" and gShellCurMapping.\r
+  //\r
+  CurDir = EfiShellGetCurDir (NULL);\r
+  if (CurDir != NULL) {\r
+    if (EFI_ERROR(ShellFileExists (CurDir))) {\r
+      //\r
+      // EfiShellSetCurDir() cannot set current directory to NULL.\r
+      // EfiShellSetEnv() is not allowed to set the "cwd" variable.\r
+      // Only InternalEfiShellSetEnv () is allowed setting the "cwd" variable.\r
+      //\r
+      InternalEfiShellSetEnv (L"cwd", NULL, TRUE);\r
+      gShellCurMapping = NULL;\r
+    }\r
+  }\r
+\r
   SHELL_FREE_NON_NULL(CleanOriginal);\r
   SHELL_FREE_NON_NULL(FirstParameter);\r
 \r
   return (Status);\r
 }\r
 \r
   SHELL_FREE_NON_NULL(CleanOriginal);\r
   SHELL_FREE_NON_NULL(FirstParameter);\r
 \r
   return (Status);\r
 }\r
 \r
-STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};\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
+  Function will process and run a command line.\r
 \r
 \r
-  @param[in] CommandName    The name to check\r
+  This will determine if the command line represents an internal shell\r
+  command or dispatch an external application.\r
 \r
 \r
-  @retval TRUE              CommandName could be a command name\r
-  @retval FALSE             CommandName could not be a valid command name\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
 **/\r
-BOOLEAN\r
-EFIAPI\r
-IsValidCommandName(\r
-  IN CONST CHAR16     *CommandName\r
+EFI_STATUS\r
+RunCommand(\r
+  IN CONST CHAR16   *CmdLine\r
   )\r
 {\r
   )\r
 {\r
-  UINTN Count;\r
-  if (CommandName == NULL) {\r
-    ASSERT(FALSE);\r
-    return (FALSE);\r
-  }\r
-  for ( Count = 0\r
-      ; Count < sizeof(InvalidChars) / sizeof(InvalidChars[0])\r
-      ; Count++\r
-     ){\r
-    if (ScanMem16(CommandName, StrSize(CommandName), InvalidChars[Count]) != NULL) {\r
-      return (FALSE);\r
-    }\r
-  }\r
-  return (TRUE);\r
+  return (RunShellCommand(CmdLine, NULL));\r
 }\r
 \r
 /**\r
 }\r
 \r
 /**\r
@@ -2569,7 +2780,6 @@ IsValidCommandName(
   @retval EFI_SUCCESS           the script completed successfully\r
 **/\r
 EFI_STATUS\r
   @retval EFI_SUCCESS           the script completed successfully\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 RunScriptFileHandle (\r
   IN SHELL_FILE_HANDLE  Handle,\r
   IN CONST CHAR16       *Name\r
 RunScriptFileHandle (\r
   IN SHELL_FILE_HANDLE  Handle,\r
   IN CONST CHAR16       *Name\r
@@ -2589,6 +2799,7 @@ RunScriptFileHandle (
   CONST CHAR16        *CurDir;\r
   UINTN               LineCount;\r
   CHAR16              LeString[50];\r
   CONST CHAR16        *CurDir;\r
   UINTN               LineCount;\r
   CHAR16              LeString[50];\r
+  LIST_ENTRY          OldBufferList;\r
 \r
   ASSERT(!ShellCommandGetScriptExit());\r
 \r
 \r
   ASSERT(!ShellCommandGetScriptExit());\r
 \r
@@ -2620,7 +2831,12 @@ RunScriptFileHandle (
       DeleteScriptFileStruct(NewScriptFile);\r
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
       DeleteScriptFileStruct(NewScriptFile);\r
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
-    for (LoopVar = 0 ; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) {\r
+    //\r
+    // Put the full path of the script file into Argv[0] as required by section\r
+    // 3.6.2 of version 2.2 of the shell specification.\r
+    //\r
+    NewScriptFile->Argv[0] = StrnCatGrow(&NewScriptFile->Argv[0], NULL, NewScriptFile->ScriptName, 0);\r
+    for (LoopVar = 1 ; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) {\r
       ASSERT(NewScriptFile->Argv[LoopVar] == NULL);\r
       NewScriptFile->Argv[LoopVar] = StrnCatGrow(&NewScriptFile->Argv[LoopVar], NULL, ShellInfoObject.NewShellParametersProtocol->Argv[LoopVar], 0);\r
       if (NewScriptFile->Argv[LoopVar] == NULL) {\r
       ASSERT(NewScriptFile->Argv[LoopVar] == NULL);\r
       NewScriptFile->Argv[LoopVar] = StrnCatGrow(&NewScriptFile->Argv[LoopVar], NULL, ShellInfoObject.NewShellParametersProtocol->Argv[LoopVar], 0);\r
       if (NewScriptFile->Argv[LoopVar] == NULL) {\r
@@ -2685,12 +2901,14 @@ RunScriptFileHandle (
       ; // conditional increment in the body of the loop\r
   ){\r
     ASSERT(CommandLine2 != NULL);\r
       ; // conditional increment in the body of the loop\r
   ){\r
     ASSERT(CommandLine2 != NULL);\r
-    StrnCpyS( CommandLine2, \r
-              PrintBuffSize/sizeof(CHAR16), \r
+    StrnCpyS( CommandLine2,\r
+              PrintBuffSize/sizeof(CHAR16),\r
               NewScriptFile->CurrentCommand->Cl,\r
               PrintBuffSize/sizeof(CHAR16) - 1\r
               );\r
 \r
               NewScriptFile->CurrentCommand->Cl,\r
               PrintBuffSize/sizeof(CHAR16) - 1\r
               );\r
 \r
+    SaveBufferList(&OldBufferList);\r
+\r
     //\r
     // NULL out comments\r
     //\r
     //\r
     // NULL out comments\r
     //\r
@@ -2710,8 +2928,8 @@ RunScriptFileHandle (
       //\r
       // Due to variability in starting the find and replace action we need to have both buffers the same.\r
       //\r
       //\r
       // Due to variability in starting the find and replace action we need to have both buffers the same.\r
       //\r
-      StrnCpyS( CommandLine, \r
-                PrintBuffSize/sizeof(CHAR16), \r
+      StrnCpyS( CommandLine,\r
+                PrintBuffSize/sizeof(CHAR16),\r
                 CommandLine2,\r
                 PrintBuffSize/sizeof(CHAR16) - 1\r
                 );\r
                 CommandLine2,\r
                 PrintBuffSize/sizeof(CHAR16) - 1\r
                 );\r
@@ -2722,34 +2940,34 @@ RunScriptFileHandle (
       if (NewScriptFile->Argv != NULL) {\r
         switch (NewScriptFile->Argc) {\r
           default:\r
       if (NewScriptFile->Argv != NULL) {\r
         switch (NewScriptFile->Argc) {\r
           default:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 9:\r
             ASSERT_EFI_ERROR(Status);\r
           case 9:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 8:\r
             ASSERT_EFI_ERROR(Status);\r
           case 8:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 7:\r
             ASSERT_EFI_ERROR(Status);\r
           case 7:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 6:\r
             ASSERT_EFI_ERROR(Status);\r
           case 6:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 5:\r
             ASSERT_EFI_ERROR(Status);\r
           case 5:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 4:\r
             ASSERT_EFI_ERROR(Status);\r
           case 4:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 3:\r
             ASSERT_EFI_ERROR(Status);\r
           case 3:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 2:\r
             ASSERT_EFI_ERROR(Status);\r
           case 2:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 1:\r
             ASSERT_EFI_ERROR(Status);\r
           case 1:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, TRUE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
             break;\r
           case 0:\r
             ASSERT_EFI_ERROR(Status);\r
             break;\r
           case 0:\r
@@ -2766,8 +2984,8 @@ RunScriptFileHandle (
       Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%8", L"\"\"", FALSE, FALSE);\r
       Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%9", L"\"\"", FALSE, FALSE);\r
 \r
       Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%8", L"\"\"", FALSE, FALSE);\r
       Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%9", L"\"\"", FALSE, FALSE);\r
 \r
-      StrnCpyS( CommandLine2, \r
-                PrintBuffSize/sizeof(CHAR16), \r
+      StrnCpyS( CommandLine2,\r
+                PrintBuffSize/sizeof(CHAR16),\r
                 CommandLine,\r
                 PrintBuffSize/sizeof(CHAR16) - 1\r
                 );\r
                 CommandLine,\r
                 PrintBuffSize/sizeof(CHAR16) - 1\r
                 );\r
@@ -2825,15 +3043,19 @@ RunScriptFileHandle (
 \r
           ShellCommandRegisterExit(FALSE, 0);\r
           Status = EFI_SUCCESS;\r
 \r
           ShellCommandRegisterExit(FALSE, 0);\r
           Status = EFI_SUCCESS;\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
         if (ShellGetExecutionBreakFlag()) {\r
           break;\r
         }\r
         if (ShellGetExecutionBreakFlag()) {\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
         if (EFI_ERROR(Status)) {\r
           break;\r
         }\r
         if (EFI_ERROR(Status)) {\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
         if (ShellCommandGetExit()) {\r
           break;\r
         }\r
         if (ShellCommandGetExit()) {\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
       }\r
           break;\r
         }\r
       }\r
@@ -2852,6 +3074,7 @@ RunScriptFileHandle (
         NewScriptFile->CurrentCommand->Reset = TRUE;\r
       }\r
     }\r
         NewScriptFile->CurrentCommand->Reset = TRUE;\r
       }\r
     }\r
+    RestoreBufferList(&OldBufferList);\r
   }\r
 \r
 \r
   }\r
 \r
 \r
@@ -2879,7 +3102,6 @@ RunScriptFileHandle (
   @retval EFI_SUCCESS           the script completed successfully\r
 **/\r
 EFI_STATUS\r
   @retval EFI_SUCCESS           the script completed successfully\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 RunScriptFile (\r
   IN CONST CHAR16                   *ScriptPath,\r
   IN SHELL_FILE_HANDLE              Handle OPTIONAL,\r
 RunScriptFile (\r
   IN CONST CHAR16                   *ScriptPath,\r
   IN SHELL_FILE_HANDLE              Handle OPTIONAL,\r
@@ -2899,7 +3121,7 @@ RunScriptFile (
   //\r
   // get the argc and argv updated for scripts\r
   //\r
   //\r
   // get the argc and argv updated for scripts\r
   //\r
-  Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc);\r
+  Status = UpdateArgcArgv(ParamProtocol, CmdLine, Script_File_Name, &Argv, &Argc);\r
   if (!EFI_ERROR(Status)) {\r
 \r
     if (Handle == NULL) {\r
   if (!EFI_ERROR(Status)) {\r
 \r
     if (Handle == NULL) {\r
@@ -2943,7 +3165,6 @@ RunScriptFile (
   @retval CHAR_NULL no instance of any character in CharacterList was found in String\r
 **/\r
 CONST CHAR16*\r
   @retval CHAR_NULL no instance of any character in CharacterList was found in String\r
 **/\r
 CONST CHAR16*\r
-EFIAPI\r
 FindFirstCharacter(\r
   IN CONST CHAR16 *String,\r
   IN CONST CHAR16 *CharacterList,\r
 FindFirstCharacter(\r
   IN CONST CHAR16 *String,\r
   IN CONST CHAR16 *CharacterList,\r