Use EFI_SIMPLE_TEXT_INPUT_EX to support key combinations.

This commit is contained in:
Peter Jones 2015-10-25 16:36:28 +01:00 committed by Vladimir Serbinenko
parent a3645c1240
commit 9e5f70174e
2 changed files with 163 additions and 22 deletions

View File

@ -104,26 +104,12 @@ const unsigned efi_codes[] =
GRUB_TERM_KEY_DC, GRUB_TERM_KEY_PPAGE, GRUB_TERM_KEY_NPAGE, GRUB_TERM_KEY_F1,
GRUB_TERM_KEY_F2, GRUB_TERM_KEY_F3, GRUB_TERM_KEY_F4, GRUB_TERM_KEY_F5,
GRUB_TERM_KEY_F6, GRUB_TERM_KEY_F7, GRUB_TERM_KEY_F8, GRUB_TERM_KEY_F9,
GRUB_TERM_KEY_F10, 0, 0, '\e'
GRUB_TERM_KEY_F10, GRUB_TERM_KEY_F11, GRUB_TERM_KEY_F12, '\e'
};
static int
grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
grub_efi_translate_key (grub_efi_input_key_t key)
{
grub_efi_simple_input_interface_t *i;
grub_efi_input_key_t key;
grub_efi_status_t status;
if (grub_efi_is_finished)
return 0;
i = grub_efi_system_table->con_in;
status = efi_call_2 (i->read_key_stroke, i, &key);
if (status != GRUB_EFI_SUCCESS)
return GRUB_TERM_NO_KEY;
if (key.scan_code == 0)
{
/* Some firmware implementations use VT100-style codes against the spec.
@ -139,9 +125,100 @@ grub_console_getkey (struct grub_term_input *term __attribute__ ((unused)))
else if (key.scan_code < ARRAY_SIZE (efi_codes))
return efi_codes[key.scan_code];
if (key.unicode_char >= 0x20 && key.unicode_char <= 0x7f
|| key.unicode_char == '\t' || key.unicode_char == '\b'
|| key.unicode_char == '\n' || key.unicode_char == '\r')
return key.unicode_char;
return GRUB_TERM_NO_KEY;
}
static int
grub_console_getkey_con (struct grub_term_input *term __attribute__ ((unused)))
{
grub_efi_simple_input_interface_t *i;
grub_efi_input_key_t key;
grub_efi_status_t status;
i = grub_efi_system_table->con_in;
status = efi_call_2 (i->read_key_stroke, i, &key);
if (status != GRUB_EFI_SUCCESS)
return GRUB_TERM_NO_KEY;
return grub_efi_translate_key(key);
}
static int
grub_console_getkey_ex(struct grub_term_input *term)
{
grub_efi_key_data_t key_data;
grub_efi_status_t status;
grub_efi_uint32_t kss;
int key = -1;
grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
status = efi_call_2 (text_input->read_key_stroke, text_input, &key_data);
if (status != GRUB_EFI_SUCCESS)
return GRUB_TERM_NO_KEY;
kss = key_data.key_state.key_shift_state;
key = grub_efi_translate_key(key_data.key);
if (key == GRUB_TERM_NO_KEY)
return GRUB_TERM_NO_KEY;
if (kss & GRUB_EFI_SHIFT_STATE_VALID)
{
if ((kss & GRUB_EFI_LEFT_SHIFT_PRESSED
|| kss & GRUB_EFI_RIGHT_SHIFT_PRESSED)
&& (key & GRUB_TERM_EXTENDED))
key |= GRUB_TERM_SHIFT;
if (kss & GRUB_EFI_LEFT_ALT_PRESSED || kss & GRUB_EFI_RIGHT_ALT_PRESSED)
key |= GRUB_TERM_ALT;
if (kss & GRUB_EFI_LEFT_CONTROL_PRESSED
|| kss & GRUB_EFI_RIGHT_CONTROL_PRESSED)
key |= GRUB_TERM_CTRL;
}
return key;
}
static grub_err_t
grub_efi_console_input_init (struct grub_term_input *term)
{
grub_efi_guid_t text_input_ex_guid =
GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
if (grub_efi_is_finished)
return 0;
grub_efi_simple_text_input_ex_interface_t *text_input = term->data;
if (text_input)
return 0;
text_input = grub_efi_open_protocol(grub_efi_system_table->console_in_handler,
&text_input_ex_guid,
GRUB_EFI_OPEN_PROTOCOL_GET_PROTOCOL);
term->data = (void *)text_input;
return 0;
}
static int
grub_console_getkey (struct grub_term_input *term)
{
if (grub_efi_is_finished)
return 0;
if (term->data)
return grub_console_getkey_ex(term);
else
return grub_console_getkey_con(term);
}
static struct grub_term_coordinate
grub_console_getwh (struct grub_term_output *term __attribute__ ((unused)))
{
@ -243,7 +320,7 @@ grub_console_setcursor (struct grub_term_output *term __attribute__ ((unused)),
}
static grub_err_t
grub_efi_console_init (struct grub_term_output *term)
grub_efi_console_output_init (struct grub_term_output *term)
{
grub_efi_set_text_mode (1);
grub_console_setcursor (term, 1);
@ -251,7 +328,7 @@ grub_efi_console_init (struct grub_term_output *term)
}
static grub_err_t
grub_efi_console_fini (struct grub_term_output *term)
grub_efi_console_output_fini (struct grub_term_output *term)
{
grub_console_setcursor (term, 0);
grub_efi_set_text_mode (0);
@ -262,13 +339,14 @@ static struct grub_term_input grub_console_term_input =
{
.name = "console",
.getkey = grub_console_getkey,
.init = grub_efi_console_input_init,
};
static struct grub_term_output grub_console_term_output =
{
.name = "console",
.init = grub_efi_console_init,
.fini = grub_efi_console_fini,
.init = grub_efi_console_output_init,
.fini = grub_efi_console_output_fini,
.putchar = grub_console_putchar,
.getwh = grub_console_getwh,
.getxy = grub_console_getxy,
@ -291,8 +369,8 @@ grub_console_init (void)
return;
}
grub_term_register_input ("console", &grub_console_term_input);
grub_term_register_output ("console", &grub_console_term_output);
grub_term_register_input ("console", &grub_console_term_input);
}
void

View File

@ -111,7 +111,7 @@
{ 0x8e, 0x39, 0x00, 0xa0, 0xc9, 0x69, 0x72, 0x3b } \
}
#define EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
#define GRUB_EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID \
{ 0xdd9e7534, 0x7762, 0x4698, \
{ 0x8c, 0x14, 0xf5, 0x85, 0x17, 0xa6, 0x25, 0xaa } \
}
@ -952,6 +952,32 @@ struct grub_efi_input_key
};
typedef struct grub_efi_input_key grub_efi_input_key_t;
typedef grub_efi_uint8_t grub_efi_key_toggle_state_t;
struct grub_efi_key_state
{
grub_efi_uint32_t key_shift_state;
grub_efi_key_toggle_state_t key_toggle_state;
};
typedef struct grub_efi_key_state grub_efi_key_state_t;
#define GRUB_EFI_SHIFT_STATE_VALID 0x80000000
#define GRUB_EFI_RIGHT_SHIFT_PRESSED 0x00000001
#define GRUB_EFI_LEFT_SHIFT_PRESSED 0x00000002
#define GRUB_EFI_RIGHT_CONTROL_PRESSED 0x00000004
#define GRUB_EFI_LEFT_CONTROL_PRESSED 0x00000008
#define GRUB_EFI_RIGHT_ALT_PRESSED 0x00000010
#define GRUB_EFI_LEFT_ALT_PRESSED 0x00000020
#define GRUB_EFI_RIGHT_LOGO_PRESSED 0x00000040
#define GRUB_EFI_LEFT_LOGO_PRESSED 0x00000080
#define GRUB_EFI_MENU_KEY_PRESSED 0x00000100
#define GRUB_EFI_SYS_REQ_PRESSED 0x00000200
#define GRUB_EFI_TOGGLE_STATE_VALID 0x80
#define GRUB_EFI_KEY_STATE_EXPOSED 0x40
#define GRUB_EFI_SCROLL_LOCK_ACTIVE 0x01
#define GRUB_EFI_NUM_LOCK_ACTIVE 0x02
#define GRUB_EFI_CAPS_LOCK_ACTIVE 0x04
struct grub_efi_simple_text_output_mode
{
grub_efi_int32_t max_mode;
@ -1294,6 +1320,43 @@ struct grub_efi_simple_input_interface
};
typedef struct grub_efi_simple_input_interface grub_efi_simple_input_interface_t;
struct grub_efi_key_data {
grub_efi_input_key_t key;
grub_efi_key_state_t key_state;
};
typedef struct grub_efi_key_data grub_efi_key_data_t;
typedef grub_efi_status_t (*grub_efi_key_notify_function_t) (
grub_efi_key_data_t *key_data
);
struct grub_efi_simple_text_input_ex_interface
{
grub_efi_status_t
(*reset) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_boolean_t extended_verification);
grub_efi_status_t
(*read_key_stroke) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_key_data_t *key_data);
grub_efi_event_t wait_for_key;
grub_efi_status_t
(*set_state) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_key_toggle_state_t *key_toggle_state);
grub_efi_status_t
(*register_key_notify) (struct grub_efi_simple_text_input_ex_interface *this,
grub_efi_key_data_t *key_data,
grub_efi_key_notify_function_t key_notification_function);
grub_efi_status_t
(*unregister_key_notify) (struct grub_efi_simple_text_input_ex_interface *this,
void *notification_handle);
};
typedef struct grub_efi_simple_text_input_ex_interface grub_efi_simple_text_input_ex_interface_t;
struct grub_efi_simple_text_output_interface
{
grub_efi_status_t