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
230 // Terminal driver only support mode 0
233 if (Mode
->Mode
!= 0) {
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_OUTPUT_PROTOCOL.QueryMode().
435 It returns information for an available text mode
436 that the terminal supports.
437 In this driver, we only support text mode 80x25, which is
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
> 1) {
468 return EFI_DEVICE_ERROR
;
471 if (ModeNumber
== 0) {
473 *Columns
= MODE0_COLUMN_COUNT
;
474 *Rows
= MODE0_ROW_COUNT
;
479 return EFI_UNSUPPORTED
;
484 TerminalConOutSetMode (
485 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
491 Implements EFI_SIMPLE_TEXT_OUT.SetMode().
492 Set the terminal to a specified display mode.
493 In this driver, we only support mode 0.
498 Indicates the calling context.
501 The text mode to set.
506 The requested text mode is set.
509 The requested text mode cannot be set because of serial device error.
512 The text mode number is not valid.
517 TERMINAL_DEV
*TerminalDevice
;
520 // get Terminal device data structure pointer.
522 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
524 if (ModeNumber
!= 0) {
525 return EFI_UNSUPPORTED
;
528 This
->Mode
->Mode
= 0;
530 This
->ClearScreen (This
);
532 TerminalDevice
->OutputEscChar
= TRUE
;
533 Status
= This
->OutputString (This
, mSetModeString
);
534 TerminalDevice
->OutputEscChar
= FALSE
;
536 if (EFI_ERROR (Status
)) {
537 return EFI_DEVICE_ERROR
;
540 This
->Mode
->Mode
= 0;
542 Status
= This
->ClearScreen (This
);
543 if (EFI_ERROR (Status
)) {
544 return EFI_DEVICE_ERROR
;
553 TerminalConOutSetAttribute (
554 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
560 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
565 Indicates the calling context.
568 The attribute to set. Only bit0..6 are valid, all other bits
569 are undefined and must be zero.
574 The requested attribute is set.
577 The requested attribute cannot be set due to serial port error.
580 The attribute requested is not defined by EFI spec.
584 UINT8 ForegroundControl
;
585 UINT8 BackgroundControl
;
590 TERMINAL_DEV
*TerminalDevice
;
596 // get Terminal device data structure pointer.
598 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
601 // only the bit0..6 of the Attribute is valid
603 if ((Attribute
| 0x7f) != 0x7f) {
604 return EFI_UNSUPPORTED
;
607 // convert Attribute value to terminal emulator
608 // understandable foreground color
610 switch (Attribute
& 0x07) {
613 ForegroundControl
= 30;
617 ForegroundControl
= 34;
621 ForegroundControl
= 32;
625 ForegroundControl
= 36;
629 ForegroundControl
= 31;
633 ForegroundControl
= 35;
637 ForegroundControl
= 33;
643 ForegroundControl
= 37;
648 // bit4 of the Attribute indicates bright control
649 // of terminal emulator.
651 BrightControl
= (UINT8
) ((Attribute
>> 3) & 1);
654 // convert Attribute value to terminal emulator
655 // understandable background color.
657 switch ((Attribute
>> 4) & 0x07) {
660 BackgroundControl
= 40;
664 BackgroundControl
= 44;
668 BackgroundControl
= 42;
672 BackgroundControl
= 46;
676 BackgroundControl
= 41;
680 BackgroundControl
= 45;
684 BackgroundControl
= 43;
690 BackgroundControl
= 47;
694 // terminal emulator's control sequence to set attributes
696 mSetAttributeString
[BRIGHT_CONTROL_OFFSET
] = (CHAR16
) ('0' + BrightControl
);
697 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (ForegroundControl
/ 10));
698 mSetAttributeString
[FOREGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (ForegroundControl
% 10));
699 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 0] = (CHAR16
) ('0' + (BackgroundControl
/ 10));
700 mSetAttributeString
[BACKGROUND_CONTROL_OFFSET
+ 1] = (CHAR16
) ('0' + (BackgroundControl
% 10));
703 // save current column and row
704 // for future scrolling back use.
706 SavedColumn
= This
->Mode
->CursorColumn
;
707 SavedRow
= This
->Mode
->CursorRow
;
709 TerminalDevice
->OutputEscChar
= TRUE
;
710 Status
= This
->OutputString (This
, mSetAttributeString
);
711 TerminalDevice
->OutputEscChar
= FALSE
;
713 if (EFI_ERROR (Status
)) {
714 return EFI_DEVICE_ERROR
;
717 // scroll back to saved cursor position.
719 This
->Mode
->CursorColumn
= SavedColumn
;
720 This
->Mode
->CursorRow
= SavedRow
;
722 This
->Mode
->Attribute
= (INT32
) Attribute
;
730 TerminalConOutClearScreen (
731 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
736 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
737 It clears the ANSI terminal's display to the
738 currently selected background color.
744 Indicates the calling context.
749 The operation completed successfully.
752 The terminal screen cannot be cleared due to serial port error.
755 The terminal is not in a valid display mode.
760 TERMINAL_DEV
*TerminalDevice
;
762 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
765 // control sequence for clear screen request
767 TerminalDevice
->OutputEscChar
= TRUE
;
768 Status
= This
->OutputString (This
, mClearScreenString
);
769 TerminalDevice
->OutputEscChar
= FALSE
;
771 if (EFI_ERROR (Status
)) {
772 return EFI_DEVICE_ERROR
;
775 Status
= This
->SetCursorPosition (This
, 0, 0);
782 TerminalConOutSetCursorPosition (
783 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
790 Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
795 Indicates the calling context.
798 The row to set cursor to.
801 The column to set cursor to.
806 The operation completed successfully.
809 The request fails due to serial port error.
812 The terminal is not in a valid text mode, or the cursor position
813 is invalid for current mode.
817 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
821 TERMINAL_DEV
*TerminalDevice
;
823 TerminalDevice
= TERMINAL_CON_OUT_DEV_FROM_THIS (This
);
831 // get geometry of current mode
833 Status
= This
->QueryMode (
839 if (EFI_ERROR (Status
)) {
840 return EFI_UNSUPPORTED
;
843 if (Column
>= MaxColumn
|| Row
>= MaxRow
) {
844 return EFI_UNSUPPORTED
;
847 // control sequence to move the cursor
849 mSetCursorPositionString
[ROW_OFFSET
+ 0] = (CHAR16
) ('0' + ((Row
+ 1) / 10));
850 mSetCursorPositionString
[ROW_OFFSET
+ 1] = (CHAR16
) ('0' + ((Row
+ 1) % 10));
851 mSetCursorPositionString
[COLUMN_OFFSET
+ 0] = (CHAR16
) ('0' + ((Column
+ 1) / 10));
852 mSetCursorPositionString
[COLUMN_OFFSET
+ 1] = (CHAR16
) ('0' + ((Column
+ 1) % 10));
854 TerminalDevice
->OutputEscChar
= TRUE
;
855 Status
= This
->OutputString (This
, mSetCursorPositionString
);
856 TerminalDevice
->OutputEscChar
= FALSE
;
858 if (EFI_ERROR (Status
)) {
859 return EFI_DEVICE_ERROR
;
862 // update current cursor position
863 // in the Mode data structure.
865 Mode
->CursorColumn
= (INT32
) Column
;
866 Mode
->CursorRow
= (INT32
) Row
;
873 TerminalConOutEnableCursor (
874 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
880 Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
881 In this driver, the cursor cannot be hidden.
886 Indicates the calling context.
889 If TRUE, the cursor is set to be visible,
890 If FALSE, the cursor is set to be invisible.
895 The request is valid.
898 The terminal does not support cursor hidden.
903 return EFI_UNSUPPORTED
;
910 TerminalIsValidTextGraphics (
912 OUT CHAR8
*PcAnsi
, OPTIONAL
913 OUT CHAR8
*Ascii OPTIONAL
919 Detects if a Unicode char is for Box Drawing text graphics.
923 Graphic - Unicode char to test.
925 PcAnsi - Optional pointer to return PCANSI equivalent of Graphic.
927 Ascii - Optional pointer to return ASCII equivalent of Graphic.
931 TRUE if Graphic is a supported Unicode Box Drawing character.
935 UNICODE_TO_CHAR
*Table
;
937 if ((((Graphic
& 0xff00) != 0x2500) && ((Graphic
& 0xff00) != 0x2100))) {
939 // Unicode drawing code charts are all in the 0x25xx range,
945 for (Table
= UnicodeToPcAnsiOrAscii
; Table
->Unicode
!= 0x0000; Table
++) {
946 if (Graphic
== Table
->Unicode
) {
947 if (PcAnsi
!= NULL
) {
948 *PcAnsi
= Table
->PcAnsi
;
952 *Ascii
= Table
->Ascii
;
963 TerminalIsValidAscii (
968 // valid ascii code lies in the extent of 0x20 ~ 0x7f
970 if ((Ascii
>= 0x20) && (Ascii
<= 0x7f)) {
978 TerminalIsValidEfiCntlChar (
983 // only support four control characters.
985 if (CharC
== CHAR_NULL
||
986 CharC
== CHAR_BACKSPACE
||
987 CharC
== CHAR_LINEFEED
||
988 CharC
== CHAR_CARRIAGE_RETURN
||