]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/Shell.c
ShellPkg: Correct files with CRLF line ending
[mirror_edk2.git] / ShellPkg / Application / Shell / Shell.c
index a570b7b1254cc32eb2c67d407eb0fb2c06053505..0f1fb9c287b83c253b40e76e979e43782055c95a 100644 (file)
@@ -1,8 +1,8 @@
 /** @file\r
   This is THE shell (application)\r
 \r
-  Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
-  (C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P.\r
+  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<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
@@ -33,6 +33,7 @@ SHELL_INFO ShellInfoObject = {
       0,\r
       0,\r
       0,\r
+      0,\r
       0\r
     }},\r
     0,\r
@@ -69,6 +70,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
+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
@@ -123,7 +127,7 @@ FindNextInstance(
   Temp = StrStr(SourceString, FindString);\r
 \r
   //\r
-  // If nothing found, or we dont care about escape characters\r
+  // If nothing found, or we don't care about escape characters\r
   //\r
   if (Temp == NULL || !CheckForEscapeCharacter) {\r
     return (Temp);\r
@@ -143,7 +147,7 @@ FindNextInstance(
 }\r
 \r
 /**\r
-  Check whether the string between a pair of % is a valid envifronment variable name.\r
+  Check whether the string between a pair of % is a valid environment variable name.\r
 \r
   @param[in] BeginPercent       pointer to the first percent.\r
   @param[in] EndPercent          pointer to the last percent.\r
@@ -189,33 +193,6 @@ IsValidEnvironmentVariableName(
   return TRUE;\r
 }\r
 \r
-/**\r
-  Find a command line contains a split operation\r
-\r
-  @param[in] CmdLine      The command line to parse.\r
-\r
-  @retval                 A pointer to the | character in CmdLine or NULL if not present.\r
-**/\r
-CONST CHAR16*\r
-EFIAPI\r
-FindSplit(\r
-  IN CONST CHAR16 *CmdLine\r
-  )\r
-{\r
-  CONST CHAR16 *TempSpot;\r
-  TempSpot = NULL;\r
-  if (StrStr(CmdLine, L"|") != NULL) {\r
-    for (TempSpot = CmdLine ; TempSpot != NULL && *TempSpot != CHAR_NULL ; TempSpot++) {\r
-      if (*TempSpot == L'^' && *(TempSpot+1) == L'|') {\r
-        TempSpot++;\r
-      } else if (*TempSpot == L'|') {\r
-        break;\r
-      }\r
-    }\r
-  }\r
-  return (TempSpot);\r
-}\r
-\r
 /**\r
   Determine if a command line contains a split operation\r
 \r
@@ -236,7 +213,7 @@ ContainsSplit(
 \r
   FirstQuote    = FindNextInstance (CmdLine, L"\"", TRUE);\r
   SecondQuote   = NULL;\r
-  TempSpot      = FindSplit(CmdLine);\r
+  TempSpot      = ShellFindFirstCharacter(CmdLine, L"|", TRUE);\r
 \r
   if (FirstQuote == NULL    || \r
       TempSpot == NULL      || \r
@@ -259,7 +236,7 @@ ContainsSplit(
       continue;\r
     } else {\r
       FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);\r
-      TempSpot = FindSplit(TempSpot + 1);\r
+      TempSpot = ShellFindFirstCharacter(TempSpot + 1, L"|", TRUE);\r
       continue;\r
     } \r
   }\r
@@ -272,7 +249,7 @@ ContainsSplit(
   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 mnemory available.\r
+  @retval EFI_OUT_OF_RESOURCES  There is not enough memory available.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -365,6 +342,7 @@ UefiMain (
   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
@@ -468,6 +446,8 @@ UefiMain (
     Status = CommandInit();\r
     ASSERT_EFI_ERROR(Status);\r
 \r
+    Status = ShellInitEnvVarList ();\r
+\r
     //\r
     // Check the command line\r
     //\r
@@ -483,6 +463,29 @@ UefiMain (
       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
@@ -673,7 +676,17 @@ FreeResources:
   }\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
@@ -702,6 +715,9 @@ FreeResources:
     DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);\r
   }\r
 \r
+  ShellFreeEnvVarList ();\r
+  ShellSetRawCmdLine (NULL);\r
+\r
   if (ShellCommandGetExit()) {\r
     return ((EFI_STATUS)ShellCommandGetExitCode());\r
   }\r
@@ -711,7 +727,7 @@ FreeResources:
 /**\r
   Sets all the alias' that were registered with the ShellCommandLib library.\r
 \r
-  @retval EFI_SUCCESS           all init commands were run sucessfully.\r
+  @retval EFI_SUCCESS           all init commands were run successfully.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -796,10 +812,10 @@ IsScriptOnlyCommand(
   loaded image protocol installed on it.  The FilePath will point to the device path\r
   for the file that was loaded.\r
 \r
-  @param[in, out] DevPath       On a sucessful return the device path to the loaded image.\r
-  @param[in, out] FilePath      On a sucessful return the device path to the file.\r
+  @param[in, out] DevPath       On a successful return the device path to the loaded image.\r
+  @param[in, out] FilePath      On a successful return the device path to the file.\r
 \r
-  @retval EFI_SUCCESS           The 2 device paths were sucessfully returned.\r
+  @retval EFI_SUCCESS           The 2 device paths were successfully returned.\r
   @retval other                 A error from gBS->HandleProtocol.\r
 \r
   @sa HandleProtocol\r
@@ -900,12 +916,19 @@ ProcessCommandLine(
   // 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
-    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
@@ -918,6 +941,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.NoNest       = FALSE;\r
   ShellInfoObject.ShellInitSettings.Delay = 5;\r
 \r
   //\r
@@ -977,6 +1001,13 @@ ProcessCommandLine(
                                  ) == 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
@@ -1006,7 +1037,7 @@ ProcessCommandLine(
                                    ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit         = TRUE;\r
     } else if (StrnCmp (L"-", CurrentArg, 1) == 0) {\r
-      // Unrecognised option\r
+      // Unrecognized option\r
       ShellPrintHiiEx(-1, -1, NULL,\r
         STRING_TOKEN (STR_GEN_PROBLEM),\r
         ShellInfoObject.HiiHandle,\r
@@ -1080,6 +1111,7 @@ DoStartupScript(
   )\r
 {\r
   EFI_STATUS                    Status;\r
+  EFI_STATUS                    CalleeStatus;\r
   UINTN                         Delay;\r
   EFI_INPUT_KEY                 Key;\r
   SHELL_FILE_HANDLE             FileHandle;\r
@@ -1106,12 +1138,15 @@ DoStartupScript(
     if (FileStringPath == NULL) {\r
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
-    StrnCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName, NewSize/sizeof(CHAR16) -1);\r
+    StrCpyS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileName);\r
     if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {\r
-      StrnCat(FileStringPath, L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
-      StrnCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\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 = RunShellCommand(FileStringPath, &CalleeStatus);\r
+    if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) {\r
+      ShellCommandRegisterExit(gEfiShellProtocol->BatchIsActive(), (UINT64)CalleeStatus);\r
     }\r
-    Status = RunCommand(FileStringPath);\r
     FreePool(FileStringPath);\r
     return (Status);\r
 \r
@@ -1194,7 +1229,7 @@ DoStartupScript(
     FileStringPath = ShellFindFilePath(mStartupScript);\r
     if (FileStringPath == NULL) {\r
       //\r
-      // we return success since we dont need to have a startup script\r
+      // we return success since we don't need to have a startup script\r
       //\r
       Status = EFI_SUCCESS;\r
       ASSERT(FileHandle == NULL);\r
@@ -1228,6 +1263,7 @@ DoShellPrompt (
   CONST CHAR16  *CurDir;\r
   UINTN         BufferSize;\r
   EFI_STATUS    Status;\r
+  LIST_ENTRY    OldBufferList;\r
 \r
   CurDir  = NULL;\r
 \r
@@ -1241,6 +1277,7 @@ DoShellPrompt (
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
+  SaveBufferList(&OldBufferList);\r
   CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
 \r
   //\r
@@ -1270,6 +1307,7 @@ DoShellPrompt (
   //\r
   // Done with this command\r
   //\r
+  RestoreBufferList(&OldBufferList);\r
   FreePool (CmdLine);\r
   return Status;\r
 }\r
@@ -1282,7 +1320,7 @@ DoShellPrompt (
 **/\r
 VOID*\r
 EFIAPI\r
