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