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