-AddBufferToFreeList(\r
+AddBufferToFreeList (\r
   VOID *Buffer\r
   )\r
 {\r
@@ -1292,13 +1330,46 @@ AddBufferToFreeList(
     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
-  InsertTailList(&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);\r
+  InsertTailList (&ShellInfoObject.BufferToFreeList.Link, &BufferListEntry->Link);\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
@@ -1311,13 +1382,46 @@ AddLineToCommandHistory(
   )\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
-  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
-  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
@@ -1376,7 +1480,7 @@ StripUnreplacedEnvironmentVariables(
     SecondPercent = FirstPercent!=NULL?FindNextInstance(FirstPercent+1, L"%", TRUE):NULL;\r
     if (FirstPercent == NULL || SecondPercent == NULL) {\r
       //\r
-      // If we ever dont have 2 % we are done.\r
+      // If we ever don't have 2 % we are done.\r
       //\r
       break;\r
     }\r
@@ -1408,7 +1512,7 @@ StripUnreplacedEnvironmentVariables(
         //\r
         CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));\r
         //\r
-        // dont need to update the locator.  both % characters are gone.\r
+        // don't need to update the locator.  both % characters are gone.\r
         //\r
       } else {\r
         CurrentLocator = SecondPercent + 1;\r
@@ -1428,7 +1532,7 @@ StripUnreplacedEnvironmentVariables(
 \r
   @param[in] OriginalCommandLine    The original command line\r
 \r
-  @retval NULL                      An error ocurred.\r
+  @retval NULL                      An error occurred.\r
   @return                           The new command line with no environment variables present.\r
 **/\r
 CHAR16*\r
@@ -1469,7 +1573,7 @@ ShellConvertVariables (
         ;  Temp = StrStr(Temp+1, AliasListNode->Alias)\r
        ){\r
         //\r
-        // we need a preceeding and if there is space no ^ preceeding (if no space ignore)\r
+        // we need a preceding and if there is space no ^ preceding (if no space ignore)\r
         //\r
         if ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2)) {\r
           NewSize += StrSize(AliasListNode->CommandString);\r
@@ -1490,7 +1594,7 @@ ShellConvertVariables (
       ;  Temp = StrStr(Temp+1, MasterEnvList)\r
      ){\r
       //\r
-      // we need a preceeding and following % and if there is space no ^ preceeding (if no space ignore)\r
+      // we need a preceding and following % and if there is space no ^ preceding (if no space ignore)\r
       //\r
       if (*(Temp-1) == L'%' && *(Temp+StrLen(MasterEnvList)) == L'%' &&\r
         ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2))) {\r
@@ -1515,11 +1619,20 @@ ShellConvertVariables (
     ;  MasterEnvList != NULL && *MasterEnvList != CHAR_NULL\r
     ;  MasterEnvList += StrLen(MasterEnvList) + 1\r
    ){\r
-    StrnCpy(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1);\r
-    StrnCat(ItemTemp, MasterEnvList, ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp));\r
-    StrnCat(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp));\r
+    StrCpyS( ItemTemp, \r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+              L"%"\r
+              );\r
+    StrCatS( ItemTemp, \r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+              MasterEnvList\r
+              );\r
+    StrCatS( ItemTemp, \r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+              L"%"\r
+              );\r
     ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);\r
-    StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);\r
+    StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
   }\r
   if (CurrentScriptFile != NULL) {\r
     for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList)\r
