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