]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/Shell.c
ShellPkg: Fix MSFT C4255 warning
[mirror_edk2.git] / ShellPkg / Application / Shell / Shell.c
index 0f1fb9c287b83c253b40e76e979e43782055c95a..2adc99240c483f01e5282002122028e5df842e15 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   This is THE shell (application)\r
 \r
-  Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2017, 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
@@ -80,7 +80,6 @@ CONST CHAR16 mNoNestingFalse[]              = L"False";
   @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
@@ -113,7 +112,6 @@ TrimSpaces(
   @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
@@ -202,7 +200,6 @@ IsValidEnvironmentVariableName(
   @retval FALSE           CmdLine does not have a valid split.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 ContainsSplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -213,7 +210,7 @@ ContainsSplit(
 \r
   FirstQuote    = FindNextInstance (CmdLine, L"\"", TRUE);\r
   SecondQuote   = NULL;\r
-  TempSpot      = ShellFindFirstCharacter(CmdLine, L"|", TRUE);\r
+  TempSpot      = FindFirstCharacter(CmdLine, L"|", L'^');\r
 \r
   if (FirstQuote == NULL    || \r
       TempSpot == NULL      || \r
@@ -236,7 +233,7 @@ ContainsSplit(
       continue;\r
     } else {\r
       FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);\r
-      TempSpot = ShellFindFirstCharacter(TempSpot + 1, L"|", TRUE);\r
+      TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^');\r
       continue;\r
     } \r
   }\r
@@ -252,7 +249,6 @@ ContainsSplit(
   @retval EFI_OUT_OF_RESOURCES  There is not enough memory available.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 InternalEfiShellStartCtrlSMonitor(\r
   VOID\r
   )\r
@@ -667,7 +663,7 @@ FreeResources:
     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
@@ -716,7 +712,6 @@ FreeResources:
   }\r
 \r
   ShellFreeEnvVarList ();\r
-  ShellSetRawCmdLine (NULL);\r
 \r
   if (ShellCommandGetExit()) {\r
     return ((EFI_STATUS)ShellCommandGetExitCode());\r
@@ -730,8 +725,8 @@ FreeResources:
   @retval EFI_SUCCESS           all init commands were run successfully.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 SetBuiltInAlias(\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -769,7 +764,6 @@ SetBuiltInAlias(
   @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
@@ -790,7 +784,6 @@ IsCommand(
   @retval FALSE             The command is not a script only command.\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 IsScriptOnlyCommand(\r
   IN CONST CHAR16 *CommandName\r
   )\r
@@ -821,7 +814,6 @@ IsScriptOnlyCommand(
   @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
@@ -897,7 +889,6 @@ GetDevicePathsForImageAndFile (
   @retval EFI_SUCCESS           The variable is initialized.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ProcessCommandLine(\r
   VOID\r
   )\r
@@ -1032,7 +1023,7 @@ ProcessCommandLine(
       }\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
@@ -1052,11 +1043,31 @@ ProcessCommandLine(
         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 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
@@ -1065,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
-        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
@@ -1081,6 +1107,19 @@ ProcessCommandLine(
           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
@@ -1093,6 +1132,64 @@ ProcessCommandLine(
   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
+    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
@@ -1104,7 +1201,6 @@ ProcessCommandLine(
   @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
@@ -1114,17 +1210,11 @@ DoStartupScript(
   EFI_STATUS                    CalleeStatus;\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                        *TempSpot;\r
   UINTN                         NewSize;\r
-  CONST CHAR16                  *MapName;\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
@@ -1186,60 +1276,17 @@ DoStartupScript(
     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
-    } 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
-    }\r
-  }\r
-  if (EFI_ERROR(Status)) {\r
-    NamePath = FileDevicePath (NULL, mStartupScript);\r
-    NewPath = AppendDevicePathNode (ImagePath, NamePath);\r
-    FreePool(NamePath);\r
-\r
+  FileStringPath = LocateStartupScript (ImagePath, FilePath);\r
+  if (FileStringPath != NULL) {\r
+    Status = RunScriptFile (FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);\r
+    FreePool (FileStringPath);\r
+  } else {\r
     //\r
-    // Try the location\r
+    // we return success since startup script is not mandatory.\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
   return (Status);\r
 }\r
 \r
@@ -1252,7 +1299,6 @@ DoStartupScript(
   @retval RETURN_ABORTED\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 DoShellPrompt (\r
   VOID\r
   )\r
@@ -1319,7 +1365,6 @@ DoShellPrompt (
   @param Buffer   Something to pass to FreePool when the shell is exiting.\r
 **/\r
 VOID*\r
-EFIAPI\r
 AddBufferToFreeList (\r
   VOID *Buffer\r
   )\r
@@ -1376,7 +1421,6 @@ RestoreBufferList (
   @param Buffer     The line buffer to add.\r
 **/\r
 VOID\r
-EFIAPI\r
 AddLineToCommandHistory(\r
   IN CONST CHAR16 *Buffer\r
   )\r
@@ -1438,7 +1482,6 @@ AddLineToCommandHistory(
   @retval EFI_OUT_OF_RESOURCES    A memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellConvertAlias(\r
   IN OUT CHAR16 **CommandString\r
   )\r
@@ -1463,7 +1506,6 @@ ShellConvertAlias(
   @param[in,out] CmdLine   The command line to update.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 StripUnreplacedEnvironmentVariables(\r
   IN OUT CHAR16 *CmdLine\r
   )\r
@@ -1536,7 +1578,6 @@ StripUnreplacedEnvironmentVariables(
   @return                           The new command line with no environment variables present.\r
 **/\r
 CHAR16*\r
-EFIAPI\r
 ShellConvertVariables (\r
   IN CONST CHAR16 *OriginalCommandLine\r
   )\r
@@ -1606,7 +1647,7 @@ ShellConvertVariables (
   //\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
@@ -1615,6 +1656,8 @@ ShellConvertVariables (
     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
@@ -1672,11 +1715,10 @@ ShellConvertVariables (
   @retval other             Some error occurs when executing the split command.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\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
@@ -1685,7 +1727,7 @@ RunSplitCommand(
   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
@@ -1751,7 +1793,7 @@ RunSplitCommand(
     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
@@ -1767,11 +1809,10 @@ RunSplitCommand(
   // Note that the original StdIn is now the StdOut...\r
   //\r
   if (Split->SplitStdOut != NULL) {\r
-    ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdOut));\r
+    ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdOut);\r
   }\r
   if (Split->SplitStdIn != NULL) {\r
-    ShellInfoObject.NewEfiShellProtocol->CloseFile(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn));\r
-    FreePool (Split->SplitStdIn);\r
+    ShellInfoObject.NewEfiShellProtocol->CloseFile (Split->SplitStdIn);\r
   }\r
 \r
   FreePool(Split);\r
@@ -1791,7 +1832,6 @@ RunSplitCommand(
   @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellSubstituteVariables(\r
   IN CHAR16 **CmdLine\r
   )\r
@@ -1816,7 +1856,6 @@ ShellSubstituteVariables(
   @retval EFI_OUT_OF_RESOURCES  a memory allocation failed.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ShellSubstituteAliases(\r
   IN CHAR16 **CmdLine\r
   )\r
@@ -1888,7 +1927,6 @@ ShellSubstituteAliases(
   @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
@@ -1957,7 +1995,6 @@ GetOperationType(
   @retval EFI_NOT_FOUND         The operation type is unknown or invalid.\r
 **/\r
 EFI_STATUS \r
-EFIAPI\r
 IsValidSplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -1993,7 +2030,7 @@ IsValidSplit(
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
     TempWalker = (CHAR16*)Temp;\r
-    if (!EFI_ERROR (ShellGetNextParameter (&TempWalker, FirstParameter, StrSize(CmdLine), TRUE))) {\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
@@ -2016,7 +2053,6 @@ IsValidSplit(
   @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
@@ -2042,7 +2078,7 @@ VerifySplit(
   //\r
   // recurse to verify the next item\r
   //\r
-  TempSpot = ShellFindFirstCharacter(CmdLine, L"|", TRUE) + 1;\r
+  TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;\r
   if (*TempSpot == L'a' && \r
       (*(TempSpot + 1) == L' ' || *(TempSpot + 1) == CHAR_NULL)\r
      ) {\r
@@ -2062,7 +2098,6 @@ VerifySplit(
   @return               an error occurred.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ProcessNewSplitCommandLine(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -2103,7 +2138,6 @@ ProcessNewSplitCommandLine(
   @retval EFI_SUCCESS The operation was successful.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ChangeMappedDrive(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -2139,7 +2173,6 @@ ChangeMappedDrive(
   @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
@@ -2159,7 +2192,7 @@ DoHelpUpdate(
 \r
   Walker = *CmdLine;\r
   while(Walker != NULL && *Walker != CHAR_NULL) {\r
-    if (!EFI_ERROR (ShellGetNextParameter (&Walker, CurrentParameter, StrSize(*CmdLine), TRUE))) {\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
@@ -2193,7 +2226,6 @@ DoHelpUpdate(
   @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
@@ -2220,7 +2252,6 @@ SetLastError(
   @return                       some other error occurred\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 ProcessCommandLineToFinal(\r
   IN OUT CHAR16 **CmdLine\r
   )\r
@@ -2273,7 +2304,6 @@ ProcessCommandLineToFinal(
   @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
@@ -2386,7 +2416,6 @@ RunInternalCommand(
   @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
@@ -2516,7 +2545,6 @@ RunCommandOrFile(
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 SetupAndRunCommandOrFile(\r
   IN   SHELL_OPERATION_TYPES          Type,\r
   IN   CHAR16                         *CmdLine,\r
@@ -2579,7 +2607,6 @@ SetupAndRunCommandOrFile(
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 RunShellCommand(\r
   IN CONST CHAR16   *CmdLine,\r
   OUT EFI_STATUS    *CommandStatus\r
@@ -2590,7 +2617,7 @@ RunShellCommand(
   CHAR16                    *FirstParameter;\r
   CHAR16                    *TempWalker;\r
   SHELL_OPERATION_TYPES     Type;\r
-  CHAR16                    *OldCmdLine;\r
+  CONST CHAR16              *CurDir;\r
 \r
   ASSERT(CmdLine != NULL);\r
   if (StrLen(CmdLine) == 0) {\r
@@ -2598,14 +2625,11 @@ RunShellCommand(
   }\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
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto Done;\r
+    return (EFI_OUT_OF_RESOURCES);\r
   }\r
 \r
   TrimSpaces(&CleanOriginal);\r
@@ -2632,36 +2656,35 @@ RunShellCommand(
   // Handle case that passed in command line is just 1 or more " " characters.\r
   //\r
   if (StrLen (CleanOriginal) == 0) {\r
-    Status = EFI_SUCCESS;\r
-    goto Done;\r
+    SHELL_FREE_NON_NULL(CleanOriginal);\r
+    return (EFI_SUCCESS);\r
   }\r
 \r
   Status = ProcessCommandLineToFinal(&CleanOriginal);\r
   if (EFI_ERROR(Status)) {\r
-    goto Done;\r
+    SHELL_FREE_NON_NULL(CleanOriginal);\r
+    return (Status);\r
   }\r
 \r
-  OldCmdLine = ShellGetRawCmdLine ();\r
-  ShellSetRawCmdLine (CleanOriginal);\r
-\r
   //\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
-    goto Done;\r
-  }\r
+    SHELL_FREE_NON_NULL(CleanOriginal);\r
+    return (Status);\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
-    Status = EFI_OUT_OF_RESOURCES;\r
-    goto Done;\r
+    SHELL_FREE_NON_NULL(CleanOriginal);\r
+    return (EFI_OUT_OF_RESOURCES);\r
   }\r
   TempWalker = CleanOriginal;\r
-  if (!EFI_ERROR (ShellGetNextParameter (&TempWalker, FirstParameter, StrSize(CleanOriginal), TRUE))) {\r
+  if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal), TRUE))) {\r
     //\r
     // Depending on the first parameter we change the behavior\r
     //\r
@@ -2686,12 +2709,24 @@ RunShellCommand(
     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
     SetLastError(SHELL_NOT_FOUND);\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
-Done:\r
-  ShellSetRawCmdLine (OldCmdLine);\r
-  SHELL_FREE_NON_NULL (OldCmdLine);\r
-  SHELL_FREE_NON_NULL (CleanOriginal);\r
-  SHELL_FREE_NON_NULL (FirstParameter);\r
+  SHELL_FREE_NON_NULL(CleanOriginal);\r
+  SHELL_FREE_NON_NULL(FirstParameter);\r
 \r
   return (Status);\r
 }\r
@@ -2708,7 +2743,6 @@ Done:
   @retval EFI_ABORTED     The command's operation was aborted.\r
 **/\r
 EFI_STATUS\r
-EFIAPI\r
 RunCommand(\r
   IN CONST CHAR16   *CmdLine\r
   )\r
@@ -2728,7 +2762,6 @@ STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"'
   @retval FALSE             CommandName could not be a valid command name\r
 **/\r
 BOOLEAN\r
-EFIAPI\r
 IsValidCommandName(\r
   IN CONST CHAR16     *CommandName\r
   )\r
@@ -2758,7 +2791,6 @@ IsValidCommandName(
   @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
@@ -3076,7 +3108,6 @@ RunScriptFileHandle (
   @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
@@ -3129,3 +3160,36 @@ RunScriptFile (
   return (Status);\r
 }\r
 \r
+/**\r
+  Return the pointer to the first occurrence of any character from a list of characters.\r
+\r
+  @param[in] String           the string to parse\r
+  @param[in] CharacterList    the list of character to look for\r
+  @param[in] EscapeCharacter  An escape character to skip\r
+\r
+  @return the location of the first character in the string\r
+  @retval CHAR_NULL no instance of any character in CharacterList was found in String\r
+**/\r
+CONST CHAR16*\r
+FindFirstCharacter(\r
+  IN CONST CHAR16 *String,\r
+  IN CONST CHAR16 *CharacterList,\r
+  IN CONST CHAR16 EscapeCharacter\r
+  )\r
+{\r
+  UINT32 WalkChar;\r
+  UINT32 WalkStr;\r
+\r
+  for (WalkStr = 0; WalkStr < StrLen(String); WalkStr++) {\r
+    if (String[WalkStr] == EscapeCharacter) {\r
+      WalkStr++;\r
+      continue;\r
+    }\r
+    for (WalkChar = 0; WalkChar < StrLen(CharacterList); WalkChar++) {\r
+      if (String[WalkStr] == CharacterList[WalkChar]) {\r
+        return (&String[WalkStr]);\r
+      }\r
+    }\r
+  }\r
+  return (String + StrLen(String));\r
+}\r