summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKay Sievers <kay@vrfy.org>2013-09-22 15:28:49 -0500
committerKay Sievers <kay@vrfy.org>2013-09-22 15:28:49 -0500
commit6ab76f37af8d23816248d5271575d187d823ae3f (patch)
tree556fd7a0786881912f2063442c5a9980930d28cf
parentbe92c65ffc88eb3e52f2a85194bc5303bd20f642 (diff)
try harder to work around firmware with broken SIMPLE_TEXT_INPUT_EX_PROTOCOL
-rw-r--r--src/efi/gummiboot.c84
1 files changed, 36 insertions, 48 deletions
diff --git a/src/efi/gummiboot.c b/src/efi/gummiboot.c
index 1e16ef0..3855c95 100644
--- a/src/efi/gummiboot.c
+++ b/src/efi/gummiboot.c
@@ -284,10 +284,8 @@ static EFI_STATUS key_read(UINT64 *key, BOOLEAN wait) {
EFI_GUID EfiSimpleTextInputExProtocolGuid = EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *TextInputEx;
static BOOLEAN checked;
- EFI_KEY_DATA keydata;
- UINT32 shift = 0;
- UINT64 keypress;
UINTN index;
+ EFI_INPUT_KEY k;
EFI_STATUS err;
if (!checked) {
@@ -298,59 +296,49 @@ static EFI_STATUS key_read(UINT64 *key, BOOLEAN wait) {
checked = TRUE;
}
-fallback:
- if (!TextInputEx) {
- EFI_INPUT_KEY k;
-
- /* fallback for firmware which does not support SimpleTextInputExProtocol */
- if (wait)
+ /* wait until key is pressed */
+ if (wait) {
+ if (TextInputEx)
+ uefi_call_wrapper(BS->WaitForEvent, 3, 1, &TextInputEx->WaitForKeyEx, &index);
+ else
uefi_call_wrapper(BS->WaitForEvent, 3, 1, &ST->ConIn->WaitForKey, &index);
- err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k);
- if (EFI_ERROR(err))
- return err;
-
- *key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
- return 0;
}
- if (wait) {
- /* wait for key press */
- err = uefi_call_wrapper(BS->WaitForEvent, 3, 1, &TextInputEx->WaitForKeyEx, &index);
- if (EFI_ERROR(err)) {
- /* some firmware exposes SimpleTextInputExProtocol, but it doesn't work */
- TextInputEx = NULL;
- goto fallback;
- }
- }
+ if (TextInputEx) {
+ EFI_KEY_DATA keydata;
+ UINT64 keypress;
- err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
- if (EFI_ERROR(err)) {
- if (err != EFI_NOT_READY) {
- /* some firmware exposes SimpleTextInputExProtocol, but it doesn't work */
- TextInputEx = NULL;
- goto fallback;
+ err = uefi_call_wrapper(TextInputEx->ReadKeyStrokeEx, 2, TextInputEx, &keydata);
+ if (!EFI_ERROR(err)) {
+ UINT32 shift = 0;
+
+ /* do not distinguish between left and right keys */
+ if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
+ if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
+ shift |= EFI_CONTROL_PRESSED;
+ if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
+ shift |= EFI_ALT_PRESSED;
+ };
+
+ /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
+ keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
+ if (keypress > 0) {
+ *key = keypress;
+ return 0;
+ }
}
-
- return err;
}
- /* do not distinguish between left and right keys */
- if (keydata.KeyState.KeyShiftState & EFI_SHIFT_STATE_VALID) {
- if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_CONTROL_PRESSED|EFI_LEFT_CONTROL_PRESSED))
- shift |= EFI_CONTROL_PRESSED;
- if (keydata.KeyState.KeyShiftState & (EFI_RIGHT_ALT_PRESSED|EFI_LEFT_ALT_PRESSED))
- shift |= EFI_ALT_PRESSED;
- };
-
- /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
- keypress = KEYPRESS(shift, keydata.Key.ScanCode, keydata.Key.UnicodeChar);
- if (keypress == 0) {
- /* some firmware exposes SimpleTextInputExProtocol, but it doesn't work */
- TextInputEx = NULL;
- goto fallback;
- }
+ /* fallback for firmware which does not support SimpleTextInputExProtocol
+ *
+ * This is also called in case ReadKeyStrokeEx did not return a key, because
+ * some broken firmwares offer SimpleTextInputExProtocol, but never acually
+ * handle any key. */
+ err = uefi_call_wrapper(ST->ConIn->ReadKeyStroke, 2, ST->ConIn, &k);
+ if (EFI_ERROR(err))
+ return err;
- *key = keypress;
+ *key = KEYPRESS(0, k.ScanCode, k.UnicodeChar);
return 0;
}