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