diff --git a/CorebootModulePkg/Library/CorebootBdsLib/BdsPlatform.c b/CorebootModulePkg/Library/CorebootBdsLib/BdsPlatform.c index 859cfd946d..def2ad241d 100644 --- a/CorebootModulePkg/Library/CorebootBdsLib/BdsPlatform.c +++ b/CorebootModulePkg/Library/CorebootBdsLib/BdsPlatform.c @@ -1169,6 +1169,19 @@ InstallReadyToLock ( 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 EFIAPI PlatformBdsPolicyBehavior ( @@ -1198,9 +1211,13 @@ Returns: --*/ { EFI_STATUS Status; - UINT16 Timeout; + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *SimpleTextInEx; + EFI_KEY_DATA EscapeKeyData; + EFI_HANDLE EscapeKeyHandle; EFI_EVENT UserInputDurationTime; + EFI_EVENT Events[2]; UINTN Index; + UINT16 Timeout; EFI_INPUT_KEY Key; EFI_BOOT_MODE BootMode; @@ -1238,6 +1255,30 @@ Returns: 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 // @@ -1250,9 +1291,9 @@ Returns: // 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 ( EVT_TIMER, @@ -1265,24 +1306,49 @@ Returns: Status = gBS->SetTimer (UserInputDurationTime, TimerRelative, 20000000); ASSERT (Status == EFI_SUCCESS); - // - // 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 - // Check whether the user input after the duration time has expired - // - gBS->WaitForEvent (1, &UserInputDurationTime, &Index); - gBS->CloseEvent (UserInputDurationTime); - Status = gST->ConIn->ReadKeyStroke (gST->ConIn, &Key); - - if (!EFI_ERROR (Status)) { - // - // Enter Setup if user input - // - Timeout = 0xffff; - } else { - Timeout = 0; + // 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. + // BDS should still give user a chance to enter Setup + // Check whether the user input after the duration time has expired + // + Events[0] = gST->ConIn->WaitForKey; + Events[1] = UserInputDurationTime; + gBS->WaitForEvent (2, Events, &Index); } - + gBS->CloseEvent (UserInputDurationTime); + + 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)) { + // + // Enter Setup if user input + // + ESCAPE_KEY_DETECTED = TRUE; + } + } + + if (ESCAPE_KEY_DETECTED) { + 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 { + Timeout = 0; + } + BdsLibEnumerateAllBootOption (BootOptionList); PlatformBdsEnterFrontPage (Timeout, FALSE); //not run/reached if Timeout = 0xffff @@ -1315,10 +1381,15 @@ Returns: --*/ { - CHAR16 *TmpStr; + EFI_INPUT_KEY Key; + CHAR16 *TmpStr; + // Clear screen before showing success message 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 // select loop then we need to pop up a UI and wait for user input. @@ -1360,10 +1431,15 @@ Returns: --*/ { - CHAR16 *TmpStr; + EFI_INPUT_KEY Key; + CHAR16 *TmpStr; + // Clear screen before showing fail message 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 // for user input.