/** @file\r
This is THE shell (application)\r
\r
- Copyright (c) 2009 - 2012, Intel Corporation. All rights reserved.<BR>\r
+ Copyright (c) 2009 - 2013, 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
which accompanies this distribution. The full text of the license may be found at\r
FALSE,\r
FALSE,\r
{\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
- 0,\r
+ {{\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0,\r
+ 0\r
+ }},\r
0,\r
NULL,\r
NULL\r
},\r
- {0,0},\r
+ {{NULL, NULL}, NULL},\r
{\r
- {0,0},\r
+ {{NULL, NULL}, NULL},\r
0,\r
0,\r
TRUE\r
NULL,\r
NULL,\r
NULL,\r
- {0,0,NULL,NULL},\r
- {0,0},\r
+ {{NULL, NULL}, NULL, NULL},\r
+ {{NULL, NULL}, NULL, NULL},\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
+ NULL,\r
NULL,\r
NULL,\r
NULL,\r
STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";\r
STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";\r
\r
+/**\r
+ Cleans off leading and trailing spaces and tabs\r
+\r
+ @param[in] String pointer to the string to trim them off\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+TrimSpaces(\r
+ IN CHAR16 **String\r
+ )\r
+{\r
+ ASSERT(String != NULL);\r
+ ASSERT(*String!= NULL);\r
+ //\r
+ // Remove any spaces and tabs at the beginning of the (*String).\r
+ //\r
+ while (((*String)[0] == L' ') || ((*String)[0] == L'\t')) {\r
+ CopyMem((*String), (*String)+1, StrSize((*String)) - sizeof((*String)[0]));\r
+ }\r
+\r
+ //\r
+ // Remove any spaces at the end of the (*String).\r
+ //\r
+ while ((*String)[StrLen((*String))-1] == L' ') {\r
+ (*String)[StrLen((*String))-1] = CHAR_NULL;\r
+ }\r
+\r
+ return (EFI_SUCCESS);\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\r
+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
+ @param[in] CmdLine The command line to parse.\r
+\r
+ @retval TRUE CmdLine has a valid split.\r
+ @retval FALSE CmdLine does not have a valid split.\r
+**/\r
+BOOLEAN\r
+EFIAPI\r
+ContainsSplit(\r
+ IN CONST CHAR16 *CmdLine\r
+ )\r
+{\r
+ CONST CHAR16 *TempSpot;\r
+ TempSpot = FindSplit(CmdLine);\r
+ return (TempSpot != NULL && *TempSpot != CHAR_NULL);\r
+}\r
+\r
/**\r
Function to start monitoring for CTRL-S using SimpleTextInputEx. This \r
feature's enabled state was not known when the shell initially launched.\r
SimpleEx,\r
&KeyData,\r
NotificationFunction,\r
- &ShellInfoObject.CtrlSNotifyHandle2);\r
+ &ShellInfoObject.CtrlSNotifyHandle3);\r
} \r
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
if (!EFI_ERROR(Status)) {\r
SimpleEx,\r
&KeyData,\r
NotificationFunction,\r
- &ShellInfoObject.CtrlSNotifyHandle2);\r
+ &ShellInfoObject.CtrlSNotifyHandle4);\r
}\r
return (Status);\r
}\r
0,\r
gST->ConOut->Mode->CursorRow,\r
NULL,\r
- STRING_TOKEN (STR_VER_OUTPUT_MAIN),\r
+ STRING_TOKEN (STR_VER_OUTPUT_MAIN_SHELL),\r
ShellInfoObject.HiiHandle,\r
SupportLevel[PcdGet8(PcdShellSupportLevel)],\r
gEfiShellProtocol->MajorVersion,\r
- gEfiShellProtocol->MinorVersion,\r
+ gEfiShellProtocol->MinorVersion\r
+ );\r
+\r
+ ShellPrintHiiEx (\r
+ -1,\r
+ -1,\r
+ NULL,\r
+ STRING_TOKEN (STR_VER_OUTPUT_MAIN_SUPPLIER),\r
+ ShellInfoObject.HiiHandle,\r
+ (CHAR16 *) PcdGetPtr (PcdShellSupplier)\r
+ );\r
+\r
+ ShellPrintHiiEx (\r
+ -1,\r
+ -1,\r
+ NULL,\r
+ STRING_TOKEN (STR_VER_OUTPUT_MAIN_UEFI),\r
+ ShellInfoObject.HiiHandle,\r
(gST->Hdr.Revision&0xffff0000)>>16,\r
(gST->Hdr.Revision&0x0000ffff),\r
gST->FirmwareVendor,\r
Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
}\r
\r
- if (!ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
+ if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
//\r
// begin the UI waiting loop\r
//\r
}\r
if (ShellInfoObject.NewEfiShellProtocol != NULL){\r
if (ShellInfoObject.NewEfiShellProtocol->IsRootShell()){\r
- ShellInfoObject.NewEfiShellProtocol->SetEnv(L"cwd", L"", TRUE);\r
+ InternalEfiShellSetEnv(L"cwd", NULL, TRUE);\r
}\r
CleanUpShellProtocol(ShellInfoObject.NewEfiShellProtocol);\r
DEBUG_CODE(ShellInfoObject.NewEfiShellProtocol = NULL;);\r
{L"-noversion", TypeFlag},\r
{L"-startup", TypeFlag},\r
{L"-delay", TypeValue},\r
+ {L"-_exit", TypeFlag},\r
{NULL, TypeMax}\r
};\r
\r
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap = ShellCommandLineGetFlag(Package, L"-nomap");\r
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = ShellCommandLineGetFlag(Package, L"-noversion");\r
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = ShellCommandLineGetFlag(Package, L"-delay");\r
+ ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = ShellCommandLineGetFlag(Package, L"-_exit");\r
\r
ShellInfoObject.ShellInitSettings.Delay = 5;\r
\r
//\r
// print out our warning and see if they press a key\r
//\r
- for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay * 10\r
+ for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay\r
; Delay != 0 && EFI_ERROR(Status)\r
; Delay--\r
){\r
- ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay/10);\r
- gBS->Stall (100000);\r
+ ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay);\r
+ gBS->Stall (1000000);\r
if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
}\r
CHAR16 *NewCommandLine1;\r
CHAR16 *NewCommandLine2;\r
CHAR16 *Temp;\r
+ CHAR16 *Temp2;\r
UINTN ItemSize;\r
CHAR16 *ItemTemp;\r
SCRIPT_FILE *CurrentScriptFile;\r
}\r
}\r
\r
- //\r
- // Quick out if none were found...\r
- //\r
- if (NewSize == StrSize(OriginalCommandLine)) {\r
- ASSERT(Temp == NULL);\r
- Temp = StrnCatGrow(&Temp, NULL, OriginalCommandLine, 0);\r
- return (Temp);\r
- }\r
-\r
//\r
// now do the replacements...\r
//\r
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);\r
StrCpy(NewCommandLine1, NewCommandLine2);\r
}\r
+\r
+ //\r
+ // Remove non-existant environment variables in scripts only\r
+ //\r
+ for (Temp = NewCommandLine1 ; Temp != NULL ; ) {\r
+ Temp = StrStr(Temp, L"%");\r
+ if (Temp == NULL) {\r
+ break;\r
+ }\r
+ while (*(Temp - 1) == L'^') {\r
+ Temp = StrStr(Temp + 1, L"%");\r
+ if (Temp == NULL) {\r
+ break;\r
+ }\r
+ }\r
+ if (Temp == NULL) {\r
+ break;\r
+ }\r
+ \r
+ Temp2 = StrStr(Temp + 1, L"%");\r
+ if (Temp2 == NULL) {\r
+ break;\r
+ }\r
+ while (*(Temp2 - 1) == L'^') {\r
+ Temp2 = StrStr(Temp2 + 1, L"%");\r
+ if (Temp2 == NULL) {\r
+ break;\r
+ }\r
+ }\r
+ if (Temp2 == NULL) {\r
+ break;\r
+ }\r
+ \r
+ Temp2++;\r
+ CopyMem(Temp, Temp2, StrSize(Temp2));\r
+ }\r
+\r
}\r
\r
+ //\r
+ // Now cleanup any straggler intentionally ignored "%" characters\r
+ //\r
+ ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);\r
+ StrCpy(NewCommandLine1, NewCommandLine2);\r
+ \r
FreePool(NewCommandLine2);\r
FreePool(ItemTemp);\r
\r
UINTN Argc;\r
CHAR16 **Argv;\r
BOOLEAN LastError;\r
- CHAR16 LeString[11];\r
+ CHAR16 LeString[19];\r
CHAR16 *PostAliasCmdLine;\r
UINTN PostAliasSize;\r
CHAR16 *PostVariableCmdLine;\r
SHELL_FILE_HANDLE OriginalStdOut;\r
SHELL_FILE_HANDLE OriginalStdErr;\r
SYSTEM_TABLE_INFO OriginalSystemTableInfo;\r
- CHAR16 *TempLocation3;\r
UINTN Count;\r
UINTN Count2;\r
CHAR16 *CleanOriginal;\r
if (CleanOriginal == NULL) {\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
- while (CleanOriginal[StrLen(CleanOriginal)-1] == L' ') {\r
- CleanOriginal[StrLen(CleanOriginal)-1] = CHAR_NULL;\r
- }\r
- while (CleanOriginal[0] == L' ') {\r
- CopyMem(CleanOriginal, CleanOriginal+1, StrSize(CleanOriginal) - sizeof(CleanOriginal[0]));\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
+ if (CleanOriginal != NULL) {\r
+ FreePool(CleanOriginal);\r
+ CleanOriginal = NULL;\r
+ }\r
+ return (EFI_SUCCESS);\r
}\r
\r
CommandName = NULL;\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
\r
- while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') {\r
- PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL;\r
- }\r
- while (PostVariableCmdLine[0] == L' ') {\r
- CopyMem(PostVariableCmdLine, PostVariableCmdLine+1, StrSize(PostVariableCmdLine) - sizeof(PostVariableCmdLine[0]));\r
- }\r
+ TrimSpaces(&PostVariableCmdLine);\r
\r
//\r
// We dont do normal processing with a split command line (output from one command input to another)\r
//\r
- TempLocation3 = NULL;\r
- if (StrStr(PostVariableCmdLine, L"|") != NULL) {\r
- for (TempLocation3 = PostVariableCmdLine ; TempLocation3 != NULL && *TempLocation3 != CHAR_NULL ; TempLocation3++) {\r
- if (*TempLocation3 == L'^' && *(TempLocation3+1) == L'|') {\r
- TempLocation3++;\r
- } else if (*TempLocation3 == L'|') {\r
- break;\r
- }\r
- }\r
- }\r
- if (TempLocation3 != NULL && *TempLocation3 != CHAR_NULL) {\r
+ if (ContainsSplit(PostVariableCmdLine)) {\r
//\r
// are we in an existing split???\r
//\r
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
}\r
} else {\r
- while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') {\r
- PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL;\r
- }\r
- while (PostVariableCmdLine[0] == L' ') {\r
- CopyMem(PostVariableCmdLine, PostVariableCmdLine+1, StrSize(PostVariableCmdLine) - sizeof(PostVariableCmdLine[0]));\r
- }\r
-\r
+ TrimSpaces(&PostVariableCmdLine);\r
+ \r
//\r
// get the argc and argv updated for internal commands\r
//\r
if (!EFI_ERROR(Status)) {\r
Status = ShellCommandRunCommandHandler(ShellInfoObject.NewShellParametersProtocol->Argv[0], &ShellStatus, &LastError);\r
ASSERT_EFI_ERROR(Status);\r
- UnicodeSPrint(LeString, sizeof(LeString)*sizeof(LeString[0]), L"0x%08x", ShellStatus);\r
- DEBUG_CODE(InternalEfiShellSetEnv(L"DebugLasterror", LeString, TRUE););\r
+\r
+ if (sizeof(EFI_STATUS) == sizeof(UINT64)) {\r
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ShellStatus);\r
+ } else {\r
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%x", ShellStatus);\r
+ }\r
+ DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE););\r
if (LastError) {\r
- InternalEfiShellSetEnv(L"Lasterror", LeString, TRUE);\r
+ InternalEfiShellSetEnv(L"lasterror", LeString, TRUE);\r
}\r
//\r
// Pass thru the exitcode from the app.\r
}\r
if (CommandWithPath == NULL || ShellIsDirectory(CommandWithPath) == EFI_SUCCESS) {\r
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, ShellInfoObject.NewShellParametersProtocol->Argv[0]);\r
+\r
+ if (sizeof(EFI_STATUS) == sizeof(UINT64)) {\r
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", EFI_NOT_FOUND);\r
+ } else {\r
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%x", EFI_NOT_FOUND);\r
+ }\r
+ DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE););\r
+ InternalEfiShellSetEnv(L"lasterror", LeString, TRUE);\r
} else {\r
//\r
// Check if it's a NSH (script) file.\r
);\r
\r
//\r
- // Updatet last error status.\r
+ // Update last error status.\r
//\r
- UnicodeSPrint(LeString, sizeof(LeString)*sizeof(LeString[0]), L"0x%08x", StatusCode);\r
- DEBUG_CODE(InternalEfiShellSetEnv(L"DebugLasterror", LeString, TRUE););\r
- InternalEfiShellSetEnv(L"Lasterror", LeString, TRUE);\r
+ if (sizeof(EFI_STATUS) == sizeof(UINT64)) {\r
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", StatusCode);\r
+ } else {\r
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%x", StatusCode);\r
+ }\r
+ DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE););\r
+ InternalEfiShellSetEnv(L"lasterror", LeString, TRUE);\r
}\r
}\r
}\r
Status = RunCommand(CommandLine3+1);\r
\r
//\r
- // Now restore the pre-'@' echo state.\r
+ // If command was "@echo -off" or "@echo -on" then don't restore echo state\r
//\r
- ShellCommandSetEchoState(PreCommandEchoState);\r
+ if (StrCmp (L"@echo -off", CommandLine3) != 0 &&\r
+ StrCmp (L"@echo -on", CommandLine3) != 0) {\r
+ //\r
+ // Now restore the pre-'@' echo state.\r
+ //\r
+ ShellCommandSetEchoState(PreCommandEchoState);\r
+ }\r
} else {\r
if (ShellCommandGetEchoState()) {\r
CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
}\r
\r
if (ShellCommandGetScriptExit()) {\r
- UnicodeSPrint(LeString, sizeof(LeString)*sizeof(LeString[0]), L"0x%Lx", ShellCommandGetExitCode());\r
- DEBUG_CODE(InternalEfiShellSetEnv(L"DebugLasterror", LeString, TRUE););\r
- InternalEfiShellSetEnv(L"Lasterror", LeString, TRUE);\r
+ //\r
+ // ShellCommandGetExitCode() always returns a UINT64\r
+ //\r
+ UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ShellCommandGetExitCode());\r
+ DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE););\r
+ InternalEfiShellSetEnv(L"lasterror", LeString, TRUE);\r
\r
ShellCommandRegisterExit(FALSE, 0);\r
Status = EFI_SUCCESS;\r