efi_loader: rework event handling for console
[platform/kernel/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 #include <common.h>
9 #include <charset.h>
10 #include <dm/device.h>
11 #include <efi_loader.h>
12 #include <stdio_dev.h>
13 #include <video_console.h>
14
15 #define EFI_COUT_MODE_2 2
16 #define EFI_MAX_COUT_MODE 3
17
18 struct cout_mode {
19         unsigned long columns;
20         unsigned long rows;
21         int present;
22 };
23
24 static struct cout_mode efi_cout_modes[] = {
25         /* EFI Mode 0 is 80x25 and always present */
26         {
27                 .columns = 80,
28                 .rows = 25,
29                 .present = 1,
30         },
31         /* EFI Mode 1 is always 80x50 */
32         {
33                 .columns = 80,
34                 .rows = 50,
35                 .present = 0,
36         },
37         /* Value are unknown until we query the console */
38         {
39                 .columns = 0,
40                 .rows = 0,
41                 .present = 0,
42         },
43 };
44
45 const efi_guid_t efi_guid_text_output_protocol =
46                         EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID;
47 const efi_guid_t efi_guid_text_input_protocol =
48                         EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID;
49
50 #define cESC '\x1b'
51 #define ESC "\x1b"
52
53 /* Default to mode 0 */
54 static struct simple_text_output_mode efi_con_mode = {
55         .max_mode = 1,
56         .mode = 0,
57         .attribute = 0,
58         .cursor_column = 0,
59         .cursor_row = 0,
60         .cursor_visible = 1,
61 };
62
63 /*
64  * Receive and parse a reply from the terminal.
65  *
66  * @n:          array of return values
67  * @num:        number of return values expected
68  * @end_char:   character indicating end of terminal message
69  * @return:     non-zero indicates error
70  */
71 static int term_read_reply(int *n, int num, char end_char)
72 {
73         char c;
74         int i = 0;
75
76         c = getc();
77         if (c != cESC)
78                 return -1;
79         c = getc();
80         if (c != '[')
81                 return -1;
82
83         n[0] = 0;
84         while (1) {
85                 c = getc();
86                 if (c == ';') {
87                         i++;
88                         if (i >= num)
89                                 return -1;
90                         n[i] = 0;
91                         continue;
92                 } else if (c == end_char) {
93                         break;
94                 } else if (c > '9' || c < '0') {
95                         return -1;
96                 }
97
98                 /* Read one more decimal position */
99                 n[i] *= 10;
100                 n[i] += c - '0';
101         }
102         if (i != num - 1)
103                 return -1;
104
105         return 0;
106 }
107
108 static efi_status_t EFIAPI efi_cout_output_string(
109                         struct efi_simple_text_output_protocol *this,
110                         const efi_string_t string)
111 {
112         struct simple_text_output_mode *con = &efi_con_mode;
113         struct cout_mode *mode = &efi_cout_modes[con->mode];
114         char *buf, *pos;
115         u16 *p;
116         efi_status_t ret = EFI_SUCCESS;
117
118         EFI_ENTRY("%p, %p", this, string);
119
120         buf = malloc(utf16_utf8_strlen(string) + 1);
121         if (!buf) {
122                 ret = EFI_OUT_OF_RESOURCES;
123                 goto out;
124         }
125         pos = buf;
126         utf16_utf8_strcpy(&pos, string);
127         fputs(stdout, buf);
128         free(buf);
129
130         /*
131          * Update the cursor position.
132          *
133          * The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
134          * and U000D. All other characters, including control characters
135          * U+0007 (BEL) and U+0009 (TAB), have to increase the column by one.
136          */
137         for (p = string; *p; ++p) {
138                 switch (*p) {
139                 case '\b':      /* U+0008, backspace */
140                         con->cursor_column = max(0, con->cursor_column - 1);
141                         break;
142                 case '\n':      /* U+000A, newline */
143                         con->cursor_column = 0;
144                         con->cursor_row++;
145                         break;
146                 case '\r':      /* U+000D, carriage-return */
147                         con->cursor_column = 0;
148                         break;
149                 case 0xd800 ... 0xdbff:
150                         /*
151                          * Ignore high surrogates, we do not want to count a
152                          * Unicode character twice.
153                          */
154                         break;
155                 default:
156                         con->cursor_column++;
157                         break;
158                 }
159                 if (con->cursor_column >= mode->columns) {
160                         con->cursor_column = 0;
161                         con->cursor_row++;
162                 }
163                 con->cursor_row = min(con->cursor_row, (s32)mode->rows - 1);
164         }
165
166 out:
167         return EFI_EXIT(ret);
168 }
169
170 static efi_status_t EFIAPI efi_cout_test_string(
171                         struct efi_simple_text_output_protocol *this,
172                         const efi_string_t string)
173 {
174         EFI_ENTRY("%p, %p", this, string);
175         return EFI_EXIT(EFI_SUCCESS);
176 }
177
178 static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
179 {
180         if (!mode->present)
181                 return false;
182
183         return (mode->rows == rows) && (mode->columns == cols);
184 }
185
186 static int query_console_serial(int *rows, int *cols)
187 {
188         /* Ask the terminal about its size */
189         int n[3];
190         u64 timeout;
191
192         /* Empty input buffer */
193         while (tstc())
194                 getc();
195
196         printf(ESC"[18t");
197
198         /* Check if we have a terminal that understands */
199         timeout = timer_get_us() + 1000000;
200         while (!tstc())
201                 if (timer_get_us() > timeout)
202                         return -1;
203
204         /* Read {depth,rows,cols} */
205         if (term_read_reply(n, 3, 't'))
206                 return -1;
207
208         *cols = n[2];
209         *rows = n[1];
210
211         return 0;
212 }
213
214 /*
215  * Update the mode table.
216  *
217  * By default the only mode available is 80x25. If the console has at least 50
218  * lines, enable mode 80x50. If we can query the console size and it is neither
219  * 80x25 nor 80x50, set it as an additional mode.
220  */
221 static void query_console_size(void)
222 {
223         const char *stdout_name = env_get("stdout");
224         int rows = 25, cols = 80;
225
226         if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
227             IS_ENABLED(CONFIG_DM_VIDEO)) {
228                 struct stdio_dev *stdout_dev =
229                         stdio_get_by_name("vidconsole");
230                 struct udevice *dev = stdout_dev->priv;
231                 struct vidconsole_priv *priv =
232                         dev_get_uclass_priv(dev);
233                 rows = priv->rows;
234                 cols = priv->cols;
235         } else if (query_console_serial(&rows, &cols)) {
236                 return;
237         }
238
239         /* Test if we can have Mode 1 */
240         if (cols >= 80 && rows >= 50) {
241                 efi_cout_modes[1].present = 1;
242                 efi_con_mode.max_mode = 2;
243         }
244
245         /*
246          * Install our mode as mode 2 if it is different
247          * than mode 0 or 1 and set it as the currently selected mode
248          */
249         if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) &&
250             !cout_mode_matches(&efi_cout_modes[1], rows, cols)) {
251                 efi_cout_modes[EFI_COUT_MODE_2].columns = cols;
252                 efi_cout_modes[EFI_COUT_MODE_2].rows = rows;
253                 efi_cout_modes[EFI_COUT_MODE_2].present = 1;
254                 efi_con_mode.max_mode = EFI_MAX_COUT_MODE;
255                 efi_con_mode.mode = EFI_COUT_MODE_2;
256         }
257 }
258
259 static efi_status_t EFIAPI efi_cout_query_mode(
260                         struct efi_simple_text_output_protocol *this,
261                         unsigned long mode_number, unsigned long *columns,
262                         unsigned long *rows)
263 {
264         EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
265
266         if (mode_number >= efi_con_mode.max_mode)
267                 return EFI_EXIT(EFI_UNSUPPORTED);
268
269         if (efi_cout_modes[mode_number].present != 1)
270                 return EFI_EXIT(EFI_UNSUPPORTED);
271
272         if (columns)
273                 *columns = efi_cout_modes[mode_number].columns;
274         if (rows)
275                 *rows = efi_cout_modes[mode_number].rows;
276
277         return EFI_EXIT(EFI_SUCCESS);
278 }
279
280 static efi_status_t EFIAPI efi_cout_set_mode(
281                         struct efi_simple_text_output_protocol *this,
282                         unsigned long mode_number)
283 {
284         EFI_ENTRY("%p, %ld", this, mode_number);
285
286
287         if (mode_number > efi_con_mode.max_mode)
288                 return EFI_EXIT(EFI_UNSUPPORTED);
289
290         efi_con_mode.mode = mode_number;
291         efi_con_mode.cursor_column = 0;
292         efi_con_mode.cursor_row = 0;
293
294         return EFI_EXIT(EFI_SUCCESS);
295 }
296
297 static const struct {
298         unsigned int fg;
299         unsigned int bg;
300 } color[] = {
301         { 30, 40 },     /* 0: black */
302         { 34, 44 },     /* 1: blue */
303         { 32, 42 },     /* 2: green */
304         { 36, 46 },     /* 3: cyan */
305         { 31, 41 },     /* 4: red */
306         { 35, 45 },     /* 5: magenta */
307         { 33, 43 },     /* 6: brown, map to yellow as EDK2 does*/
308         { 37, 47 },     /* 7: light gray, map to white */
309 };
310
311 /* See EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). */
312 static efi_status_t EFIAPI efi_cout_set_attribute(
313                         struct efi_simple_text_output_protocol *this,
314                         unsigned long attribute)
315 {
316         unsigned int bold = EFI_ATTR_BOLD(attribute);
317         unsigned int fg = EFI_ATTR_FG(attribute);
318         unsigned int bg = EFI_ATTR_BG(attribute);
319
320         EFI_ENTRY("%p, %lx", this, attribute);
321
322         if (attribute)
323                 printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg);
324         else
325                 printf(ESC"[0;37;40m");
326
327         return EFI_EXIT(EFI_SUCCESS);
328 }
329
330 static efi_status_t EFIAPI efi_cout_clear_screen(
331                         struct efi_simple_text_output_protocol *this)
332 {
333         EFI_ENTRY("%p", this);
334
335         printf(ESC"[2J");
336         efi_con_mode.cursor_column = 0;
337         efi_con_mode.cursor_row = 0;
338
339         return EFI_EXIT(EFI_SUCCESS);
340 }
341
342 static efi_status_t EFIAPI efi_cout_reset(
343                         struct efi_simple_text_output_protocol *this,
344                         char extended_verification)
345 {
346         EFI_ENTRY("%p, %d", this, extended_verification);
347
348         /* Clear screen */
349         EFI_CALL(efi_cout_clear_screen(this));
350         /* Set default colors */
351         printf(ESC "[0;37;40m");
352
353         return EFI_EXIT(EFI_SUCCESS);
354 }
355
356 static efi_status_t EFIAPI efi_cout_set_cursor_position(
357                         struct efi_simple_text_output_protocol *this,
358                         unsigned long column, unsigned long row)
359 {
360         EFI_ENTRY("%p, %ld, %ld", this, column, row);
361
362         printf(ESC"[%d;%df", (int)row, (int)column);
363         efi_con_mode.cursor_column = column;
364         efi_con_mode.cursor_row = row;
365
366         return EFI_EXIT(EFI_SUCCESS);
367 }
368
369 static efi_status_t EFIAPI efi_cout_enable_cursor(
370                         struct efi_simple_text_output_protocol *this,
371                         bool enable)
372 {
373         EFI_ENTRY("%p, %d", this, enable);
374
375         printf(ESC"[?25%c", enable ? 'h' : 'l');
376
377         return EFI_EXIT(EFI_SUCCESS);
378 }
379
380 struct efi_simple_text_output_protocol efi_con_out = {
381         .reset = efi_cout_reset,
382         .output_string = efi_cout_output_string,
383         .test_string = efi_cout_test_string,
384         .query_mode = efi_cout_query_mode,
385         .set_mode = efi_cout_set_mode,
386         .set_attribute = efi_cout_set_attribute,
387         .clear_screen = efi_cout_clear_screen,
388         .set_cursor_position = efi_cout_set_cursor_position,
389         .enable_cursor = efi_cout_enable_cursor,
390         .mode = (void*)&efi_con_mode,
391 };
392
393 static bool key_available;
394 static struct efi_input_key next_key;
395
396 /**
397  * skip_modifiers() - analyze modifiers (shift, alt, ctrl) for function keys
398  *
399  * This gets called when we have already parsed CSI.
400  *
401  * @modifiers:  bitmask (shift, alt, ctrl)
402  * @return:     the unmodified code
403  */
404 static char skip_modifiers(int *modifiers)
405 {
406         char c, mod = 0, ret = 0;
407
408         c = getc();
409
410         if (c != ';') {
411                 ret = c;
412                 if (c == '~')
413                         goto out;
414                 c = getc();
415         }
416         for (;;) {
417                 switch (c) {
418                 case '0'...'9':
419                         mod *= 10;
420                         mod += c - '0';
421                 /* fall through */
422                 case ';':
423                         c = getc();
424                         break;
425                 default:
426                         goto out;
427                 }
428         }
429 out:
430         if (mod)
431                 --mod;
432         if (modifiers)
433                 *modifiers = mod;
434         if (!ret)
435                 ret = c;
436         return ret;
437 }
438
439 /**
440  * efi_cin_read_key() - read a key from the console input
441  *
442  * @key:        - key received
443  * Return:      - status code
444  */
445 static efi_status_t efi_cin_read_key(struct efi_input_key *key)
446 {
447         efi_status_t ret;
448         struct efi_input_key pressed_key = {
449                 .scan_code = 0,
450                 .unicode_char = 0,
451         };
452         s32 ch;
453
454         ret = console_read_unicode(&ch);
455         if (ret)
456                 return EFI_NOT_READY;
457         /* We do not support multi-word codes */
458         if (ch >= 0x10000)
459                 ch = '?';
460         if (ch == cESC) {
461                 /*
462                  * Xterm Control Sequences
463                  * https://www.xfree86.org/4.8.0/ctlseqs.html
464                  */
465                 ch = getc();
466                 switch (ch) {
467                 case cESC: /* ESC */
468                         pressed_key.scan_code = 23;
469                         break;
470                 case 'O': /* F1 - F4 */
471                         ch = getc();
472                         /* skip modifiers */
473                         if (ch <= '9')
474                                 ch = getc();
475                         pressed_key.scan_code = ch - 'P' + 11;
476                         break;
477                 case 'a'...'z':
478                         ch = ch - 'a';
479                         break;
480                 case '[':
481                         ch = getc();
482                         switch (ch) {
483                         case 'A'...'D': /* up, down right, left */
484                                 pressed_key.scan_code = ch - 'A' + 1;
485                                 break;
486                         case 'F': /* End */
487                                 pressed_key.scan_code = 6;
488                                 break;
489                         case 'H': /* Home */
490                                 pressed_key.scan_code = 5;
491                                 break;
492                         case '1':
493                                 ch = skip_modifiers(NULL);
494                                 switch (ch) {
495                                 case '1'...'5': /* F1 - F5 */
496                                         pressed_key.scan_code = ch - '1' + 11;
497                                         break;
498                                 case '7'...'9': /* F6 - F8 */
499                                         pressed_key.scan_code = ch - '7' + 16;
500                                         break;
501                                 case 'A'...'D': /* up, down right, left */
502                                         pressed_key.scan_code = ch - 'A' + 1;
503                                         break;
504                                 case 'F':
505                                         pressed_key.scan_code = 6; /* End */
506                                         break;
507                                 case 'H':
508                                         pressed_key.scan_code = 5; /* Home */
509                                         break;
510                                 }
511                                 break;
512                         case '2':
513                                 ch = skip_modifiers(NULL);
514                                 switch (ch) {
515                                 case '0'...'1': /* F9 - F10 */
516                                         pressed_key.scan_code = ch - '0' + 19;
517                                         break;
518                                 case '3'...'4': /* F11 - F12 */
519                                         pressed_key.scan_code = ch - '3' + 21;
520                                         break;
521                                 case '~': /* INS */
522                                         pressed_key.scan_code = 7;
523                                         break;
524                                 }
525                                 break;
526                         case '3': /* DEL */
527                                 pressed_key.scan_code = 8;
528                                 skip_modifiers(NULL);
529                                 break;
530                         case '5': /* PG UP */
531                                 pressed_key.scan_code = 9;
532                                 skip_modifiers(NULL);
533                                 break;
534                         case '6': /* PG DOWN */
535                                 pressed_key.scan_code = 10;
536                                 skip_modifiers(NULL);
537                                 break;
538                         }
539                         break;
540                 }
541         } else if (ch == 0x7f) {
542                 /* Backspace */
543                 ch = 0x08;
544         }
545         if (!pressed_key.scan_code)
546                 pressed_key.unicode_char = ch;
547         *key = pressed_key;
548
549         return EFI_SUCCESS;
550 }
551
552 /**
553  * efi_cin_check() - check if keyboard input is available
554  */
555 static void efi_cin_check(void)
556 {
557         efi_status_t ret;
558
559         if (key_available) {
560                 efi_signal_event(efi_con_in.wait_for_key, true);
561                 return;
562         }
563
564         if (tstc()) {
565                 ret = efi_cin_read_key(&next_key);
566                 if (ret == EFI_SUCCESS) {
567                         key_available = true;
568
569                         /* Queue the wait for key event */
570                         efi_signal_event(efi_con_in.wait_for_key, true);
571                 }
572         }
573 }
574
575 /**
576  * efi_cin_reset() - drain the input buffer
577  *
578  * @this:                       instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
579  * @extended_verification:      allow for exhaustive verification
580  * Return:                      status code
581  *
582  * This function implements the Reset service of the
583  * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
584  *
585  * See the Unified Extensible Firmware Interface (UEFI) specification for
586  * details.
587  */
588 static efi_status_t EFIAPI efi_cin_reset
589                         (struct efi_simple_text_input_protocol *this,
590                          bool extended_verification)
591 {
592         efi_status_t ret = EFI_SUCCESS;
593
594         EFI_ENTRY("%p, %d", this, extended_verification);
595
596         /* Check parameters */
597         if (!this) {
598                 ret = EFI_INVALID_PARAMETER;
599                 goto out;
600         }
601
602         /* Empty input buffer */
603         while (tstc())
604                 getc();
605         key_available = false;
606 out:
607         return EFI_EXIT(ret);
608 }
609
610 /**
611  * efi_cin_reset() - drain the input buffer
612  *
613  * @this:       instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
614  * @key:        key read from console
615  * Return:      status code
616  *
617  * This function implements the ReadKeyStroke service of the
618  * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
619  *
620  * See the Unified Extensible Firmware Interface (UEFI) specification for
621  * details.
622  */
623 static efi_status_t EFIAPI efi_cin_read_key_stroke
624                         (struct efi_simple_text_input_protocol *this,
625                          struct efi_input_key *key)
626 {
627         efi_status_t ret = EFI_SUCCESS;
628
629         EFI_ENTRY("%p, %p", this, key);
630
631         /* Check parameters */
632         if (!this || !key) {
633                 ret = EFI_INVALID_PARAMETER;
634                 goto out;
635         }
636
637         /* We don't do interrupts, so check for timers cooperatively */
638         efi_timer_check();
639
640         /* Enable console input after ExitBootServices */
641         efi_cin_check();
642
643         if (!key_available) {
644                 ret = EFI_NOT_READY;
645                 goto out;
646         }
647         *key = next_key;
648         key_available = false;
649         efi_con_in.wait_for_key->is_signaled = false;
650 out:
651         return EFI_EXIT(ret);
652 }
653
654 struct efi_simple_text_input_protocol efi_con_in = {
655         .reset = efi_cin_reset,
656         .read_key_stroke = efi_cin_read_key_stroke,
657         .wait_for_key = NULL,
658 };
659
660 static struct efi_event *console_timer_event;
661
662 /*
663  * efi_console_timer_notify() - notify the console timer event
664  *
665  * @event:      console timer event
666  * @context:    not used
667  */
668 static void EFIAPI efi_console_timer_notify(struct efi_event *event,
669                                             void *context)
670 {
671         EFI_ENTRY("%p, %p", event, context);
672         efi_cin_check();
673         EFI_EXIT(EFI_SUCCESS);
674 }
675
676 /**
677  * efi_key_notify() - notify the wait for key event
678  *
679  * @event:      wait for key event
680  * @context:    not used
681  */
682 static void EFIAPI efi_key_notify(struct efi_event *event, void *context)
683 {
684         EFI_ENTRY("%p, %p", event, context);
685         efi_cin_check();
686         EFI_EXIT(EFI_SUCCESS);
687 }
688
689 /**
690  * efi_console_register() - install the console protocols
691  *
692  * This function is called from do_bootefi_exec().
693  */
694 int efi_console_register(void)
695 {
696         efi_status_t r;
697         struct efi_object *efi_console_output_obj;
698         struct efi_object *efi_console_input_obj;
699
700         /* Set up mode information */
701         query_console_size();
702
703         /* Create handles */
704         r = efi_create_handle((efi_handle_t *)&efi_console_output_obj);
705         if (r != EFI_SUCCESS)
706                 goto out_of_memory;
707
708         r = efi_add_protocol(efi_console_output_obj->handle,
709                              &efi_guid_text_output_protocol, &efi_con_out);
710         if (r != EFI_SUCCESS)
711                 goto out_of_memory;
712         systab.con_out_handle = efi_console_output_obj->handle;
713         systab.stderr_handle = efi_console_output_obj->handle;
714
715         r = efi_create_handle((efi_handle_t *)&efi_console_input_obj);
716         if (r != EFI_SUCCESS)
717                 goto out_of_memory;
718
719         r = efi_add_protocol(efi_console_input_obj->handle,
720                              &efi_guid_text_input_protocol, &efi_con_in);
721         if (r != EFI_SUCCESS)
722                 goto out_of_memory;
723         systab.con_in_handle = efi_console_input_obj->handle;
724
725         /* Create console events */
726         r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify,
727                              NULL, NULL, &efi_con_in.wait_for_key);
728         if (r != EFI_SUCCESS) {
729                 printf("ERROR: Failed to register WaitForKey event\n");
730                 return r;
731         }
732         r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
733                              efi_console_timer_notify, NULL, NULL,
734                              &console_timer_event);
735         if (r != EFI_SUCCESS) {
736                 printf("ERROR: Failed to register console event\n");
737                 return r;
738         }
739         /* 5000 ns cycle is sufficient for 2 MBaud */
740         r = efi_set_timer(console_timer_event, EFI_TIMER_PERIODIC, 50);
741         if (r != EFI_SUCCESS)
742                 printf("ERROR: Failed to set console timer\n");
743         return r;
744 out_of_memory:
745         printf("ERROR: Out of memory\n");
746         return r;
747 }