@@ -1527,12 +1640,12 @@ ShellConvertVariables (
       ;  AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link)\r
    ){\r
     ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);\r
-    StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);\r
+    StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
     }\r
   }\r
 \r
   //\r
-  // Remove non-existant environment variables\r
+  // Remove non-existent environment variables\r
   //\r
   StripUnreplacedEnvironmentVariables(NewCommandLine1);\r
 \r
@@ -1540,7 +1653,7 @@ ShellConvertVariables (
   // Now cleanup any straggler intentionally ignored "%" characters\r
   //\r
   ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);\r
-  StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);\r
+  StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
   \r
   FreePool(NewCommandLine2);\r
   FreePool(ItemTemp);\r
@@ -1596,11 +1709,18 @@ RunSplitCommand(
     SHELL_FREE_NON_NULL(OurCommandLine);\r
     SHELL_FREE_NON_NULL(NextCommandLine);\r
     return (EFI_INVALID_PARAMETER);\r
-  } else if (NextCommandLine[0] != CHAR_NULL &&\r
-      NextCommandLine[0] == L'a' &&\r
-      NextCommandLine[1] == L' '\r
-     ){\r
+  } else if (NextCommandLine[0] == L'a' &&\r
+             (NextCommandLine[1] == L' ' || NextCommandLine[1] == CHAR_NULL)\r
+            ){\r
     CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));\r
