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