Revise key handling in boot phase

Add escape key handler as early as possible, and set timeout immediately
upon displaying splash.
This commit is contained in:
Jeremy Soller
2019-10-03 15:24:51 -06:00
committed by Tim Crawford
parent 52d5d1b2c5
commit 976842130a

View File

@ -1169,6 +1169,19 @@ InstallReadyToLock (
return; return;
} }
static BOOLEAN ESCAPE_KEY_DETECTED = FALSE;
EFI_STATUS
EFIAPI
EscapeKeyNotify (
EFI_KEY_DATA *KeyData
)
{
DEBUG((DEBUG_INFO, "Detected escape key\n"));
ESCAPE_KEY_DETECTED = TRUE;
return EFI_SUCCESS;
}
VOID VOID
EFIAPI EFIAPI
PlatformBdsPolicyBehavior ( PlatformBdsPolicyBehavior (
@ -1198,9 +1211,13 @@ Returns:
--*/ --*/
{ {
EFI_STATUS Status; EFI_STATUS Status;
UINT16 Timeout; EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx;
EFI_KEY_DATA EscapeKeyData;
EFI_HANDLE EscapeKeyHandle;
EFI_EVENT UserInputDurationTime; EFI_EVENT UserInputDurationTime;
EFI_EVENT Events[2];
UINTN Index; UINTN Index;
UINT16 Timeout;
EFI_INPUT_KEY Key; EFI_INPUT_KEY Key;
EFI_BOOT_MODE BootMode; EFI_BOOT_MODE BootMode;
@ -1238,6 +1255,30 @@ Returns:
PlatformBdsNoConsoleAction (); PlatformBdsNoConsoleAction ();
} }
// Find simple text input extension protocol for console in
SimpleTextInEx = NULL;
Status = gBS->HandleProtocol(
gST->ConsoleInHandle,
&gEfiSimpleTextInputExProtocolGuid,
(VOID **) &SimpleTextInEx
);
// Register a handler for escape key
ESCAPE_KEY_DETECTED = FALSE;
if (SimpleTextInEx != NULL) {
EscapeKeyData.Key.ScanCode = SCAN_ESC;
EscapeKeyData.Key.UnicodeChar = 0;
EscapeKeyData.KeyState.KeyShiftState = 0;
EscapeKeyData.KeyState.KeyToggleState = 0;
Status = SimpleTextInEx->RegisterKeyNotify(
SimpleTextInEx,
&EscapeKeyData,
EscapeKeyNotify,
&EscapeKeyHandle
);
ASSERT (Status == EFI_SUCCESS);
}
// //
// Perform some platform specific connect sequence // Perform some platform specific connect sequence
// //
@ -1252,7 +1293,7 @@ Returns:
BdsLibConnectAll (); BdsLibConnectAll ();
// //
// Create a 1s duration event to ensure user has enough input time to enter Setup // Create a 2s duration event to ensure user has enough input time to enter Setup
// //
Status = gBS->CreateEvent ( Status = gBS->CreateEvent (
EVT_TIMER, EVT_TIMER,
@ -1265,20 +1306,45 @@ Returns:
Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 20000000); Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 20000000);
ASSERT (Status == EFI_SUCCESS); ASSERT (Status == EFI_SUCCESS);
// Connect all drivers, could be delayed
BdsLibConnectAll ();
// The escape key could have been pressed already
if (!ESCAPE_KEY_DETECTED) {
// //
// To give the User a chance to enter Setup here, if user set TimeOut is 0. // To give the User a chance to enter Setup here, if user set TimeOut is 0.
// BDS should still give user a chance to enter Setup // BDS should still give user a chance to enter Setup
// Check whether the user input after the duration time has expired // Check whether the user input after the duration time has expired
// //
gBS->WaitForEvent (1, &UserInputDurationTime, &Index); Events[0] = gST->ConIn->WaitForKey;
Events[1] = UserInputDurationTime;
gBS->WaitForEvent (2, Events, &Index);
}
gBS->CloseEvent (UserInputDurationTime); gBS->CloseEvent (UserInputDurationTime);
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if (SimpleTextInEx != NULL) {
// Remove escape key handler
Status = SimpleTextInEx->UnregisterKeyNotify(
SimpleTextInEx,
EscapeKeyHandle
);
ASSERT (Status == EFI_SUCCESS);
} else {
Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key);
if (!EFI_ERROR (Status)) { if (!EFI_ERROR (Status)) {
// //
// Enter Setup if user input // Enter Setup if user input
// //
ESCAPE_KEY_DETECTED = TRUE;
}
}
if (ESCAPE_KEY_DETECTED) {
Timeout = 0xffff; Timeout = 0xffff;
DEBUG((DEBUG_INFO, "Escape key detected, going to menu\n"));
// Clear pending keypresses if we are going to the menu
while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {}
} else { } else {
Timeout = 0; Timeout = 0;
} }
@ -1315,10 +1381,15 @@ Returns:
--*/ --*/
{ {
EFI_INPUT_KEY Key;
CHAR16 *TmpStr; CHAR16 *TmpStr;
// Clear screen before showing success message
gST->ConOut->ClearScreen(gST->ConOut); gST->ConOut->ClearScreen(gST->ConOut);
// Clear pending keypresses before showing success message
while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {}
// //
// If Boot returned with EFI_SUCCESS and there is not in the boot device // If Boot returned with EFI_SUCCESS and there is not in the boot device
// select loop then we need to pop up a UI and wait for user input. // select loop then we need to pop up a UI and wait for user input.
@ -1360,10 +1431,15 @@ Returns:
--*/ --*/
{ {
EFI_INPUT_KEY Key;
CHAR16 *TmpStr; CHAR16 *TmpStr;
// Clear screen before showing fail message
gST->ConOut->ClearScreen(gST->ConOut); gST->ConOut->ClearScreen(gST->ConOut);
// Clear pending keypresses before showing fail message
while (!EFI_ERROR (gST->ConIn->ReadKeyStroke (gST->ConIn, &Key))) {}
// //
// If Boot returned with failed status then we need to pop up a UI and wait // If Boot returned with failed status then we need to pop up a UI and wait
// for user input. // for user input.