diff options
| author | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
|---|---|---|
| committer | kx <kx@radix.pro> | 2024-06-04 06:43:08 +0300 |
| commit | 7e2ccccace24636f29ddc210b94606abd4c7e42b (patch) | |
| tree | 545d43ea12671048956cafeb12303e84d601e571 /MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c | |
| parent | 27b044605cd5f6b33a3d231576003850b3fe305b (diff) | |
| download | edk2-trunk.tar.xz | |
Renormalized end-of-lines from master@27b044605cd5f6b33a3d231576003850b3fe305btrunk
Diffstat (limited to 'MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c')
| -rw-r--r-- | MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c | 1890 |
1 files changed, 945 insertions, 945 deletions
diff --git a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c index 7809869e7d..a6ef4e62f3 100644 --- a/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c +++ b/MdeModulePkg/Universal/Console/TerminalDxe/TerminalConOut.c @@ -1,945 +1,945 @@ -/** @file
- Implementation for EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL protocol.
-
-Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR>
-Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR>
-SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include "Terminal.h"
-
-//
-// This list is used to define the valid extend chars.
-// It also provides a mapping from Unicode to PCANSI or
-// ASCII. The ASCII mapping we just made up.
-//
-//
-UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = {
- { BOXDRAW_HORIZONTAL, 0xc4, L'-' },
- { BOXDRAW_VERTICAL, 0xb3, L'|' },
- { BOXDRAW_DOWN_RIGHT, 0xda, L'/' },
- { BOXDRAW_DOWN_LEFT, 0xbf, L'\\' },
- { BOXDRAW_UP_RIGHT, 0xc0, L'\\' },
- { BOXDRAW_UP_LEFT, 0xd9, L'/' },
- { BOXDRAW_VERTICAL_RIGHT, 0xc3, L'|' },
- { BOXDRAW_VERTICAL_LEFT, 0xb4, L'|' },
- { BOXDRAW_DOWN_HORIZONTAL, 0xc2, L'+' },
- { BOXDRAW_UP_HORIZONTAL, 0xc1, L'+' },
- { BOXDRAW_VERTICAL_HORIZONTAL, 0xc5, L'+' },
- { BOXDRAW_DOUBLE_HORIZONTAL, 0xcd, L'-' },
- { BOXDRAW_DOUBLE_VERTICAL, 0xba, L'|' },
- { BOXDRAW_DOWN_RIGHT_DOUBLE, 0xd5, L'/' },
- { BOXDRAW_DOWN_DOUBLE_RIGHT, 0xd6, L'/' },
- { BOXDRAW_DOUBLE_DOWN_RIGHT, 0xc9, L'/' },
- { BOXDRAW_DOWN_LEFT_DOUBLE, 0xb8, L'\\' },
- { BOXDRAW_DOWN_DOUBLE_LEFT, 0xb7, L'\\' },
- { BOXDRAW_DOUBLE_DOWN_LEFT, 0xbb, L'\\' },
- { BOXDRAW_UP_RIGHT_DOUBLE, 0xd4, L'\\' },
- { BOXDRAW_UP_DOUBLE_RIGHT, 0xd3, L'\\' },
- { BOXDRAW_DOUBLE_UP_RIGHT, 0xc8, L'\\' },
- { BOXDRAW_UP_LEFT_DOUBLE, 0xbe, L'/' },
- { BOXDRAW_UP_DOUBLE_LEFT, 0xbd, L'/' },
- { BOXDRAW_DOUBLE_UP_LEFT, 0xbc, L'/' },
- { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0xc6, L'|' },
- { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0xc7, L'|' },
- { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0xcc, L'|' },
- { BOXDRAW_VERTICAL_LEFT_DOUBLE, 0xb5, L'|' },
- { BOXDRAW_VERTICAL_DOUBLE_LEFT, 0xb6, L'|' },
- { BOXDRAW_DOUBLE_VERTICAL_LEFT, 0xb9, L'|' },
- { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0xd1, L'+' },
- { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0xd2, L'+' },
- { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0xcb, L'+' },
- { BOXDRAW_UP_HORIZONTAL_DOUBLE, 0xcf, L'+' },
- { BOXDRAW_UP_DOUBLE_HORIZONTAL, 0xd0, L'+' },
- { BOXDRAW_DOUBLE_UP_HORIZONTAL, 0xca, L'+' },
- { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0xd8, L'+' },
- { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0xd7, L'+' },
- { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0xce, L'+' },
-
- { BLOCKELEMENT_FULL_BLOCK, 0xdb, L'*' },
- { BLOCKELEMENT_LIGHT_SHADE, 0xb0, L'+' },
-
- { GEOMETRICSHAPE_UP_TRIANGLE, '^', L'^' },
- { GEOMETRICSHAPE_RIGHT_TRIANGLE, '>', L'>' },
- { GEOMETRICSHAPE_DOWN_TRIANGLE, 'v', L'v' },
- { GEOMETRICSHAPE_LEFT_TRIANGLE, '<', L'<' },
-
- { ARROW_LEFT, '<', L'<' },
- { ARROW_UP, '^', L'^' },
- { ARROW_RIGHT, '>', L'>' },
- { ARROW_DOWN, 'v', L'v' },
-
- { 0x0000, 0x00, L'\0' }
-};
-
-CHAR16 mSetModeString[] = { ESC, '[', '=', '3', 'h', 0 };
-CHAR16 mSetAttributeString[] = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 };
-CHAR16 mClearScreenString[] = { ESC, '[', '2', 'J', 0 };
-CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 };
-CHAR16 mCursorForwardString[] = { ESC, '[', '0', '0', 'C', 0 };
-CHAR16 mCursorBackwardString[] = { ESC, '[', '0', '0', 'D', 0 };
-
-//
-// Body of the ConOut functions
-//
-
-/**
- Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset().
-
- If ExtendeVerification is TRUE, then perform dependent serial device reset,
- and set display mode to mode 0.
- If ExtendedVerification is FALSE, only set display mode to mode 0.
-
- @param This Indicates the calling context.
- @param ExtendedVerification Indicates that the driver may perform a more
- exhaustive verification operation of the device
- during reset.
-
- @retval EFI_SUCCESS The reset operation succeeds.
- @retval EFI_DEVICE_ERROR The terminal is not functioning correctly or the serial port reset fails.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutReset (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN BOOLEAN ExtendedVerification
- )
-{
- EFI_STATUS Status;
- TERMINAL_DEV *TerminalDevice;
-
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
-
- //
- // Perform a more exhaustive reset by resetting the serial port.
- //
- if (ExtendedVerification) {
- //
- // Report progress code here
- //
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_PROGRESS_CODE,
- (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET),
- TerminalDevice->DevicePath
- );
-
- Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo);
- if (EFI_ERROR (Status)) {
- //
- // Report error code here
- //
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_ERROR_CODE | EFI_ERROR_MINOR,
- (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR),
- TerminalDevice->DevicePath
- );
-
- return Status;
- }
- }
-
- This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK));
-
- Status = This->SetMode (This, 0);
-
- return Status;
-}
-
-/**
- Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString().
-
- The Unicode string will be converted to terminal expressible data stream
- and send to terminal via serial port.
-
- @param This Indicates the calling context.
- @param WString The Null-terminated Unicode string to be displayed
- on the terminal screen.
-
- @retval EFI_SUCCESS The string is output successfully.
- @retval EFI_DEVICE_ERROR The serial port fails to send the string out.
- @retval EFI_WARN_UNKNOWN_GLYPH Indicates that some of the characters in the Unicode string could not
- be rendered and are skipped.
- @retval EFI_UNSUPPORTED If current display mode is out of range.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutOutputString (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN CHAR16 *WString
- )
-{
- TERMINAL_DEV *TerminalDevice;
- EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
- UINTN MaxColumn;
- UINTN MaxRow;
- UINTN Length;
- UTF8_CHAR Utf8Char;
- CHAR8 GraphicChar;
- CHAR8 AsciiChar;
- EFI_STATUS Status;
- UINT8 ValidBytes;
- CHAR8 CrLfStr[2];
- //
- // flag used to indicate whether condition happens which will cause
- // return EFI_WARN_UNKNOWN_GLYPH
- //
- BOOLEAN Warning;
-
- ValidBytes = 0;
- Warning = FALSE;
- AsciiChar = 0;
-
- //
- // get Terminal device data structure pointer.
- //
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
-
- //
- // Get current display mode
- //
- Mode = This->Mode;
-
- if (Mode->Mode >= Mode->MaxMode) {
- return EFI_UNSUPPORTED;
- }
-
- This->QueryMode (
- This,
- Mode->Mode,
- &MaxColumn,
- &MaxRow
- );
-
- for ( ; *WString != CHAR_NULL; WString++) {
- switch (TerminalDevice->TerminalType) {
- case TerminalTypePcAnsi:
- case TerminalTypeVt100:
- case TerminalTypeVt100Plus:
- case TerminalTypeTtyTerm:
- case TerminalTypeLinux:
- case TerminalTypeXtermR6:
- case TerminalTypeVt400:
- case TerminalTypeSCO:
-
- if (!TerminalIsValidTextGraphics (*WString, &GraphicChar, &AsciiChar)) {
- //
- // If it's not a graphic character convert Unicode to ASCII.
- //
- GraphicChar = (CHAR8)*WString;
-
- if (!(TerminalIsValidAscii (GraphicChar) || TerminalIsValidEfiCntlChar (GraphicChar))) {
- //
- // when this driver use the OutputString to output control string,
- // TerminalDevice->OutputEscChar is set to let the Esc char
- // to be output to the terminal emulation software.
- //
- if ((GraphicChar == 27) && TerminalDevice->OutputEscChar) {
- GraphicChar = 27;
- } else {
- GraphicChar = '?';
- Warning = TRUE;
- }
- }
-
- AsciiChar = GraphicChar;
- }
-
- if (TerminalDevice->TerminalType != TerminalTypePcAnsi) {
- GraphicChar = AsciiChar;
- }
-
- Length = 1;
-
- Status = TerminalDevice->SerialIo->Write (
- TerminalDevice->SerialIo,
- &Length,
- &GraphicChar
- );
-
- if (EFI_ERROR (Status)) {
- goto OutputError;
- }
-
- break;
-
- case TerminalTypeVtUtf8:
- UnicodeToUtf8 (*WString, &Utf8Char, &ValidBytes);
- Length = ValidBytes;
- Status = TerminalDevice->SerialIo->Write (
- TerminalDevice->SerialIo,
- &Length,
- (UINT8 *)&Utf8Char
- );
- if (EFI_ERROR (Status)) {
- goto OutputError;
- }
-
- break;
- }
-
- //
- // Update cursor position.
- //
- switch (*WString) {
- case CHAR_BACKSPACE:
- if (Mode->CursorColumn > 0) {
- Mode->CursorColumn--;
- }
-
- break;
-
- case CHAR_LINEFEED:
- if (Mode->CursorRow < (INT32)(MaxRow - 1)) {
- Mode->CursorRow++;
- }
-
- break;
-
- case CHAR_CARRIAGE_RETURN:
- Mode->CursorColumn = 0;
- break;
-
- default:
- if (Mode->CursorColumn < (INT32)(MaxColumn - 1)) {
- Mode->CursorColumn++;
- } else {
- Mode->CursorColumn = 0;
- if (Mode->CursorRow < (INT32)(MaxRow - 1)) {
- Mode->CursorRow++;
- }
-
- if ((TerminalDevice->TerminalType == TerminalTypeTtyTerm) &&
- !TerminalDevice->OutputEscChar)
- {
- //
- // We've written the last character on the line. The
- // terminal doesn't actually wrap its cursor until we print
- // the next character, but the driver thinks it has wrapped
- // already. Print CR LF to synchronize the terminal with
- // the driver, but only if we're not in the middle of
- // printing an escape sequence.
- //
- CrLfStr[0] = '\r';
- CrLfStr[1] = '\n';
-
- Length = sizeof (CrLfStr);
-
- Status = TerminalDevice->SerialIo->Write (
- TerminalDevice->SerialIo,
- &Length,
- CrLfStr
- );
-
- if (EFI_ERROR (Status)) {
- goto OutputError;
- }
- }
- }
-
- break;
- }
- }
-
- if (Warning) {
- return EFI_WARN_UNKNOWN_GLYPH;
- }
-
- return EFI_SUCCESS;
-
-OutputError:
- REPORT_STATUS_CODE_WITH_DEVICE_PATH (
- EFI_ERROR_CODE | EFI_ERROR_MINOR,
- (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR),
- TerminalDevice->DevicePath
- );
-
- return EFI_DEVICE_ERROR;
-}
-
-/**
- Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString().
-
- If one of the characters in the *Wstring is
- neither valid Unicode drawing characters,
- not ASCII code, then this function will return
- EFI_UNSUPPORTED.
-
- @param This Indicates the calling context.
- @param WString The Null-terminated Unicode string to be tested.
-
- @retval EFI_SUCCESS The terminal is capable of rendering the output string.
- @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be rendered.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutTestString (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN CHAR16 *WString
- )
-{
- TERMINAL_DEV *TerminalDevice;
- EFI_STATUS Status;
-
- //
- // get Terminal device data structure pointer.
- //
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
-
- switch (TerminalDevice->TerminalType) {
- case TerminalTypePcAnsi:
- case TerminalTypeVt100:
- case TerminalTypeVt100Plus:
- case TerminalTypeTtyTerm:
- Status = AnsiTestString (TerminalDevice, WString);
- break;
-
- case TerminalTypeVtUtf8:
- Status = VTUTF8TestString (TerminalDevice, WString);
- break;
-
- default:
- Status = EFI_UNSUPPORTED;
- break;
- }
-
- return Status;
-}
-
-/**
- Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode().
-
- It returns information for an available text mode
- that the terminal supports.
-
- @param This Indicates the calling context.
- @param ModeNumber The mode number to return information on.
- @param Columns The returned columns of the requested mode.
- @param Rows The returned rows of the requested mode.
-
- @retval EFI_SUCCESS The requested mode information is returned.
- @retval EFI_UNSUPPORTED The mode number is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutQueryMode (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN UINTN ModeNumber,
- OUT UINTN *Columns,
- OUT UINTN *Rows
- )
-{
- TERMINAL_DEV *TerminalDevice;
-
- if (ModeNumber >= (UINTN)This->Mode->MaxMode) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Get Terminal device data structure pointer.
- //
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
- *Columns = TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns;
- *Rows = TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows;
-
- return EFI_SUCCESS;
-}
-
-/**
- Implements EFI_SIMPLE_TEXT_OUT.SetMode().
-
- Set the terminal to a specified display mode.
- In this driver, we only support mode 0.
-
- @param This Indicates the calling context.
- @param ModeNumber The text mode to set.
-
- @retval EFI_SUCCESS The requested text mode is set.
- @retval EFI_DEVICE_ERROR The requested text mode cannot be set
- because of serial device error.
- @retval EFI_UNSUPPORTED The text mode number is not valid.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutSetMode (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN UINTN ModeNumber
- )
-{
- EFI_STATUS Status;
- TERMINAL_DEV *TerminalDevice;
-
- //
- // get Terminal device data structure pointer.
- //
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
-
- if (ModeNumber >= (UINTN)This->Mode->MaxMode) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Set the current mode
- //
- This->Mode->Mode = (INT32)ModeNumber;
-
- This->ClearScreen (This);
-
- TerminalDevice->OutputEscChar = TRUE;
- Status = This->OutputString (This, mSetModeString);
- TerminalDevice->OutputEscChar = FALSE;
-
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- This->Mode->Mode = (INT32)ModeNumber;
-
- Status = This->ClearScreen (This);
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute().
-
- @param This Indicates the calling context.
- @param Attribute The attribute to set. Only bit0..6 are valid, all other bits
- are undefined and must be zero.
-
- @retval EFI_SUCCESS The requested attribute is set.
- @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to serial port error.
- @retval EFI_UNSUPPORTED The attribute requested is not defined by EFI spec.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutSetAttribute (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN UINTN Attribute
- )
-{
- UINT8 ForegroundControl;
- UINT8 BackgroundControl;
- UINT8 BrightControl;
- INT32 SavedColumn;
- INT32 SavedRow;
- EFI_STATUS Status;
- TERMINAL_DEV *TerminalDevice;
-
- SavedColumn = 0;
- SavedRow = 0;
-
- //
- // get Terminal device data structure pointer.
- //
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
-
- //
- // only the bit0..6 of the Attribute is valid
- //
- if ((Attribute | 0x7f) != 0x7f) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Skip outputting the command string for the same attribute
- // It improves the terminal performance significantly
- //
- if (This->Mode->Attribute == (INT32)Attribute) {
- return EFI_SUCCESS;
- }
-
- //
- // convert Attribute value to terminal emulator
- // understandable foreground color
- //
- switch (Attribute & 0x07) {
- case EFI_BLACK:
- ForegroundControl = 30;
- break;
-
- case EFI_BLUE:
- ForegroundControl = 34;
- break;
-
- case EFI_GREEN:
- ForegroundControl = 32;
- break;
-
- case EFI_CYAN:
- ForegroundControl = 36;
- break;
-
- case EFI_RED:
- ForegroundControl = 31;
- break;
-
- case EFI_MAGENTA:
- ForegroundControl = 35;
- break;
-
- case EFI_BROWN:
- ForegroundControl = 33;
- break;
-
- default:
-
- case EFI_LIGHTGRAY:
- ForegroundControl = 37;
- break;
- }
-
- //
- // bit4 of the Attribute indicates bright control
- // of terminal emulator.
- //
- BrightControl = (UINT8)((Attribute >> 3) & 1);
-
- //
- // convert Attribute value to terminal emulator
- // understandable background color.
- //
- switch ((Attribute >> 4) & 0x07) {
- case EFI_BLACK:
- BackgroundControl = 40;
- break;
-
- case EFI_BLUE:
- BackgroundControl = 44;
- break;
-
- case EFI_GREEN:
- BackgroundControl = 42;
- break;
-
- case EFI_CYAN:
- BackgroundControl = 46;
- break;
-
- case EFI_RED:
- BackgroundControl = 41;
- break;
-
- case EFI_MAGENTA:
- BackgroundControl = 45;
- break;
-
- case EFI_BROWN:
- BackgroundControl = 43;
- break;
-
- default:
-
- case EFI_LIGHTGRAY:
- BackgroundControl = 47;
- break;
- }
-
- //
- // terminal emulator's control sequence to set attributes
- //
- mSetAttributeString[BRIGHT_CONTROL_OFFSET] = (CHAR16)('0' + BrightControl);
- mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0] = (CHAR16)('0' + (ForegroundControl / 10));
- mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1] = (CHAR16)('0' + (ForegroundControl % 10));
- mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0] = (CHAR16)('0' + (BackgroundControl / 10));
- mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1] = (CHAR16)('0' + (BackgroundControl % 10));
-
- //
- // save current column and row
- // for future scrolling back use.
- //
- SavedColumn = This->Mode->CursorColumn;
- SavedRow = This->Mode->CursorRow;
-
- TerminalDevice->OutputEscChar = TRUE;
- Status = This->OutputString (This, mSetAttributeString);
- TerminalDevice->OutputEscChar = FALSE;
-
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // scroll back to saved cursor position.
- //
- This->Mode->CursorColumn = SavedColumn;
- This->Mode->CursorRow = SavedRow;
-
- This->Mode->Attribute = (INT32)Attribute;
-
- return EFI_SUCCESS;
-}
-
-/**
- Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen().
- It clears the ANSI terminal's display to the
- currently selected background color.
-
- @param This Indicates the calling context.
-
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_DEVICE_ERROR The terminal screen cannot be cleared due to serial port error.
- @retval EFI_UNSUPPORTED The terminal is not in a valid display mode.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutClearScreen (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
- )
-{
- EFI_STATUS Status;
- TERMINAL_DEV *TerminalDevice;
-
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
-
- //
- // control sequence for clear screen request
- //
- TerminalDevice->OutputEscChar = TRUE;
- Status = This->OutputString (This, mClearScreenString);
- TerminalDevice->OutputEscChar = FALSE;
-
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- Status = This->SetCursorPosition (This, 0, 0);
-
- return Status;
-}
-
-/**
- Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition().
-
- @param This Indicates the calling context.
- @param Column The row to set cursor to.
- @param Row The column to set cursor to.
-
- @retval EFI_SUCCESS The operation completed successfully.
- @retval EFI_DEVICE_ERROR The request fails due to serial port error.
- @retval EFI_UNSUPPORTED The terminal is not in a valid text mode, or the cursor position
- is invalid for current mode.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutSetCursorPosition (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN UINTN Column,
- IN UINTN Row
- )
-{
- EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
- UINTN MaxColumn;
- UINTN MaxRow;
- EFI_STATUS Status;
- TERMINAL_DEV *TerminalDevice;
- CHAR16 *String;
-
- TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This);
-
- //
- // get current mode
- //
- Mode = This->Mode;
-
- //
- // get geometry of current mode
- //
- Status = This->QueryMode (
- This,
- Mode->Mode,
- &MaxColumn,
- &MaxRow
- );
- if (EFI_ERROR (Status)) {
- return EFI_UNSUPPORTED;
- }
-
- if ((Column >= MaxColumn) || (Row >= MaxRow)) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // control sequence to move the cursor
- //
- // Optimize cursor motion control sequences for TtyTerm. Move
- // within the current line if possible, and don't output anyting if
- // it isn't necessary.
- //
- if ((TerminalDevice->TerminalType == TerminalTypeTtyTerm) &&
- ((UINTN)Mode->CursorRow == Row))
- {
- if ((UINTN)Mode->CursorColumn > Column) {
- mCursorBackwardString[FW_BACK_OFFSET + 0] = (CHAR16)('0' + ((Mode->CursorColumn - Column) / 10));
- mCursorBackwardString[FW_BACK_OFFSET + 1] = (CHAR16)('0' + ((Mode->CursorColumn - Column) % 10));
- String = mCursorBackwardString;
- } else if (Column > (UINTN)Mode->CursorColumn) {
- mCursorForwardString[FW_BACK_OFFSET + 0] = (CHAR16)('0' + ((Column - Mode->CursorColumn) / 10));
- mCursorForwardString[FW_BACK_OFFSET + 1] = (CHAR16)('0' + ((Column - Mode->CursorColumn) % 10));
- String = mCursorForwardString;
- } else {
- String = L""; // No cursor motion necessary
- }
- } else {
- mSetCursorPositionString[ROW_OFFSET + 0] = (CHAR16)('0' + ((Row + 1) / 10));
- mSetCursorPositionString[ROW_OFFSET + 1] = (CHAR16)('0' + ((Row + 1) % 10));
- mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16)('0' + ((Column + 1) / 10));
- mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16)('0' + ((Column + 1) % 10));
- String = mSetCursorPositionString;
- }
-
- TerminalDevice->OutputEscChar = TRUE;
- Status = This->OutputString (This, String);
- TerminalDevice->OutputEscChar = FALSE;
-
- if (EFI_ERROR (Status)) {
- return EFI_DEVICE_ERROR;
- }
-
- //
- // update current cursor position
- // in the Mode data structure.
- //
- Mode->CursorColumn = (INT32)Column;
- Mode->CursorRow = (INT32)Row;
-
- return EFI_SUCCESS;
-}
-
-/**
- Implements SIMPLE_TEXT_OUTPUT.EnableCursor().
-
- In this driver, the cursor cannot be hidden.
-
- @param This Indicates the calling context.
- @param Visible If TRUE, the cursor is set to be visible,
- If FALSE, the cursor is set to be invisible.
-
- @retval EFI_SUCCESS The request is valid.
- @retval EFI_UNSUPPORTED The terminal does not support cursor hidden.
-
-**/
-EFI_STATUS
-EFIAPI
-TerminalConOutEnableCursor (
- IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
- IN BOOLEAN Visible
- )
-{
- if (!Visible) {
- return EFI_UNSUPPORTED;
- }
-
- return EFI_SUCCESS;
-}
-
-/**
- Detects if a Unicode char is for Box Drawing text graphics.
-
- @param Graphic Unicode char to test.
- @param PcAnsi Optional pointer to return PCANSI equivalent of
- Graphic.
- @param Ascii Optional pointer to return ASCII equivalent of
- Graphic.
-
- @retval TRUE If Graphic is a supported Unicode Box Drawing character.
-
-**/
-BOOLEAN
-TerminalIsValidTextGraphics (
- IN CHAR16 Graphic,
- OUT CHAR8 *PcAnsi OPTIONAL,
- OUT CHAR8 *Ascii OPTIONAL
- )
-{
- UNICODE_TO_CHAR *Table;
-
- if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) {
- //
- // Unicode drawing code charts are all in the 0x25xx range,
- // arrows are 0x21xx
- //
- return FALSE;
- }
-
- for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) {
- if (Graphic == Table->Unicode) {
- if (PcAnsi != NULL) {
- *PcAnsi = Table->PcAnsi;
- }
-
- if (Ascii != NULL) {
- *Ascii = Table->Ascii;
- }
-
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Detects if a valid ASCII char.
-
- @param Ascii An ASCII character.
-
- @retval TRUE If it is a valid ASCII character.
- @retval FALSE If it is not a valid ASCII character.
-
-**/
-BOOLEAN
-TerminalIsValidAscii (
- IN CHAR16 Ascii
- )
-{
- //
- // valid ascii code lies in the extent of 0x20 ~ 0x7f
- //
- if ((Ascii >= 0x20) && (Ascii <= 0x7f)) {
- return TRUE;
- }
-
- return FALSE;
-}
-
-/**
- Detects if a valid EFI control character.
-
- @param CharC An input EFI Control character.
-
- @retval TRUE If it is a valid EFI control character.
- @retval FALSE If it is not a valid EFI control character.
-
-**/
-BOOLEAN
-TerminalIsValidEfiCntlChar (
- IN CHAR16 CharC
- )
-{
- //
- // only support four control characters.
- //
- if ((CharC == CHAR_NULL) ||
- (CharC == CHAR_BACKSPACE) ||
- (CharC == CHAR_LINEFEED) ||
- (CharC == CHAR_CARRIAGE_RETURN) ||
- (CharC == CHAR_TAB)
- )
- {
- return TRUE;
- }
-
- return FALSE;
-}
+/** @file + Implementation for EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL protocol. + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.<BR> +Copyright (C) 2016 Silicon Graphics, Inc. All rights reserved.<BR> +SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "Terminal.h" + +// +// This list is used to define the valid extend chars. +// It also provides a mapping from Unicode to PCANSI or +// ASCII. The ASCII mapping we just made up. +// +// +UNICODE_TO_CHAR UnicodeToPcAnsiOrAscii[] = { + { BOXDRAW_HORIZONTAL, 0xc4, L'-' }, + { BOXDRAW_VERTICAL, 0xb3, L'|' }, + { BOXDRAW_DOWN_RIGHT, 0xda, L'/' }, + { BOXDRAW_DOWN_LEFT, 0xbf, L'\\' }, + { BOXDRAW_UP_RIGHT, 0xc0, L'\\' }, + { BOXDRAW_UP_LEFT, 0xd9, L'/' }, + { BOXDRAW_VERTICAL_RIGHT, 0xc3, L'|' }, + { BOXDRAW_VERTICAL_LEFT, 0xb4, L'|' }, + { BOXDRAW_DOWN_HORIZONTAL, 0xc2, L'+' }, + { BOXDRAW_UP_HORIZONTAL, 0xc1, L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL, 0xc5, L'+' }, + { BOXDRAW_DOUBLE_HORIZONTAL, 0xcd, L'-' }, + { BOXDRAW_DOUBLE_VERTICAL, 0xba, L'|' }, + { BOXDRAW_DOWN_RIGHT_DOUBLE, 0xd5, L'/' }, + { BOXDRAW_DOWN_DOUBLE_RIGHT, 0xd6, L'/' }, + { BOXDRAW_DOUBLE_DOWN_RIGHT, 0xc9, L'/' }, + { BOXDRAW_DOWN_LEFT_DOUBLE, 0xb8, L'\\' }, + { BOXDRAW_DOWN_DOUBLE_LEFT, 0xb7, L'\\' }, + { BOXDRAW_DOUBLE_DOWN_LEFT, 0xbb, L'\\' }, + { BOXDRAW_UP_RIGHT_DOUBLE, 0xd4, L'\\' }, + { BOXDRAW_UP_DOUBLE_RIGHT, 0xd3, L'\\' }, + { BOXDRAW_DOUBLE_UP_RIGHT, 0xc8, L'\\' }, + { BOXDRAW_UP_LEFT_DOUBLE, 0xbe, L'/' }, + { BOXDRAW_UP_DOUBLE_LEFT, 0xbd, L'/' }, + { BOXDRAW_DOUBLE_UP_LEFT, 0xbc, L'/' }, + { BOXDRAW_VERTICAL_RIGHT_DOUBLE, 0xc6, L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_RIGHT, 0xc7, L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_RIGHT, 0xcc, L'|' }, + { BOXDRAW_VERTICAL_LEFT_DOUBLE, 0xb5, L'|' }, + { BOXDRAW_VERTICAL_DOUBLE_LEFT, 0xb6, L'|' }, + { BOXDRAW_DOUBLE_VERTICAL_LEFT, 0xb9, L'|' }, + { BOXDRAW_DOWN_HORIZONTAL_DOUBLE, 0xd1, L'+' }, + { BOXDRAW_DOWN_DOUBLE_HORIZONTAL, 0xd2, L'+' }, + { BOXDRAW_DOUBLE_DOWN_HORIZONTAL, 0xcb, L'+' }, + { BOXDRAW_UP_HORIZONTAL_DOUBLE, 0xcf, L'+' }, + { BOXDRAW_UP_DOUBLE_HORIZONTAL, 0xd0, L'+' }, + { BOXDRAW_DOUBLE_UP_HORIZONTAL, 0xca, L'+' }, + { BOXDRAW_VERTICAL_HORIZONTAL_DOUBLE, 0xd8, L'+' }, + { BOXDRAW_VERTICAL_DOUBLE_HORIZONTAL, 0xd7, L'+' }, + { BOXDRAW_DOUBLE_VERTICAL_HORIZONTAL, 0xce, L'+' }, + + { BLOCKELEMENT_FULL_BLOCK, 0xdb, L'*' }, + { BLOCKELEMENT_LIGHT_SHADE, 0xb0, L'+' }, + + { GEOMETRICSHAPE_UP_TRIANGLE, '^', L'^' }, + { GEOMETRICSHAPE_RIGHT_TRIANGLE, '>', L'>' }, + { GEOMETRICSHAPE_DOWN_TRIANGLE, 'v', L'v' }, + { GEOMETRICSHAPE_LEFT_TRIANGLE, '<', L'<' }, + + { ARROW_LEFT, '<', L'<' }, + { ARROW_UP, '^', L'^' }, + { ARROW_RIGHT, '>', L'>' }, + { ARROW_DOWN, 'v', L'v' }, + + { 0x0000, 0x00, L'\0' } +}; + +CHAR16 mSetModeString[] = { ESC, '[', '=', '3', 'h', 0 }; +CHAR16 mSetAttributeString[] = { ESC, '[', '0', 'm', ESC, '[', '4', '0', 'm', ESC, '[', '4', '0', 'm', 0 }; +CHAR16 mClearScreenString[] = { ESC, '[', '2', 'J', 0 }; +CHAR16 mSetCursorPositionString[] = { ESC, '[', '0', '0', ';', '0', '0', 'H', 0 }; +CHAR16 mCursorForwardString[] = { ESC, '[', '0', '0', 'C', 0 }; +CHAR16 mCursorBackwardString[] = { ESC, '[', '0', '0', 'D', 0 }; + +// +// Body of the ConOut functions +// + +/** + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.Reset(). + + If ExtendeVerification is TRUE, then perform dependent serial device reset, + and set display mode to mode 0. + If ExtendedVerification is FALSE, only set display mode to mode 0. + + @param This Indicates the calling context. + @param ExtendedVerification Indicates that the driver may perform a more + exhaustive verification operation of the device + during reset. + + @retval EFI_SUCCESS The reset operation succeeds. + @retval EFI_DEVICE_ERROR The terminal is not functioning correctly or the serial port reset fails. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutReset ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // Perform a more exhaustive reset by resetting the serial port. + // + if (ExtendedVerification) { + // + // Report progress code here + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_PROGRESS_CODE, + (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_PC_RESET), + TerminalDevice->DevicePath + ); + + Status = TerminalDevice->SerialIo->Reset (TerminalDevice->SerialIo); + if (EFI_ERROR (Status)) { + // + // Report error code here + // + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_CONTROLLER_ERROR), + TerminalDevice->DevicePath + ); + + return Status; + } + } + + This->SetAttribute (This, EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BLACK)); + + Status = This->SetMode (This, 0); + + return Status; +} + +/** + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.OutputString(). + + The Unicode string will be converted to terminal expressible data stream + and send to terminal via serial port. + + @param This Indicates the calling context. + @param WString The Null-terminated Unicode string to be displayed + on the terminal screen. + + @retval EFI_SUCCESS The string is output successfully. + @retval EFI_DEVICE_ERROR The serial port fails to send the string out. + @retval EFI_WARN_UNKNOWN_GLYPH Indicates that some of the characters in the Unicode string could not + be rendered and are skipped. + @retval EFI_UNSUPPORTED If current display mode is out of range. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutOutputString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + TERMINAL_DEV *TerminalDevice; + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + UINTN Length; + UTF8_CHAR Utf8Char; + CHAR8 GraphicChar; + CHAR8 AsciiChar; + EFI_STATUS Status; + UINT8 ValidBytes; + CHAR8 CrLfStr[2]; + // + // flag used to indicate whether condition happens which will cause + // return EFI_WARN_UNKNOWN_GLYPH + // + BOOLEAN Warning; + + ValidBytes = 0; + Warning = FALSE; + AsciiChar = 0; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // Get current display mode + // + Mode = This->Mode; + + if (Mode->Mode >= Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + + for ( ; *WString != CHAR_NULL; WString++) { + switch (TerminalDevice->TerminalType) { + case TerminalTypePcAnsi: + case TerminalTypeVt100: + case TerminalTypeVt100Plus: + case TerminalTypeTtyTerm: + case TerminalTypeLinux: + case TerminalTypeXtermR6: + case TerminalTypeVt400: + case TerminalTypeSCO: + + if (!TerminalIsValidTextGraphics (*WString, &GraphicChar, &AsciiChar)) { + // + // If it's not a graphic character convert Unicode to ASCII. + // + GraphicChar = (CHAR8)*WString; + + if (!(TerminalIsValidAscii (GraphicChar) || TerminalIsValidEfiCntlChar (GraphicChar))) { + // + // when this driver use the OutputString to output control string, + // TerminalDevice->OutputEscChar is set to let the Esc char + // to be output to the terminal emulation software. + // + if ((GraphicChar == 27) && TerminalDevice->OutputEscChar) { + GraphicChar = 27; + } else { + GraphicChar = '?'; + Warning = TRUE; + } + } + + AsciiChar = GraphicChar; + } + + if (TerminalDevice->TerminalType != TerminalTypePcAnsi) { + GraphicChar = AsciiChar; + } + + Length = 1; + + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + &GraphicChar + ); + + if (EFI_ERROR (Status)) { + goto OutputError; + } + + break; + + case TerminalTypeVtUtf8: + UnicodeToUtf8 (*WString, &Utf8Char, &ValidBytes); + Length = ValidBytes; + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + (UINT8 *)&Utf8Char + ); + if (EFI_ERROR (Status)) { + goto OutputError; + } + + break; + } + + // + // Update cursor position. + // + switch (*WString) { + case CHAR_BACKSPACE: + if (Mode->CursorColumn > 0) { + Mode->CursorColumn--; + } + + break; + + case CHAR_LINEFEED: + if (Mode->CursorRow < (INT32)(MaxRow - 1)) { + Mode->CursorRow++; + } + + break; + + case CHAR_CARRIAGE_RETURN: + Mode->CursorColumn = 0; + break; + + default: + if (Mode->CursorColumn < (INT32)(MaxColumn - 1)) { + Mode->CursorColumn++; + } else { + Mode->CursorColumn = 0; + if (Mode->CursorRow < (INT32)(MaxRow - 1)) { + Mode->CursorRow++; + } + + if ((TerminalDevice->TerminalType == TerminalTypeTtyTerm) && + !TerminalDevice->OutputEscChar) + { + // + // We've written the last character on the line. The + // terminal doesn't actually wrap its cursor until we print + // the next character, but the driver thinks it has wrapped + // already. Print CR LF to synchronize the terminal with + // the driver, but only if we're not in the middle of + // printing an escape sequence. + // + CrLfStr[0] = '\r'; + CrLfStr[1] = '\n'; + + Length = sizeof (CrLfStr); + + Status = TerminalDevice->SerialIo->Write ( + TerminalDevice->SerialIo, + &Length, + CrLfStr + ); + + if (EFI_ERROR (Status)) { + goto OutputError; + } + } + } + + break; + } + } + + if (Warning) { + return EFI_WARN_UNKNOWN_GLYPH; + } + + return EFI_SUCCESS; + +OutputError: + REPORT_STATUS_CODE_WITH_DEVICE_PATH ( + EFI_ERROR_CODE | EFI_ERROR_MINOR, + (EFI_PERIPHERAL_REMOTE_CONSOLE | EFI_P_EC_OUTPUT_ERROR), + TerminalDevice->DevicePath + ); + + return EFI_DEVICE_ERROR; +} + +/** + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.TestString(). + + If one of the characters in the *Wstring is + neither valid Unicode drawing characters, + not ASCII code, then this function will return + EFI_UNSUPPORTED. + + @param This Indicates the calling context. + @param WString The Null-terminated Unicode string to be tested. + + @retval EFI_SUCCESS The terminal is capable of rendering the output string. + @retval EFI_UNSUPPORTED Some of the characters in the Unicode string cannot be rendered. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutTestString ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN CHAR16 *WString + ) +{ + TERMINAL_DEV *TerminalDevice; + EFI_STATUS Status; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + switch (TerminalDevice->TerminalType) { + case TerminalTypePcAnsi: + case TerminalTypeVt100: + case TerminalTypeVt100Plus: + case TerminalTypeTtyTerm: + Status = AnsiTestString (TerminalDevice, WString); + break; + + case TerminalTypeVtUtf8: + Status = VTUTF8TestString (TerminalDevice, WString); + break; + + default: + Status = EFI_UNSUPPORTED; + break; + } + + return Status; +} + +/** + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.QueryMode(). + + It returns information for an available text mode + that the terminal supports. + + @param This Indicates the calling context. + @param ModeNumber The mode number to return information on. + @param Columns The returned columns of the requested mode. + @param Rows The returned rows of the requested mode. + + @retval EFI_SUCCESS The requested mode information is returned. + @retval EFI_UNSUPPORTED The mode number is not valid. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutQueryMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber, + OUT UINTN *Columns, + OUT UINTN *Rows + ) +{ + TERMINAL_DEV *TerminalDevice; + + if (ModeNumber >= (UINTN)This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + // + // Get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + *Columns = TerminalDevice->TerminalConsoleModeData[ModeNumber].Columns; + *Rows = TerminalDevice->TerminalConsoleModeData[ModeNumber].Rows; + + return EFI_SUCCESS; +} + +/** + Implements EFI_SIMPLE_TEXT_OUT.SetMode(). + + Set the terminal to a specified display mode. + In this driver, we only support mode 0. + + @param This Indicates the calling context. + @param ModeNumber The text mode to set. + + @retval EFI_SUCCESS The requested text mode is set. + @retval EFI_DEVICE_ERROR The requested text mode cannot be set + because of serial device error. + @retval EFI_UNSUPPORTED The text mode number is not valid. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutSetMode ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN ModeNumber + ) +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + if (ModeNumber >= (UINTN)This->Mode->MaxMode) { + return EFI_UNSUPPORTED; + } + + // + // Set the current mode + // + This->Mode->Mode = (INT32)ModeNumber; + + This->ClearScreen (This); + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetModeString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + This->Mode->Mode = (INT32)ModeNumber; + + Status = This->ClearScreen (This); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + return EFI_SUCCESS; +} + +/** + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). + + @param This Indicates the calling context. + @param Attribute The attribute to set. Only bit0..6 are valid, all other bits + are undefined and must be zero. + + @retval EFI_SUCCESS The requested attribute is set. + @retval EFI_DEVICE_ERROR The requested attribute cannot be set due to serial port error. + @retval EFI_UNSUPPORTED The attribute requested is not defined by EFI spec. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutSetAttribute ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Attribute + ) +{ + UINT8 ForegroundControl; + UINT8 BackgroundControl; + UINT8 BrightControl; + INT32 SavedColumn; + INT32 SavedRow; + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + SavedColumn = 0; + SavedRow = 0; + + // + // get Terminal device data structure pointer. + // + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // only the bit0..6 of the Attribute is valid + // + if ((Attribute | 0x7f) != 0x7f) { + return EFI_UNSUPPORTED; + } + + // + // Skip outputting the command string for the same attribute + // It improves the terminal performance significantly + // + if (This->Mode->Attribute == (INT32)Attribute) { + return EFI_SUCCESS; + } + + // + // convert Attribute value to terminal emulator + // understandable foreground color + // + switch (Attribute & 0x07) { + case EFI_BLACK: + ForegroundControl = 30; + break; + + case EFI_BLUE: + ForegroundControl = 34; + break; + + case EFI_GREEN: + ForegroundControl = 32; + break; + + case EFI_CYAN: + ForegroundControl = 36; + break; + + case EFI_RED: + ForegroundControl = 31; + break; + + case EFI_MAGENTA: + ForegroundControl = 35; + break; + + case EFI_BROWN: + ForegroundControl = 33; + break; + + default: + + case EFI_LIGHTGRAY: + ForegroundControl = 37; + break; + } + + // + // bit4 of the Attribute indicates bright control + // of terminal emulator. + // + BrightControl = (UINT8)((Attribute >> 3) & 1); + + // + // convert Attribute value to terminal emulator + // understandable background color. + // + switch ((Attribute >> 4) & 0x07) { + case EFI_BLACK: + BackgroundControl = 40; + break; + + case EFI_BLUE: + BackgroundControl = 44; + break; + + case EFI_GREEN: + BackgroundControl = 42; + break; + + case EFI_CYAN: + BackgroundControl = 46; + break; + + case EFI_RED: + BackgroundControl = 41; + break; + + case EFI_MAGENTA: + BackgroundControl = 45; + break; + + case EFI_BROWN: + BackgroundControl = 43; + break; + + default: + + case EFI_LIGHTGRAY: + BackgroundControl = 47; + break; + } + + // + // terminal emulator's control sequence to set attributes + // + mSetAttributeString[BRIGHT_CONTROL_OFFSET] = (CHAR16)('0' + BrightControl); + mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 0] = (CHAR16)('0' + (ForegroundControl / 10)); + mSetAttributeString[FOREGROUND_CONTROL_OFFSET + 1] = (CHAR16)('0' + (ForegroundControl % 10)); + mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 0] = (CHAR16)('0' + (BackgroundControl / 10)); + mSetAttributeString[BACKGROUND_CONTROL_OFFSET + 1] = (CHAR16)('0' + (BackgroundControl % 10)); + + // + // save current column and row + // for future scrolling back use. + // + SavedColumn = This->Mode->CursorColumn; + SavedRow = This->Mode->CursorRow; + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mSetAttributeString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // scroll back to saved cursor position. + // + This->Mode->CursorColumn = SavedColumn; + This->Mode->CursorRow = SavedRow; + + This->Mode->Attribute = (INT32)Attribute; + + return EFI_SUCCESS; +} + +/** + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.ClearScreen(). + It clears the ANSI terminal's display to the + currently selected background color. + + @param This Indicates the calling context. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The terminal screen cannot be cleared due to serial port error. + @retval EFI_UNSUPPORTED The terminal is not in a valid display mode. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutClearScreen ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This + ) +{ + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // control sequence for clear screen request + // + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, mClearScreenString); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + Status = This->SetCursorPosition (This, 0, 0); + + return Status; +} + +/** + Implements EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetCursorPosition(). + + @param This Indicates the calling context. + @param Column The row to set cursor to. + @param Row The column to set cursor to. + + @retval EFI_SUCCESS The operation completed successfully. + @retval EFI_DEVICE_ERROR The request fails due to serial port error. + @retval EFI_UNSUPPORTED The terminal is not in a valid text mode, or the cursor position + is invalid for current mode. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutSetCursorPosition ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN UINTN Column, + IN UINTN Row + ) +{ + EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode; + UINTN MaxColumn; + UINTN MaxRow; + EFI_STATUS Status; + TERMINAL_DEV *TerminalDevice; + CHAR16 *String; + + TerminalDevice = TERMINAL_CON_OUT_DEV_FROM_THIS (This); + + // + // get current mode + // + Mode = This->Mode; + + // + // get geometry of current mode + // + Status = This->QueryMode ( + This, + Mode->Mode, + &MaxColumn, + &MaxRow + ); + if (EFI_ERROR (Status)) { + return EFI_UNSUPPORTED; + } + + if ((Column >= MaxColumn) || (Row >= MaxRow)) { + return EFI_UNSUPPORTED; + } + + // + // control sequence to move the cursor + // + // Optimize cursor motion control sequences for TtyTerm. Move + // within the current line if possible, and don't output anyting if + // it isn't necessary. + // + if ((TerminalDevice->TerminalType == TerminalTypeTtyTerm) && + ((UINTN)Mode->CursorRow == Row)) + { + if ((UINTN)Mode->CursorColumn > Column) { + mCursorBackwardString[FW_BACK_OFFSET + 0] = (CHAR16)('0' + ((Mode->CursorColumn - Column) / 10)); + mCursorBackwardString[FW_BACK_OFFSET + 1] = (CHAR16)('0' + ((Mode->CursorColumn - Column) % 10)); + String = mCursorBackwardString; + } else if (Column > (UINTN)Mode->CursorColumn) { + mCursorForwardString[FW_BACK_OFFSET + 0] = (CHAR16)('0' + ((Column - Mode->CursorColumn) / 10)); + mCursorForwardString[FW_BACK_OFFSET + 1] = (CHAR16)('0' + ((Column - Mode->CursorColumn) % 10)); + String = mCursorForwardString; + } else { + String = L""; // No cursor motion necessary + } + } else { + mSetCursorPositionString[ROW_OFFSET + 0] = (CHAR16)('0' + ((Row + 1) / 10)); + mSetCursorPositionString[ROW_OFFSET + 1] = (CHAR16)('0' + ((Row + 1) % 10)); + mSetCursorPositionString[COLUMN_OFFSET + 0] = (CHAR16)('0' + ((Column + 1) / 10)); + mSetCursorPositionString[COLUMN_OFFSET + 1] = (CHAR16)('0' + ((Column + 1) % 10)); + String = mSetCursorPositionString; + } + + TerminalDevice->OutputEscChar = TRUE; + Status = This->OutputString (This, String); + TerminalDevice->OutputEscChar = FALSE; + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // + // update current cursor position + // in the Mode data structure. + // + Mode->CursorColumn = (INT32)Column; + Mode->CursorRow = (INT32)Row; + + return EFI_SUCCESS; +} + +/** + Implements SIMPLE_TEXT_OUTPUT.EnableCursor(). + + In this driver, the cursor cannot be hidden. + + @param This Indicates the calling context. + @param Visible If TRUE, the cursor is set to be visible, + If FALSE, the cursor is set to be invisible. + + @retval EFI_SUCCESS The request is valid. + @retval EFI_UNSUPPORTED The terminal does not support cursor hidden. + +**/ +EFI_STATUS +EFIAPI +TerminalConOutEnableCursor ( + IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This, + IN BOOLEAN Visible + ) +{ + if (!Visible) { + return EFI_UNSUPPORTED; + } + + return EFI_SUCCESS; +} + +/** + Detects if a Unicode char is for Box Drawing text graphics. + + @param Graphic Unicode char to test. + @param PcAnsi Optional pointer to return PCANSI equivalent of + Graphic. + @param Ascii Optional pointer to return ASCII equivalent of + Graphic. + + @retval TRUE If Graphic is a supported Unicode Box Drawing character. + +**/ +BOOLEAN +TerminalIsValidTextGraphics ( + IN CHAR16 Graphic, + OUT CHAR8 *PcAnsi OPTIONAL, + OUT CHAR8 *Ascii OPTIONAL + ) +{ + UNICODE_TO_CHAR *Table; + + if ((((Graphic & 0xff00) != 0x2500) && ((Graphic & 0xff00) != 0x2100))) { + // + // Unicode drawing code charts are all in the 0x25xx range, + // arrows are 0x21xx + // + return FALSE; + } + + for (Table = UnicodeToPcAnsiOrAscii; Table->Unicode != 0x0000; Table++) { + if (Graphic == Table->Unicode) { + if (PcAnsi != NULL) { + *PcAnsi = Table->PcAnsi; + } + + if (Ascii != NULL) { + *Ascii = Table->Ascii; + } + + return TRUE; + } + } + + return FALSE; +} + +/** + Detects if a valid ASCII char. + + @param Ascii An ASCII character. + + @retval TRUE If it is a valid ASCII character. + @retval FALSE If it is not a valid ASCII character. + +**/ +BOOLEAN +TerminalIsValidAscii ( + IN CHAR16 Ascii + ) +{ + // + // valid ascii code lies in the extent of 0x20 ~ 0x7f + // + if ((Ascii >= 0x20) && (Ascii <= 0x7f)) { + return TRUE; + } + + return FALSE; +} + +/** + Detects if a valid EFI control character. + + @param CharC An input EFI Control character. + + @retval TRUE If it is a valid EFI control character. + @retval FALSE If it is not a valid EFI control character. + +**/ +BOOLEAN +TerminalIsValidEfiCntlChar ( + IN CHAR16 CharC + ) +{ + // + // only support four control characters. + // + if ((CharC == CHAR_NULL) || + (CharC == CHAR_BACKSPACE) || + (CharC == CHAR_LINEFEED) || + (CharC == CHAR_CARRIAGE_RETURN) || + (CharC == CHAR_TAB) + ) + { + return TRUE; + } + + return FALSE; +} |
