2 * This program is free software; you can redistribute it and/or modify it
3 * under the terms of the GNU Lesser General Public License as published by
4 * the Free Software Foundation; either version 2.1 of the License, or
5 * (at your option) any later version.
7 * This program is distributed in the hope that it will be useful, but
8 * WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
10 * Lesser General Public License for more details.
12 * Copyright (C) 2012-2013 Kay Sievers <kay@vrfy.org>
13 * Copyright (C) 2012 Harald Hoyer <harald@redhat.com>
22 #define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
23 { 0xdd9e7534, 0x7762, 0x4698, { 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } }
25 struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
;
27 typedef EFI_STATUS (EFIAPI
*EFI_INPUT_RESET_EX
)(
28 struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
29 BOOLEAN ExtendedVerification
32 typedef UINT8 EFI_KEY_TOGGLE_STATE
;
36 EFI_KEY_TOGGLE_STATE KeyToggleState
;
41 EFI_KEY_STATE KeyState
;
44 typedef EFI_STATUS (EFIAPI
*EFI_INPUT_READ_KEY_EX
)(
45 struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
49 typedef EFI_STATUS (EFIAPI
*EFI_SET_STATE
)(
50 struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
51 EFI_KEY_TOGGLE_STATE
*KeyToggleState
54 typedef EFI_STATUS (EFIAPI
*EFI_KEY_NOTIFY_FUNCTION
)(
58 typedef EFI_STATUS (EFIAPI
*EFI_REGISTER_KEYSTROKE_NOTIFY
)(
59 struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
61 EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction
,
65 typedef EFI_STATUS (EFIAPI
*EFI_UNREGISTER_KEYSTROKE_NOTIFY
)(
66 struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*This
,
67 VOID
*NotificationHandle
70 typedef struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
{
71 EFI_INPUT_RESET_EX Reset
;
72 EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx
;
73 EFI_EVENT WaitForKeyEx
;
74 EFI_SET_STATE SetState
;
75 EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify
;
76 EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify
;
77 } EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
;
79 EFI_STATUS
console_key_read(UINT64
*key
, BOOLEAN wait
) {
80 EFI_GUID EfiSimpleTextInputExProtocolGuid
= EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID
;
81 static EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL
*TextInputEx
;
82 static BOOLEAN checked
;
88 err
= LibLocateProtocol(&EfiSimpleTextInputExProtocolGuid
, (VOID
**)&TextInputEx
);
95 /* wait until key is pressed */
98 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1, &TextInputEx
->WaitForKeyEx
, &index
);
100 uefi_call_wrapper(BS
->WaitForEvent
, 3, 1, &ST
->ConIn
->WaitForKey
, &index
);
104 EFI_KEY_DATA keydata
;
107 err
= uefi_call_wrapper(TextInputEx
->ReadKeyStrokeEx
, 2, TextInputEx
, &keydata
);
108 if (!EFI_ERROR(err
)) {
111 /* do not distinguish between left and right keys */
112 if (keydata
.KeyState
.KeyShiftState
& EFI_SHIFT_STATE_VALID
) {
113 if (keydata
.KeyState
.KeyShiftState
& (EFI_RIGHT_CONTROL_PRESSED
|EFI_LEFT_CONTROL_PRESSED
))
114 shift
|= EFI_CONTROL_PRESSED
;
115 if (keydata
.KeyState
.KeyShiftState
& (EFI_RIGHT_ALT_PRESSED
|EFI_LEFT_ALT_PRESSED
))
116 shift
|= EFI_ALT_PRESSED
;
119 /* 32 bit modifier keys + 16 bit scan code + 16 bit unicode */
120 keypress
= KEYPRESS(shift
, keydata
.Key
.ScanCode
, keydata
.Key
.UnicodeChar
);
128 /* fallback for firmware which does not support SimpleTextInputExProtocol
130 * This is also called in case ReadKeyStrokeEx did not return a key, because
131 * some broken firmwares offer SimpleTextInputExProtocol, but never acually
133 err
= uefi_call_wrapper(ST
->ConIn
->ReadKeyStroke
, 2, ST
->ConIn
, &k
);
137 *key
= KEYPRESS(0, k
.ScanCode
, k
.UnicodeChar
);