blob: de44224ce1c08800ef45275989dfe54f7df666b4 [file] [log] [blame]
Heinrich Schuchardt3394f202018-09-11 22:38:10 +02001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * efi_selftest_textinput
4 *
5 * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
6 *
7 * Provides a unit test for the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
8 * The unicode character and the scan code are printed for text
9 * input. To run the test:
10 *
11 * setenv efi_selftest extended text input
12 * bootefi selftest
13 */
14
15#include <efi_selftest.h>
16
17static const efi_guid_t text_input_ex_protocol_guid =
18 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
19
20static struct efi_simple_text_input_ex_protocol *con_in_ex;
21
22static struct efi_boot_services *boottime;
23
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +020024static void *efi_key_notify_handle;
25static bool efi_running;
26
27/**
28 * efi_key_notify_function() - key notification function
29 *
30 * This function is called when the registered key is hit.
31 *
32 * @key_data: next key
33 * Return: status code
34 */
35static efi_status_t EFIAPI efi_key_notify_function
36 (struct efi_key_data *key_data)
37{
38 efi_running = false;
39
40 return EFI_SUCCESS;
41}
42
Heinrich Schuchardt3394f202018-09-11 22:38:10 +020043/*
44 * Setup unit test.
45 *
46 * @handle: handle of the loaded image
47 * @systable: system table
48 * @return: EFI_ST_SUCCESS for success
49 */
50static int setup(const efi_handle_t handle,
51 const struct efi_system_table *systable)
52{
53 efi_status_t ret;
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +020054 struct efi_key_data key_data = {
55 .key = {
56 .scan_code = 0,
57 .unicode_char = 0x18
58 },
59 .key_state = {
60 .key_shift_state = EFI_SHIFT_STATE_VALID |
61 EFI_LEFT_CONTROL_PRESSED,
62 .key_toggle_state = EFI_TOGGLE_STATE_INVALID,
63 },
64 };
Heinrich Schuchardt3394f202018-09-11 22:38:10 +020065
66 boottime = systable->boottime;
67
68 ret = boottime->locate_protocol(&text_input_ex_protocol_guid, NULL,
69 (void **)&con_in_ex);
70 if (ret != EFI_SUCCESS) {
71 con_in_ex = NULL;
72 efi_st_error
73 ("Extended text input protocol is not available.\n");
74 return EFI_ST_FAILURE;
75 }
76
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +020077 ret = con_in_ex->register_key_notify(con_in_ex, &key_data,
78 efi_key_notify_function,
79 &efi_key_notify_handle);
80 if (ret != EFI_SUCCESS) {
81 efi_key_notify_handle = NULL;
82 efi_st_error
83 ("Notify function could not be registered.\n");
84 return EFI_ST_FAILURE;
85 }
86 efi_running = true;
87
Heinrich Schuchardt3394f202018-09-11 22:38:10 +020088 return EFI_ST_SUCCESS;
89}
90
91/*
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +020092 * Tear down unit test.
93 *
94 * Unregister notify function.
95 *
96 * @return: EFI_ST_SUCCESS for success
97 */
98static int teardown(void)
99{
100 efi_status_t ret;
101
102 ret = con_in_ex->unregister_key_notify
103 (con_in_ex, efi_key_notify_handle);
104 if (ret != EFI_SUCCESS) {
105 efi_st_error
106 ("Notify function could not be registered.\n");
107 return EFI_ST_FAILURE;
108 }
109
110 return EFI_ST_SUCCESS;
111}
112/*
Heinrich Schuchardt3394f202018-09-11 22:38:10 +0200113 * Execute unit test.
114 *
115 * @return: EFI_ST_SUCCESS for success
116 */
117static int execute(void)
118{
Heinrich Schuchardte1020382018-09-15 21:00:52 +0200119 struct efi_key_data input_key = { {0, 0}, {0, 0} };
Heinrich Schuchardt3394f202018-09-11 22:38:10 +0200120 efi_status_t ret;
121 efi_uintn_t index;
122
123 if (!con_in_ex) {
124 efi_st_printf("Setup failed\n");
125 return EFI_ST_FAILURE;
126 }
127
128 /* Drain the console input */
129 ret = con_in_ex->reset(con_in_ex, true);
130 if (ret != EFI_SUCCESS) {
131 efi_st_error("Reset failed\n");
132 return EFI_ST_FAILURE;
133 }
134 ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
135 if (ret != EFI_NOT_READY) {
136 efi_st_error("Empty buffer not reported\n");
137 return EFI_ST_FAILURE;
138 }
139
140 efi_st_printf("Waiting for your input\n");
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +0200141 efi_st_printf("To terminate type 'CTRL+x'\n");
Heinrich Schuchardt3394f202018-09-11 22:38:10 +0200142
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +0200143 while (efi_running) {
Heinrich Schuchardt3394f202018-09-11 22:38:10 +0200144 /* Wait for next key */
145 ret = boottime->wait_for_event(1, &con_in_ex->wait_for_key_ex,
146 &index);
147 if (ret != EFI_ST_SUCCESS) {
148 efi_st_error("WaitForEvent failed\n");
149 return EFI_ST_FAILURE;
150 }
151 ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
152 if (ret != EFI_SUCCESS) {
153 efi_st_error("ReadKeyStroke failed\n");
154 return EFI_ST_FAILURE;
155 }
156
157 /* Allow 5 minutes until time out */
158 boottime->set_watchdog_timer(300, 0, 0, NULL);
159
160 efi_st_printf("Unicode char %u (%ps), scan code %u (",
161 (unsigned int)input_key.key.unicode_char,
162 efi_st_translate_char(input_key.key.unicode_char),
163 (unsigned int)input_key.key.scan_code);
164 if (input_key.key_state.key_shift_state &
165 EFI_SHIFT_STATE_VALID) {
166 if (input_key.key_state.key_shift_state &
167 (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED))
168 efi_st_printf("SHIFT+");
169 if (input_key.key_state.key_shift_state &
170 (EFI_LEFT_ALT_PRESSED | EFI_RIGHT_ALT_PRESSED))
171 efi_st_printf("ALT+");
172 if (input_key.key_state.key_shift_state &
173 (EFI_LEFT_CONTROL_PRESSED |
174 EFI_RIGHT_CONTROL_PRESSED))
175 efi_st_printf("CTRL+");
176 if (input_key.key_state.key_shift_state &
177 (EFI_LEFT_LOGO_PRESSED | EFI_RIGHT_LOGO_PRESSED))
178 efi_st_printf("META+");
179 if (input_key.key_state.key_shift_state ==
180 EFI_SHIFT_STATE_VALID)
181 efi_st_printf("+");
182 }
183
184 efi_st_printf("%ps)\n",
185 efi_st_translate_code(input_key.key.scan_code));
186
Heinrich Schuchardt3394f202018-09-11 22:38:10 +0200187 }
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +0200188 return EFI_ST_SUCCESS;
Heinrich Schuchardt3394f202018-09-11 22:38:10 +0200189}
190
191EFI_UNIT_TEST(textinputex) = {
192 .name = "extended text input",
193 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
194 .setup = setup,
195 .execute = execute,
Heinrich Schuchardt6dec8732018-09-11 22:38:13 +0200196 .teardown = teardown,
Heinrich Schuchardt3394f202018-09-11 22:38:10 +0200197 .on_request = true,
198};