+    while (NextCommandLine[0] == L' ') {\r
+      CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));\r
+    }\r
+    if (NextCommandLine[0] == CHAR_NULL) {\r
+      SHELL_FREE_NON_NULL(OurCommandLine);\r
+      SHELL_FREE_NON_NULL(NextCommandLine);\r
+      return (EFI_INVALID_PARAMETER);\r
+    }\r
     Unicode = FALSE;\r
   } else {\r
     Unicode = TRUE;\r
@@ -1611,7 +1731,9 @@ RunSplitCommand(
   // 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
@@ -1644,11 +1766,12 @@ RunSplitCommand(
   //\r
   // Note that the original StdIn is now the StdOut...\r
   //\r
-  if (Split->SplitStdOut != NULL && Split->SplitStdOut != StdIn) {\r
+  if (Split->SplitStdOut != NULL) {\r
     ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdOut));\r
   }\r
   if (Split->SplitStdIn != NULL) {\r
     ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn));\r
+    FreePool (Split->SplitStdIn);\r
   }\r
 \r
   FreePool(Split);\r
@@ -1870,12 +1993,12 @@ IsValidSplit(
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
     TempWalker = (CHAR16*)Temp;\r
-    GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine));\r
-\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
-      Status = EFI_NOT_FOUND;\r
+    if (!EFI_ERROR (ShellGetNextParameter (&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
+        Status = EFI_NOT_FOUND;\r
+      }\r
     }\r
   }\r
 \r
@@ -1902,24 +2025,31 @@ VerifySplit(
   EFI_STATUS    Status;\r
 \r
   //\r
-  // Verify up to the pipe or end character\r
+  // If this was the only item, then get out\r
   //\r
-  Status = IsValidSplit(CmdLine);\r
-  if (EFI_ERROR(Status)) {\r
-    return (Status);\r
+  if (!ContainsSplit(CmdLine)) {\r
+    return (EFI_SUCCESS);\r
   }\r
 \r
   //\r
-  // If this was the only item, then get out\r
+  // Verify up to the pipe or end character\r
   //\r
-  if (!ContainsSplit(CmdLine)) {\r
-    return (EFI_SUCCESS);\r
+  Status = IsValidSplit(CmdLine);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
   }\r
 \r
   //\r
   // recurse to verify the next item\r
   //\r
-  TempSpot = FindSplit(CmdLine)+1;\r
+  TempSpot = ShellFindFirstCharacter(CmdLine, L"|", TRUE) + 1;\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
+  \r
   return (VerifySplit(TempSpot));\r
 }\r
 \r
@@ -1929,7 +2059,7 @@ VerifySplit(
   @param[in] CmdLine    pointer to the command line to process\r
 \r
   @retval EFI_SUCCESS   The operation was successful\r
-  @return               an error occured.\r
+  @return               an error occurred.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2016,9 +2146,9 @@ DoHelpUpdate(
 {\r
   CHAR16 *CurrentParameter;\r
   CHAR16 *Walker;\r
-  CHAR16 *LastWalker;\r
   CHAR16 *NewCommandLine;\r
   EFI_STATUS Status;\r
+  UINTN  NewCmdLineSize;\r
 \r
   Status = EFI_SUCCESS;\r
 \r
@@ -2029,25 +2159,26 @@ DoHelpUpdate(
 \r
   Walker = *CmdLine;\r
   while(Walker != NULL && *Walker != CHAR_NULL) {\r
-    LastWalker = Walker;\r
-    GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine));\r
-    if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {\r
-      LastWalker[0] = L' ';\r
-      LastWalker[1] = L' ';\r
-      NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine));\r
-      if (NewCommandLine == NULL) {\r
-        Status = EFI_OUT_OF_RESOURCES;\r
+    if (!EFI_ERROR (ShellGetNextParameter (&Walker, CurrentParameter, StrSize(*CmdLine), TRUE))) {\r
+      if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {\r
+        CurrentParameter[0] = L' ';\r
+        CurrentParameter[1] = L' ';\r
+        NewCmdLineSize = StrSize(L"help ") + StrSize(*CmdLine);\r
+        NewCommandLine = AllocateZeroPool(NewCmdLineSize);\r
+        if (NewCommandLine == NULL) {\r
+          Status = EFI_OUT_OF_RESOURCES;\r
+          break;\r
+        }\r
+\r
+        //\r
+        // We know the space is sufficient since we just calculated it.\r
+        //\r
+        StrnCpyS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), L"help ", 5);\r
+        StrnCatS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), *CmdLine, StrLen(*CmdLine));\r
+        SHELL_FREE_NON_NULL(*CmdLine);\r
+        *CmdLine = NewCommandLine;\r
         break;\r
       }\r
-\r
-      //\r
-      // We know the space is sufficient since we just calculated it.\r
-      //\r
-      StrnCpy(NewCommandLine, L"help ", 5);\r
-      StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine));\r
-      SHELL_FREE_NON_NULL(*CmdLine);\r
-      *CmdLine = NewCommandLine;\r
-      break;\r
     }\r
   }\r
 \r
