+\r
+ if (ExitStatus != NULL) {\r
+ *ExitStatus = CalleeExitStatus;\r
+ }\r
+\r
+ return (Status);\r
+}\r
+\r
+/**\r
+ Function to setup StdIn, StdErr, StdOut, and then run the command or file.\r
+\r
+ @param[in] Type the type of operation being run.\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
+\r
+ @param[out] ExitStatus The exit code of the command or file.\r
+ Ignored if NULL.\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
+ IN SHELL_OPERATION_TYPES Type,\r
+ IN CHAR16 *CmdLine,\r
+ IN CHAR16 *FirstParameter,\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,\r
+ OUT SHELL_STATUS *ExitStatus\r
+)\r
+{\r
+ EFI_STATUS Status;\r
+ SHELL_FILE_HANDLE OriginalStdIn;\r
+ SHELL_FILE_HANDLE OriginalStdOut;\r
+ SHELL_FILE_HANDLE OriginalStdErr;\r
+ SYSTEM_TABLE_INFO OriginalSystemTableInfo;\r
+\r
+ //\r
+ // Update the StdIn, StdOut, and StdErr for redirection to environment variables, files, etc... unicode and ASCII\r
+ //\r
+ Status = UpdateStdInStdOutStdErr(ParamProtocol, CmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);\r
+\r
+ //\r
+ // The StdIn, StdOut, and StdErr are set up.\r
+ // Now run the command, script, or application\r
+ //\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = RunCommandOrFile(\r
+ Type,\r
+ CmdLine,\r
+ FirstParameter,\r
+ ParamProtocol,\r
+ ExitStatus\r
+ );\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
+ }\r
+\r
+ //\r
+ // put back the original StdIn, StdOut, and StdErr\r
+ //\r
+ RestoreStdInStdOutStdErr(ParamProtocol, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);\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
+ @param[out] ExitStatus The exit code of the command. Ignored if NULL.\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
+ OUT SHELL_STATUS *ExitStatus\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ CHAR16 *CleanOriginal;\r
+ CHAR16 *FirstParameter;\r
+ CHAR16 *TempWalker;\r
+ SHELL_OPERATION_TYPES Type;\r
+\r
+ ASSERT(CmdLine != NULL);\r
+ if (StrLen(CmdLine) == 0) {\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ Status = EFI_SUCCESS;\r
+ CleanOriginal = NULL;\r
+\r
+ CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0);\r
+ if (CleanOriginal == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+\r
+ TrimSpaces(&CleanOriginal);\r
+\r
+ //\r
+ // 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
+ }\r
+\r
+ Status = ProcessCommandLineToFinal(&CleanOriginal);\r
+ if (EFI_ERROR(Status)) {\r
+ SHELL_FREE_NON_NULL(CleanOriginal);\r
+ return (Status);\r
+ }\r
+\r
+ //\r
+ // We dont do normal processing with a split command line (output from one command input to another)\r
+ //\r
+ if (ContainsSplit(CleanOriginal)) {\r
+ Status = ProcessNewSplitCommandLine(CleanOriginal, ExitStatus);\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
+ SHELL_FREE_NON_NULL(CleanOriginal);\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ }\r
+ TempWalker = CleanOriginal;\r
+ GetNextParameter(&TempWalker, &FirstParameter);\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(\r
+ Type,\r
+ CleanOriginal,\r
+ FirstParameter,\r
+ ShellInfoObject.NewShellParametersProtocol,\r
+ ExitStatus\r
+ );\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
+ \r
+ SHELL_FREE_NON_NULL(CleanOriginal);\r
+ SHELL_FREE_NON_NULL(FirstParameter);\r