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.
24 #include <Common/StatusCode.h>
27 // This list is used to define the valid extend chars.
28 // It also provides a mapping from Unicode to PCANSI or
29 // ASCII. The ASCII mapping we just made up.
32 STATIC UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii
[] = {
33 { BOXDRAW_HORIZONTAL
, 0xc4, L
'-' },
34 { BOXDRAW_VERTICAL
, 0xb3, L
'|' },
35 { BOXDRAW_DOWN_RIGHT
, 0xda, L
'/' },
36 { BOXDRAW_DOWN_LEFT
, 0xbf, L
'\\' },
37 { BOXDRAW_UP_RIGHT
, 0xc0, L
'\\' },
38 { BOXDRAW_UP_LEFT
, 0xd9, L
'/' },
39 { BOXDRAW_VERTICAL_RIGHT
, 0xc3, L
'|' },
40 { BOXDRAW_VERTICAL_LEFT
, 0xb4, L
'|' },
41 { BOXDRAW_DOWN_HORIZONTAL
, 0xc2, L
'+' },
42 { BOXDRAW_UP_HORIZONTAL
, 0xc1, L
'+' },
43 { BOXDRAW_VERTICAL_HORIZONTAL
, 0xc5, L
'+' },
44 { BOXDRAW_DOUBLE_HORIZONTAL
, 0xcd, L
'-' },
45 { BOXDRAW_DOUBLE_VERTICAL
, 0xba, L
'|' },
46 { BOXDRAW_DOWN_RIGHT_DOUBLE
, 0xd5, L
'/' },
47 { BOXDRAW_DOWN_DOUBLE_RIGHT
, 0xd6, L
'/' },
48 { BOXDRAW_DOUBLE_DOWN_RIGHT
, 0xc9, L
'/' },
49 { BOXDRAW_DOWN_LEFT_DOUBLE
, 0xb8, L
'\\' },
50 { BOXDRAW_DOWN_DOUBLE_LEFT
, 0xb7, L
'\\' },
51 { BOXDRAW_DOUBLE_DOWN_LEFT
, 0xbb, L
'\\' },
52 { BOXDRAW_UP_RIGHT_DOUBLE
, 0xd4, L
'\\' },
53 { BOXDRAW_UP_DOUBLE_RIGHT
, 0xd3, L
'\\' },
54 { BOXDRAW_DOUBLE_UP_RIGHT
, 0xc8, L
'\\' },
55 { BOXDRAW_UP_LEFT_DOUBLE
, 0xbe, L
'/' },
56 { BOXDRAW_UP_DOUBLE_LEFT
, 0xbd, L
'/' },
57 { BOXDRAW_DOUBLE_UP_LEFT
, 0xbc, L
'/' },
58 { BOXDRAW_VERTICAL_RIGHT_DOUBLE
, 0xc6, L
'|' },
59 { BOXDRAW_VERTICAL_DOUBLE_RIGHT
, 0xc7, L
'|' },
60 { BOXDRAW_DOUBLE_VERTICAL_RIGHT
, 0xcc, L
'|' },
61 { BOXDRAW_VERTICAL_LEFT_DOUBLE
, 0xb5, L
'|' },
62 { BOXDRAW_VERTICAL_DOUBLE_LEFT
, 0xb6, L
'|' },
63 { BOXDRAW_DOUBLE_VERTICAL_LEFT
, 0xb9, L
'|' },
64 { BOXDRAW_DOWN_HORIZONTAL_DOUBLE
, 0xd1, L
'+' },
65 { BOXDRAW_DOWN_DOUBLE_HORIZONTAL
, 0xd2, L
'+' },
66 { BOXDRAW_DOUBLE_DOWN_HORIZONTAL
, 0xcb, L
'+' },
67 { BOXDRAW_UP_HORIZONTAL_DOUBLE
, 0xcf, L
'+' },
68 { BOXDRAW_UP_DOUBLE_HORIZONTAL
, 0xd0, L
'+' },
69 { BOXDRAW_DOUBLE_UP_HORIZONTAL
, 0xca, L
'+' },
70 { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE
, 0xd8, L
'+' },
71 { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL
, 0xd7, L
'+' },
72 { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL
, 0xce, L
'+' },
74 { BLOCKELEMENT_FULL_BLOCK
, 0xdb, L
'*' },
75 { BLOCKELEMENT_LIGHT_SHADE
, 0xb0, L
'+' },
77 { GEOMETRICSHAPE_UP_TRIANGLE
, 0x1e, L
'^' },
78 { GEOMETRICSHAPE_RIGHT_TRIANGLE
, 0x10, L
'>' },
79 { GEOMETRICSHAPE_DOWN_TRIANGLE
, 0x1f, L
'v' },
80 { GEOMETRICSHAPE_LEFT_TRIANGLE
, 0x11, L
'<' },
82 { ARROW_LEFT
, 0x3c, L
'<' },
83 { ARROW_UP
, 0x18, L
'^' },
84 { ARROW_RIGHT
, 0x3e, L
'>' },
85 { ARROW_DOWN
, 0x19, L
'v' },
87 { 0x0000, 0x00, L
'\0' }
90 CHAR16 mSetModeString
[] = { ESC
, '[', '=', '3', 'h', 0 };
91 CHAR16 mSetAttributeString
[] = { ESC
, '[', '0', 'm', ESC
, '[', '4', '0', 'm', ESC
, '[', '4', '0', 'm', 0 };
92 CHAR16 mClearScreenString
[] = { ESC
, '[', '2', 'J', 0 };
93 CHAR16 mSetCursorPositionString
[] = { ESC
, '[', '0', '0', ';', '0', '0', 'H', 0 };
96 // Body of the ConOut functions
100 TerminalConOutReset (
101 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
102 IN BOOLEAN ExtendedVerification
107 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.Reset().
108 If ExtendeVerification is TRUE, then perform dependent serial device reset,
109 and set display mode to mode 0.
110 If ExtendedVerification is FALSE, only set display mode to mode 0.
114 This - Indicates the calling context.
116 ExtendedVerification - Indicates that the driver may perform a more exhaustive
117 verification operation of the device during reset.
122 The reset operation succeeds.
125 The terminal is not functioning correctly or the serial port reset fails.
130 TERMINAL_DEV
*TerminalDevice
;
132 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
135 // Perform a more exhaustive reset by resetting the serial port.
137 if (ExtendedVerification
) {
139 // Report progress code here
141 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
143 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_PC_RESET
,
144 TerminalDevice
->DevicePath
147 Status
= TerminalDevice
->SerialIo
->Reset (TerminalDevice
->SerialIo
);
148 if (EFI_ERROR (Status
)) {
150 // Report error code here
152 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
153 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
154 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
155 TerminalDevice
->DevicePath
162 This
->SetAttribute (This
, EFI_TEXT_ATTR (This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
));
164 Status
= This
->SetMode (This
, 0);
171 TerminalConOutOutputString (
172 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
178 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.OutputString().
179 The Unicode string will be converted to terminal expressible data stream
180 and send to terminal via serial port.
185 This - Indicates the calling context.
187 WString - The Null-terminated Unicode string to be displayed on
193 The string is output successfully.
196 The serial port fails to send the string out.
198 EFI_WARN_UNKNOWN_GLYPH
199 Indicates that some of the characters in the Unicode string could not
200 be rendered and are skipped.
206 TERMINAL_DEV
*TerminalDevice
;
207 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
217 // flag used to indicate whether condition happens which will cause
218 // return EFI_WARN_UNKNOWN_GLYPH
226 // get Terminal device data structure pointer.
228 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
231 // get current display mode
232 // Terminal driver only support mode 0
235 if (Mode
->Mode
!= 0) {
236 return EFI_UNSUPPORTED
;
246 for (; *WString
!= CHAR_NULL
; WString
++) {
248 switch (TerminalDevice
->TerminalType
) {
254 if (!TerminalIsValidTextGraphics (*WString
, &GraphicChar
, &AsciiChar
)) {
256 // If it's not a graphic character convert Unicode to ASCII.
258 GraphicChar
= (CHAR8
) *WString
;
260 if (!(TerminalIsValidAscii (GraphicChar
) || TerminalIsValidEfiCntlChar (GraphicChar
))) {
262 // when this driver use the OutputString to output control string,
263 // TerminalDevice->OutputEscChar is set to let the Esc char
264 // to be output to the terminal emulation software.
266 if ((GraphicChar
== 27) && TerminalDevice
->OutputEscChar
) {
274 AsciiChar
= GraphicChar
;
278 if (TerminalDevice
->TerminalType
!= PcAnsiType
) {
279 GraphicChar
= AsciiChar
;
284 Status
= TerminalDevice
->SerialIo
->Write (
285 TerminalDevice
->SerialIo
,
290 if (EFI_ERROR (Status
)) {
297 UnicodeToUtf8 (*WString
, &Utf8Char
, &ValidBytes
);
299 Status
= TerminalDevice
->SerialIo
->Write (
300 TerminalDevice
->SerialIo
,
304 if (EFI_ERROR (Status
)) {
310 // Update cursor position.
315 if (Mode
->CursorColumn
> 0) {
316 Mode
->CursorColumn
--;
321 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
326 case CHAR_CARRIAGE_RETURN
:
327 Mode
->CursorColumn
= 0;
331 if (Mode
->CursorColumn
< (INT32
) (MaxColumn
- 1)) {
333 Mode
->CursorColumn
++;
337 Mode
->CursorColumn
= 0;
338 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
350 return EFI_WARN_UNKNOWN_GLYPH
;
356 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
357 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
358 EFI_PERIPHERAL_REMOTE_CONSOLE
| EFI_P_EC_OUTPUT_ERROR
,
359 TerminalDevice
->DevicePath
362 return EFI_DEVICE_ERROR
;
367 TerminalConOutTestString (
368 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
374 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.TestString().
375 If one of the characters in the *Wstring is
376 neither valid Unicode drawing characters,
377 not ASCII code, then this function will return
383 This - Indicates the calling context.
385 WString - The Null-terminated Unicode string to be tested.
390 The terminal is capable of rendering the output string.
393 Some of the characters in the Unicode string cannot be rendered.
397 TERMINAL_DEV
*TerminalDevice
;
401 // get Terminal device data structure pointer.
403 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
405 switch (TerminalDevice
->TerminalType
) {
410 Status
= AnsiTestString (TerminalDevice
, WString
);
414 Status
= VTUTF8TestString (TerminalDevice
, WString
);
418 Status
= EFI_UNSUPPORTED
;
427 TerminalConOutQueryMode (
428 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
436 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.QueryMode().
437 It returns information for an available text mode
438 that the terminal supports.
439 In this driver, we only support text mode 80x25, which is
446 Indicates the calling context.
449 The mode number to return information on.
452 The returned columns of the requested mode.
455 The returned rows of the requested mode.
460 The requested mode information is returned.
463 The mode number is not valid.
469 if (This
->Mode
->MaxMode
> 1) {
470 return EFI_DEVICE_ERROR
;
473 if (ModeNumber
== 0) {
475 *Columns
= MODE0_COLUMN_COUNT
;
476 *Rows
= MODE0_ROW_COUNT
;
481 return EFI_UNSUPPORTED
;
486 TerminalConOutSetMode (
487 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
493 Implements EFI_SIMPLE_TEXT_OUT.SetMode().
494 Set the terminal to a specified display mode.
495 In this driver, we only support mode 0.
500 Indicates the calling context.
503 The text mode to set.
508 The requested text mode is set.
511 The requested text mode cannot be set because of serial device error.
514 The text mode number is not valid.
519 TERMINAL_DEV
*TerminalDevice
;
522 // get Terminal device data structure pointer.
524 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
526 if (ModeNumber
!= 0) {
527 return EFI_UNSUPPORTED
;
530 This
->Mode
->Mode
= 0;
532 This
->ClearScreen (This
);
534 TerminalDevice
->OutputEscChar
= TRUE
;
535 Status
= This
->OutputString (This
, mSetModeString
);
536 TerminalDevice
->OutputEscChar
= FALSE
;
538 if (EFI_ERROR (Status
)) {
539 return EFI_DEVICE_ERROR
;
542 This
->Mode
->Mode
= 0;
544 Status
= This
->ClearScreen (This
);
545 if (EFI_ERROR (Status
)) {
546 return EFI_DEVICE_ERROR
;
555 TerminalConOutSetAttribute (
556 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
562 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.SetAttribute().
567 Indicates the calling context.
570 The attribute to set. Only bit0..6 are valid, all other bits
571 are undefined and must be zero.
576 The requested attribute is set.
579 The requested attribute cannot be set due to serial port error.
582 The attribute requested is not defined by EFI spec.
586 UINT8 ForegroundControl
;
587 UINT8 BackgroundControl
;
592 TERMINAL_DEV
*TerminalDevice
;
598 // get Terminal device data structure pointer.
600 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
603 // only the bit0..6 of the Attribute is valid
605 if ((Attribute
| 0x7f) != 0x7f) {
606 return EFI_UNSUPPORTED
;
609 // convert Attribute value to terminal emulator
610 // understandable foreground color
612 switch (Attribute
& 0x07) {
615 ForegroundControl
= 30;
619 ForegroundControl
= 34;
623 ForegroundControl
= 32;
627 ForegroundControl
= 36;
631 ForegroundControl
= 31;
635 ForegroundControl
= 35;
639 ForegroundControl
= 33;
645 ForegroundControl
= 37;
650 // bit4 of the Attribute indicates bright control
651 // of terminal emulator.
653 BrightControl
= (UINT8
) ((Attribute
>> 3) & 1);
656 // convert Attribute value to terminal emulator
657 // understandable background color.
659 switch ((Attribute
>> 4) & 0x07) {
662 BackgroundControl
= 40;
666 BackgroundControl
= 44;
670 BackgroundControl
= 42;
674 BackgroundControl
= 46;
678 BackgroundControl
= 41;
682 BackgroundControl
= 45;
686 BackgroundControl
= 43;
692 BackgroundControl
= 47;
696 // terminal emulator's control sequence to set attributes
698 mSetAttributeString
[BRIGHT_CONTROL_OFFSET
] = (CHAR16
) ('0' + BrightControl
);
699 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (ForegroundControl
/ 10));
700 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (ForegroundControl
% 10));
701 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (BackgroundControl
/ 10));
702 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (BackgroundControl
% 10));
705 // save current column and row
706 // for future scrolling back use.
708 SavedColumn
= This
->Mode
->CursorColumn
;
709 SavedRow
= This
->Mode
->CursorRow
;
711 TerminalDevice
->OutputEscChar
= TRUE
;
712 Status
= This
->OutputString (This
, mSetAttributeString
);
713 TerminalDevice
->OutputEscChar
= FALSE
;
715 if (EFI_ERROR (Status
)) {
716 return EFI_DEVICE_ERROR
;
719 // scroll back to saved cursor position.
721 This
->Mode
->CursorColumn
= SavedColumn
;
722 This
->Mode
->CursorRow
= SavedRow
;
724 This
->Mode
->Attribute
= (INT32
) Attribute
;
732 TerminalConOutClearScreen (
733 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
738 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.ClearScreen().
739 It clears the ANSI terminal's display to the
740 currently selected background color.
746 Indicates the calling context.
751 The operation completed successfully.
754 The terminal screen cannot be cleared due to serial port error.
757 The terminal is not in a valid display mode.
762 TERMINAL_DEV
*TerminalDevice
;
764 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
767 // control sequence for clear screen request
769 TerminalDevice
->OutputEscChar
= TRUE
;
770 Status
= This
->OutputString (This
, mClearScreenString
);
771 TerminalDevice
->OutputEscChar
= FALSE
;
773 if (EFI_ERROR (Status
)) {
774 return EFI_DEVICE_ERROR
;
777 Status
= This
->SetCursorPosition (This
, 0, 0);
784 TerminalConOutSetCursorPosition (
785 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
792 Implements EFI_SIMPLE_TEXT_OUT_PROTOCOL.SetCursorPosition().
797 Indicates the calling context.
800 The row to set cursor to.
803 The column to set cursor to.
808 The operation completed successfully.
811 The request fails due to serial port error.
814 The terminal is not in a valid text mode, or the cursor position
815 is invalid for current mode.
819 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
823 TERMINAL_DEV
*TerminalDevice
;
825 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
833 // get geometry of current mode
835 Status
= This
->QueryMode (
841 if (EFI_ERROR (Status
)) {
842 return EFI_UNSUPPORTED
;
845 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
846 return EFI_UNSUPPORTED
;
849 // control sequence to move the cursor
851 mSetCursorPositionString
[ROW_OFFSET
+ 0] = (CHAR16
) ('0' + ((Row
+ 1) / 10));
852 mSetCursorPositionString
[ROW_OFFSET
+ 1] = (CHAR16
) ('0' + ((Row
+ 1) % 10));
853 mSetCursorPositionString
[COLUMN_OFFSET
+ 0] = (CHAR16
) ('0' + ((Column
+ 1) / 10));
854 mSetCursorPositionString
[COLUMN_OFFSET
+ 1] = (CHAR16
) ('0' + ((Column
+ 1) % 10));
856 TerminalDevice
->OutputEscChar
= TRUE
;
857 Status
= This
->OutputString (This
, mSetCursorPositionString
);
858 TerminalDevice
->OutputEscChar
= FALSE
;
860 if (EFI_ERROR (Status
)) {
861 return EFI_DEVICE_ERROR
;
864 // update current cursor position
865 // in the Mode data structure.
867 Mode
->CursorColumn
= (INT32
) Column
;
868 Mode
->CursorRow
= (INT32
) Row
;
875 TerminalConOutEnableCursor (
876 IN EFI_SIMPLE_TEXT_OUT_PROTOCOL
*This
,
882 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
883 In this driver, the cursor cannot be hidden.
888 Indicates the calling context.
891 If TRUE, the cursor is set to be visible,
892 If FALSE, the cursor is set to be invisible.
897 The request is valid.
900 The terminal does not support cursor hidden.
905 return EFI_UNSUPPORTED
;
912 TerminalIsValidTextGraphics (
914 OUT CHAR8
*PcAnsi
, OPTIONAL
915 OUT CHAR8
*Ascii OPTIONAL
921 Detects if a Unicode char is for Box Drawing text graphics.
925 Graphic - Unicode char to test.
927 PcAnsi - Optional pointer to return PCANSI equivalent of Graphic.
929 Ascii - Optional pointer to return ASCII equivalent of Graphic.
933 TRUE if Graphic is a supported Unicode Box Drawing character.
937 UNICODE_TO_CHAR
*Table
;
939 if ((((Graphic
& 0xff00) != 0x2500) && ((Graphic
& 0xff00) != 0x2100))) {
941 // Unicode drawing code charts are all in the 0x25xx range,
947 for (Table
= UnicodeToPcAnsiOrAscii
; Table
->Unicode
!= 0x0000; Table
++) {
948 if (Graphic
== Table
->Unicode
) {
949 if (PcAnsi
!= NULL
) {
950 *PcAnsi
= Table
->PcAnsi
;
954 *Ascii
= Table
->Ascii
;
965 TerminalIsValidAscii (
970 // valid ascii code lies in the extent of 0x20 ~ 0x7f
972 if ((Ascii
>= 0x20) && (Ascii
<= 0x7f)) {
980 TerminalIsValidEfiCntlChar (
985 // only support four control characters.
987 if (CharC
== CHAR_NULL
||
988 CharC
== CHAR_BACKSPACE
||
989 CharC
== CHAR_LINEFEED
||
990 CharC
== CHAR_CARRIAGE_RETURN
||