@@ -2086,7 +2217,7 @@ SetLastError(
 \r
   @retval EFI_SUCCESS           The operation was successful\r
   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
-  @return                       some other error occured\r
+  @return                       some other error occurred\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2131,11 +2262,12 @@ ProcessCommandLineToFinal(
 /**\r
   Run an internal shell command.\r
 \r
-  This API will upadate the shell's environment since these commands are libraries.\r
+  This API will update the shell's environment since these commands are libraries.\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[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
@@ -2145,7 +2277,8 @@ EFIAPI
 RunInternalCommand(\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
+  OUT EFI_STATUS                    *CommandStatus\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2170,7 +2303,7 @@ RunInternalCommand(
   //\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
@@ -2178,6 +2311,14 @@ RunInternalCommand(
     Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError);\r
 \r
     if (!EFI_ERROR(Status)) {\r
+      if (CommandStatus != NULL) {\r
+        if (CommandReturnedStatus != SHELL_SUCCESS) {\r
+          *CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT);\r
+        } else {\r
+          *CommandStatus = EFI_SUCCESS;\r
+        }\r
+      }\r
+\r
       //\r
       // Update last error status.\r
       // some commands do not update last error.\r
@@ -2209,13 +2350,13 @@ RunInternalCommand(
   }\r
 \r
   //\r
-  // This is guarenteed to be called after UpdateArgcArgv no matter what else happened.\r
+  // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.\r
   // This is safe even if the update API failed.  In this case, it may be a no-op.\r
   //\r
   RestoreArgcArgv(ParamProtocol, &Argv, &Argc);\r
 \r
   //\r
-  // If a script is running and the command is not a scipt only command, then\r
+  // If a script is running and the command is not a script only command, then\r
   // change return value to success so the script won't halt (unless aborted).\r
   //\r
   // Script only commands have to be able halt the script since the script will\r
@@ -2239,6 +2380,7 @@ RunInternalCommand(
   @param[in] CmdLine          the command line to run.\r
   @param[in] FirstParameter   the first parameter on the command line\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
+  @param[out] CommandStatus   the status from the command line.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
@@ -2249,7 +2391,8 @@ RunCommandOrFile(
   IN       SHELL_OPERATION_TYPES    Type,\r
   IN CONST CHAR16                   *CmdLine,\r
   IN       CHAR16                   *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
+  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
+  OUT EFI_STATUS                    *CommandStatus\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2265,7 +2408,7 @@ RunCommandOrFile(
 \r
   switch (Type) {\r
     case   Internal_Command:\r
-      Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol);\r
+      Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol, CommandStatus);\r
       break;\r
     case   Script_File_Name:\r
     case   Efi_Application:\r
@@ -2331,6 +2474,10 @@ RunCommandOrFile(
             CalleeExitStatus = (SHELL_STATUS) StartStatus;\r
           }\r
 \r
+          if (CommandStatus != NULL) {\r
+            *CommandStatus = CalleeExitStatus;\r
+          }\r
+\r
           //\r
           // Update last error status.\r
           //\r
@@ -2363,6 +2510,7 @@ RunCommandOrFile(
   @param[in] CmdLine          the command line to run.\r
   @param[in] FirstParameter   the first parameter on the command line.\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
+  @param[out] CommandStatus   the status from the command line.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
@@ -2370,10 +2518,11 @@ RunCommandOrFile(
 EFI_STATUS\r
 EFIAPI\r
 SetupAndRunCommandOrFile(\r
-  IN SHELL_OPERATION_TYPES          Type,\r
-  IN CHAR16                         *CmdLine,\r
-  IN CHAR16                         *FirstParameter,\r
-  IN EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol\r
+  IN   SHELL_OPERATION_TYPES          Type,\r
+  IN   CHAR16                         *CmdLine,\r
+  IN   CHAR16                         *FirstParameter,\r
+  IN   EFI_SHELL_PARAMETERS_PROTOCOL  *ParamProtocol,\r
+  OUT EFI_STATUS                      *CommandStatus\r
 )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2381,6 +2530,7 @@ SetupAndRunCommandOrFile(
   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
@@ -2393,14 +2543,19 @@ SetupAndRunCommandOrFile(
   //\r
   if (!EFI_ERROR(Status)) {\r
     TrimSpaces(&CmdLine);\r
-    Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol);\r
+    Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus);\r
   }\r
 \r
   //\r
   // 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
@@ -2418,14 +2573,16 @@ SetupAndRunCommandOrFile(
   command or dispatch an external application.\r
 \r
   @param[in] CmdLine      The command line to parse.\r
+  @param[out] CommandStatus   The status from the command line.\r
 \r
   @retval EFI_SUCCESS     The command was completed.\r
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
-RunCommand(\r
-  IN CONST CHAR16   *CmdLine\r
+RunShellCommand(\r
+  IN CONST CHAR16   *CmdLine,\r
+  OUT EFI_STATUS    *CommandStatus\r
   )\r
 {\r
   EFI_STATUS                Status;\r
@@ -2433,6 +2590,7 @@ RunCommand(
   CHAR16                    *FirstParameter;\r
   CHAR16                    *TempWalker;\r
   SHELL_OPERATION_TYPES     Type;\r
+  CHAR16                    *OldCmdLine;\r
 \r
   ASSERT(CmdLine != NULL);\r
   if (StrLen(CmdLine) == 0) {\r
@@ -2440,11 +2598,14 @@ RunCommand(
   }\r
 \r
   Status              = EFI_SUCCESS;\r
+  FirstParameter      = NULL;\r
   CleanOriginal       = NULL;\r
+  OldCmdLine          = NULL;\r
 \r
   CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0);\r
   if (CleanOriginal == NULL) {\r
-    return (EFI_OUT_OF_RESOURCES);\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
   }\r
 \r
   TrimSpaces(&CleanOriginal);\r
@@ -2453,7 +2614,7 @@ RunCommand(
   // NULL out comments (leveraged from RunScriptFileHandle() ).\r
   // The # character on a line is used to denote that all characters on the same line\r
   // and to the right of the # are to be ignored by the shell.\r
-  // Afterward, again remove spaces, in case any were between the last command-parameter and '#'.\r
+  // Afterwards, again remove spaces, in case any were between the last command-parameter and '#'.\r
   //\r
   for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) {\r
     if (*TempWalker == L'^') {\r
@@ -2471,66 +2632,94 @@ RunCommand(
   // Handle case that passed in command line is just 1 or more " " characters.\r
   //\r
   if (StrLen (CleanOriginal) == 0) {\r
-    SHELL_FREE_NON_NULL(CleanOriginal);\r
-    return (EFI_SUCCESS);\r
+    Status = EFI_SUCCESS;\r
+    goto Done;\r
   }\r
 \r
   Status = ProcessCommandLineToFinal(&CleanOriginal);\r
   if (EFI_ERROR(Status)) {\r
-    SHELL_FREE_NON_NULL(CleanOriginal);\r
-    return (Status);\r
+    goto Done;\r
   }\r
 \r
+  OldCmdLine = ShellGetRawCmdLine ();\r
+  ShellSetRawCmdLine (CleanOriginal);\r
+\r
   //\r
-  // We dont do normal processing with a split command line (output from one command input to another)\r
+  // We don't do normal processing with a split command line (output from one command input to another)\r
   //\r
   if (ContainsSplit(CleanOriginal)) {\r
     Status = ProcessNewSplitCommandLine(CleanOriginal);\r
-    SHELL_FREE_NON_NULL(CleanOriginal);\r
-    return (Status);\r
-  } \r
+    goto Done;\r
+  }\r
 \r
   //\r
   // We need the first parameter information so we can determine the operation type\r
   //\r
   FirstParameter = AllocateZeroPool(StrSize(CleanOriginal));\r
   if (FirstParameter == NULL) {\r
-    SHELL_FREE_NON_NULL(CleanOriginal);\r
-    return (EFI_OUT_OF_RESOURCES);\r
+    Status = EFI_OUT_OF_RESOURCES;\r
+    goto Done;\r
   }\r
   TempWalker = CleanOriginal;\r
-  GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal));\r
-\r
-  //\r
-  // Depending on the first parameter we change the behavior\r
-  //\r
-  switch (Type = GetOperationType(FirstParameter)) {\r
-    case   File_Sys_Change:\r
-      Status = ChangeMappedDrive (FirstParameter);\r
-      break;\r
-    case   Internal_Command:\r
-    case   Script_File_Name:\r
-    case   Efi_Application:\r
-      Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol);\r
-      break;\r
-    default:\r
-      //\r
-      // Whatever was typed, it was invalid.\r
-      //\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
-      SetLastError(SHELL_NOT_FOUND);\r
-      break;\r
+  if (!EFI_ERROR (ShellGetNextParameter (&TempWalker, FirstParameter, StrSize(CleanOriginal), TRUE))) {\r
+    //\r
+    // Depending on the first parameter we change the behavior\r
+    //\r
+    switch (Type = GetOperationType(FirstParameter)) {\r
+      case   File_Sys_Change:\r
+        Status = ChangeMappedDrive (FirstParameter);\r
+        break;\r
+      case   Internal_Command:\r
+      case   Script_File_Name:\r
+      case   Efi_Application:\r
+        Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus);\r
+        break;\r
+      default:\r
+        //\r
+        // Whatever was typed, it was invalid.\r
+        //\r
+        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
+        SetLastError(SHELL_NOT_FOUND);\r
+        break;\r
+    }\r
+  } else {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
+    SetLastError(SHELL_NOT_FOUND);\r
   }\r
\r
-  SHELL_FREE_NON_NULL(CleanOriginal);\r
-  SHELL_FREE_NON_NULL(FirstParameter);\r
+\r
+Done:\r
+  ShellSetRawCmdLine (OldCmdLine);\r
+  SHELL_FREE_NON_NULL (OldCmdLine);\r
+  SHELL_FREE_NON_NULL (CleanOriginal);\r
+  SHELL_FREE_NON_NULL (FirstParameter);\r
 \r
   return (Status);\r
 }\r
 \r
+/**\r
+  Function will process and run a command line.\r
+\r
+  This will determine if the command line represents an internal shell \r
+  command or dispatch an external application.\r
+\r
+  @param[in] CmdLine      The command line to parse.\r
+\r
+  @retval EFI_SUCCESS     The command was completed.\r
+  @retval EFI_ABORTED     The command's operation was aborted.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunCommand(\r
+  IN CONST CHAR16   *CmdLine\r
+  )\r
+{\r
+  return (RunShellCommand(CmdLine, NULL));\r
+}\r
+\r
+\r
 STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};\r
 /**\r
-  Function determins if the CommandName COULD be a valid command.  It does not determine whether\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
 \r
   @param[in] CommandName    The name to check\r
@@ -2566,7 +2755,7 @@ IsValidCommandName(
   @param[in] Handle             The handle to the already opened file.\r
   @param[in] Name               The name of the script file.\r
 \r
-  @retval EFI_SUCCESS           the script completed sucessfully\r
+  @retval EFI_SUCCESS           the script completed successfully\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2578,6 +2767,7 @@ RunScriptFileHandle (
   EFI_STATUS          Status;\r
   SCRIPT_FILE         *NewScriptFile;\r
   UINTN               LoopVar;\r
+  UINTN               PrintBuffSize;\r
   CHAR16              *CommandLine;\r
   CHAR16              *CommandLine2;\r
   CHAR16              *CommandLine3;\r
@@ -2588,10 +2778,12 @@ RunScriptFileHandle (
   CONST CHAR16        *CurDir;\r
   UINTN               LineCount;\r
   CHAR16              LeString[50];\r
+  LIST_ENTRY          OldBufferList;\r
 \r
   ASSERT(!ShellCommandGetScriptExit());\r
 \r
   PreScriptEchoState = ShellCommandGetEchoState();\r
+  PrintBuffSize = PcdGet16(PcdShellPrintBufferSize);\r
 \r
   NewScriptFile = (SCRIPT_FILE*)AllocateZeroPool(sizeof(SCRIPT_FILE));\r
   if (NewScriptFile == NULL) {\r
@@ -2666,12 +2858,12 @@ RunScriptFileHandle (
   //\r
   // Now enumerate through the commands and run each one.\r
   //\r
-  CommandLine = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
+  CommandLine = AllocateZeroPool(PrintBuffSize);\r
   if (CommandLine == NULL) {\r
     DeleteScriptFileStruct(NewScriptFile);\r
     return (EFI_OUT_OF_RESOURCES);\r
   }\r
-  CommandLine2 = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
+  CommandLine2 = AllocateZeroPool(PrintBuffSize);\r
   if (CommandLine2 == NULL) {\r
     FreePool(CommandLine);\r
     DeleteScriptFileStruct(NewScriptFile);\r
@@ -2683,7 +2875,13 @@ RunScriptFileHandle (
       ; // conditional increment in the body of the loop\r
   ){\r
     ASSERT(CommandLine2 != NULL);\r
-    StrnCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);\r
+    StrnCpyS( CommandLine2, \r
+              PrintBuffSize/sizeof(CHAR16), \r
+              NewScriptFile->CurrentCommand->Cl,\r
+              PrintBuffSize/sizeof(CHAR16) - 1\r
+              );\r
+\r
+    SaveBufferList(&OldBufferList);\r
 \r
     //\r
     // NULL out comments\r
@@ -2704,7 +2902,11 @@ RunScriptFileHandle (
       //\r
       // Due to variability in starting the find and replace action we need to have both buffers the same.\r
       //\r
-      StrnCpy(CommandLine, CommandLine2, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);\r
+      StrnCpyS( CommandLine, \r
+                PrintBuffSize/sizeof(CHAR16), \r
+                CommandLine2,\r
+                PrintBuffSize/sizeof(CHAR16) - 1\r
+                );\r
 \r
       //\r
       // Remove the %0 to %9 from the command line (if we have some arguments)\r
@@ -2712,51 +2914,55 @@ RunScriptFileHandle (
       if (NewScriptFile->Argv != NULL) {\r
         switch (NewScriptFile->Argc) {\r
           default:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 9:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 8:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 7:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 6:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 5:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 4:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 3:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 2:\r
-            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
           case 1:\r
-            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, FALSE);\r
+            Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE);\r
             ASSERT_EFI_ERROR(Status);\r
             break;\r
           case 0:\r
             break;\r
         }\r
       }\r
-      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", L"\"\"", FALSE, FALSE);\r
-      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", L"\"\"", FALSE, FALSE);\r
-\r
-      StrnCpy(CommandLine2, CommandLine, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%1", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%2", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%3", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%4", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%5", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%6", L"\"\"", FALSE, FALSE);\r
+      Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%7", L"\"\"", FALSE, FALSE);\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
+                CommandLine,\r
+                PrintBuffSize/sizeof(CHAR16) - 1\r
+                );\r
 \r
       LastCommand = NewScriptFile->CurrentCommand;\r
 \r
@@ -2811,15 +3017,19 @@ RunScriptFileHandle (
 \r
           ShellCommandRegisterExit(FALSE, 0);\r
           Status = EFI_SUCCESS;\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
         if (ShellGetExecutionBreakFlag()) {\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
         if (EFI_ERROR(Status)) {\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
         if (ShellCommandGetExit()) {\r
+          RestoreBufferList(&OldBufferList);\r
           break;\r
         }\r
       }\r
@@ -2838,6 +3048,7 @@ RunScriptFileHandle (
         NewScriptFile->CurrentCommand->Reset = TRUE;\r
       }\r
     }\r
+    RestoreBufferList(&OldBufferList);\r
   }\r
 \r
 \r
@@ -2862,7 +3073,7 @@ RunScriptFileHandle (
   @param[in] CmdLine            the command line to run.\r
   @param[in] ParamProtocol      the shell parameters protocol pointer\r
 \r
-  @retval EFI_SUCCESS           the script completed sucessfully\r
+  @retval EFI_SUCCESS           the script completed successfully\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2885,7 +3096,7 @@ RunScriptFile (
   //\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
@@ -2910,10 +3121,11 @@ RunScriptFile (
   }\r
 \r
   //\r
-  // This is guarenteed to be called after UpdateArgcArgv no matter what else happened.\r
+  // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.\r
   // This is safe even if the update API failed.  In this case, it may be a no-op.\r
   //\r
   RestoreArgcArgv(ParamProtocol, &Argv, &Argc);\r
 \r
   return (Status);\r
 }\r
+\r