]> Git Repo - u-boot.git/blob - lib/efi_loader/efi_console.c
Merge tag 'u-boot-amlogic-20220701' of https://source.denx.de/u-boot/custodians/u...
[u-boot.git] / lib / efi_loader / efi_console.c
1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  *  EFI application console interface
4  *
5  *  Copyright (c) 2016 Alexander Graf
6  */
7
8 #define LOG_CATEGORY LOGC_EFI
9
10 #include <common.h>
11 #include <charset.h>
12 #include <malloc.h>
13 #include <time.h>
14 #include <dm/device.h>
15 #include <efi_loader.h>
16 #include <env.h>
17 #include <log.h>
18 #include <stdio_dev.h>
19 #include <video_console.h>
20 #include <linux/delay.h>
21
22 #define EFI_COUT_MODE_2 2
23 #define EFI_MAX_COUT_MODE 3
24
25 struct cout_mode {
26         unsigned long columns;
27         unsigned long rows;
28         int present;
29 };
30
31 __maybe_unused static struct efi_object uart_obj;
32
33 static struct cout_mode efi_cout_modes[] = {
34         /* EFI Mode 0 is 80x25 and always present */
35         {
36                 .columns = 80,
37                 .rows = 25,
38                 .present = 1,
39         },
40         /* EFI Mode 1 is always 80x50 */
41         {
42                 .columns = 80,
43                 .rows = 50,
44                 .present = 0,
45         },
46         /* Value are unknown until we query the console */
47         {
48                 .columns = 0,
49                 .rows = 0,
50                 .present = 0,
51         },
52 };
53
54 const efi_guid_t efi_guid_text_input_ex_protocol =
55                         EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
56 const efi_guid_t efi_guid_text_input_protocol =
57                         EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID;
58 const efi_guid_t efi_guid_text_output_protocol =
59                         EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID;
60
61 #define cESC '\x1b'
62 #define ESC "\x1b"
63
64 /*
65  * efi_con_mode - mode information of the Simple Text Output Protocol
66  *
67  * Use safe settings before efi_setup_console_size() is called.
68  * By default enable only the 80x25 mode which must always exist.
69  */
70 static struct simple_text_output_mode efi_con_mode = {
71         .max_mode = 1,
72         .mode = 0,
73         .attribute = 0,
74         .cursor_column = 0,
75         .cursor_row = 0,
76         .cursor_visible = 1,
77 };
78
79 static int term_get_char(s32 *c)
80 {
81         u64 timeout;
82
83         /* Wait up to 100 ms for a character */
84         timeout = timer_get_us() + 100000;
85
86         while (!tstc())
87                 if (timer_get_us() > timeout)
88                         return 1;
89
90         *c = getchar();
91         return 0;
92 }
93
94 /**
95  * Receive and parse a reply from the terminal.
96  *
97  * @n:          array of return values
98  * @num:        number of return values expected
99  * @end_char:   character indicating end of terminal message
100  * Return:      non-zero indicates error
101  */
102 static int term_read_reply(int *n, int num, char end_char)
103 {
104         s32 c;
105         int i = 0;
106
107         if (term_get_char(&c) || c != cESC)
108                 return -1;
109
110         if (term_get_char(&c) || c != '[')
111                 return -1;
112
113         n[0] = 0;
114         while (1) {
115                 if (!term_get_char(&c)) {
116                         if (c == ';') {
117                                 i++;
118                                 if (i >= num)
119                                         return -1;
120                                 n[i] = 0;
121                                 continue;
122                         } else if (c == end_char) {
123                                 break;
124                         } else if (c > '9' || c < '0') {
125                                 return -1;
126                         }
127
128                         /* Read one more decimal position */
129                         n[i] *= 10;
130                         n[i] += c - '0';
131                 } else {
132                         return -1;
133                 }
134         }
135         if (i != num - 1)
136                 return -1;
137
138         return 0;
139 }
140
141 /**
142  * efi_cout_output_string() - write Unicode string to console
143  *
144  * This function implements the OutputString service of the simple text output
145  * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
146  * for details.
147  *
148  * @this:       simple text output protocol
149  * @string:     u16 string
150  * Return:      status code
151  */
152 static efi_status_t EFIAPI efi_cout_output_string(
153                         struct efi_simple_text_output_protocol *this,
154                         const u16 *string)
155 {
156         struct simple_text_output_mode *con = &efi_con_mode;
157         struct cout_mode *mode = &efi_cout_modes[con->mode];
158         char *buf, *pos;
159         const u16 *p;
160         efi_status_t ret = EFI_SUCCESS;
161
162         EFI_ENTRY("%p, %p", this, string);
163
164         if (!this || !string) {
165                 ret = EFI_INVALID_PARAMETER;
166                 goto out;
167         }
168
169         buf = malloc(utf16_utf8_strlen(string) + 1);
170         if (!buf) {
171                 ret = EFI_OUT_OF_RESOURCES;
172                 goto out;
173         }
174         pos = buf;
175         utf16_utf8_strcpy(&pos, string);
176         fputs(stdout, buf);
177         free(buf);
178
179         /*
180          * Update the cursor position.
181          *
182          * The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
183          * and U000D. All other control characters are ignored. Any non-control
184          * character increase the column by one.
185          */
186         for (p = string; *p; ++p) {
187                 switch (*p) {
188                 case '\b':      /* U+0008, backspace */
189                         if (con->cursor_column)
190                                 con->cursor_column--;
191                         break;
192                 case '\n':      /* U+000A, newline */
193                         con->cursor_column = 0;
194                         con->cursor_row++;
195                         break;
196                 case '\r':      /* U+000D, carriage-return */
197                         con->cursor_column = 0;
198                         break;
199                 case 0xd800 ... 0xdbff:
200                         /*
201                          * Ignore high surrogates, we do not want to count a
202                          * Unicode character twice.
203                          */
204                         break;
205                 default:
206                         /* Exclude control codes */
207                         if (*p > 0x1f)
208                                 con->cursor_column++;
209                         break;
210                 }
211                 if (con->cursor_column >= mode->columns) {
212                         con->cursor_column = 0;
213                         con->cursor_row++;
214                 }
215                 /*
216                  * When we exceed the row count the terminal will scroll up one
217                  * line. We have to adjust the cursor position.
218                  */
219                 if (con->cursor_row >= mode->rows && con->cursor_row)
220                         con->cursor_row--;
221         }
222
223 out:
224         return EFI_EXIT(ret);
225 }
226
227 /**
228  * efi_cout_test_string() - test writing Unicode string to console
229  *
230  * This function implements the TestString service of the simple text output
231  * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
232  * for details.
233  *
234  * As in OutputString we simply convert UTF-16 to UTF-8 there are no unsupported
235  * code points and we can always return EFI_SUCCESS.
236  *
237  * @this:       simple text output protocol
238  * @string:     u16 string
239  * Return:      status code
240  */
241 static efi_status_t EFIAPI efi_cout_test_string(
242                         struct efi_simple_text_output_protocol *this,
243                         const u16 *string)
244 {
245         EFI_ENTRY("%p, %p", this, string);
246         return EFI_EXIT(EFI_SUCCESS);
247 }
248
249 /**
250  * cout_mode_matches() - check if mode has given terminal size
251  *
252  * @mode:       text mode
253  * @rows:       number of rows
254  * @cols:       number of columns
255  * Return:      true if number of rows and columns matches the mode and
256  *              the mode is present
257  */
258 static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
259 {
260         if (!mode->present)
261                 return false;
262
263         return (mode->rows == rows) && (mode->columns == cols);
264 }
265
266 /**
267  * query_console_serial() - query serial console size
268  *
269  * When using a serial console or the net console we can only devise the
270  * terminal size by querying the terminal using ECMA-48 control sequences.
271  *
272  * @rows:       pointer to return number of rows
273  * @cols:       pointer to return number of columns
274  * Returns:     0 on success
275  */
276 static int query_console_serial(int *rows, int *cols)
277 {
278         int ret = 0;
279         int n[2];
280
281         /* Empty input buffer */
282         while (tstc())
283                 getchar();
284
285         /*
286          * Not all terminals understand CSI [18t for querying the console size.
287          * We should adhere to escape sequences documented in the console_codes
288          * man page and the ECMA-48 standard.
289          *
290          * So here we follow a different approach. We position the cursor to the
291          * bottom right and query its position. Before leaving the function we
292          * restore the original cursor position.
293          */
294         printf(ESC "7"          /* Save cursor position */
295                ESC "[r"         /* Set scrolling region to full window */
296                ESC "[999;999H"  /* Move to bottom right corner */
297                ESC "[6n");      /* Query cursor position */
298
299         /* Read {rows,cols} */
300         if (term_read_reply(n, 2, 'R')) {
301                 ret = 1;
302                 goto out;
303         }
304
305         *cols = n[1];
306         *rows = n[0];
307 out:
308         printf(ESC "8");        /* Restore cursor position */
309         return ret;
310 }
311
312 /**
313  * query_vidconsole() - query video console size
314  *
315  *
316  * @rows:       pointer to return number of rows
317  * @cols:       pointer to return number of columns
318  * Returns:     0 on success
319  */
320 static int __maybe_unused query_vidconsole(int *rows, int *cols)
321 {
322         const char *stdout_name = env_get("stdout");
323         struct stdio_dev *stdout_dev;
324         struct udevice *dev;
325         struct vidconsole_priv *priv;
326
327         if (!stdout_name || strncmp(stdout_name, "vidconsole", 10))
328                 return -ENODEV;
329         stdout_dev = stdio_get_by_name("vidconsole");
330         if (!stdout_dev)
331                 return -ENODEV;
332         dev = stdout_dev->priv;
333         if (!dev)
334                 return -ENODEV;
335         priv = dev_get_uclass_priv(dev);
336         if (!priv)
337                 return -ENODEV;
338         *rows = priv->rows;
339         *cols = priv->cols;
340         return 0;
341 }
342
343 /**
344  * efi_setup_console_size() - update the mode table.
345  *
346  * By default the only mode available is 80x25. If the console has at least 50
347  * lines, enable mode 80x50. If we can query the console size and it is neither
348  * 80x25 nor 80x50, set it as an additional mode.
349  */
350 void efi_setup_console_size(void)
351 {
352         int rows = 25, cols = 80;
353         int ret = -ENODEV;
354
355         if (IS_ENABLED(CONFIG_DM_VIDEO))
356                 ret = query_vidconsole(&rows, &cols);
357         if (ret)
358                 ret = query_console_serial(&rows, &cols);
359         if (ret)
360                 return;
361
362         log_debug("Console size %dx%d\n", rows, cols);
363
364         /* Test if we can have Mode 1 */
365         if (cols >= 80 && rows >= 50) {
366                 efi_cout_modes[1].present = 1;
367                 efi_con_mode.max_mode = 2;
368         }
369
370         /*
371          * Install our mode as mode 2 if it is different
372          * than mode 0 or 1 and set it as the currently selected mode
373          */
374         if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) &&
375             !cout_mode_matches(&efi_cout_modes[1], rows, cols)) {
376                 efi_cout_modes[EFI_COUT_MODE_2].columns = cols;
377                 efi_cout_modes[EFI_COUT_MODE_2].rows = rows;
378                 efi_cout_modes[EFI_COUT_MODE_2].present = 1;
379                 efi_con_mode.max_mode = EFI_MAX_COUT_MODE;
380                 efi_con_mode.mode = EFI_COUT_MODE_2;
381         }
382 }
383
384 /**
385  * efi_cout_query_mode() - get terminal size for a text mode
386  *
387  * This function implements the QueryMode service of the simple text output
388  * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
389  * for details.
390  *
391  * @this:               simple text output protocol
392  * @mode_number:        mode number to retrieve information on
393  * @columns:            number of columns
394  * @rows:               number of rows
395  * Return:              status code
396  */
397 static efi_status_t EFIAPI efi_cout_query_mode(
398                         struct efi_simple_text_output_protocol *this,
399                         unsigned long mode_number, unsigned long *columns,
400                         unsigned long *rows)
401 {
402         EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
403
404         if (mode_number >= efi_con_mode.max_mode)
405                 return EFI_EXIT(EFI_UNSUPPORTED);
406
407         if (efi_cout_modes[mode_number].present != 1)
408                 return EFI_EXIT(EFI_UNSUPPORTED);
409
410         if (columns)
411                 *columns = efi_cout_modes[mode_number].columns;
412         if (rows)
413                 *rows = efi_cout_modes[mode_number].rows;
414
415         return EFI_EXIT(EFI_SUCCESS);
416 }
417
418 static const struct {
419         unsigned int fg;
420         unsigned int bg;
421 } color[] = {
422         { 30, 40 },     /* 0: black */
423         { 34, 44 },     /* 1: blue */
424         { 32, 42 },     /* 2: green */
425         { 36, 46 },     /* 3: cyan */
426         { 31, 41 },     /* 4: red */
427         { 35, 45 },     /* 5: magenta */
428         { 33, 43 },     /* 6: brown, map to yellow as EDK2 does*/
429         { 37, 47 },     /* 7: light gray, map to white */
430 };
431
432 /**
433  * efi_cout_set_attribute() - set fore- and background color
434  *
435  * This function implements the SetAttribute service of the simple text output
436  * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
437  * for details.
438  *
439  * @this:       simple text output protocol
440  * @attribute:  foreground color - bits 0-3, background color - bits 4-6
441  * Return:      status code
442  */
443 static efi_status_t EFIAPI efi_cout_set_attribute(
444                         struct efi_simple_text_output_protocol *this,
445                         unsigned long attribute)
446 {
447         unsigned int bold = EFI_ATTR_BOLD(attribute);
448         unsigned int fg = EFI_ATTR_FG(attribute);
449         unsigned int bg = EFI_ATTR_BG(attribute);
450
451         EFI_ENTRY("%p, %lx", this, attribute);
452
453         efi_con_mode.attribute = attribute;
454         if (attribute)
455                 printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg);
456         else
457                 printf(ESC"[0;37;40m");
458
459         return EFI_EXIT(EFI_SUCCESS);
460 }
461
462 /**
463  * efi_cout_clear_screen() - clear screen
464  *
465  * This function implements the ClearScreen service of the simple text output
466  * protocol. See the Unified Extensible Firmware Interface (UEFI) specification
467  * for details.
468  *
469  * @this:       pointer to the protocol instance
470  * Return:      status code
471  */
472 static efi_status_t EFIAPI efi_cout_clear_screen(
473                         struct efi_simple_text_output_protocol *this)
474 {
475         EFI_ENTRY("%p", this);
476
477         /*
478          * The Linux console wants both a clear and a home command. The video
479          * uclass does not support <ESC>[H without coordinates, yet.
480          */
481         printf(ESC "[2J" ESC "[1;1H");
482         efi_con_mode.cursor_column = 0;
483         efi_con_mode.cursor_row = 0;
484
485         return EFI_EXIT(EFI_SUCCESS);
486 }
487
488 /**
489  * efi_cout_clear_set_mode() - set text model
490  *
491  * This function implements the SetMode service of the simple text output
492  * protocol. See the Unified Extensible Firmware  Interface (UEFI) specification
493  * for details.
494  *
495  * @this:               pointer to the protocol instance
496  * @mode_number:        number of the text mode to set
497  * Return:              status code
498  */
499 static efi_status_t EFIAPI efi_cout_set_mode(
500                         struct efi_simple_text_output_protocol *this,
501                         unsigned long mode_number)
502 {
503         EFI_ENTRY("%p, %ld", this, mode_number);
504
505         if (mode_number >= efi_con_mode.max_mode)
506                 return EFI_EXIT(EFI_UNSUPPORTED);
507
508         if (!efi_cout_modes[mode_number].present)
509                 return EFI_EXIT(EFI_UNSUPPORTED);
510
511         efi_con_mode.mode = mode_number;
512         EFI_CALL(efi_cout_clear_screen(this));
513
514         return EFI_EXIT(EFI_SUCCESS);
515 }
516
517 /**
518  * efi_cout_reset() - reset the terminal
519  *
520  * This function implements the Reset service of the simple text output
521  * protocol. See the Unified Extensible Firmware  Interface (UEFI) specification
522  * for details.
523  *
524  * @this:                       pointer to the protocol instance
525  * @extended_verification:      if set an extended verification may be executed
526  * Return:                      status code
527  */
528 static efi_status_t EFIAPI efi_cout_reset(
529                         struct efi_simple_text_output_protocol *this,
530                         char extended_verification)
531 {
532         EFI_ENTRY("%p, %d", this, extended_verification);
533
534         /* Set default colors */
535         efi_con_mode.attribute = 0x07;
536         printf(ESC "[0;37;40m");
537         /* Clear screen */
538         EFI_CALL(efi_cout_clear_screen(this));
539
540         return EFI_EXIT(EFI_SUCCESS);
541 }
542
543 /**
544  * efi_cout_set_cursor_position() - reset the terminal
545  *
546  * This function implements the SetCursorPosition service of the simple text
547  * output protocol. See the Unified Extensible Firmware  Interface (UEFI)
548  * specification for details.
549  *
550  * @this:       pointer to the protocol instance
551  * @column:     column to move to
552  * @row:        row to move to
553  * Return:      status code
554  */
555 static efi_status_t EFIAPI efi_cout_set_cursor_position(
556                         struct efi_simple_text_output_protocol *this,
557                         unsigned long column, unsigned long row)
558 {
559         efi_status_t ret = EFI_SUCCESS;
560         struct simple_text_output_mode *con = &efi_con_mode;
561         struct cout_mode *mode = &efi_cout_modes[con->mode];
562
563         EFI_ENTRY("%p, %ld, %ld", this, column, row);
564
565         /* Check parameters */
566         if (!this) {
567                 ret = EFI_INVALID_PARAMETER;
568                 goto out;
569         }
570         if (row >= mode->rows || column >= mode->columns) {
571                 ret = EFI_UNSUPPORTED;
572                 goto out;
573         }
574
575         /*
576          * Set cursor position by sending CSI H.
577          * EFI origin is [0, 0], terminal origin is [1, 1].
578          */
579         printf(ESC "[%d;%dH", (int)row + 1, (int)column + 1);
580         efi_con_mode.cursor_column = column;
581         efi_con_mode.cursor_row = row;
582 out:
583         return EFI_EXIT(ret);
584 }
585
586 /**
587  * efi_cout_enable_cursor() - enable the cursor
588  *
589  * This function implements the EnableCursor service of the simple text  output
590  * protocol. See the Unified Extensible Firmware  Interface (UEFI) specification
591  * for details.
592  *
593  * @this:       pointer to the protocol instance
594  * @enable:     if true enable, if false disable the cursor
595  * Return:      status code
596  */
597 static efi_status_t EFIAPI efi_cout_enable_cursor(
598                         struct efi_simple_text_output_protocol *this,
599                         bool enable)
600 {
601         EFI_ENTRY("%p, %d", this, enable);
602
603         printf(ESC"[?25%c", enable ? 'h' : 'l');
604         efi_con_mode.cursor_visible = !!enable;
605
606         return EFI_EXIT(EFI_SUCCESS);
607 }
608
609 struct efi_simple_text_output_protocol efi_con_out = {
610         .reset = efi_cout_reset,
611         .output_string = efi_cout_output_string,
612         .test_string = efi_cout_test_string,
613         .query_mode = efi_cout_query_mode,
614         .set_mode = efi_cout_set_mode,
615         .set_attribute = efi_cout_set_attribute,
616         .clear_screen = efi_cout_clear_screen,
617         .set_cursor_position = efi_cout_set_cursor_position,
618         .enable_cursor = efi_cout_enable_cursor,
619         .mode = (void*)&efi_con_mode,
620 };
621
622 /**
623  * struct efi_cin_notify_function - registered console input notify function
624  *
625  * @link:       link to list
626  * @key:        key to notify
627  * @function:   function to call
628  */
629 struct efi_cin_notify_function {
630         struct list_head link;
631         struct efi_key_data key;
632         efi_status_t (EFIAPI *function)
633                 (struct efi_key_data *key_data);
634 };
635
636 static bool key_available;
637 static struct efi_key_data next_key;
638 static LIST_HEAD(cin_notify_functions);
639
640 /**
641  * set_shift_mask() - set shift mask
642  *
643  * @mod:        Xterm shift mask
644  * @key_state:  receives the state of the shift, alt, control, and logo keys
645  */
646 void set_shift_mask(int mod, struct efi_key_state *key_state)
647 {
648         key_state->key_shift_state = EFI_SHIFT_STATE_VALID;
649         if (mod) {
650                 --mod;
651                 if (mod & 1)
652                         key_state->key_shift_state |= EFI_LEFT_SHIFT_PRESSED;
653                 if (mod & 2)
654                         key_state->key_shift_state |= EFI_LEFT_ALT_PRESSED;
655                 if (mod & 4)
656                         key_state->key_shift_state |= EFI_LEFT_CONTROL_PRESSED;
657                 if (!mod || (mod & 8))
658                         key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
659         }
660 }
661
662 /**
663  * analyze_modifiers() - analyze modifiers (shift, alt, ctrl) for function keys
664  *
665  * This gets called when we have already parsed CSI.
666  *
667  * @key_state:  receives the state of the shift, alt, control, and logo keys
668  * Return:      the unmodified code
669  */
670 static int analyze_modifiers(struct efi_key_state *key_state)
671 {
672         int c, mod = 0, ret = 0;
673
674         c = getchar();
675
676         if (c != ';') {
677                 ret = c;
678                 if (c == '~')
679                         goto out;
680                 c = getchar();
681         }
682         for (;;) {
683                 switch (c) {
684                 case '0'...'9':
685                         mod *= 10;
686                         mod += c - '0';
687                 /* fall through */
688                 case ';':
689                         c = getchar();
690                         break;
691                 default:
692                         goto out;
693                 }
694         }
695 out:
696         set_shift_mask(mod, key_state);
697         if (!ret)
698                 ret = c;
699         return ret;
700 }
701
702 /**
703  * efi_cin_read_key() - read a key from the console input
704  *
705  * @key:        - key received
706  * Return:      - status code
707  */
708 static efi_status_t efi_cin_read_key(struct efi_key_data *key)
709 {
710         struct efi_input_key pressed_key = {
711                 .scan_code = 0,
712                 .unicode_char = 0,
713         };
714         s32 ch;
715
716         if (console_read_unicode(&ch))
717                 return EFI_NOT_READY;
718
719         key->key_state.key_shift_state = EFI_SHIFT_STATE_INVALID;
720         key->key_state.key_toggle_state = EFI_TOGGLE_STATE_INVALID;
721
722         /* We do not support multi-word codes */
723         if (ch >= 0x10000)
724                 ch = '?';
725
726         switch (ch) {
727         case 0x1b:
728                 /*
729                  * If a second key is received within 10 ms, assume that we are
730                  * dealing with an escape sequence. Otherwise consider this the
731                  * escape key being hit. 10 ms is long enough to work fine at
732                  * 1200 baud and above.
733                  */
734                 udelay(10000);
735                 if (!tstc()) {
736                         pressed_key.scan_code = 23;
737                         break;
738                 }
739                 /*
740                  * Xterm Control Sequences
741                  * https://www.xfree86.org/4.8.0/ctlseqs.html
742                  */
743                 ch = getchar();
744                 switch (ch) {
745                 case cESC: /* ESC */
746                         pressed_key.scan_code = 23;
747                         break;
748                 case 'O': /* F1 - F4, End */
749                         ch = getchar();
750                         /* consider modifiers */
751                         if (ch == 'F') { /* End */
752                                 pressed_key.scan_code = 6;
753                                 break;
754                         } else if (ch < 'P') {
755                                 set_shift_mask(ch - '0', &key->key_state);
756                                 ch = getchar();
757                         }
758                         pressed_key.scan_code = ch - 'P' + 11;
759                         break;
760                 case '[':
761                         ch = getchar();
762                         switch (ch) {
763                         case 'A'...'D': /* up, down right, left */
764                                 pressed_key.scan_code = ch - 'A' + 1;
765                                 break;
766                         case 'F': /* End */
767                                 pressed_key.scan_code = 6;
768                                 break;
769                         case 'H': /* Home */
770                                 pressed_key.scan_code = 5;
771                                 break;
772                         case '1':
773                                 ch = analyze_modifiers(&key->key_state);
774                                 switch (ch) {
775                                 case '1'...'5': /* F1 - F5 */
776                                         pressed_key.scan_code = ch - '1' + 11;
777                                         break;
778                                 case '6'...'9': /* F5 - F8 */
779                                         pressed_key.scan_code = ch - '6' + 15;
780                                         break;
781                                 case 'A'...'D': /* up, down right, left */
782                                         pressed_key.scan_code = ch - 'A' + 1;
783                                         break;
784                                 case 'F': /* End */
785                                         pressed_key.scan_code = 6;
786                                         break;
787                                 case 'H': /* Home */
788                                         pressed_key.scan_code = 5;
789                                         break;
790                                 case '~': /* Home */
791                                         pressed_key.scan_code = 5;
792                                         break;
793                                 }
794                                 break;
795                         case '2':
796                                 ch = analyze_modifiers(&key->key_state);
797                                 switch (ch) {
798                                 case '0'...'1': /* F9 - F10 */
799                                         pressed_key.scan_code = ch - '0' + 19;
800                                         break;
801                                 case '3'...'4': /* F11 - F12 */
802                                         pressed_key.scan_code = ch - '3' + 21;
803                                         break;
804                                 case '~': /* INS */
805                                         pressed_key.scan_code = 7;
806                                         break;
807                                 }
808                                 break;
809                         case '3': /* DEL */
810                                 pressed_key.scan_code = 8;
811                                 analyze_modifiers(&key->key_state);
812                                 break;
813                         case '5': /* PG UP */
814                                 pressed_key.scan_code = 9;
815                                 analyze_modifiers(&key->key_state);
816                                 break;
817                         case '6': /* PG DOWN */
818                                 pressed_key.scan_code = 10;
819                                 analyze_modifiers(&key->key_state);
820                                 break;
821                         } /* [ */
822                         break;
823                 default:
824                         /* ALT key */
825                         set_shift_mask(3, &key->key_state);
826                 }
827                 break;
828         case 0x7f:
829                 /* Backspace */
830                 ch = 0x08;
831         }
832         if (pressed_key.scan_code) {
833                 key->key_state.key_shift_state |= EFI_SHIFT_STATE_VALID;
834         } else {
835                 pressed_key.unicode_char = ch;
836
837                 /*
838                  * Assume left control key for control characters typically
839                  * entered using the control key.
840                  */
841                 if (ch >= 0x01 && ch <= 0x1f) {
842                         key->key_state.key_shift_state |=
843                                         EFI_SHIFT_STATE_VALID;
844                         switch (ch) {
845                         case 0x01 ... 0x07:
846                         case 0x0b ... 0x0c:
847                         case 0x0e ... 0x1f:
848                                 key->key_state.key_shift_state |=
849                                                 EFI_LEFT_CONTROL_PRESSED;
850                         }
851                 }
852         }
853         key->key = pressed_key;
854
855         return EFI_SUCCESS;
856 }
857
858 /**
859  * efi_cin_notify() - notify registered functions
860  */
861 static void efi_cin_notify(void)
862 {
863         struct efi_cin_notify_function *item;
864
865         list_for_each_entry(item, &cin_notify_functions, link) {
866                 bool match = true;
867
868                 /* We do not support toggle states */
869                 if (item->key.key.unicode_char || item->key.key.scan_code) {
870                         if (item->key.key.unicode_char !=
871                             next_key.key.unicode_char ||
872                             item->key.key.scan_code != next_key.key.scan_code)
873                                 match = false;
874                 }
875                 if (item->key.key_state.key_shift_state &&
876                     item->key.key_state.key_shift_state !=
877                     next_key.key_state.key_shift_state)
878                         match = false;
879
880                 if (match)
881                         /* We don't bother about the return code */
882                         EFI_CALL(item->function(&next_key));
883         }
884 }
885
886 /**
887  * efi_cin_check() - check if keyboard input is available
888  */
889 static void efi_cin_check(void)
890 {
891         efi_status_t ret;
892
893         if (key_available) {
894                 efi_signal_event(efi_con_in.wait_for_key);
895                 return;
896         }
897
898         if (tstc()) {
899                 ret = efi_cin_read_key(&next_key);
900                 if (ret == EFI_SUCCESS) {
901                         key_available = true;
902
903                         /* Notify registered functions */
904                         efi_cin_notify();
905
906                         /* Queue the wait for key event */
907                         if (key_available)
908                                 efi_signal_event(efi_con_in.wait_for_key);
909                 }
910         }
911 }
912
913 /**
914  * efi_cin_empty_buffer() - empty input buffer
915  */
916 static void efi_cin_empty_buffer(void)
917 {
918         while (tstc())
919                 getchar();
920         key_available = false;
921 }
922
923 /**
924  * efi_cin_reset_ex() - reset console input
925  *
926  * @this:                       - the extended simple text input protocol
927  * @extended_verification:      - extended verification
928  *
929  * This function implements the reset service of the
930  * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
931  *
932  * See the Unified Extensible Firmware Interface (UEFI) specification for
933  * details.
934  *
935  * Return: old value of the task priority level
936  */
937 static efi_status_t EFIAPI efi_cin_reset_ex(
938                 struct efi_simple_text_input_ex_protocol *this,
939                 bool extended_verification)
940 {
941         efi_status_t ret = EFI_SUCCESS;
942
943         EFI_ENTRY("%p, %d", this, extended_verification);
944
945         /* Check parameters */
946         if (!this) {
947                 ret = EFI_INVALID_PARAMETER;
948                 goto out;
949         }
950
951         efi_cin_empty_buffer();
952 out:
953         return EFI_EXIT(ret);
954 }
955
956 /**
957  * efi_cin_read_key_stroke_ex() - read key stroke
958  *
959  * @this:       instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
960  * @key_data:   key read from console
961  * Return:      status code
962  *
963  * This function implements the ReadKeyStrokeEx service of the
964  * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
965  *
966  * See the Unified Extensible Firmware Interface (UEFI) specification for
967  * details.
968  */
969 static efi_status_t EFIAPI efi_cin_read_key_stroke_ex(
970                 struct efi_simple_text_input_ex_protocol *this,
971                 struct efi_key_data *key_data)
972 {
973         efi_status_t ret = EFI_SUCCESS;
974
975         EFI_ENTRY("%p, %p", this, key_data);
976
977         /* Check parameters */
978         if (!this || !key_data) {
979                 ret = EFI_INVALID_PARAMETER;
980                 goto out;
981         }
982
983         /* We don't do interrupts, so check for timers cooperatively */
984         efi_timer_check();
985
986         /* Enable console input after ExitBootServices */
987         efi_cin_check();
988
989         if (!key_available) {
990                 ret = EFI_NOT_READY;
991                 goto out;
992         }
993         /*
994          * CTRL+A - CTRL+Z have to be signaled as a - z.
995          * SHIFT+CTRL+A - SHIFT+CTRL+Z have to be signaled as A - Z.
996          */
997         switch (next_key.key.unicode_char) {
998         case 0x01 ... 0x07:
999         case 0x0b ... 0x0c:
1000         case 0x0e ... 0x1a:
1001                 if (!(next_key.key_state.key_toggle_state &
1002                       EFI_CAPS_LOCK_ACTIVE) ^
1003                     !(next_key.key_state.key_shift_state &
1004                       (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)))
1005                         next_key.key.unicode_char += 0x40;
1006                 else
1007                         next_key.key.unicode_char += 0x60;
1008         }
1009         *key_data = next_key;
1010         key_available = false;
1011         efi_con_in.wait_for_key->is_signaled = false;
1012
1013 out:
1014         return EFI_EXIT(ret);
1015 }
1016
1017 /**
1018  * efi_cin_set_state() - set toggle key state
1019  *
1020  * @this:               instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1021  * @key_toggle_state:   pointer to key toggle state
1022  * Return:              status code
1023  *
1024  * This function implements the SetState service of the
1025  * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
1026  *
1027  * See the Unified Extensible Firmware Interface (UEFI) specification for
1028  * details.
1029  */
1030 static efi_status_t EFIAPI efi_cin_set_state(
1031                 struct efi_simple_text_input_ex_protocol *this,
1032                 u8 *key_toggle_state)
1033 {
1034         EFI_ENTRY("%p, %p", this, key_toggle_state);
1035         /*
1036          * U-Boot supports multiple console input sources like serial and
1037          * net console for which a key toggle state cannot be set at all.
1038          *
1039          * According to the UEFI specification it is allowable to not implement
1040          * this service.
1041          */
1042         return EFI_EXIT(EFI_UNSUPPORTED);
1043 }
1044
1045 /**
1046  * efi_cin_register_key_notify() - register key notification function
1047  *
1048  * @this:                       instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1049  * @key_data:                   key to be notified
1050  * @key_notify_function:        function to be called if the key is pressed
1051  * @notify_handle:              handle for unregistering the notification
1052  * Return:                      status code
1053  *
1054  * This function implements the SetState service of the
1055  * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
1056  *
1057  * See the Unified Extensible Firmware Interface (UEFI) specification for
1058  * details.
1059  */
1060 static efi_status_t EFIAPI efi_cin_register_key_notify(
1061                 struct efi_simple_text_input_ex_protocol *this,
1062                 struct efi_key_data *key_data,
1063                 efi_status_t (EFIAPI *key_notify_function)(
1064                         struct efi_key_data *key_data),
1065                 void **notify_handle)
1066 {
1067         efi_status_t ret = EFI_SUCCESS;
1068         struct efi_cin_notify_function *notify_function;
1069
1070         EFI_ENTRY("%p, %p, %p, %p",
1071                   this, key_data, key_notify_function, notify_handle);
1072
1073         /* Check parameters */
1074         if (!this || !key_data || !key_notify_function || !notify_handle) {
1075                 ret = EFI_INVALID_PARAMETER;
1076                 goto out;
1077         }
1078
1079         EFI_PRINT("u+%04x, sc %04x, sh %08x, tg %02x\n",
1080                   key_data->key.unicode_char,
1081                key_data->key.scan_code,
1082                key_data->key_state.key_shift_state,
1083                key_data->key_state.key_toggle_state);
1084
1085         notify_function = calloc(1, sizeof(struct efi_cin_notify_function));
1086         if (!notify_function) {
1087                 ret = EFI_OUT_OF_RESOURCES;
1088                 goto out;
1089         }
1090         notify_function->key = *key_data;
1091         notify_function->function = key_notify_function;
1092         list_add_tail(&notify_function->link, &cin_notify_functions);
1093         *notify_handle = notify_function;
1094 out:
1095         return EFI_EXIT(ret);
1096 }
1097
1098 /**
1099  * efi_cin_unregister_key_notify() - unregister key notification function
1100  *
1101  * @this:                       instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1102  * @notification_handle:        handle received when registering
1103  * Return:                      status code
1104  *
1105  * This function implements the SetState service of the
1106  * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
1107  *
1108  * See the Unified Extensible Firmware Interface (UEFI) specification for
1109  * details.
1110  */
1111 static efi_status_t EFIAPI efi_cin_unregister_key_notify(
1112                 struct efi_simple_text_input_ex_protocol *this,
1113                 void *notification_handle)
1114 {
1115         efi_status_t ret = EFI_INVALID_PARAMETER;
1116         struct efi_cin_notify_function *item, *notify_function =
1117                         notification_handle;
1118
1119         EFI_ENTRY("%p, %p", this, notification_handle);
1120
1121         /* Check parameters */
1122         if (!this || !notification_handle)
1123                 goto out;
1124
1125         list_for_each_entry(item, &cin_notify_functions, link) {
1126                 if (item == notify_function) {
1127                         ret = EFI_SUCCESS;
1128                         break;
1129                 }
1130         }
1131         if (ret != EFI_SUCCESS)
1132                 goto out;
1133
1134         /* Remove the notify function */
1135         list_del(&notify_function->link);
1136         free(notify_function);
1137 out:
1138         return EFI_EXIT(ret);
1139 }
1140
1141
1142 /**
1143  * efi_cin_reset() - drain the input buffer
1144  *
1145  * @this:                       instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1146  * @extended_verification:      allow for exhaustive verification
1147  * Return:                      status code
1148  *
1149  * This function implements the Reset service of the
1150  * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
1151  *
1152  * See the Unified Extensible Firmware Interface (UEFI) specification for
1153  * details.
1154  */
1155 static efi_status_t EFIAPI efi_cin_reset
1156                         (struct efi_simple_text_input_protocol *this,
1157                          bool extended_verification)
1158 {
1159         efi_status_t ret = EFI_SUCCESS;
1160
1161         EFI_ENTRY("%p, %d", this, extended_verification);
1162
1163         /* Check parameters */
1164         if (!this) {
1165                 ret = EFI_INVALID_PARAMETER;
1166                 goto out;
1167         }
1168
1169         efi_cin_empty_buffer();
1170 out:
1171         return EFI_EXIT(ret);
1172 }
1173
1174 /**
1175  * efi_cin_read_key_stroke() - read key stroke
1176  *
1177  * @this:       instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
1178  * @key:        key read from console
1179  * Return:      status code
1180  *
1181  * This function implements the ReadKeyStroke service of the
1182  * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
1183  *
1184  * See the Unified Extensible Firmware Interface (UEFI) specification for
1185  * details.
1186  */
1187 static efi_status_t EFIAPI efi_cin_read_key_stroke
1188                         (struct efi_simple_text_input_protocol *this,
1189                          struct efi_input_key *key)
1190 {
1191         efi_status_t ret = EFI_SUCCESS;
1192
1193         EFI_ENTRY("%p, %p", this, key);
1194
1195         /* Check parameters */
1196         if (!this || !key) {
1197                 ret = EFI_INVALID_PARAMETER;
1198                 goto out;
1199         }
1200
1201         /* We don't do interrupts, so check for timers cooperatively */
1202         efi_timer_check();
1203
1204         /* Enable console input after ExitBootServices */
1205         efi_cin_check();
1206
1207         if (!key_available) {
1208                 ret = EFI_NOT_READY;
1209                 goto out;
1210         }
1211         *key = next_key.key;
1212         key_available = false;
1213         efi_con_in.wait_for_key->is_signaled = false;
1214 out:
1215         return EFI_EXIT(ret);
1216 }
1217
1218 static struct efi_simple_text_input_ex_protocol efi_con_in_ex = {
1219         .reset = efi_cin_reset_ex,
1220         .read_key_stroke_ex = efi_cin_read_key_stroke_ex,
1221         .wait_for_key_ex = NULL,
1222         .set_state = efi_cin_set_state,
1223         .register_key_notify = efi_cin_register_key_notify,
1224         .unregister_key_notify = efi_cin_unregister_key_notify,
1225 };
1226
1227 struct efi_simple_text_input_protocol efi_con_in = {
1228         .reset = efi_cin_reset,
1229         .read_key_stroke = efi_cin_read_key_stroke,
1230         .wait_for_key = NULL,
1231 };
1232
1233 static struct efi_event *console_timer_event;
1234
1235 /*
1236  * efi_console_timer_notify() - notify the console timer event
1237  *
1238  * @event:      console timer event
1239  * @context:    not used
1240  */
1241 static void EFIAPI efi_console_timer_notify(struct efi_event *event,
1242                                             void *context)
1243 {
1244         EFI_ENTRY("%p, %p", event, context);
1245         efi_cin_check();
1246         EFI_EXIT(EFI_SUCCESS);
1247 }
1248
1249 /**
1250  * efi_key_notify() - notify the wait for key event
1251  *
1252  * @event:      wait for key event
1253  * @context:    not used
1254  */
1255 static void EFIAPI efi_key_notify(struct efi_event *event, void *context)
1256 {
1257         EFI_ENTRY("%p, %p", event, context);
1258         efi_cin_check();
1259         EFI_EXIT(EFI_SUCCESS);
1260 }
1261
1262 /**
1263  * efi_console_register() - install the console protocols
1264  *
1265  * This function is called from do_bootefi_exec().
1266  *
1267  * Return:      status code
1268  */
1269 efi_status_t efi_console_register(void)
1270 {
1271         efi_status_t r;
1272         struct efi_device_path *dp;
1273
1274         /* Install protocols on root node */
1275         r = EFI_CALL(efi_install_multiple_protocol_interfaces
1276                      (&efi_root,
1277                       &efi_guid_text_output_protocol, &efi_con_out,
1278                       &efi_guid_text_input_protocol, &efi_con_in,
1279                       &efi_guid_text_input_ex_protocol, &efi_con_in_ex,
1280                       NULL));
1281
1282         /* Create console node and install device path protocols */
1283         if (CONFIG_IS_ENABLED(DM_SERIAL)) {
1284                 dp = efi_dp_from_uart();
1285                 if (!dp)
1286                         goto out_of_memory;
1287
1288                 /* Hook UART up to the device list */
1289                 efi_add_handle(&uart_obj);
1290
1291                 /* Install device path */
1292                 r = efi_add_protocol(&uart_obj, &efi_guid_device_path, dp);
1293                 if (r != EFI_SUCCESS)
1294                         goto out_of_memory;
1295         }
1296
1297         /* Create console events */
1298         r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify,
1299                              NULL, NULL, &efi_con_in.wait_for_key);
1300         if (r != EFI_SUCCESS) {
1301                 printf("ERROR: Failed to register WaitForKey event\n");
1302                 return r;
1303         }
1304         efi_con_in_ex.wait_for_key_ex = efi_con_in.wait_for_key;
1305         r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
1306                              efi_console_timer_notify, NULL, NULL,
1307                              &console_timer_event);
1308         if (r != EFI_SUCCESS) {
1309                 printf("ERROR: Failed to register console event\n");
1310                 return r;
1311         }
1312         /* 5000 ns cycle is sufficient for 2 MBaud */
1313         r = efi_set_timer(console_timer_event, EFI_TIMER_PERIODIC, 50);
1314         if (r != EFI_SUCCESS)
1315                 printf("ERROR: Failed to set console timer\n");
1316         return r;
1317 out_of_memory:
1318         printf("ERROR: Out of memory\n");
1319         return r;
1320 }
This page took 0.105548 seconds and 4 git commands to generate.