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