console logger - support disabling the console out.
console wrapper - comment fixes. file handle wrappers - allow for creation of layers of file interfaces to automatically convert ASCII to UCS-2. shell - add CTRL-S support and change how searching for startup.nsh. shellenvvar - zero the memory allocations. shall man parser - input verification on the help text. shellparameters protocol - input redirection verification enhanced, leave ^ behind when not used. shell protocol - remove ASSERTs, fixed GetDeviceName, allow mapping of BlockIO devices, and enhanced key monitoring for CTRL-S (now CTRL-S and CTRL-C). git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11440 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
@ -1,7 +1,7 @@
|
||||
/** @file
|
||||
This is THE shell (application)
|
||||
|
||||
Copyright (c) 2009 - 2010, Intel Corporation. All rights reserved.<BR>
|
||||
Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
are licensed and made available under the terms and conditions of the BSD License
|
||||
which accompanies this distribution. The full text of the license may be found at
|
||||
@ -62,6 +62,82 @@ STATIC CONST CHAR16 mScriptExtension[] = L".NSH";
|
||||
STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI";
|
||||
STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh";
|
||||
|
||||
/**
|
||||
Function to start monitoring for CTRL-S using SimpleTextInputEx. This
|
||||
feature's enabled state was not known when the shell initially launched.
|
||||
|
||||
@retval EFI_SUCCESS The feature is enabled.
|
||||
@retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InternalEfiShellStartCtrlSMonitor(
|
||||
VOID
|
||||
)
|
||||
{
|
||||
EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleEx;
|
||||
EFI_KEY_DATA KeyData;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = gBS->OpenProtocol(
|
||||
gST->ConsoleInHandle,
|
||||
&gEfiSimpleTextInputExProtocolGuid,
|
||||
(VOID**)&SimpleEx,
|
||||
gImageHandle,
|
||||
NULL,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL);
|
||||
if (EFI_ERROR(Status)) {
|
||||
ShellPrintHiiEx(
|
||||
-1,
|
||||
-1,
|
||||
NULL,
|
||||
STRING_TOKEN (STR_SHELL_NO_IN_EX),
|
||||
ShellInfoObject.HiiHandle);
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
|
||||
KeyData.KeyState.KeyToggleState = 0;
|
||||
KeyData.Key.ScanCode = 0;
|
||||
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
|
||||
KeyData.Key.UnicodeChar = L's';
|
||||
|
||||
Status = SimpleEx->RegisterKeyNotify(
|
||||
SimpleEx,
|
||||
&KeyData,
|
||||
NotificationFunction,
|
||||
&ShellInfoObject.CtrlSNotifyHandle1);
|
||||
|
||||
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = SimpleEx->RegisterKeyNotify(
|
||||
SimpleEx,
|
||||
&KeyData,
|
||||
NotificationFunction,
|
||||
&ShellInfoObject.CtrlSNotifyHandle2);
|
||||
}
|
||||
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_LEFT_CONTROL_PRESSED;
|
||||
KeyData.Key.UnicodeChar = 19;
|
||||
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = SimpleEx->RegisterKeyNotify(
|
||||
SimpleEx,
|
||||
&KeyData,
|
||||
NotificationFunction,
|
||||
&ShellInfoObject.CtrlSNotifyHandle2);
|
||||
}
|
||||
KeyData.KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;
|
||||
if (!EFI_ERROR(Status)) {
|
||||
Status = SimpleEx->RegisterKeyNotify(
|
||||
SimpleEx,
|
||||
&KeyData,
|
||||
NotificationFunction,
|
||||
&ShellInfoObject.CtrlSNotifyHandle2);
|
||||
}
|
||||
return (Status);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
The entry point for the application.
|
||||
|
||||
@ -278,6 +354,13 @@ UefiMain (
|
||||
Status = InernalEfiShellStartMonitor();
|
||||
}
|
||||
|
||||
if (!EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
|
||||
//
|
||||
// Set up the event for CTRL-S monitoring...
|
||||
//
|
||||
Status = InternalEfiShellStartCtrlSMonitor();
|
||||
}
|
||||
|
||||
if (!EFI_ERROR(Status) && PcdGet8(PcdShellSupportLevel) >= 1) {
|
||||
//
|
||||
// process the startup script or launch the called app.
|
||||
@ -577,6 +660,7 @@ ProcessCommandLine(
|
||||
UINTN Count;
|
||||
UINTN LoopVar;
|
||||
CHAR16 *ProblemParam;
|
||||
UINT64 Intermediate;
|
||||
|
||||
Package = NULL;
|
||||
ProblemParam = NULL;
|
||||
@ -587,7 +671,7 @@ ProcessCommandLine(
|
||||
Size = 0;
|
||||
TempConst = ShellCommandLineGetRawValue(Package, Count++);
|
||||
if (TempConst != NULL && StrLen(TempConst)) {
|
||||
ShellInfoObject.ShellInitSettings.FileName = AllocatePool(StrSize(TempConst));
|
||||
ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(TempConst));
|
||||
if (ShellInfoObject.ShellInitSettings.FileName == NULL) {
|
||||
return (EFI_OUT_OF_RESOURCES);
|
||||
}
|
||||
@ -641,17 +725,19 @@ ProcessCommandLine(
|
||||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoVersion = ShellCommandLineGetFlag(Package, L"-noversion");
|
||||
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay = ShellCommandLineGetFlag(Package, L"-delay");
|
||||
|
||||
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay) {
|
||||
TempConst = ShellCommandLineGetValue(Package, L"-delay");
|
||||
if (TempConst != NULL) {
|
||||
ShellInfoObject.ShellInitSettings.Delay = StrDecimalToUintn (TempConst);
|
||||
} else {
|
||||
ShellInfoObject.ShellInitSettings.Delay = 5;
|
||||
}
|
||||
} else {
|
||||
ShellInfoObject.ShellInitSettings.Delay = 5;
|
||||
}
|
||||
ShellInfoObject.ShellInitSettings.Delay = 5;
|
||||
|
||||
if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoInterrupt) {
|
||||
ShellInfoObject.ShellInitSettings.Delay = 0;
|
||||
} else if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay) {
|
||||
TempConst = ShellCommandLineGetValue(Package, L"-delay");
|
||||
if (*TempConst == L':') {
|
||||
TempConst++;
|
||||
}
|
||||
if (TempConst != NULL && !EFI_ERROR(ShellConvertStringToUint64(TempConst, &Intermediate, FALSE, FALSE))) {
|
||||
ShellInfoObject.ShellInitSettings.Delay = (UINTN)Intermediate;
|
||||
}
|
||||
}
|
||||
ShellCommandLineFreeVarList(Package);
|
||||
|
||||
return (Status);
|
||||
@ -681,7 +767,9 @@ DoStartupScript(
|
||||
EFI_DEVICE_PATH_PROTOCOL *NewPath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *NamePath;
|
||||
CHAR16 *FileStringPath;
|
||||
CHAR16 *TempSpot;
|
||||
UINTN NewSize;
|
||||
CONST CHAR16 *MapName;
|
||||
|
||||
Key.UnicodeChar = CHAR_NULL;
|
||||
Key.ScanCode = 0;
|
||||
@ -723,13 +811,15 @@ DoStartupScript(
|
||||
//
|
||||
// print out our warning and see if they press a key
|
||||
//
|
||||
for ( Status = EFI_UNSUPPORTED, Delay = (ShellInfoObject.ShellInitSettings.Delay * 10)
|
||||
; Delay > 0 && EFI_ERROR(Status)
|
||||
for ( Status = EFI_UNSUPPORTED, Delay = ShellInfoObject.ShellInitSettings.Delay * 10
|
||||
; Delay != 0 && EFI_ERROR(Status)
|
||||
; Delay--
|
||||
){
|
||||
ShellPrintHiiEx(0, gST->ConOut->Mode->CursorRow, NULL, STRING_TOKEN (STR_SHELL_STARTUP_QUESTION), ShellInfoObject.HiiHandle, Delay/10);
|
||||
gBS->Stall (100000);
|
||||
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
|
||||
if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) {
|
||||
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
|
||||
}
|
||||
}
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_CRLF), ShellInfoObject.HiiHandle);
|
||||
|
||||
@ -740,25 +830,39 @@ DoStartupScript(
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
|
||||
NamePath = FileDevicePath (NULL, mStartupScript);
|
||||
//
|
||||
// Try the first location
|
||||
// Try the first location (must be file system)
|
||||
//
|
||||
NewPath = AppendDevicePathNode (ImagePath, NamePath);
|
||||
Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);
|
||||
if (EFI_ERROR(Status)) {
|
||||
//
|
||||
// Try the second location
|
||||
//
|
||||
FreePool(NewPath);
|
||||
NewPath = AppendDevicePathNode (FilePath , NamePath);
|
||||
Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);
|
||||
MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath(&ImagePath);
|
||||
if (MapName != NULL) {
|
||||
FileStringPath = NULL;
|
||||
NewSize = 0;
|
||||
FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, MapName, 0);
|
||||
TempSpot = StrStr(FileStringPath, L";");
|
||||
if (TempSpot != NULL) {
|
||||
*TempSpot = CHAR_NULL;
|
||||
}
|
||||
FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, ((FILEPATH_DEVICE_PATH*)FilePath)->PathName, 0);
|
||||
ChopLastSlash(FileStringPath);
|
||||
FileStringPath = StrnCatGrow(&FileStringPath, &NewSize, mStartupScript, 0);
|
||||
Status = ShellInfoObject.NewEfiShellProtocol->OpenFileByName(FileStringPath, &FileHandle, EFI_FILE_MODE_READ);
|
||||
FreePool(FileStringPath);
|
||||
}
|
||||
if (EFI_ERROR(Status)) {
|
||||
NamePath = FileDevicePath (NULL, mStartupScript);
|
||||
NewPath = AppendDevicePathNode (ImagePath, NamePath);
|
||||
FreePool(NamePath);
|
||||
|
||||
//
|
||||
// Try the location
|
||||
//
|
||||
Status = InternalOpenFileDevicePath(NewPath, &FileHandle, EFI_FILE_MODE_READ, 0);
|
||||
FreePool(NewPath);
|
||||
}
|
||||
//
|
||||
// If we got a file, run it
|
||||
//
|
||||
if (!EFI_ERROR(Status)) {
|
||||
if (!EFI_ERROR(Status) && FileHandle != NULL) {
|
||||
Status = RunScriptFileHandle (FileHandle, mStartupScript);
|
||||
ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle);
|
||||
} else {
|
||||
@ -775,8 +879,6 @@ DoStartupScript(
|
||||
}
|
||||
}
|
||||
|
||||
FreePool(NamePath);
|
||||
FreePool(NewPath);
|
||||
|
||||
return (Status);
|
||||
}
|
||||
@ -920,7 +1022,7 @@ ShellConvertAlias(
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
FreePool(*CommandString);
|
||||
*CommandString = AllocatePool(StrSize(NewString));
|
||||
*CommandString = AllocateZeroPool(StrSize(NewString));
|
||||
if (*CommandString == NULL) {
|
||||
return (EFI_OUT_OF_RESOURCES);
|
||||
}
|
||||
@ -1185,7 +1287,7 @@ RunCommand(
|
||||
UINTN PostAliasSize;
|
||||
CHAR16 *PostVariableCmdLine;
|
||||
CHAR16 *CommandWithPath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevPath;
|
||||
CONST EFI_DEVICE_PATH_PROTOCOL *DevPath;
|
||||
CONST CHAR16 *TempLocation;
|
||||
CONST CHAR16 *TempLocation2;
|
||||
SHELL_FILE_HANDLE OriginalStdIn;
|
||||
@ -1319,7 +1421,11 @@ RunCommand(
|
||||
|
||||
Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);
|
||||
if (EFI_ERROR(Status)) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);
|
||||
if (Status == EFI_NOT_FOUND) {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);
|
||||
} else {
|
||||
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// remove the < and/or > from the command line now
|
||||
@ -1452,7 +1558,6 @@ RunCommand(
|
||||
SHELL_FREE_NON_NULL(CommandName);
|
||||
SHELL_FREE_NON_NULL(CommandWithPath);
|
||||
SHELL_FREE_NON_NULL(PostVariableCmdLine);
|
||||
SHELL_FREE_NON_NULL(DevPath);
|
||||
|
||||
return (Status);
|
||||
}
|
||||
@ -1591,12 +1696,12 @@ RunScriptFileHandle (
|
||||
//
|
||||
// Now enumerate through the commands and run each one.
|
||||
//
|
||||
CommandLine = AllocatePool(PcdGet16(PcdShellPrintBufferSize));
|
||||
CommandLine = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));
|
||||
if (CommandLine == NULL) {
|
||||
DeleteScriptFileStruct(NewScriptFile);
|
||||
return (EFI_OUT_OF_RESOURCES);
|
||||
}
|
||||
CommandLine2 = AllocatePool(PcdGet16(PcdShellPrintBufferSize));
|
||||
CommandLine2 = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));
|
||||
if (CommandLine2 == NULL) {
|
||||
FreePool(CommandLine);
|
||||
DeleteScriptFileStruct(NewScriptFile);
|
||||
@ -1732,11 +1837,17 @@ RunScriptFileHandle (
|
||||
}
|
||||
}
|
||||
|
||||
ShellCommandSetEchoState(PreScriptEchoState);
|
||||
|
||||
FreePool(CommandLine);
|
||||
FreePool(CommandLine2);
|
||||
ShellCommandSetNewScript (NULL);
|
||||
|
||||
//
|
||||
// Only if this was the last script reset the state.
|
||||
//
|
||||
if (ShellCommandGetCurrentScriptFile()==NULL) {
|
||||
ShellCommandSetEchoState(PreScriptEchoState);
|
||||
}
|
||||
return (EFI_SUCCESS);
|
||||
}
|
||||
|
||||
|
Reference in New Issue
Block a user