1 // SPDX-License-Identifier: GPL-2.0+
3 * EFI application console interface
5 * Copyright (c) 2016 Alexander Graf
12 #include <dm/device.h>
13 #include <efi_loader.h>
15 #include <stdio_dev.h>
16 #include <video_console.h>
17 #include <linux/delay.h>
19 #define EFI_COUT_MODE_2 2
20 #define EFI_MAX_COUT_MODE 3
23 unsigned long columns;
28 static struct cout_mode efi_cout_modes[] = {
29 /* EFI Mode 0 is 80x25 and always present */
35 /* EFI Mode 1 is always 80x50 */
41 /* Value are unknown until we query the console */
49 const efi_guid_t efi_guid_text_input_ex_protocol =
50 EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
51 const efi_guid_t efi_guid_text_input_protocol =
52 EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID;
53 const efi_guid_t efi_guid_text_output_protocol =
54 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID;
59 /* Default to mode 0 */
60 static struct simple_text_output_mode efi_con_mode = {
69 static int term_get_char(s32 *c)
73 /* Wait up to 100 ms for a character */
74 timeout = timer_get_us() + 100000;
77 if (timer_get_us() > timeout)
85 * Receive and parse a reply from the terminal.
87 * @n: array of return values
88 * @num: number of return values expected
89 * @end_char: character indicating end of terminal message
90 * Return: non-zero indicates error
92 static int term_read_reply(int *n, int num, char end_char)
97 if (term_get_char(&c) || c != cESC)
100 if (term_get_char(&c) || c != '[')
105 if (!term_get_char(&c)) {
112 } else if (c == end_char) {
114 } else if (c > '9' || c < '0') {
118 /* Read one more decimal position */
132 * efi_cout_output_string() - write Unicode string to console
134 * This function implements the OutputString service of the simple text output
135 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
138 * @this: simple text output protocol
139 * @string: u16 string
140 * Return: status code
142 static efi_status_t EFIAPI efi_cout_output_string(
143 struct efi_simple_text_output_protocol *this,
144 const efi_string_t string)
146 struct simple_text_output_mode *con = &efi_con_mode;
147 struct cout_mode *mode = &efi_cout_modes[con->mode];
150 efi_status_t ret = EFI_SUCCESS;
152 EFI_ENTRY("%p, %p", this, string);
154 if (!this || !string) {
155 ret = EFI_INVALID_PARAMETER;
159 buf = malloc(utf16_utf8_strlen(string) + 1);
161 ret = EFI_OUT_OF_RESOURCES;
165 utf16_utf8_strcpy(&pos, string);
170 * Update the cursor position.
172 * The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
173 * and U000D. All other control characters are ignored. Any non-control
174 * character increase the column by one.
176 for (p = string; *p; ++p) {
178 case '\b': /* U+0008, backspace */
179 if (con->cursor_column)
180 con->cursor_column--;
182 case '\n': /* U+000A, newline */
183 con->cursor_column = 0;
186 case '\r': /* U+000D, carriage-return */
187 con->cursor_column = 0;
189 case 0xd800 ... 0xdbff:
191 * Ignore high surrogates, we do not want to count a
192 * Unicode character twice.
196 /* Exclude control codes */
198 con->cursor_column++;
201 if (con->cursor_column >= mode->columns) {
202 con->cursor_column = 0;
206 * When we exceed the row count the terminal will scroll up one
207 * line. We have to adjust the cursor position.
209 if (con->cursor_row >= mode->rows && con->cursor_row)
214 return EFI_EXIT(ret);
218 * efi_cout_test_string() - test writing Unicode string to console
220 * This function implements the TestString service of the simple text output
221 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
224 * As in OutputString we simply convert UTF-16 to UTF-8 there are no unsupported
225 * code points and we can always return EFI_SUCCESS.
227 * @this: simple text output protocol
228 * @string: u16 string
229 * Return: status code
231 static efi_status_t EFIAPI efi_cout_test_string(
232 struct efi_simple_text_output_protocol *this,
233 const efi_string_t string)
235 EFI_ENTRY("%p, %p", this, string);
236 return EFI_EXIT(EFI_SUCCESS);
240 * cout_mode_matches() - check if mode has given terminal size
243 * @rows: number of rows
244 * @cols: number of columns
245 * Return: true if number of rows and columns matches the mode and
246 * the mode is present
248 static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
253 return (mode->rows == rows) && (mode->columns == cols);
257 * query_console_serial() - query console size
259 * When using a serial console or the net console we can only devise the
260 * terminal size by querying the terminal using ECMA-48 control sequences.
262 * @rows: pointer to return number of rows
263 * @cols: pointer to return number of columns
264 * Returns: 0 on success
266 static int query_console_serial(int *rows, int *cols)
271 /* Empty input buffer */
276 * Not all terminals understand CSI [18t for querying the console size.
277 * We should adhere to escape sequences documented in the console_codes
278 * man page and the ECMA-48 standard.
280 * So here we follow a different approach. We position the cursor to the
281 * bottom right and query its position. Before leaving the function we
282 * restore the original cursor position.
284 printf(ESC "7" /* Save cursor position */
285 ESC "[r" /* Set scrolling region to full window */
286 ESC "[999;999H" /* Move to bottom right corner */
287 ESC "[6n"); /* Query cursor position */
289 /* Read {rows,cols} */
290 if (term_read_reply(n, 2, 'R')) {
298 printf(ESC "8"); /* Restore cursor position */
303 * query_console_size() - update the mode table.
305 * By default the only mode available is 80x25. If the console has at least 50
306 * lines, enable mode 80x50. If we can query the console size and it is neither
307 * 80x25 nor 80x50, set it as an additional mode.
309 static void query_console_size(void)
311 const char *stdout_name = env_get("stdout");
312 int rows = 25, cols = 80;
314 if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
315 IS_ENABLED(CONFIG_DM_VIDEO)) {
316 struct stdio_dev *stdout_dev =
317 stdio_get_by_name("vidconsole");
318 struct udevice *dev = stdout_dev->priv;
319 struct vidconsole_priv *priv =
320 dev_get_uclass_priv(dev);
323 } else if (query_console_serial(&rows, &cols)) {
327 /* Test if we can have Mode 1 */
328 if (cols >= 80 && rows >= 50) {
329 efi_cout_modes[1].present = 1;
330 efi_con_mode.max_mode = 2;
334 * Install our mode as mode 2 if it is different
335 * than mode 0 or 1 and set it as the currently selected mode
337 if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) &&
338 !cout_mode_matches(&efi_cout_modes[1], rows, cols)) {
339 efi_cout_modes[EFI_COUT_MODE_2].columns = cols;
340 efi_cout_modes[EFI_COUT_MODE_2].rows = rows;
341 efi_cout_modes[EFI_COUT_MODE_2].present = 1;
342 efi_con_mode.max_mode = EFI_MAX_COUT_MODE;
343 efi_con_mode.mode = EFI_COUT_MODE_2;
349 * efi_cout_query_mode() - get terminal size for a text mode
351 * This function implements the QueryMode service of the simple text output
352 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
355 * @this: simple text output protocol
356 * @mode_number: mode number to retrieve information on
357 * @columns: number of columns
358 * @rows: number of rows
359 * Return: status code
361 static efi_status_t EFIAPI efi_cout_query_mode(
362 struct efi_simple_text_output_protocol *this,
363 unsigned long mode_number, unsigned long *columns,
366 EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
368 if (mode_number >= efi_con_mode.max_mode)
369 return EFI_EXIT(EFI_UNSUPPORTED);
371 if (efi_cout_modes[mode_number].present != 1)
372 return EFI_EXIT(EFI_UNSUPPORTED);
375 *columns = efi_cout_modes[mode_number].columns;
377 *rows = efi_cout_modes[mode_number].rows;
379 return EFI_EXIT(EFI_SUCCESS);
382 static const struct {
386 { 30, 40 }, /* 0: black */
387 { 34, 44 }, /* 1: blue */
388 { 32, 42 }, /* 2: green */
389 { 36, 46 }, /* 3: cyan */
390 { 31, 41 }, /* 4: red */
391 { 35, 45 }, /* 5: magenta */
392 { 33, 43 }, /* 6: brown, map to yellow as EDK2 does*/
393 { 37, 47 }, /* 7: light gray, map to white */
397 * efi_cout_set_attribute() - set fore- and background color
399 * This function implements the SetAttribute service of the simple text output
400 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
403 * @this: simple text output protocol
404 * @attribute: foreground color - bits 0-3, background color - bits 4-6
405 * Return: status code
407 static efi_status_t EFIAPI efi_cout_set_attribute(
408 struct efi_simple_text_output_protocol *this,
409 unsigned long attribute)
411 unsigned int bold = EFI_ATTR_BOLD(attribute);
412 unsigned int fg = EFI_ATTR_FG(attribute);
413 unsigned int bg = EFI_ATTR_BG(attribute);
415 EFI_ENTRY("%p, %lx", this, attribute);
417 efi_con_mode.attribute = attribute;
419 printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg);
421 printf(ESC"[0;37;40m");
423 return EFI_EXIT(EFI_SUCCESS);
427 * efi_cout_clear_screen() - clear screen
429 * This function implements the ClearScreen service of the simple text output
430 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
433 * @this: pointer to the protocol instance
434 * Return: status code
436 static efi_status_t EFIAPI efi_cout_clear_screen(
437 struct efi_simple_text_output_protocol *this)
439 EFI_ENTRY("%p", this);
442 * The Linux console wants both a clear and a home command. The video
443 * uclass does not support <ESC>[H without coordinates, yet.
445 printf(ESC "[2J" ESC "[1;1H");
446 efi_con_mode.cursor_column = 0;
447 efi_con_mode.cursor_row = 0;
449 return EFI_EXIT(EFI_SUCCESS);
453 * efi_cout_clear_set_mode() - set text model
455 * This function implements the SetMode service of the simple text output
456 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
459 * @this: pointer to the protocol instance
460 * @mode_number: number of the text mode to set
461 * Return: status code
463 static efi_status_t EFIAPI efi_cout_set_mode(
464 struct efi_simple_text_output_protocol *this,
465 unsigned long mode_number)
467 EFI_ENTRY("%p, %ld", this, mode_number);
469 if (mode_number >= efi_con_mode.max_mode)
470 return EFI_EXIT(EFI_UNSUPPORTED);
472 if (!efi_cout_modes[mode_number].present)
473 return EFI_EXIT(EFI_UNSUPPORTED);
475 efi_con_mode.mode = mode_number;
476 EFI_CALL(efi_cout_clear_screen(this));
478 return EFI_EXIT(EFI_SUCCESS);
482 * efi_cout_reset() - reset the terminal
484 * This function implements the Reset service of the simple text output
485 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
488 * @this: pointer to the protocol instance
489 * @extended_verification: if set an extended verification may be executed
490 * Return: status code
492 static efi_status_t EFIAPI efi_cout_reset(
493 struct efi_simple_text_output_protocol *this,
494 char extended_verification)
496 EFI_ENTRY("%p, %d", this, extended_verification);
499 EFI_CALL(efi_cout_clear_screen(this));
500 /* Set default colors */
501 efi_con_mode.attribute = 0x07;
502 printf(ESC "[0;37;40m");
504 return EFI_EXIT(EFI_SUCCESS);
508 * efi_cout_set_cursor_position() - reset the terminal
510 * This function implements the SetCursorPosition service of the simple text
511 * output protocol. See the Unified Extensible Firmware Interface (UEFI)
512 * specification for details.
514 * @this: pointer to the protocol instance
515 * @column: column to move to
516 * @row: row to move to
517 * Return: status code
519 static efi_status_t EFIAPI efi_cout_set_cursor_position(
520 struct efi_simple_text_output_protocol *this,
521 unsigned long column, unsigned long row)
523 efi_status_t ret = EFI_SUCCESS;
524 struct simple_text_output_mode *con = &efi_con_mode;
525 struct cout_mode *mode = &efi_cout_modes[con->mode];
527 EFI_ENTRY("%p, %ld, %ld", this, column, row);
529 /* Check parameters */
531 ret = EFI_INVALID_PARAMETER;
534 if (row >= mode->rows || column >= mode->columns) {
535 ret = EFI_UNSUPPORTED;
540 * Set cursor position by sending CSI H.
541 * EFI origin is [0, 0], terminal origin is [1, 1].
543 printf(ESC "[%d;%dH", (int)row + 1, (int)column + 1);
544 efi_con_mode.cursor_column = column;
545 efi_con_mode.cursor_row = row;
547 return EFI_EXIT(ret);
551 * efi_cout_enable_cursor() - enable the cursor
553 * This function implements the EnableCursor service of the simple text output
554 * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
557 * @this: pointer to the protocol instance
558 * @enable: if true enable, if false disable the cursor
559 * Return: status code
561 static efi_status_t EFIAPI efi_cout_enable_cursor(
562 struct efi_simple_text_output_protocol *this,
565 EFI_ENTRY("%p, %d", this, enable);
567 printf(ESC"[?25%c", enable ? 'h' : 'l');
568 efi_con_mode.cursor_visible = !!enable;
570 return EFI_EXIT(EFI_SUCCESS);
573 struct efi_simple_text_output_protocol efi_con_out = {
574 .reset = efi_cout_reset,
575 .output_string = efi_cout_output_string,
576 .test_string = efi_cout_test_string,
577 .query_mode = efi_cout_query_mode,
578 .set_mode = efi_cout_set_mode,
579 .set_attribute = efi_cout_set_attribute,
580 .clear_screen = efi_cout_clear_screen,
581 .set_cursor_position = efi_cout_set_cursor_position,
582 .enable_cursor = efi_cout_enable_cursor,
583 .mode = (void*)&efi_con_mode,
587 * struct efi_cin_notify_function - registered console input notify function
589 * @link: link to list
590 * @key: key to notify
591 * @function: function to call
593 struct efi_cin_notify_function {
594 struct list_head link;
595 struct efi_key_data key;
596 efi_status_t (EFIAPI *function)
597 (struct efi_key_data *key_data);
600 static bool key_available;
601 static struct efi_key_data next_key;
602 static LIST_HEAD(cin_notify_functions);
605 * set_shift_mask() - set shift mask
607 * @mod: Xterm shift mask
608 * @key_state: receives the state of the shift, alt, control, and logo keys
610 void set_shift_mask(int mod, struct efi_key_state *key_state)
612 key_state->key_shift_state = EFI_SHIFT_STATE_VALID;
616 key_state->key_shift_state |= EFI_LEFT_SHIFT_PRESSED;
618 key_state->key_shift_state |= EFI_LEFT_ALT_PRESSED;
620 key_state->key_shift_state |= EFI_LEFT_CONTROL_PRESSED;
621 if (!mod || (mod & 8))
622 key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
627 * analyze_modifiers() - analyze modifiers (shift, alt, ctrl) for function keys
629 * This gets called when we have already parsed CSI.
631 * @key_state: receives the state of the shift, alt, control, and logo keys
632 * Return: the unmodified code
634 static int analyze_modifiers(struct efi_key_state *key_state)
636 int c, mod = 0, ret = 0;
660 set_shift_mask(mod, key_state);
667 * efi_cin_read_key() - read a key from the console input
669 * @key: - key received
670 * Return: - status code
672 static efi_status_t efi_cin_read_key(struct efi_key_data *key)
674 struct efi_input_key pressed_key = {
680 if (console_read_unicode(&ch))
681 return EFI_NOT_READY;
683 key->key_state.key_shift_state = EFI_SHIFT_STATE_INVALID;
684 key->key_state.key_toggle_state = EFI_TOGGLE_STATE_INVALID;
686 /* We do not support multi-word codes */
693 * If a second key is received within 10 ms, assume that we are
694 * dealing with an escape sequence. Otherwise consider this the
695 * escape key being hit. 10 ms is long enough to work fine at
696 * 1200 baud and above.
700 pressed_key.scan_code = 23;
704 * Xterm Control Sequences
705 * https://www.xfree86.org/4.8.0/ctlseqs.html
710 pressed_key.scan_code = 23;
712 case 'O': /* F1 - F4, End */
714 /* consider modifiers */
715 if (ch == 'F') { /* End */
716 pressed_key.scan_code = 6;
718 } else if (ch < 'P') {
719 set_shift_mask(ch - '0', &key->key_state);
722 pressed_key.scan_code = ch - 'P' + 11;
727 case 'A'...'D': /* up, down right, left */
728 pressed_key.scan_code = ch - 'A' + 1;
731 pressed_key.scan_code = 6;
734 pressed_key.scan_code = 5;
737 ch = analyze_modifiers(&key->key_state);
739 case '1'...'5': /* F1 - F5 */
740 pressed_key.scan_code = ch - '1' + 11;
742 case '6'...'9': /* F5 - F8 */
743 pressed_key.scan_code = ch - '6' + 15;
745 case 'A'...'D': /* up, down right, left */
746 pressed_key.scan_code = ch - 'A' + 1;
749 pressed_key.scan_code = 6;
752 pressed_key.scan_code = 5;
755 pressed_key.scan_code = 5;
760 ch = analyze_modifiers(&key->key_state);
762 case '0'...'1': /* F9 - F10 */
763 pressed_key.scan_code = ch - '0' + 19;
765 case '3'...'4': /* F11 - F12 */
766 pressed_key.scan_code = ch - '3' + 21;
769 pressed_key.scan_code = 7;
774 pressed_key.scan_code = 8;
775 analyze_modifiers(&key->key_state);
777 case '5': /* PG UP */
778 pressed_key.scan_code = 9;
779 analyze_modifiers(&key->key_state);
781 case '6': /* PG DOWN */
782 pressed_key.scan_code = 10;
783 analyze_modifiers(&key->key_state);
789 set_shift_mask(3, &key->key_state);
796 if (pressed_key.scan_code) {
797 key->key_state.key_shift_state |= EFI_SHIFT_STATE_VALID;
799 pressed_key.unicode_char = ch;
802 * Assume left control key for control characters typically
803 * entered using the control key.
805 if (ch >= 0x01 && ch <= 0x1f) {
806 key->key_state.key_shift_state |=
807 EFI_SHIFT_STATE_VALID;
812 key->key_state.key_shift_state |=
813 EFI_LEFT_CONTROL_PRESSED;
817 key->key = pressed_key;
823 * efi_cin_notify() - notify registered functions
825 static void efi_cin_notify(void)
827 struct efi_cin_notify_function *item;
829 list_for_each_entry(item, &cin_notify_functions, link) {
832 /* We do not support toggle states */
833 if (item->key.key.unicode_char || item->key.key.scan_code) {
834 if (item->key.key.unicode_char !=
835 next_key.key.unicode_char ||
836 item->key.key.scan_code != next_key.key.scan_code)
839 if (item->key.key_state.key_shift_state &&
840 item->key.key_state.key_shift_state !=
841 next_key.key_state.key_shift_state)
845 /* We don't bother about the return code */
846 EFI_CALL(item->function(&next_key));
851 * efi_cin_check() - check if keyboard input is available
853 static void efi_cin_check(void)
858 efi_signal_event(efi_con_in.wait_for_key);
863 ret = efi_cin_read_key(&next_key);
864 if (ret == EFI_SUCCESS) {
865 key_available = true;
867 /* Notify registered functions */
870 /* Queue the wait for key event */
872 efi_signal_event(efi_con_in.wait_for_key);
878 * efi_cin_empty_buffer() - empty input buffer
880 static void efi_cin_empty_buffer(void)
884 key_available = false;
888 * efi_cin_reset_ex() - reset console input
890 * @this: - the extended simple text input protocol
891 * @extended_verification: - extended verification
893 * This function implements the reset service of the
894 * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
896 * See the Unified Extensible Firmware Interface (UEFI) specification for
899 * Return: old value of the task priority level
901 static efi_status_t EFIAPI efi_cin_reset_ex(
902 struct efi_simple_text_input_ex_protocol *this,
903 bool extended_verification)
905 efi_status_t ret = EFI_SUCCESS;
907 EFI_ENTRY("%p, %d", this, extended_verification);
909 /* Check parameters */
911 ret = EFI_INVALID_PARAMETER;
915 efi_cin_empty_buffer();
917 return EFI_EXIT(ret);
921 * efi_cin_read_key_stroke_ex() - read key stroke
923 * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
924 * @key_data: key read from console
925 * Return: status code
927 * This function implements the ReadKeyStrokeEx service of the
928 * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
930 * See the Unified Extensible Firmware Interface (UEFI) specification for
933 static efi_status_t EFIAPI efi_cin_read_key_stroke_ex(
934 struct efi_simple_text_input_ex_protocol *this,
935 struct efi_key_data *key_data)
937 efi_status_t ret = EFI_SUCCESS;
939 EFI_ENTRY("%p, %p", this, key_data);
941 /* Check parameters */
942 if (!this || !key_data) {
943 ret = EFI_INVALID_PARAMETER;
947 /* We don't do interrupts, so check for timers cooperatively */
950 /* Enable console input after ExitBootServices */
953 if (!key_available) {
958 * CTRL+A - CTRL+Z have to be signaled as a - z.
959 * SHIFT+CTRL+A - SHIFT+CTRL+Z have to be signaled as A - Z.
961 switch (next_key.key.unicode_char) {
965 if (!(next_key.key_state.key_toggle_state &
966 EFI_CAPS_LOCK_ACTIVE) ^
967 !(next_key.key_state.key_shift_state &
968 (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)))
969 next_key.key.unicode_char += 0x40;
971 next_key.key.unicode_char += 0x60;
973 *key_data = next_key;
974 key_available = false;
975 efi_con_in.wait_for_key->is_signaled = false;
978 return EFI_EXIT(ret);
982 * efi_cin_set_state() - set toggle key state
984 * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
985 * @key_toggle_state: pointer to key toggle state
986 * Return: status code
988 * This function implements the SetState service of the
989 * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
991 * See the Unified Extensible Firmware Interface (UEFI) specification for
994 static efi_status_t EFIAPI efi_cin_set_state(
995 struct efi_simple_text_input_ex_protocol *this,
996 u8 *key_toggle_state)
998 EFI_ENTRY("%p, %p", this, key_toggle_state);
1000 * U-Boot supports multiple console input sources like serial and
1001 * net console for which a key toggle state cannot be set at all.
1003 * According to the UEFI specification it is allowable to not implement
1006 return EFI_EXIT(EFI_UNSUPPORTED);
1010 * efi_cin_register_key_notify() - register key notification function
1012 * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1013 * @key_data: key to be notified
1014 * @key_notify_function: function to be called if the key is pressed
1015 * @notify_handle: handle for unregistering the notification
1016 * Return: status code
1018 * This function implements the SetState service of the
1019 * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
1021 * See the Unified Extensible Firmware Interface (UEFI) specification for
1024 static efi_status_t EFIAPI efi_cin_register_key_notify(
1025 struct efi_simple_text_input_ex_protocol *this,
1026 struct efi_key_data *key_data,
1027 efi_status_t (EFIAPI *key_notify_function)(
1028 struct efi_key_data *key_data),
1029 void **notify_handle)
1031 efi_status_t ret = EFI_SUCCESS;
1032 struct efi_cin_notify_function *notify_function;
1034 EFI_ENTRY("%p, %p, %p, %p",
1035 this, key_data, key_notify_function, notify_handle);
1037 /* Check parameters */
1038 if (!this || !key_data || !key_notify_function || !notify_handle) {
1039 ret = EFI_INVALID_PARAMETER;
1043 EFI_PRINT("u+%04x, sc %04x, sh %08x, tg %02x\n",
1044 key_data->key.unicode_char,
1045 key_data->key.scan_code,
1046 key_data->key_state.key_shift_state,
1047 key_data->key_state.key_toggle_state);
1049 notify_function = calloc(1, sizeof(struct efi_cin_notify_function));
1050 if (!notify_function) {
1051 ret = EFI_OUT_OF_RESOURCES;
1054 notify_function->key = *key_data;
1055 notify_function->function = key_notify_function;
1056 list_add_tail(¬ify_function->link, &cin_notify_functions);
1057 *notify_handle = notify_function;
1059 return EFI_EXIT(ret);
1063 * efi_cin_unregister_key_notify() - unregister key notification function
1065 * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1066 * @notification_handle: handle received when registering
1067 * Return: status code
1069 * This function implements the SetState service of the
1070 * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
1072 * See the Unified Extensible Firmware Interface (UEFI) specification for
1075 static efi_status_t EFIAPI efi_cin_unregister_key_notify(
1076 struct efi_simple_text_input_ex_protocol *this,
1077 void *notification_handle)
1079 efi_status_t ret = EFI_INVALID_PARAMETER;
1080 struct efi_cin_notify_function *item, *notify_function =
1081 notification_handle;
1083 EFI_ENTRY("%p, %p", this, notification_handle);
1085 /* Check parameters */
1086 if (!this || !notification_handle)
1089 list_for_each_entry(item, &cin_notify_functions, link) {
1090 if (item == notify_function) {
1095 if (ret != EFI_SUCCESS)
1098 /* Remove the notify function */
1099 list_del(¬ify_function->link);
1100 free(notify_function);
1102 return EFI_EXIT(ret);
1107 * efi_cin_reset() - drain the input buffer
1109 * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1110 * @extended_verification: allow for exhaustive verification
1111 * Return: status code
1113 * This function implements the Reset service of the
1114 * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
1116 * See the Unified Extensible Firmware Interface (UEFI) specification for
1119 static efi_status_t EFIAPI efi_cin_reset
1120 (struct efi_simple_text_input_protocol *this,
1121 bool extended_verification)
1123 efi_status_t ret = EFI_SUCCESS;
1125 EFI_ENTRY("%p, %d", this, extended_verification);
1127 /* Check parameters */
1129 ret = EFI_INVALID_PARAMETER;
1133 efi_cin_empty_buffer();
1135 return EFI_EXIT(ret);
1139 * efi_cin_read_key_stroke() - read key stroke
1141 * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1142 * @key: key read from console
1143 * Return: status code
1145 * This function implements the ReadKeyStroke service of the
1146 * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
1148 * See the Unified Extensible Firmware Interface (UEFI) specification for
1151 static efi_status_t EFIAPI efi_cin_read_key_stroke
1152 (struct efi_simple_text_input_protocol *this,
1153 struct efi_input_key *key)
1155 efi_status_t ret = EFI_SUCCESS;
1157 EFI_ENTRY("%p, %p", this, key);
1159 /* Check parameters */
1160 if (!this || !key) {
1161 ret = EFI_INVALID_PARAMETER;
1165 /* We don't do interrupts, so check for timers cooperatively */
1168 /* Enable console input after ExitBootServices */
1171 if (!key_available) {
1172 ret = EFI_NOT_READY;
1175 *key = next_key.key;
1176 key_available = false;
1177 efi_con_in.wait_for_key->is_signaled = false;
1179 return EFI_EXIT(ret);
1182 static struct efi_simple_text_input_ex_protocol efi_con_in_ex = {
1183 .reset = efi_cin_reset_ex,
1184 .read_key_stroke_ex = efi_cin_read_key_stroke_ex,
1185 .wait_for_key_ex = NULL,
1186 .set_state = efi_cin_set_state,
1187 .register_key_notify = efi_cin_register_key_notify,
1188 .unregister_key_notify = efi_cin_unregister_key_notify,
1191 struct efi_simple_text_input_protocol efi_con_in = {
1192 .reset = efi_cin_reset,
1193 .read_key_stroke = efi_cin_read_key_stroke,
1194 .wait_for_key = NULL,
1197 static struct efi_event *console_timer_event;
1200 * efi_console_timer_notify() - notify the console timer event
1202 * @event: console timer event
1203 * @context: not used
1205 static void EFIAPI efi_console_timer_notify(struct efi_event *event,
1208 EFI_ENTRY("%p, %p", event, context);
1210 EFI_EXIT(EFI_SUCCESS);
1214 * efi_key_notify() - notify the wait for key event
1216 * @event: wait for key event
1217 * @context: not used
1219 static void EFIAPI efi_key_notify(struct efi_event *event, void *context)
1221 EFI_ENTRY("%p, %p", event, context);
1223 EFI_EXIT(EFI_SUCCESS);
1227 * efi_console_register() - install the console protocols
1229 * This function is called from do_bootefi_exec().
1231 * Return: status code
1233 efi_status_t efi_console_register(void)
1236 efi_handle_t console_output_handle;
1237 efi_handle_t console_input_handle;
1239 /* Set up mode information */
1240 query_console_size();
1242 /* Create handles */
1243 r = efi_create_handle(&console_output_handle);
1244 if (r != EFI_SUCCESS)
1247 r = efi_add_protocol(console_output_handle,
1248 &efi_guid_text_output_protocol, &efi_con_out);
1249 if (r != EFI_SUCCESS)
1251 systab.con_out_handle = console_output_handle;
1252 systab.stderr_handle = console_output_handle;
1254 r = efi_create_handle(&console_input_handle);
1255 if (r != EFI_SUCCESS)
1258 r = efi_add_protocol(console_input_handle,
1259 &efi_guid_text_input_protocol, &efi_con_in);
1260 if (r != EFI_SUCCESS)
1262 systab.con_in_handle = console_input_handle;
1263 r = efi_add_protocol(console_input_handle,
1264 &efi_guid_text_input_ex_protocol, &efi_con_in_ex);
1265 if (r != EFI_SUCCESS)
1268 /* Create console events */
1269 r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify,
1270 NULL, NULL, &efi_con_in.wait_for_key);
1271 if (r != EFI_SUCCESS) {
1272 printf("ERROR: Failed to register WaitForKey event\n");
1275 efi_con_in_ex.wait_for_key_ex = efi_con_in.wait_for_key;
1276 r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
1277 efi_console_timer_notify, NULL, NULL,
1278 &console_timer_event);
1279 if (r != EFI_SUCCESS) {
1280 printf("ERROR: Failed to register console event\n");
1283 /* 5000 ns cycle is sufficient for 2 MBaud */
1284 r = efi_set_timer(console_timer_event, EFI_TIMER_PERIODIC, 50);
1285 if (r != EFI_SUCCESS)
1286 printf("ERROR: Failed to set console timer\n");
1289 printf("ERROR: Out of memory\n");