/** @file\r
This is THE shell (application)\r
\r
- Copyright (c) 2009 - 2010, 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
+ NULL,\r
+ NULL,\r
+ FALSE\r
};\r
\r
STATIC CONST CHAR16 mScriptExtension[] = L".NSH";\r
STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";\r
STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";\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
+\r
+ @retval EFI_SUCCESS The feature is enabled.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+InternalEfiShellStartCtrlSMonitor(\r
+ VOID\r
+ )\r
+{\r
+ EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;\r
+ EFI_KEY_DATA KeyData;\r
+ EFI_STATUS Status;\r
+\r
+ Status = gBS->OpenProtocol(\r
+ gST->ConsoleInHandle,\r
+ &gEfiSimpleTextInputExProtocolGuid,\r
+ (VOID**)&SimpleEx,\r
+ gImageHandle,\r
+ NULL,\r
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
+ if (EFI_ERROR(Status)) {\r
+ ShellPrintHiiEx(\r
+ -1, \r
+ -1, \r
+ NULL,\r
+ STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
+ ShellInfoObject.HiiHandle);\r
+ return (EFI_SUCCESS);\r
+ }\r
+\r
+ KeyData.KeyState.KeyToggleState = 0;\r
+ KeyData.Key.ScanCode = 0;\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+ KeyData.Key.UnicodeChar = L's';\r
+\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlSNotifyHandle1);\r
+ \r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlSNotifyHandle2);\r
+ }\r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;\r
+ KeyData.Key.UnicodeChar = 19;\r
+\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlSNotifyHandle2);\r
+ } \r
+ KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
+ if (!EFI_ERROR(Status)) {\r
+ Status = SimpleEx->RegisterKeyNotify(\r
+ SimpleEx,\r
+ &KeyData,\r
+ NotificationFunction,\r
+ &ShellInfoObject.CtrlSNotifyHandle2);\r
+ }\r
+ return (Status);\r
+}\r
+\r
+\r
+\r
/**\r
The entry point for the application.\r
\r
IN EFI_SYSTEM_TABLE *SystemTable\r
)\r
{\r
- EFI_STATUS Status;\r
- CHAR16 *TempString;\r
- UINTN Size;\r
-// EFI_INPUT_KEY Key;\r
-\r
-// gST->ConOut->OutputString(gST->ConOut, L"ReadKeyStroke Calling\r\n");\r
-//\r
-// Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\r
-//\r
-// gST->ConOut->OutputString(gST->ConOut, L"ReadKeyStroke Done\r\n");\r
-// gBS->Stall (1000000);\r
+ EFI_STATUS Status;\r
+ CHAR16 *TempString;\r
+ UINTN Size;\r
+ EFI_HANDLE ConInHandle;\r
+ EFI_SIMPLE_TEXT_INPUT_PROTOCOL *OldConIn;\r
\r
if (PcdGet8(PcdShellSupportLevel) > 3) {\r
return (EFI_UNSUPPORTED);\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 = InernalEfiShellStartMonitor();\r
}\r
\r
+ if (!EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
+ //\r
+ // Set up the event for CTRL-S monitoring...\r
+ //\r
+ Status = InternalEfiShellStartCtrlSMonitor();\r
+ }\r
+\r
+ if (!EFI_ERROR(Status) && ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {\r
+ //\r
+ // close off the gST->ConIn\r
+ //\r
+ OldConIn = gST->ConIn;\r
+ ConInHandle = gST->ConsoleInHandle;\r
+ gST->ConIn = CreateSimpleTextInOnFile((SHELL_FILE_HANDLE)&FileInterfaceNulFile, &gST->ConsoleInHandle);\r
+ } else {\r
+ OldConIn = NULL;\r
+ ConInHandle = NULL;\r
+ }\r
+\r
if (!EFI_ERROR(Status) && PcdGet8(PcdShellSupportLevel) >= 1) {\r
//\r
// process the startup script or launch the called app.\r
Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath);\r
}\r
\r
- if ((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
Status = DoShellPrompt();\r
} while (!ShellCommandGetExit());\r
}\r
+ if (OldConIn != NULL && ConInHandle != NULL) {\r
+ CloseSimpleTextInOnFile (gST->ConIn);\r
+ gST->ConIn = OldConIn;\r
+ gST->ConsoleInHandle = ConInHandle;\r
+ }\r
}\r
}\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
DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;);\r
}\r
\r
+ if (ShellCommandGetExit()) {\r
+ return ((EFI_STATUS)ShellCommandGetExitCode());\r
+ }\r
return (Status);\r
}\r
\r
return (FALSE);\r
}\r
\r
-\r
-\r
/**\r
This function will populate the 2 device path protocol parameters based on the\r
global gImageHandle. The DevPath will point to the device path for the handle that has\r
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 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
\r
@retval EFI_SUCCESS The 2 device paths were sucessfully returned.\r
@retval other A error from gBS->HandleProtocol.\r
if (!EFI_ERROR (Status)) {\r
*DevPath = DuplicateDevicePath (ImageDevicePath);\r
*FilePath = DuplicateDevicePath (LoadedImage->FilePath);\r
+ gBS->CloseProtocol(\r
+ LoadedImage->DeviceHandle,\r
+ &gEfiDevicePathProtocolGuid,\r
+ gImageHandle,\r
+ NULL);\r
}\r
gBS->CloseProtocol(\r
gImageHandle,\r
{L"-noversion", TypeFlag},\r
{L"-startup", TypeFlag},\r
{L"-delay", TypeValue},\r
+ {L"-_exit", TypeFlag},\r
{NULL, TypeMax}\r
};\r
+\r
/**\r
Process all Uefi Shell 2.0 command line options.\r
\r
UINTN Count;\r
UINTN LoopVar;\r
CHAR16 *ProblemParam;\r
+ UINT64 Intermediate;\r
\r
Package = NULL;\r
ProblemParam = NULL;\r
Size = 0;\r
TempConst = ShellCommandLineGetRawValue(Package, Count++);\r
if (TempConst != NULL && StrLen(TempConst)) {\r
- ShellInfoObject.ShellInitSettings.FileName = AllocatePool(StrSize(TempConst));\r
+ ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(TempConst));\r
if (ShellInfoObject.ShellInitSettings.FileName == NULL) {\r
return (EFI_OUT_OF_RESOURCES);\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
- if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay) {\r
+ ShellInfoObject.ShellInitSettings.Delay = 5;\r
+\r
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {\r
+ ShellInfoObject.ShellInitSettings.Delay = 0;\r
+ } else if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay) {\r
TempConst = ShellCommandLineGetValue(Package, L"-delay");\r
- if (TempConst != NULL) {\r
- ShellInfoObject.ShellInitSettings.Delay = StrDecimalToUintn (TempConst);\r
- } else {\r
- ShellInfoObject.ShellInitSettings.Delay = 5;\r
+ if (TempConst != NULL && *TempConst == L':') {\r
+ TempConst++;\r
+ }\r
+ if (TempConst != NULL && !EFI_ERROR(ShellConvertStringToUint64(TempConst, &Intermediate, FALSE, FALSE))) {\r
+ ShellInfoObject.ShellInitSettings.Delay = (UINTN)Intermediate;\r
}\r
- } else {\r
- ShellInfoObject.ShellInitSettings.Delay = 5;\r
}\r
-\r
ShellCommandLineFreeVarList(Package);\r
\r
return (Status);\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
return (EFI_SUCCESS);\r
}\r
\r
+ gST->ConOut->EnableCursor(gST->ConOut, FALSE);\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
- ; Delay > 0 && EFI_ERROR(Status)\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
- Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);\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
}\r
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle);\r
+ gST->ConOut->EnableCursor(gST->ConOut, TRUE);\r
\r
//\r
// ESC was pressed\r
return (EFI_SUCCESS);\r
}\r
\r
- NamePath = FileDevicePath (NULL, mStartupScript);\r
//\r
- // Try the first location\r
+ // Try the first location (must be file system)\r
//\r
- NewPath = AppendDevicePathNode (ImagePath, NamePath);\r
- Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);\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
//\r
- // Try the second location\r
+ // Try the location\r
//\r
- FreePool(NewPath);\r
- NewPath = AppendDevicePathNode (FilePath , NamePath);\r
Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);\r
+ FreePool(NewPath);\r
}\r
-\r
//\r
// If we got a file, run it\r
//\r
- if (!EFI_ERROR(Status)) {\r
+ if (!EFI_ERROR(Status) && FileHandle != NULL) {\r
Status = RunScriptFileHandle (FileHandle, mStartupScript);\r
ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);\r
} else {\r
}\r
}\r
\r
- FreePool(NamePath);\r
- FreePool(NewPath);\r
\r
return (Status);\r
}\r
Checks if a string is an alias for another command. If yes, then it replaces the alias name\r
with the correct command name.\r
\r
- @param[in,out] CommandString Upon entry the potential alias. Upon return the\r
- command name if it was an alias. If it was not\r
- an alias it will be unchanged. This function may\r
- change the buffer to fit the command name.\r
+ @param[in, out] CommandString Upon entry the potential alias. Upon return the\r
+ command name if it was an alias. If it was not\r
+ an alias it will be unchanged. This function may\r
+ change the buffer to fit the command name.\r
\r
@retval EFI_SUCCESS The name was changed.\r
@retval EFI_SUCCESS The name was not an alias.\r
return (EFI_SUCCESS);\r
}\r
FreePool(*CommandString);\r
- *CommandString = AllocatePool(StrSize(NewString));\r
+ *CommandString = AllocateZeroPool(StrSize(NewString));\r
if (*CommandString == NULL) {\r
return (EFI_OUT_OF_RESOURCES);\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
\r
NextCommandLine = StrnCatGrow(&NextCommandLine, &Size1, StrStr(CmdLine, L"|")+1, 0);\r
OurCommandLine = StrnCatGrow(&OurCommandLine , &Size2, CmdLine , StrStr(CmdLine, L"|") - CmdLine);\r
- if (NextCommandLine[0] != CHAR_NULL &&\r
+\r
+ if (NextCommandLine == NULL || OurCommandLine == NULL) {\r
+ SHELL_FREE_NON_NULL(OurCommandLine);\r
+ SHELL_FREE_NON_NULL(NextCommandLine);\r
+ return (EFI_OUT_OF_RESOURCES);\r
+ } else if (StrStr(OurCommandLine, L"|") != NULL || Size1 == 0 || Size2 == 0) {\r
+ 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
ASSERT(Split->SplitStdOut != NULL);\r
InsertHeadList(&ShellInfoObject.SplitList.Link, &Split->Link);\r
\r
- ASSERT(StrStr(OurCommandLine, L"|") == NULL);\r
Status = RunCommand(OurCommandLine);\r
\r
//\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_STATUS StatusCode;\r
CHAR16 *CommandName;\r
SHELL_STATUS ShellStatus;\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
CHAR16 *CommandWithPath;\r
- EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
+ CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;\r
CONST CHAR16 *TempLocation;\r
CONST CHAR16 *TempLocation2;\r
SHELL_FILE_HANDLE OriginalStdIn;\r
Split = NULL;\r
\r
CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0);\r
- while (CleanOriginal[StrLen(CleanOriginal)-1] == L' ') {\r
- CleanOriginal[StrLen(CleanOriginal)-1] = CHAR_NULL;\r
+ if (CleanOriginal == NULL) {\r
+ return (EFI_OUT_OF_RESOURCES);\r
}\r
- while (CleanOriginal[0] == L' ') {\r
+\r
+ //\r
+ // Remove any spaces and tabs at the beginning of the string.\r
+ //\r
+ while ((CleanOriginal[0] == L' ') || (CleanOriginal[0] == L'\t')) {\r
CopyMem(CleanOriginal, CleanOriginal+1, StrSize(CleanOriginal) - sizeof(CleanOriginal[0]));\r
}\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
+ //\r
+ // Remove any spaces at the end of the string.\r
+ //\r
+ while (CleanOriginal[StrLen(CleanOriginal)-1] == L' ') {\r
+ CleanOriginal[StrLen(CleanOriginal)-1] = CHAR_NULL;\r
+ }\r
+\r
CommandName = NULL;\r
if (StrStr(CleanOriginal, L" ") == NULL){\r
StrnCatGrow(&CommandName, NULL, CleanOriginal, 0);\r
} else {\r
Status = RunSplitCommand(PostVariableCmdLine, Split->SplitStdIn, Split->SplitStdOut);\r
}\r
+ if (EFI_ERROR(Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, PostVariableCmdLine);\r
+ }\r
} else {\r
\r
//\r
\r
Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);\r
if (EFI_ERROR(Status)) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
- } else {\r
- //\r
- // remove the < and/or > from the command line now\r
- //\r
- for (TempLocation3 = PostVariableCmdLine ; TempLocation3 != NULL && *TempLocation3 != CHAR_NULL ; TempLocation3++) {\r
- if (*TempLocation3 == L'^') {\r
- if (*(TempLocation3+1) == L'<' || *(TempLocation3+1) == L'>') {\r
- CopyMem(TempLocation3, TempLocation3+1, StrSize(TempLocation3) - sizeof(TempLocation3[0]));\r
- }\r
- } else if (*TempLocation3 == L'>') {\r
- *TempLocation3 = CHAR_NULL;\r
- } else if ((*TempLocation3 == L'1' || *TempLocation3 == L'2')&&(*(TempLocation3+1) == L'>')) {\r
- *TempLocation3 = CHAR_NULL;\r
- }\r
+ if (Status == EFI_NOT_FOUND) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
+ } else {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
}\r
-\r
+ } else {\r
while (PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] == L' ') {\r
PostVariableCmdLine[StrLen(PostVariableCmdLine)-1] = CHAR_NULL;\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
DevPath,\r
PostVariableCmdLine,\r
NULL,\r
- NULL\r
+ &StatusCode\r
);\r
+\r
+ //\r
+ // Update last error status.\r
+ //\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
+\r
+ //\r
+ // Print some error info.\r
+ //\r
+ if (EFI_ERROR(Status)) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_ERROR), ShellInfoObject.HiiHandle, (VOID*)(Status));\r
+ }\r
+\r
CommandName = StrnCatGrow(&CommandName, NULL, ShellInfoObject.NewShellParametersProtocol->Argv[0], 0);\r
\r
RestoreArgcArgv(ShellInfoObject.NewShellParametersProtocol, &Argv, &Argc);\r
SHELL_FREE_NON_NULL(CommandName);\r
SHELL_FREE_NON_NULL(CommandWithPath);\r
SHELL_FREE_NON_NULL(PostVariableCmdLine);\r
- SHELL_FREE_NON_NULL(DevPath);\r
\r
return (Status);\r
}\r
SCRIPT_COMMAND_LIST *LastCommand;\r
BOOLEAN Ascii;\r
BOOLEAN PreScriptEchoState;\r
+ BOOLEAN PreCommandEchoState;\r
CONST CHAR16 *CurDir;\r
UINTN LineCount;\r
+ CHAR16 LeString[50];\r
\r
ASSERT(!ShellCommandGetScriptExit());\r
\r
//\r
// Now enumerate through the commands and run each one.\r
//\r
- CommandLine = AllocatePool(PcdGet16(PcdShellPrintBufferSize));\r
+ CommandLine = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
if (CommandLine == NULL) {\r
DeleteScriptFileStruct(NewScriptFile);\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
- CommandLine2 = AllocatePool(PcdGet16(PcdShellPrintBufferSize));\r
+ CommandLine2 = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
if (CommandLine2 == NULL) {\r
FreePool(CommandLine);\r
DeleteScriptFileStruct(NewScriptFile);\r
//\r
} else {\r
if (CommandLine3 != NULL && StrLen(CommandLine3) > 0) {\r
- if (ShellCommandGetEchoState()) {\r
- CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
- if (CurDir != NULL && StrLen(CurDir) > 1) {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);\r
- } else {\r
- ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);\r
+ if (CommandLine3[0] == L'@') {\r
+ //\r
+ // We need to save the current echo state\r
+ // and disable echo for just this command.\r
+ //\r
+ PreCommandEchoState = ShellCommandGetEchoState();\r
+ ShellCommandSetEchoState(FALSE);\r
+ Status = RunCommand(CommandLine3+1);\r
+\r
+ //\r
+ // If command was "@echo -off" or "@echo -on" then don't restore echo state\r
+ //\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
- ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2);\r
+ } else {\r
+ if (ShellCommandGetEchoState()) {\r
+ CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
+ if (CurDir != NULL && StrLen(CurDir) > 1) {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CURDIR), ShellInfoObject.HiiHandle, CurDir);\r
+ } else {\r
+ ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_SHELL), ShellInfoObject.HiiHandle);\r
+ }\r
+ ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2);\r
+ }\r
+ Status = RunCommand(CommandLine3);\r
}\r
- Status = RunCommand(CommandLine3);\r
}\r
\r
if (ShellCommandGetScriptExit()) {\r
- ShellCommandRegisterExit(FALSE);\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
break;\r
}\r
+ if (ShellGetExecutionBreakFlag()) {\r
+ break;\r
+ }\r
if (EFI_ERROR(Status)) {\r
break;\r
}\r
}\r
}\r
\r
- ShellCommandSetEchoState(PreScriptEchoState);\r
\r
FreePool(CommandLine);\r
FreePool(CommandLine2);\r
ShellCommandSetNewScript (NULL);\r
+\r
+ //\r
+ // Only if this was the last script reset the state.\r
+ //\r
+ if (ShellCommandGetCurrentScriptFile()==NULL) {\r
+ ShellCommandSetEchoState(PreScriptEchoState);\r
+ }\r
return (EFI_SUCCESS);\r
}\r
\r