1 /** @file 2 Implementation for EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL protocol. 3 4 Copyright (c) 2006 - 2010, Intel Corporation. All rights reserved.<BR> 5 This program and the accompanying materials 6 are licensed and made available under the terms and conditions of the BSD License 7 which accompanies this distribution. The full text of the license may be found at 8 http://opensource.org/licenses/bsd-license.php 9 10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, 11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. 12 13 **/ 14 15 #include "Terminal.h" 16 17 // 18 // This list is used to define the valid extend chars. 19 // It also provides a mapping from Unicode to PCANSI or 20 // ASCII. The ASCII mapping we just made up. 21 // 22 // 23 UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { 24 { BOXDRAW_HORIZONTAL, 0xc4, L'-' }, 25 { BOXDRAW_VERTICAL, 0xb3, L'|' }, 26 { BOXDRAW_DOWN_RIGHT, 0xda, L'/' }, 27 { BOXDRAW_DOWN_LEFT, 0xbf, L'\\' }, 28 { BOXDRAW_UP_RIGHT, 0xc0, L'\\' }, 29 { BOXDRAW_UP_LEFT, 0xd9, L'/' }, 30 { BOXDRAW_VERTICAL_RIGHT, 0xc3, L'|' }, 31 { BOXDRAW_VERTICAL_LEFT, 0xb4, L'|' }, 32 { BOXDRAW_DOWN_HORIZONTAL, 0xc2, L'+' }, 33 { BOXDRAW_UP_HORIZONTAL, 0xc1, L'+' }, 34 { BOXDRAW_VERTICAL_HORIZONTAL, 0xc5, L'+' }, 35 { BOXDRAW_DOUBLE_HORIZONTAL, 0xcd, L'-' }, 36 { BOXDRAW_DOUBLE_VERTICAL, 0xba, L'|' }, 37 { BOXDRAW_DOWN_RIGHT_DOUBLE, 0xd5, L'/' }, 38 { BOXDRAW_DOWN_DOUBLE_RIGHT, 0xd6, L'/' }, 39 { BOXDRAW_DOUBLE_DOWN_RIGHT, 0xc9, L'/' }, 40 { BOXDRAW_DOWN_LEFT_DOUBLE, 0xb8, L'\\' }, 41 { BOXDRAW_DOWN_DOUBLE_LEFT, 0xb7, L'\\' }, 42 { BOXDRAW_DOUBLE_DOWN_LEFT, 0xbb, L'\\' }, 43 { BOXDRAW_UP_RIGHT_DOUBLE, 0xd4, L'\\' }, 44 { BOXDRAW_UP_DOUBLE_RIGHT, 0xd3, L'\\' }, 45 { BOXDRAW_DOUBLE_UP_RIGHT, 0xc8, L'\\' }, 46 { BOXDRAW_UP_LEFT_DOUBLE, 0xbe, L'/' }, 47 { BOXDRAW_UP_DOUBLE_LEFT, 0xbd, L'/' }, 48 { BOXDRAW_DOUBLE_UP_LEFT, 0xbc, L'/' }, 49 { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0xc6, L'|' }, 50 { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0xc7, L'|' }, 51 { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0xcc, L'|' }, 52 { BOXDRAW_VERTICAL_LEFT_DOUBLE, 0xb5, L'|' }, 53 { BOXDRAW_VERTICAL_DOUBLE_LEFT, 0xb6, L'|' }, 54 { BOXDRAW_DOUBLE_VERTICAL_LEFT, 0xb9, L'|' }, 55 { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0xd1, L'+' }, 56 { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0xd2, L'+' }, 57 { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0xcb, L'+' }, 58 { BOXDRAW_UP_HORIZONTAL_DOUBLE, 0xcf, L'+' }, 59 { BOXDRAW_UP_DOUBLE_HORIZONTAL, 0xd0, L'+' }, 60 { BOXDRAW_DOUBLE_UP_HORIZONTAL, 0xca, L'+' }, 61 { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0xd8, L'+' }, 62 { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0xd7, L'+' }, 63 { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0xce, L'+' }, 64 65 { BLOCKELEMENT_FULL_BLOCK, 0xdb, L'*' }, 66 { BLOCKELEMENT_LIGHT_SHADE, 0xb0, L'+' }, 67 68 { GEOMETRICSHAPE_UP_TRIANGLE, 0x1e, L'^' }, 69 { GEOMETRICSHAPE_RIGHT_TRIANGLE, 0x10, L'>' }, 70 { GEOMETRICSHAPE_DOWN_TRIANGLE, 0x1f, L'v' }, 71 { GEOMETRICSHAPE_LEFT_TRIANGLE, 0x11, L'<' }, 72 73 { ARROW_LEFT, 0x3c, L'<' }, 74 { ARROW_UP, 0x18, L'^' }, 75 { ARROW_RIGHT, 0x3e, L'>' }, 76 { ARROW_DOWN, 0x19, L'v' }, 77 78 { 0x0000, 0x00, L'\0' } 79 }; 80 81 CHAR16 mSetModeString[] = { ESC, '[', '=', '3', 'h', 0 }; 82 CHAR16 mSetAttributeString[] = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 }; 83 CHAR16 mClearScreenString[] = { ESC, '[', '2', 'J', 0 }; 84 CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 }; 85 86 // 87 // Body of the ConOut functions 88 // 89 90 /** 91 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset(). 92 93 If ExtendeVerification is TRUE, then perform dependent serial device reset, 94 and set display mode to mode 0. 95 If ExtendedVerification is FALSE, only set display mode to mode 0. 96 97 @param This Indicates the calling context. 98 @param ExtendedVerification Indicates that the driver may perform a more 99 exhaustive verification operation of the device 100 during reset. 101 102 @retval EFI_SUCCESS The reset operation succeeds. 103 @retval EFI_DEVICE_ERROR The terminal is not functioning correctly or the serial port reset fails. 104 105 **/ 106 EFI_STATUS 107 EFIAPI 108 TerminalConOutReset ( 109 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 110 IN BOOLEAN ExtendedVerification 111 ) 112 { 113 EFI_STATUS Status; 114 TERMINAL_DEV *TerminalDevice; 115 116 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 117 118 // 119 // Perform a more exhaustive reset by resetting the serial port. 120 // 121 if (ExtendedVerification) { 122 // 123 // Report progress code here 124 // 125 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 126 EFI_PROGRESS_CODE, 127 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET), 128 TerminalDevice->DevicePath 129 ); 130 131 Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo); 132 if (EFI_ERROR (Status)) { 133 // 134 // Report error code here 135 // 136 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 137 EFI_ERROR_CODE | EFI_ERROR_MINOR, 138 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR), 139 TerminalDevice->DevicePath 140 ); 141 142 return Status; 143 } 144 } 145 146 This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK)); 147 148 Status = This->SetMode (This, 0); 149 150 return Status; 151 } 152 153 154 /** 155 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(). 156 157 The Unicode string will be converted to terminal expressible data stream 158 and send to terminal via serial port. 159 160 @param This Indicates the calling context. 161 @param WString The Null-terminated Unicode string to be displayed 162 on the terminal screen. 163 164 @retval EFI_SUCCESS The string is output successfully. 165 @retval EFI_DEVICE_ERROR The serial port fails to send the string out. 166 @retval EFI_WARN_UNKNOWN_GLYPH Indicates that some of the characters in the Unicode string could not 167 be rendered and are skipped. 168 @retval EFI_UNSUPPORTED If current display mode is out of range. 169 170 **/ 171 EFI_STATUS 172 EFIAPI 173 TerminalConOutOutputString ( 174 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 175 IN CHAR16 *WString 176 ) 177 { 178 TERMINAL_DEV *TerminalDevice; 179 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; 180 UINTN MaxColumn; 181 UINTN MaxRow; 182 UINTN Length; 183 UTF8_CHAR Utf8Char; 184 CHAR8 GraphicChar; 185 CHAR8 AsciiChar; 186 EFI_STATUS Status; 187 UINT8 ValidBytes; 188 // 189 // flag used to indicate whether condition happens which will cause 190 // return EFI_WARN_UNKNOWN_GLYPH 191 // 192 BOOLEAN Warning; 193 194 ValidBytes = 0; 195 Warning = FALSE; 196 AsciiChar = 0; 197 198 // 199 // get Terminal device data structure pointer. 200 // 201 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 202 203 // 204 // Get current display mode 205 // 206 Mode = This->Mode; 207 208 if (Mode->Mode >= Mode->MaxMode) { 209 return EFI_UNSUPPORTED; 210 } 211 212 This->QueryMode ( 213 This, 214 Mode->Mode, 215 &MaxColumn, 216 &MaxRow 217 ); 218 219 for (; *WString != CHAR_NULL; WString++) { 220 221 switch (TerminalDevice->TerminalType) { 222 223 case PCANSITYPE: 224 case VT100TYPE: 225 case VT100PLUSTYPE: 226 case TTYTERMTYPE: 227 228 if (!TerminalIsValidTextGraphics (*WString, &GraphicChar, &AsciiChar)) { 229 // 230 // If it's not a graphic character convert Unicode to ASCII. 231 // 232 GraphicChar = (CHAR8) *WString; 233 234 if (!(TerminalIsValidAscii (GraphicChar) || TerminalIsValidEfiCntlChar (GraphicChar))) { 235 // 236 // when this driver use the OutputString to output control string, 237 // TerminalDevice->OutputEscChar is set to let the Esc char 238 // to be output to the terminal emulation software. 239 // 240 if ((GraphicChar == 27) && TerminalDevice->OutputEscChar) { 241 GraphicChar = 27; 242 } else { 243 GraphicChar = '?'; 244 Warning = TRUE; 245 } 246 } 247 248 AsciiChar = GraphicChar; 249 250 } 251 252 if (TerminalDevice->TerminalType != PCANSITYPE) { 253 GraphicChar = AsciiChar; 254 } 255 256 Length = 1; 257 258 Status = TerminalDevice->SerialIo->Write ( 259 TerminalDevice->SerialIo, 260 &Length, 261 &GraphicChar 262 ); 263 264 if (EFI_ERROR (Status)) { 265 goto OutputError; 266 } 267 268 break; 269 270 case VTUTF8TYPE: 271 UnicodeToUtf8 (*WString, &Utf8Char, &ValidBytes); 272 Length = ValidBytes; 273 Status = TerminalDevice->SerialIo->Write ( 274 TerminalDevice->SerialIo, 275 &Length, 276 (UINT8 *) &Utf8Char 277 ); 278 if (EFI_ERROR (Status)) { 279 goto OutputError; 280 } 281 break; 282 } 283 // 284 // Update cursor position. 285 // 286 switch (*WString) { 287 288 case CHAR_BACKSPACE: 289 if (Mode->CursorColumn > 0) { 290 Mode->CursorColumn--; 291 } 292 break; 293 294 case CHAR_LINEFEED: 295 if (Mode->CursorRow < (INT32) (MaxRow - 1)) { 296 Mode->CursorRow++; 297 } 298 break; 299 300 case CHAR_CARRIAGE_RETURN: 301 Mode->CursorColumn = 0; 302 break; 303 304 default: 305 if (Mode->CursorColumn < (INT32) (MaxColumn - 1)) { 306 307 Mode->CursorColumn++; 308 309 } else { 310 311 Mode->CursorColumn = 0; 312 if (Mode->CursorRow < (INT32) (MaxRow - 1)) { 313 Mode->CursorRow++; 314 } 315 316 } 317 break; 318 319 }; 320 321 } 322 323 if (Warning) { 324 return EFI_WARN_UNKNOWN_GLYPH; 325 } 326 327 return EFI_SUCCESS; 328 329 OutputError: 330 REPORT_STATUS_CODE_WITH_DEVICE_PATH ( 331 EFI_ERROR_CODE | EFI_ERROR_MINOR, 332 (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR), 333 TerminalDevice->DevicePath 334 ); 335 336 return EFI_DEVICE_ERROR; 337 } 338 339 340 /** 341 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString(). 342 343 If one of the characters in the *Wstring is 344 neither valid Unicode drawing characters, 345 not ASCII code, then this function will return 346 EFI_UNSUPPORTED. 347 348 @param This Indicates the calling context. 349 @param WString The Null-terminated Unicode string to be tested. 350 351 @retval EFI_SUCCESS The terminal is capable of rendering the output string. 352 @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be rendered. 353 354 **/ 355 EFI_STATUS 356 EFIAPI 357 TerminalConOutTestString ( 358 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 359 IN CHAR16 *WString 360 ) 361 { 362 TERMINAL_DEV *TerminalDevice; 363 EFI_STATUS Status; 364 365 // 366 // get Terminal device data structure pointer. 367 // 368 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 369 370 switch (TerminalDevice->TerminalType) { 371 372 case PCANSITYPE: 373 case VT100TYPE: 374 case VT100PLUSTYPE: 375 case TTYTERMTYPE: 376 Status = AnsiTestString (TerminalDevice, WString); 377 break; 378 379 case VTUTF8TYPE: 380 Status = VTUTF8TestString (TerminalDevice, WString); 381 break; 382 383 default: 384 Status = EFI_UNSUPPORTED; 385 break; 386 } 387 388 return Status; 389 } 390 391 392 /** 393 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). 394 395 It returns information for an available text mode 396 that the terminal supports. 397 398 @param This Indicates the calling context. 399 @param ModeNumber The mode number to return information on. 400 @param Columns The returned columns of the requested mode. 401 @param Rows The returned rows of the requested mode. 402 403 @retval EFI_SUCCESS The requested mode information is returned. 404 @retval EFI_UNSUPPORTED The mode number is not valid. 405 406 **/ 407 EFI_STATUS 408 EFIAPI 409 TerminalConOutQueryMode ( 410 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 411 IN UINTN ModeNumber, 412 OUT UINTN *Columns, 413 OUT UINTN *Rows 414 ) 415 { 416 TERMINAL_DEV *TerminalDevice; 417 418 if (ModeNumber >= (UINTN) This->Mode->MaxMode) { 419 return EFI_UNSUPPORTED; 420 } 421 422 // 423 // Get Terminal device data structure pointer. 424 // 425 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 426 *Columns = TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns; 427 *Rows = TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows; 428 429 return EFI_SUCCESS; 430 } 431 432 433 /** 434 Implements EFI_SIMPLE_TEXT_OUT.SetMode(). 435 436 Set the terminal to a specified display mode. 437 In this driver, we only support mode 0. 438 439 @param This Indicates the calling context. 440 @param ModeNumber The text mode to set. 441 442 @retval EFI_SUCCESS The requested text mode is set. 443 @retval EFI_DEVICE_ERROR The requested text mode cannot be set 444 because of serial device error. 445 @retval EFI_UNSUPPORTED The text mode number is not valid. 446 447 **/ 448 EFI_STATUS 449 EFIAPI 450 TerminalConOutSetMode ( 451 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 452 IN UINTN ModeNumber 453 ) 454 { 455 EFI_STATUS Status; 456 TERMINAL_DEV *TerminalDevice; 457 458 // 459 // get Terminal device data structure pointer. 460 // 461 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 462 463 if (ModeNumber >= (UINTN) This->Mode->MaxMode) { 464 return EFI_UNSUPPORTED; 465 } 466 467 // 468 // Set the current mode 469 // 470 This->Mode->Mode = (INT32) ModeNumber; 471 472 This->ClearScreen (This); 473 474 TerminalDevice->OutputEscChar = TRUE; 475 Status = This->OutputString (This, mSetModeString); 476 TerminalDevice->OutputEscChar = FALSE; 477 478 if (EFI_ERROR (Status)) { 479 return EFI_DEVICE_ERROR; 480 } 481 482 This->Mode->Mode = (INT32) ModeNumber; 483 484 Status = This->ClearScreen (This); 485 if (EFI_ERROR (Status)) { 486 return EFI_DEVICE_ERROR; 487 } 488 489 return EFI_SUCCESS; 490 491 } 492 493 494 /** 495 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). 496 497 @param This Indicates the calling context. 498 @param Attribute The attribute to set. Only bit0..6 are valid, all other bits 499 are undefined and must be zero. 500 501 @retval EFI_SUCCESS The requested attribute is set. 502 @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to serial port error. 503 @retval EFI_UNSUPPORTED The attribute requested is not defined by EFI spec. 504 505 **/ 506 EFI_STATUS 507 EFIAPI 508 TerminalConOutSetAttribute ( 509 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 510 IN UINTN Attribute 511 ) 512 { 513 UINT8 ForegroundControl; 514 UINT8 BackgroundControl; 515 UINT8 BrightControl; 516 INT32 SavedColumn; 517 INT32 SavedRow; 518 EFI_STATUS Status; 519 TERMINAL_DEV *TerminalDevice; 520 521 SavedColumn = 0; 522 SavedRow = 0; 523 524 // 525 // get Terminal device data structure pointer. 526 // 527 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 528 529 // 530 // only the bit0..6 of the Attribute is valid 531 // 532 if ((Attribute | 0x7f) != 0x7f) { 533 return EFI_UNSUPPORTED; 534 } 535 536 // 537 // Skip outputting the command string for the same attribute 538 // It improves the terminal performance significantly 539 // 540 if (This->Mode->Attribute == (INT32) Attribute) { 541 return EFI_SUCCESS; 542 } 543 544 // 545 // convert Attribute value to terminal emulator 546 // understandable foreground color 547 // 548 switch (Attribute & 0x07) { 549 550 case EFI_BLACK: 551 ForegroundControl = 30; 552 break; 553 554 case EFI_BLUE: 555 ForegroundControl = 34; 556 break; 557 558 case EFI_GREEN: 559 ForegroundControl = 32; 560 break; 561 562 case EFI_CYAN: 563 ForegroundControl = 36; 564 break; 565 566 case EFI_RED: 567 ForegroundControl = 31; 568 break; 569 570 case EFI_MAGENTA: 571 ForegroundControl = 35; 572 break; 573 574 case EFI_BROWN: 575 ForegroundControl = 33; 576 break; 577 578 default: 579 580 case EFI_LIGHTGRAY: 581 ForegroundControl = 37; 582 break; 583 584 } 585 // 586 // bit4 of the Attribute indicates bright control 587 // of terminal emulator. 588 // 589 BrightControl = (UINT8) ((Attribute >> 3) & 1); 590 591 // 592 // convert Attribute value to terminal emulator 593 // understandable background color. 594 // 595 switch ((Attribute >> 4) & 0x07) { 596 597 case EFI_BLACK: 598 BackgroundControl = 40; 599 break; 600 601 case EFI_BLUE: 602 BackgroundControl = 44; 603 break; 604 605 case EFI_GREEN: 606 BackgroundControl = 42; 607 break; 608 609 case EFI_CYAN: 610 BackgroundControl = 46; 611 break; 612 613 case EFI_RED: 614 BackgroundControl = 41; 615 break; 616 617 case EFI_MAGENTA: 618 BackgroundControl = 45; 619 break; 620 621 case EFI_BROWN: 622 BackgroundControl = 43; 623 break; 624 625 default: 626 627 case EFI_LIGHTGRAY: 628 BackgroundControl = 47; 629 break; 630 } 631 // 632 // terminal emulator's control sequence to set attributes 633 // 634 mSetAttributeString[BRIGHT_CONTROL_OFFSET] = (CHAR16) ('0' + BrightControl); 635 mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (ForegroundControl / 10)); 636 mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (ForegroundControl % 10)); 637 mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0] = (CHAR16) ('0' + (BackgroundControl / 10)); 638 mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1] = (CHAR16) ('0' + (BackgroundControl % 10)); 639 640 // 641 // save current column and row 642 // for future scrolling back use. 643 // 644 SavedColumn = This->Mode->CursorColumn; 645 SavedRow = This->Mode->CursorRow; 646 647 TerminalDevice->OutputEscChar = TRUE; 648 Status = This->OutputString (This, mSetAttributeString); 649 TerminalDevice->OutputEscChar = FALSE; 650 651 if (EFI_ERROR (Status)) { 652 return EFI_DEVICE_ERROR; 653 } 654 // 655 // scroll back to saved cursor position. 656 // 657 This->Mode->CursorColumn = SavedColumn; 658 This->Mode->CursorRow = SavedRow; 659 660 This->Mode->Attribute = (INT32) Attribute; 661 662 return EFI_SUCCESS; 663 664 } 665 666 667 /** 668 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen(). 669 It clears the ANSI terminal's display to the 670 currently selected background color. 671 672 @param This Indicates the calling context. 673 674 @retval EFI_SUCCESS The operation completed successfully. 675 @retval EFI_DEVICE_ERROR The terminal screen cannot be cleared due to serial port error. 676 @retval EFI_UNSUPPORTED The terminal is not in a valid display mode. 677 678 **/ 679 EFI_STATUS 680 EFIAPI 681 TerminalConOutClearScreen ( 682 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This 683 ) 684 { 685 EFI_STATUS Status; 686 TERMINAL_DEV *TerminalDevice; 687 688 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 689 690 // 691 // control sequence for clear screen request 692 // 693 TerminalDevice->OutputEscChar = TRUE; 694 Status = This->OutputString (This, mClearScreenString); 695 TerminalDevice->OutputEscChar = FALSE; 696 697 if (EFI_ERROR (Status)) { 698 return EFI_DEVICE_ERROR; 699 } 700 701 Status = This->SetCursorPosition (This, 0, 0); 702 703 return Status; 704 } 705 706 707 /** 708 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition(). 709 710 @param This Indicates the calling context. 711 @param Column The row to set cursor to. 712 @param Row The column to set cursor to. 713 714 @retval EFI_SUCCESS The operation completed successfully. 715 @retval EFI_DEVICE_ERROR The request fails due to serial port error. 716 @retval EFI_UNSUPPORTED The terminal is not in a valid text mode, or the cursor position 717 is invalid for current mode. 718 719 **/ 720 EFI_STATUS 721 EFIAPI 722 TerminalConOutSetCursorPosition ( 723 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 724 IN UINTN Column, 725 IN UINTN Row 726 ) 727 { 728 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; 729 UINTN MaxColumn; 730 UINTN MaxRow; 731 EFI_STATUS Status; 732 TERMINAL_DEV *TerminalDevice; 733 734 TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); 735 736 // 737 // get current mode 738 // 739 Mode = This->Mode; 740 741 // 742 // get geometry of current mode 743 // 744 Status = This->QueryMode ( 745 This, 746 Mode->Mode, 747 &MaxColumn, 748 &MaxRow 749 ); 750 if (EFI_ERROR (Status)) { 751 return EFI_UNSUPPORTED; 752 } 753 754 if (Column >= MaxColumn || Row >= MaxRow) { 755 return EFI_UNSUPPORTED; 756 } 757 // 758 // control sequence to move the cursor 759 // 760 mSetCursorPositionString[ROW_OFFSET + 0] = (CHAR16) ('0' + ((Row + 1) / 10)); 761 mSetCursorPositionString[ROW_OFFSET + 1] = (CHAR16) ('0' + ((Row + 1) % 10)); 762 mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16) ('0' + ((Column + 1) / 10)); 763 mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16) ('0' + ((Column + 1) % 10)); 764 765 TerminalDevice->OutputEscChar = TRUE; 766 Status = This->OutputString (This, mSetCursorPositionString); 767 TerminalDevice->OutputEscChar = FALSE; 768 769 if (EFI_ERROR (Status)) { 770 return EFI_DEVICE_ERROR; 771 } 772 // 773 // update current cursor position 774 // in the Mode data structure. 775 // 776 Mode->CursorColumn = (INT32) Column; 777 Mode->CursorRow = (INT32) Row; 778 779 return EFI_SUCCESS; 780 } 781 782 783 /** 784 Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). 785 786 In this driver, the cursor cannot be hidden. 787 788 @param This Indicates the calling context. 789 @param Visible If TRUE, the cursor is set to be visible, 790 If FALSE, the cursor is set to be invisible. 791 792 @retval EFI_SUCCESS The request is valid. 793 @retval EFI_UNSUPPORTED The terminal does not support cursor hidden. 794 795 **/ 796 EFI_STATUS 797 EFIAPI 798 TerminalConOutEnableCursor ( 799 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, 800 IN BOOLEAN Visible 801 ) 802 { 803 if (!Visible) { 804 return EFI_UNSUPPORTED; 805 } 806 807 return EFI_SUCCESS; 808 } 809 810 811 /** 812 Detects if a Unicode char is for Box Drawing text graphics. 813 814 @param Graphic Unicode char to test. 815 @param PcAnsi Optional pointer to return PCANSI equivalent of 816 Graphic. 817 @param Ascii Optional pointer to return ASCII equivalent of 818 Graphic. 819 820 @retval TRUE If Graphic is a supported Unicode Box Drawing character. 821 822 **/ 823 BOOLEAN 824 TerminalIsValidTextGraphics ( 825 IN CHAR16 Graphic, 826 OUT CHAR8 *PcAnsi, OPTIONAL 827 OUT CHAR8 *Ascii OPTIONAL 828 ) 829 { 830 UNICODE_TO_CHAR *Table; 831 832 if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { 833 // 834 // Unicode drawing code charts are all in the 0x25xx range, 835 // arrows are 0x21xx 836 // 837 return FALSE; 838 } 839 840 for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { 841 if (Graphic == Table->Unicode) { 842 if (PcAnsi != NULL) { 843 *PcAnsi = Table->PcAnsi; 844 } 845 846 if (Ascii != NULL) { 847 *Ascii = Table->Ascii; 848 } 849 850 return TRUE; 851 } 852 } 853 854 return FALSE; 855 } 856 857 /** 858 Detects if a valid ASCII char. 859 860 @param Ascii An ASCII character. 861 862 @retval TRUE If it is a valid ASCII character. 863 @retval FALSE If it is not a valid ASCII character. 864 865 **/ 866 BOOLEAN 867 TerminalIsValidAscii ( 868 IN CHAR16 Ascii 869 ) 870 { 871 // 872 // valid ascii code lies in the extent of 0x20 ~ 0x7f 873 // 874 if ((Ascii >= 0x20) && (Ascii <= 0x7f)) { 875 return TRUE; 876 } 877 878 return FALSE; 879 } 880 881 /** 882 Detects if a valid EFI control character. 883 884 @param CharC An input EFI Control character. 885 886 @retval TRUE If it is a valid EFI control character. 887 @retval FALSE If it is not a valid EFI control character. 888 889 **/ 890 BOOLEAN 891 TerminalIsValidEfiCntlChar ( 892 IN CHAR16 CharC 893 ) 894 { 895 // 896 // only support four control characters. 897 // 898 if (CharC == CHAR_NULL || 899 CharC == CHAR_BACKSPACE || 900 CharC == CHAR_LINEFEED || 901 CharC == CHAR_CARRIAGE_RETURN || 902 CharC == CHAR_TAB 903 ) { 904 return TRUE; 905 } 906 907 return FALSE; 908 } 909