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