]>
Commit | Line | Data |
---|---|---|
3394f200 HS |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * efi_selftest_textinput | |
4 | * | |
5 | * Copyright (c) 2018 Heinrich Schuchardt <[email protected]> | |
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 | ||
17 | static const efi_guid_t text_input_ex_protocol_guid = | |
18 | EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID; | |
19 | ||
20 | static struct efi_simple_text_input_ex_protocol *con_in_ex; | |
21 | ||
22 | static struct efi_boot_services *boottime; | |
23 | ||
6dec8739 HS |
24 | static void *efi_key_notify_handle; |
25 | static 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 | */ | |
35 | static 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 | ||
3394f200 HS |
43 | /* |
44 | * Setup unit test. | |
45 | * | |
46 | * @handle: handle of the loaded image | |
47 | * @systable: system table | |
3dd719d4 | 48 | * Return: EFI_ST_SUCCESS for success |
3394f200 HS |
49 | */ |
50 | static int setup(const efi_handle_t handle, | |
51 | const struct efi_system_table *systable) | |
52 | { | |
53 | efi_status_t ret; | |
6dec8739 HS |
54 | 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 | }; | |
3394f200 HS |
65 | |
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 | ||
6dec8739 HS |
77 | 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 | ||
3394f200 HS |
88 | return EFI_ST_SUCCESS; |
89 | } | |
90 | ||
6dec8739 HS |
91 | /* |
92 | * Tear down unit test. | |
93 | * | |
94 | * Unregister notify function. | |
95 | * | |
3dd719d4 | 96 | * Return: EFI_ST_SUCCESS for success |
6dec8739 HS |
97 | */ |
98 | static 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 | } | |
3394f200 HS |
112 | /* |
113 | * Execute unit test. | |
114 | * | |
3dd719d4 | 115 | * Return: EFI_ST_SUCCESS for success |
3394f200 HS |
116 | */ |
117 | static int execute(void) | |
118 | { | |
e1020386 | 119 | struct efi_key_data input_key = { {0, 0}, {0, 0} }; |
3394f200 HS |
120 | 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"); | |
6dec8739 | 141 | efi_st_printf("To terminate type 'CTRL+x'\n"); |
3394f200 | 142 | |
6dec8739 | 143 | while (efi_running) { |
3394f200 HS |
144 | /* 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 | ||
3394f200 | 187 | } |
6dec8739 | 188 | return EFI_ST_SUCCESS; |
3394f200 HS |
189 | } |
190 | ||
191 | EFI_UNIT_TEST(textinputex) = { | |
192 | .name = "extended text input", | |
193 | .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, | |
194 | .setup = setup, | |
195 | .execute = execute, | |
6dec8739 | 196 | .teardown = teardown, |
3394f200 HS |
197 | .on_request = true, |
198 | }; |