/** @file\r
This is THE shell (application)\r
\r
- Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.<BR>\r
Copyright (c) 2013, Hewlett-Packard Development Company, L.P.\r
This program and the accompanying materials\r
are licensed and made available under the terms and conditions of the BSD License\r
STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";\r
\r
/**\r
- Cleans off leading and trailing spaces and tabs\r
+ Cleans off leading and trailing spaces and tabs.\r
\r
- @param[in] String pointer to the string to trim them off\r
+ @param[in] String pointer to the string to trim them off.\r
**/\r
EFI_STATUS\r
EFIAPI\r
\r
@retval A pointer to the | character in CmdLine or NULL if not present.\r
**/\r
-CONST\r
-CHAR16*\r
+CONST CHAR16*\r
EFIAPI\r
FindSplit(\r
IN CONST CHAR16 *CmdLine\r
// If we got a file, run it\r
//\r
if (!EFI_ERROR(Status) && FileHandle != NULL) {\r
- Status = RunScriptFileHandle (FileHandle, mStartupScript);\r
+ Status = RunScriptFile (mStartupScript, FileHandle, L"", ShellInfoObject.NewShellParametersProtocol);\r
ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);\r
} else {\r
FileStringPath = ShellFindFilePath(mStartupScript);\r
Status = EFI_SUCCESS;\r
ASSERT(FileHandle == NULL);\r
} else {\r
- Status = RunScriptFile(FileStringPath);\r
+ Status = RunScriptFile(FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);\r
FreePool(FileStringPath);\r
}\r
}\r
if (!EFI_ERROR (Status)) {\r
CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;\r
Status = RunCommand(CmdLine);\r
- }\r
+ }\r
\r
//\r
// Done with this command\r
\r
/**\r
Take the original command line, substitute any variables, free \r
- the original string, return the modified copy\r
+ the original string, return the modified copy.\r
\r
- @param[in,out] CmdLine pointer to the command line to update\r
- @param[out]CmdName upon successful return the name of the command to be run\r
+ @param[in] CmdLine pointer to the command line to update.\r
\r
- @retval EFI_SUCCESS the function was successful\r
- @retval EFI_OUT_OF_RESOURCES a memory allocation failed\r
+ @retval EFI_SUCCESS the function was successful.\r
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.\r
**/\r
EFI_STATUS\r
EFIAPI\r
\r
/**\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
+ the original string, return the modified copy.\r
\r
- @param[in] CmdLine pointer to the command line to update\r
- @param[out]CmdName upon successful return the name of the command to be run\r
+ @param[in] CmdLine pointer to the command line to update.\r
\r
- @retval EFI_SUCCESS the function was successful\r
- @retval EFI_OUT_OF_RESOURCES a memory allocation failed\r
+ @retval EFI_SUCCESS the function was successful.\r
+ @retval EFI_OUT_OF_RESOURCES a memory allocation failed.\r
**/\r
EFI_STATUS\r
EFIAPI\r
/**\r
Takes the Argv[0] part of the command line and determine the meaning of it.\r
\r
- @param[in] CmdLine pointer to the command line to update\r
+ @param[in] CmdName pointer to the command line to update.\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 UNKNOWN_INVALID the name is unknown\r
- @retval EFI_APPLICATION the name is an application (.EFI)\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 Unknown_Invalid the name is unknown.\r
+ @retval Efi_Application the name is an application (.EFI).\r
**/\r
SHELL_OPERATION_TYPES\r
EFIAPI\r
// test for an internal command.\r
//\r
if (ShellCommandIsCommandOnList(CmdName)) {\r
- return (INTERNAL_COMMAND);\r
+ return (Internal_Command);\r
}\r
\r
//\r
//\r
if (CmdName[(StrLen(CmdName)-1)] == L':') {\r
if (StrStr(CmdName, L" ") != NULL) {\r
- return (UNKNOWN_INVALID);\r
+ return (Unknown_Invalid);\r
}\r
- return (FILE_SYS_CHANGE);\r
+ return (File_Sys_Change);\r
}\r
\r
//\r
TempLocation2 = mScriptExtension;\r
if (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0) {\r
SHELL_FREE_NON_NULL(FileWithPath);\r
- return (SCRIPT_FILE_NAME);\r
+ return (Script_File_Name);\r
}\r
}\r
\r
// Was a file, but not a script. we treat this as an application.\r
//\r
SHELL_FREE_NON_NULL(FileWithPath);\r
- return (EFI_APPLICATION);\r
+ return (Efi_Application);\r
}\r
\r
SHELL_FREE_NON_NULL(FileWithPath);\r
//\r
// No clue what this is... return invalid flag...\r
//\r
- return (UNKNOWN_INVALID);\r
+ return (Unknown_Invalid);\r
}\r
\r
+/**\r
+ Determine if the first item in a command line is valid.\r
+\r
+ @param[in] CmdLine The command line to parse.\r
+\r
+ @retval EFI_SUCCESS The item is valid.\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
IsValidSplit(\r
TempWalker = (CHAR16*)Temp;\r
GetNextParameter(&TempWalker, &FirstParameter);\r
\r
- if (GetOperationType(FirstParameter) == UNKNOWN_INVALID) {\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
- Determine if a command line contains with a split contains only valid commands\r
+ Determine if a command line contains with a split contains only valid commands.\r
\r
@param[in] CmdLine The command line to parse.\r
\r
}\r
\r
/**\r
- Handle a request to change the current file system\r
+ Handle a request to change the current file system.\r
\r
- @param[in] CmdLine The passed in command line\r
+ @param[in] CmdLine The passed in command line.\r
\r
- @retval EFI_SUCCESS The operation was successful\r
+ @retval EFI_SUCCESS The operation was successful.\r
**/\r
EFI_STATUS\r
EFIAPI\r
}\r
\r
/**\r
- Function to update the shell variable "lasterror"\r
+ Function to update the shell variable "lasterror".\r
\r
- @param[in] ErrorCode the error code to put into lasterror\r
+ @param[in] ErrorCode the error code to put into lasterror.\r
**/\r
EFI_STATUS\r
EFIAPI\r
DevPath = NULL;\r
\r
switch (Type) {\r
- case INTERNAL_COMMAND:\r
+ case Internal_Command:\r
Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol);\r
break;\r
- case SCRIPT_FILE_NAME:\r
- case EFI_APPLICATION:\r
+ case Script_File_Name:\r
+ case Efi_Application:\r
//\r
// Process a fully qualified path\r
//\r
SetLastError(SHELL_NOT_FOUND);\r
}\r
switch (Type) {\r
- case SCRIPT_FILE_NAME:\r
- Status = RunScriptFile (CommandWithPath);\r
+ case Script_File_Name:\r
+ Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);\r
break;\r
- case EFI_APPLICATION:\r
+ case Efi_Application:\r
//\r
// Get the device path of the application image\r
//\r
//\r
// Update last error status.\r
//\r
- SetLastError(StatusCode);\r
+ SetLastError((SHELL_STATUS) StatusCode);\r
break;\r
default:\r
//\r
// Depending on the first parameter we change the behavior\r
//\r
switch (Type = GetOperationType(FirstParameter)) {\r
- case FILE_SYS_CHANGE:\r
+ case File_Sys_Change:\r
Status = ChangeMappedDrive(CleanOriginal);\r
break;\r
- 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
break;\r
default:\r
while(!ShellFileHandleEof(Handle)) {\r
CommandLine = ShellFileHandleReturnLine(Handle, &Ascii);\r
LineCount++;\r
- if (CommandLine == NULL || StrLen(CommandLine) == 0) {\r
+ if (CommandLine == NULL || StrLen(CommandLine) == 0 || CommandLine[0] == '#') {\r
+ SHELL_FREE_NON_NULL(CommandLine);\r
continue;\r
}\r
NewScriptFile->CurrentCommand = AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST));\r
if (NewScriptFile->CurrentCommand == NULL) {\r
+ SHELL_FREE_NON_NULL(CommandLine);\r
DeleteScriptFileStruct(NewScriptFile);\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
Function to process a NSH script file.\r
\r
@param[in] ScriptPath Pointer to the script file name (including file system path).\r
+ @param[in] Handle the handle of the script file already opened.\r
+ @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
**/\r
EFI_STATUS\r
EFIAPI\r
RunScriptFile (\r
- IN CONST CHAR16 *ScriptPath\r
+ IN CONST CHAR16 *ScriptPath,\r
+ IN SHELL_FILE_HANDLE Handle OPTIONAL,\r
+ IN CONST CHAR16 *CmdLine,\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol\r
)\r
{\r
EFI_STATUS Status;\r
SHELL_FILE_HANDLE FileHandle;\r
+ UINTN Argc;\r
+ CHAR16 **Argv;\r
\r
if (ShellIsFile(ScriptPath) != EFI_SUCCESS) {\r
return (EFI_INVALID_PARAMETER);\r
}\r
\r
- Status = ShellOpenFileByName(ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
- }\r
+ //\r
+ // get the argc and argv updated for scripts\r
+ //\r
+ Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc);\r
+ if (!EFI_ERROR(Status)) {\r
\r
- Status = RunScriptFileHandle(FileHandle, ScriptPath);\r
+ if (Handle == NULL) {\r
+ //\r
+ // open the file\r
+ //\r
+ Status = ShellOpenFileByName(ScriptPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+ if (!EFI_ERROR(Status)) {\r
+ //\r
+ // run it\r
+ //\r
+ Status = RunScriptFileHandle(FileHandle, ScriptPath);\r
\r
- ShellCloseFile(&FileHandle);\r
+ //\r
+ // now close the file\r
+ //\r
+ ShellCloseFile(&FileHandle);\r
+ }\r
+ } else {\r
+ Status = RunScriptFileHandle(Handle, ScriptPath);\r
+ }\r
+ }\r
+\r
+ //\r
+ // This is guarenteed 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