3 Copyright (c) 2006, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
25 // This list is used to define the valid extend chars.
26 // It also provides a mapping from Unicode to PCANSI or
27 // ASCII. The ASCII mapping we just made up.
30 STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii
[] = {
31 { BOXDRAW_HORIZONTAL
, 0xc4, L
'-' },
32 { BOXDRAW_VERTICAL
, 0xb3, L
'|' },
33 { BOXDRAW_DOWN_RIGHT
, 0xda, L
'/' },
34 { BOXDRAW_DOWN_LEFT
, 0xbf, L
'\\' },
35 { BOXDRAW_UP_RIGHT
, 0xc0, L
'\\' },
36 { BOXDRAW_UP_LEFT
, 0xd9, L
'/' },
37 { BOXDRAW_VERTICAL_RIGHT
, 0xc3, L
'|' },
38 { BOXDRAW_VERTICAL_LEFT
, 0xb4, L
'|' },
39 { BOXDRAW_DOWN_HORIZONTAL
, 0xc2, L
'+' },
40 { BOXDRAW_UP_HORIZONTAL
, 0xc1, L
'+' },
41 { BOXDRAW_VERTICAL_HORIZONTAL
, 0xc5, L
'+' },
42 { BOXDRAW_DOUBLE_HORIZONTAL
, 0xcd, L
'-' },
43 { BOXDRAW_DOUBLE_VERTICAL
, 0xba, L
'|' },
44 { BOXDRAW_DOWN_RIGHT_DOUBLE
, 0xd5, L
'/' },
45 { BOXDRAW_DOWN_DOUBLE_RIGHT
, 0xd6, L
'/' },
46 { BOXDRAW_DOUBLE_DOWN_RIGHT
, 0xc9, L
'/' },
47 { BOXDRAW_DOWN_LEFT_DOUBLE
, 0xb8, L
'\\' },
48 { BOXDRAW_DOWN_DOUBLE_LEFT
, 0xb7, L
'\\' },
49 { BOXDRAW_DOUBLE_DOWN_LEFT
, 0xbb, L
'\\' },
50 { BOXDRAW_UP_RIGHT_DOUBLE
, 0xd4, L
'\\' },
51 { BOXDRAW_UP_DOUBLE_RIGHT
, 0xd3, L
'\\' },
52 { BOXDRAW_DOUBLE_UP_RIGHT
, 0xc8, L
'\\' },
53 { BOXDRAW_UP_LEFT_DOUBLE
, 0xbe, L
'/' },
54 { BOXDRAW_UP_DOUBLE_LEFT
, 0xbd, L
'/' },
55 { BOXDRAW_DOUBLE_UP_LEFT
, 0xbc, L
'/' },
56 { BOXDRAW_VERTICAL_RIGHT_DOUBLE
, 0xc6, L
'|' },
57 { BOXDRAW_VERTICAL_DOUBLE_RIGHT
, 0xc7, L
'|' },
58 { BOXDRAW_DOUBLE_VERTICAL_RIGHT
, 0xcc, L
'|' },
59 { BOXDRAW_VERTICAL_LEFT_DOUBLE
, 0xb5, L
'|' },
60 { BOXDRAW_VERTICAL_DOUBLE_LEFT
, 0xb6, L
'|' },
61 { BOXDRAW_DOUBLE_VERTICAL_LEFT
, 0xb9, L
'|' },
62 { BOXDRAW_DOWN_HORIZONTAL_DOUBLE
, 0xd1, L
'+' },
63 { BOXDRAW_DOWN_DOUBLE_HORIZONTAL
, 0xd2, L
'+' },
64 { BOXDRAW_DOUBLE_DOWN_HORIZONTAL
, 0xcb, L
'+' },
65 { BOXDRAW_UP_HORIZONTAL_DOUBLE
, 0xcf, L
'+' },
66 { BOXDRAW_UP_DOUBLE_HORIZONTAL
, 0xd0, L
'+' },
67 { BOXDRAW_DOUBLE_UP_HORIZONTAL
, 0xca, L
'+' },
68 { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE
, 0xd8, L
'+' },
69 { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL
, 0xd7, L
'+' },
70 { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL
, 0xce, L
'+' },
72 { BLOCKELEMENT_FULL_BLOCK
, 0xdb, L
'*' },
73 { BLOCKELEMENT_LIGHT_SHADE
, 0xb0, L
'+' },
75 { GEOMETRICSHAPE_UP_TRIANGLE
, 0x1e, L
'^' },
76 { GEOMETRICSHAPE_RIGHT_TRIANGLE
, 0x10, L
'>' },
77 { GEOMETRICSHAPE_DOWN_TRIANGLE
, 0x1f, L
'v' },
78 { GEOMETRICSHAPE_LEFT_TRIANGLE
, 0x11, L
'<' },
80 { ARROW_LEFT
, 0x3c, L
'<' },
81 { ARROW_UP
, 0x18, L
'^' },
82 { ARROW_RIGHT
, 0x3e, L
'>' },
83 { ARROW_DOWN
, 0x19, L
'v' },
85 { 0x0000, 0x00, L
'\0' }
88 CHAR16 mSetModeString
[] = { ESC
, '[', '=', '3', 'h', 0 };
89 CHAR16 mSetAttributeString
[] = { ESC
, '[', '0', 'm', ESC
, '[', '4', '0', 'm', ESC
, '[', '4', '0', 'm', 0 };
90 CHAR16 mClearScreenString
[] = { ESC
, '[', '2', 'J', 0 };
91 CHAR16 mSetCursorPositionString
[] = { ESC
, '[', '0', '0', ';', '0', '0', 'H', 0 };
94 // Body of the ConOut functions
99 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
100 IN BOOLEAN ExtendedVerification
105 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().
106 If ExtendeVerification is TRUE, then perform dependent serial device reset,
107 and set display mode to mode 0.
108 If ExtendedVerification is FALSE, only set display mode to mode 0.
112 This - Indicates the calling context.
114 ExtendedVerification - Indicates that the driver may perform a more exhaustive
115 verification operation of the device during reset.
120 The reset operation succeeds.
123 The terminal is not functioning correctly or the serial port reset fails.
128 TERMINAL_DEV
*TerminalDevice
;
130 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
133 // Perform a more exhaustive reset by resetting the serial port.
135 if (ExtendedVerification
) {
137 // Report progress code here
139 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
141 PcdGet32 (PcdStatusCodeValueRemoteConsoleReset
),
142 TerminalDevice
->DevicePath
145 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
146 if (EFI_ERROR (Status
)) {
148 // Report error code here
150 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
151 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
152 PcdGet32 (PcdStatusCodeValueRemoteConsoleError
),
153 TerminalDevice
->DevicePath
160 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
162 Status
= This
->SetMode (This
, 0);
169 TerminalConOutOutputString (
170 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
176 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().
177 The Unicode string will be converted to terminal expressible data stream
178 and send to terminal via serial port.
183 This - Indicates the calling context.
185 WString - The Null-terminated Unicode string to be displayed on
191 The string is output successfully.
194 The serial port fails to send the string out.
196 EFI_WARN_UNKNOWN_GLYPH
197 Indicates that some of the characters in the Unicode string could not
198 be rendered and are skipped.
204 TERMINAL_DEV
*TerminalDevice
;
205 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
215 // flag used to indicate whether condition happens which will cause
216 // return EFI_WARN_UNKNOWN_GLYPH
224 // get Terminal device data structure pointer.
226 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
229 // Get current display mode
233 if (Mode
->Mode
> 2) {
234 return EFI_UNSUPPORTED
;
244 for (; *WString
!= CHAR_NULL
; WString
++) {
246 switch (TerminalDevice
->TerminalType
) {
252 if (!TerminalIsValidTextGraphics (*WString
, &GraphicChar
, &AsciiChar
)) {
254 // If it's not a graphic character convert Unicode to ASCII.
256 GraphicChar
= (CHAR8
) *WString
;
258 if (!(TerminalIsValidAscii (GraphicChar
) || TerminalIsValidEfiCntlChar (GraphicChar
))) {
260 // when this driver use the OutputString to output control string,
261 // TerminalDevice->OutputEscChar is set to let the Esc char
262 // to be output to the terminal emulation software.
264 if ((GraphicChar
== 27) && TerminalDevice
->OutputEscChar
) {
272 AsciiChar
= GraphicChar
;
276 if (TerminalDevice
->TerminalType
!= PcAnsiType
) {
277 GraphicChar
= AsciiChar
;
282 Status
= TerminalDevice
->SerialIo
->Write (
283 TerminalDevice
->SerialIo
,
288 if (EFI_ERROR (Status
)) {
295 UnicodeToUtf8 (*WString
, &Utf8Char
, &ValidBytes
);
297 Status
= TerminalDevice
->SerialIo
->Write (
298 TerminalDevice
->SerialIo
,
302 if (EFI_ERROR (Status
)) {
308 // Update cursor position.
313 if (Mode
->CursorColumn
> 0) {
314 Mode
->CursorColumn
--;
319 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
324 case CHAR_CARRIAGE_RETURN
:
325 Mode
->CursorColumn
= 0;
329 if (Mode
->CursorColumn
< (INT32
) (MaxColumn
- 1)) {
331 Mode
->CursorColumn
++;
335 Mode
->CursorColumn
= 0;
336 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
348 return EFI_WARN_UNKNOWN_GLYPH
;
354 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
355 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
356 PcdGet32 (PcdStatusCodeValueRemoteConsoleOutputError
),
357 TerminalDevice
->DevicePath
360 return EFI_DEVICE_ERROR
;
365 TerminalConOutTestString (
366 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
372 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().
373 If one of the characters in the *Wstring is
374 neither valid Unicode drawing characters,
375 not ASCII code, then this function will return
381 This - Indicates the calling context.
383 WString - The Null-terminated Unicode string to be tested.
388 The terminal is capable of rendering the output string.
391 Some of the characters in the Unicode string cannot be rendered.
395 TERMINAL_DEV
*TerminalDevice
;
399 // get Terminal device data structure pointer.
401 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
403 switch (TerminalDevice
->TerminalType
) {
408 Status
= AnsiTestString (TerminalDevice
, WString
);
412 Status
= VTUTF8TestString (TerminalDevice
, WString
);
416 Status
= EFI_UNSUPPORTED
;
425 TerminalConOutQueryMode (
426 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
434 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.QueryMode().
435 It returns information for an available text mode
436 that the terminal supports.
437 In this driver, we support text mode 80x25 (mode 0),
438 80x50 (mode 1), 100x31 (mode 2).
444 Indicates the calling context.
447 The mode number to return information on.
450 The returned columns of the requested mode.
453 The returned rows of the requested mode.
458 The requested mode information is returned.
461 The mode number is not valid.
467 if (This
->Mode
->MaxMode
> 3) {
468 return EFI_DEVICE_ERROR
;
471 if (ModeNumber
== 0) {
472 *Columns
= MODE0_COLUMN_COUNT
;
473 *Rows
= MODE0_ROW_COUNT
;
475 } else if (ModeNumber
== 1) {
476 *Columns
= MODE1_COLUMN_COUNT
;
477 *Rows
= MODE1_ROW_COUNT
;
479 } else if (ModeNumber
== 2) {
480 *Columns
= MODE2_COLUMN_COUNT
;
481 *Rows
= MODE2_ROW_COUNT
;
485 return EFI_UNSUPPORTED
;
490 TerminalConOutSetMode (
491 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
497 Implements EFI_SIMPLE_TEXT_OUT.SetMode().
498 Set the terminal to a specified display mode.
499 In this driver, we only support mode 0.
504 Indicates the calling context.
507 The text mode to set.
512 The requested text mode is set.
515 The requested text mode cannot be set because of serial device error.
518 The text mode number is not valid.
523 TERMINAL_DEV
*TerminalDevice
;
526 // get Terminal device data structure pointer.
528 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
530 if (ModeNumber
> 2) {
531 return EFI_UNSUPPORTED
;
535 // Set the current mode
537 This
->Mode
->Mode
= (INT32
) ModeNumber
;
539 This
->ClearScreen (This
);
541 TerminalDevice
->OutputEscChar
= TRUE
;
542 Status
= This
->OutputString (This
, mSetModeString
);
543 TerminalDevice
->OutputEscChar
= FALSE
;
545 if (EFI_ERROR (Status
)) {
546 return EFI_DEVICE_ERROR
;
549 This
->Mode
->Mode
= (INT32
) ModeNumber
;
551 Status
= This
->ClearScreen (This
);
552 if (EFI_ERROR (Status
)) {
553 return EFI_DEVICE_ERROR
;
562 TerminalConOutSetAttribute (
563 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
569 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
574 Indicates the calling context.
577 The attribute to set. Only bit0..6 are valid, all other bits
578 are undefined and must be zero.
583 The requested attribute is set.
586 The requested attribute cannot be set due to serial port error.
589 The attribute requested is not defined by EFI spec.
593 UINT8 ForegroundControl
;
594 UINT8 BackgroundControl
;
599 TERMINAL_DEV
*TerminalDevice
;
605 // get Terminal device data structure pointer.
607 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
610 // only the bit0..6 of the Attribute is valid
612 if ((Attribute
| 0x7f) != 0x7f) {
613 return EFI_UNSUPPORTED
;
616 // convert Attribute value to terminal emulator
617 // understandable foreground color
619 switch (Attribute
& 0x07) {
622 ForegroundControl
= 30;
626 ForegroundControl
= 34;
630 ForegroundControl
= 32;
634 ForegroundControl
= 36;
638 ForegroundControl
= 31;
642 ForegroundControl
= 35;
646 ForegroundControl
= 33;
652 ForegroundControl
= 37;
657 // bit4 of the Attribute indicates bright control
658 // of terminal emulator.
660 BrightControl
= (UINT8
) ((Attribute
>> 3) & 1);
663 // convert Attribute value to terminal emulator
664 // understandable background color.
666 switch ((Attribute
>> 4) & 0x07) {
669 BackgroundControl
= 40;
673 BackgroundControl
= 44;
677 BackgroundControl
= 42;
681 BackgroundControl
= 46;
685 BackgroundControl
= 41;
689 BackgroundControl
= 45;
693 BackgroundControl
= 43;
699 BackgroundControl
= 47;
703 // terminal emulator's control sequence to set attributes
705 mSetAttributeString
[BRIGHT_CONTROL_OFFSET
] = (CHAR16
) ('0' + BrightControl
);
706 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (ForegroundControl
/ 10));
707 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (ForegroundControl
% 10));
708 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (BackgroundControl
/ 10));
709 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (BackgroundControl
% 10));
712 // save current column and row
713 // for future scrolling back use.
715 SavedColumn
= This
->Mode
->CursorColumn
;
716 SavedRow
= This
->Mode
->CursorRow
;
718 TerminalDevice
->OutputEscChar
= TRUE
;
719 Status
= This
->OutputString (This
, mSetAttributeString
);
720 TerminalDevice
->OutputEscChar
= FALSE
;
722 if (EFI_ERROR (Status
)) {
723 return EFI_DEVICE_ERROR
;
726 // scroll back to saved cursor position.
728 This
->Mode
->CursorColumn
= SavedColumn
;
729 This
->Mode
->CursorRow
= SavedRow
;
731 This
->Mode
->Attribute
= (INT32
) Attribute
;
739 TerminalConOutClearScreen (
740 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
745 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
746 It clears the ANSI terminal's display to the
747 currently selected background color.
753 Indicates the calling context.
758 The operation completed successfully.
761 The terminal screen cannot be cleared due to serial port error.
764 The terminal is not in a valid display mode.
769 TERMINAL_DEV
*TerminalDevice
;
771 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
774 // control sequence for clear screen request
776 TerminalDevice
->OutputEscChar
= TRUE
;
777 Status
= This
->OutputString (This
, mClearScreenString
);
778 TerminalDevice
->OutputEscChar
= FALSE
;
780 if (EFI_ERROR (Status
)) {
781 return EFI_DEVICE_ERROR
;
784 Status
= This
->SetCursorPosition (This
, 0, 0);
791 TerminalConOutSetCursorPosition (
792 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
799 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
804 Indicates the calling context.
807 The row to set cursor to.
810 The column to set cursor to.
815 The operation completed successfully.
818 The request fails due to serial port error.
821 The terminal is not in a valid text mode, or the cursor position
822 is invalid for current mode.
826 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
830 TERMINAL_DEV
*TerminalDevice
;
832 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
840 // get geometry of current mode
842 Status
= This
->QueryMode (
848 if (EFI_ERROR (Status
)) {
849 return EFI_UNSUPPORTED
;
852 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
853 return EFI_UNSUPPORTED
;
856 // control sequence to move the cursor
858 mSetCursorPositionString
[ROW_OFFSET
+ 0] = (CHAR16
) ('0' + ((Row
+ 1) / 10));
859 mSetCursorPositionString
[ROW_OFFSET
+ 1] = (CHAR16
) ('0' + ((Row
+ 1) % 10));
860 mSetCursorPositionString
[COLUMN_OFFSET
+ 0] = (CHAR16
) ('0' + ((Column
+ 1) / 10));
861 mSetCursorPositionString
[COLUMN_OFFSET
+ 1] = (CHAR16
) ('0' + ((Column
+ 1) % 10));
863 TerminalDevice
->OutputEscChar
= TRUE
;
864 Status
= This
->OutputString (This
, mSetCursorPositionString
);
865 TerminalDevice
->OutputEscChar
= FALSE
;
867 if (EFI_ERROR (Status
)) {
868 return EFI_DEVICE_ERROR
;
871 // update current cursor position
872 // in the Mode data structure.
874 Mode
->CursorColumn
= (INT32
) Column
;
875 Mode
->CursorRow
= (INT32
) Row
;
882 TerminalConOutEnableCursor (
883 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
889 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
890 In this driver, the cursor cannot be hidden.
895 Indicates the calling context.
898 If TRUE, the cursor is set to be visible,
899 If FALSE, the cursor is set to be invisible.
904 The request is valid.
907 The terminal does not support cursor hidden.
912 return EFI_UNSUPPORTED
;
919 TerminalIsValidTextGraphics (
921 OUT CHAR8
*PcAnsi
, OPTIONAL
922 OUT CHAR8
*Ascii OPTIONAL
928 Detects if a Unicode char is for Box Drawing text graphics.
932 Graphic - Unicode char to test.
934 PcAnsi - Optional pointer to return PCANSI equivalent of Graphic.
936 Ascii - Optional pointer to return ASCII equivalent of Graphic.
940 TRUE if Graphic is a supported Unicode Box Drawing character.
944 UNICODE_TO_CHAR
*Table
;
946 if ((((Graphic
& 0xff00) != 0x2500) && ((Graphic
& 0xff00) != 0x2100))) {
948 // Unicode drawing code charts are all in the 0x25xx range,
954 for (Table
= UnicodeToPcAnsiOrAscii
; Table
->Unicode
!= 0x0000; Table
++) {
955 if (Graphic
== Table
->Unicode
) {
956 if (PcAnsi
!= NULL
) {
957 *PcAnsi
= Table
->PcAnsi
;
961 *Ascii
= Table
->Ascii
;
972 TerminalIsValidAscii (
977 // valid ascii code lies in the extent of 0x20 ~ 0x7f
979 if ((Ascii
>= 0x20) && (Ascii
<= 0x7f)) {
987 TerminalIsValidEfiCntlChar (
992 // only support four control characters.
994 if (CharC
== CHAR_NULL
||
995 CharC
== CHAR_BACKSPACE
||
996 CharC
== CHAR_LINEFEED
||
997 CharC
== CHAR_CARRIAGE_RETURN
||