git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10446 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			702 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			702 lines
		
	
	
		
			16 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Simple Console that sits on a SerialLib. 
 | 
						|
 | 
						|
  Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
 | 
						|
  
 | 
						|
  This program and the accompanying materials
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at
 | 
						|
  http://opensource.org/licenses/bsd-license.php
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
/* 
 | 
						|
  Symbols used in table below
 | 
						|
===========================
 | 
						|
  ESC = 0x1B
 | 
						|
  CSI = 0x9B
 | 
						|
  DEL = 0x7f
 | 
						|
  ^   = CTRL
 | 
						|
 | 
						|
+=========+======+===========+==========+==========+
 | 
						|
|         | EFI  | UEFI 2.0  |          |          |
 | 
						|
|         | Scan |           |  VT100+  |          |
 | 
						|
|   KEY   | Code |  PC ANSI  |  VTUTF8  |   VT100  |
 | 
						|
+=========+======+===========+==========+==========+
 | 
						|
| NULL    | 0x00 |           |          |          |
 | 
						|
| UP      | 0x01 | ESC [ A   | ESC [ A  | ESC [ A  |
 | 
						|
| DOWN    | 0x02 | ESC [ B   | ESC [ B  | ESC [ B  |
 | 
						|
| RIGHT   | 0x03 | ESC [ C   | ESC [ C  | ESC [ C  |
 | 
						|
| LEFT    | 0x04 | ESC [ D   | ESC [ D  | ESC [ D  |
 | 
						|
| HOME    | 0x05 | ESC [ H   | ESC h    | ESC [ H  |
 | 
						|
| END     | 0x06 | ESC [ F   | ESC k    | ESC [ K  |
 | 
						|
| INSERT  | 0x07 | ESC [ @   | ESC +    | ESC [ @  |
 | 
						|
|         |      | ESC [ L   |          | ESC [ L  |
 | 
						|
| DELETE  | 0x08 | ESC [ X   | ESC -    | ESC [ P  |
 | 
						|
| PG UP   | 0x09 | ESC [ I   | ESC ?    | ESC [ V  |
 | 
						|
|         |      |           |          | ESC [ ?  |
 | 
						|
| PG DOWN | 0x0A | ESC [ G   | ESC /    | ESC [ U  |
 | 
						|
|         |      |           |          | ESC [ /  |
 | 
						|
| F1      | 0x0B | ESC [ M   | ESC 1    | ESC O P  |
 | 
						|
| F2      | 0x0C | ESC [ N   | ESC 2    | ESC O Q  |
 | 
						|
| F3      | 0x0D | ESC [ O   | ESC 3    | ESC O w  |
 | 
						|
| F4      | 0x0E | ESC [ P   | ESC 4    | ESC O x  |
 | 
						|
| F5      | 0x0F | ESC [ Q   | ESC 5    | ESC O t  |
 | 
						|
| F6      | 0x10 | ESC [ R   | ESC 6    | ESC O u  |
 | 
						|
| F7      | 0x11 | ESC [ S   | ESC 7    | ESC O q  |
 | 
						|
| F8      | 0x12 | ESC [ T   | ESC 8    | ESC O r  |
 | 
						|
| F9      | 0x13 | ESC [ U   | ESC 9    | ESC O p  |
 | 
						|
| F10     | 0x14 | ESC [ V   | ESC 0    | ESC O M  |
 | 
						|
| Escape  | 0x17 | ESC       | ESC      | ESC      |
 | 
						|
| F11     | 0x15 |           | ESC !    |          |
 | 
						|
| F12     | 0x16 |           | ESC @    |          |
 | 
						|
+=========+======+===========+==========+==========+
 | 
						|
 | 
						|
*/
 | 
						|
 | 
						|
#include <PiDxe.h>
 | 
						|
#include <Library/UefiLib.h>
 | 
						|
#include <Library/UefiBootServicesTableLib.h>
 | 
						|
#include <Library/BaseLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/SerialPortLib.h>
 | 
						|
#include <Library/PcdLib.h>
 | 
						|
 | 
						|
#include <Protocol/SerialIo.h>
 | 
						|
#include <Protocol/SimpleTextIn.h>
 | 
						|
#include <Protocol/SimpleTextOut.h>
 | 
						|
#include <Protocol/DevicePath.h>
 | 
						|
 | 
						|
 | 
						|
#define MODE0_COLUMN_COUNT        80
 | 
						|
#define MODE0_ROW_COUNT           25
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TextInReset(
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
 | 
						|
  IN BOOLEAN                        ExtendedVerification
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ReadKeyStroke(
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
 | 
						|
  OUT EFI_INPUT_KEY                 *Key
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TextOutReset(
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN BOOLEAN                          ExtendedVerification
 | 
						|
  );
 | 
						|
 | 
						|
CHAR8 *
 | 
						|
EFIAPI
 | 
						|
SafeUnicodeStrToAsciiStr (
 | 
						|
  IN      CONST CHAR16                *Source,
 | 
						|
  OUT     CHAR8                       *Destination
 | 
						|
  );
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
OutputString (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN CHAR16                           *String
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TestString (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN CHAR16                           *String
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
QueryMode (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN UINTN                            ModeNumber,
 | 
						|
  OUT UINTN                           *Columns,
 | 
						|
  OUT UINTN                           *Rows
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetMode(
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN UINTN                            ModeNumber
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetAttribute(
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN UINTN                            Attribute
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ClearScreen (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetCursorPosition (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN UINTN                            Column,
 | 
						|
  IN UINTN                            Row
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EnableCursor (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN BOOLEAN                          Enable
 | 
						|
  );
 | 
						|
 | 
						|
 | 
						|
 EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = {
 | 
						|
  TextInReset,
 | 
						|
  ReadKeyStroke,
 | 
						|
  NULL
 | 
						|
};
 | 
						|
 | 
						|
 EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode = {
 | 
						|
  1,
 | 
						|
  0,
 | 
						|
  EFI_TEXT_ATTR( EFI_LIGHTGRAY, EFI_BLACK ),
 | 
						|
  0,
 | 
						|
  0,
 | 
						|
  TRUE
 | 
						|
};
 | 
						|
 | 
						|
EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut = {
 | 
						|
  TextOutReset,
 | 
						|
  OutputString,
 | 
						|
  TestString,
 | 
						|
  QueryMode,
 | 
						|
  SetMode,
 | 
						|
  SetAttribute,
 | 
						|
  ClearScreen,
 | 
						|
  SetCursorPosition,
 | 
						|
  EnableCursor,
 | 
						|
  &mSimpleTextOutMode
 | 
						|
};
 | 
						|
 | 
						|
EFI_HANDLE           mInstallHandle = NULL;
 | 
						|
 | 
						|
typedef struct {
 | 
						|
  VENDOR_DEVICE_PATH        Guid;
 | 
						|
  UART_DEVICE_PATH          Uart;
 | 
						|
  EFI_DEVICE_PATH_PROTOCOL  End;
 | 
						|
} SIMPLE_TEXT_OUT_DEVICE_PATH;
 | 
						|
 | 
						|
SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath = {
 | 
						|
  {
 | 
						|
    { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0},
 | 
						|
    EFI_CALLER_ID_GUID
 | 
						|
  },
 | 
						|
  {
 | 
						|
    { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (UART_DEVICE_PATH), 0},
 | 
						|
    0,        // Reserved
 | 
						|
    FixedPcdGet64 (PcdUartDefaultBaudRate),   // BaudRate
 | 
						|
    FixedPcdGet8 (PcdUartDefaultDataBits),    // DataBits
 | 
						|
    FixedPcdGet8 (PcdUartDefaultParity),      // Parity (N)
 | 
						|
    FixedPcdGet8 (PcdUartDefaultStopBits)     // StopBits
 | 
						|
  },
 | 
						|
  { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
 | 
						|
};
 | 
						|
 | 
						|
 | 
						|
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
TextOutIsValidAscii (
 | 
						|
  IN CHAR16       Ascii
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // valid ASCII code lies in the extent of 0x20 - 0x7F
 | 
						|
  //
 | 
						|
  if ((Ascii >= 0x20) && (Ascii <= 0x7F)) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
BOOLEAN
 | 
						|
TextOutIsValidEfiCntlChar (
 | 
						|
  IN CHAR16       Char
 | 
						|
  )
 | 
						|
{
 | 
						|
  //
 | 
						|
  // only support four control characters.
 | 
						|
  //
 | 
						|
  if (Char == CHAR_NULL ||
 | 
						|
      Char == CHAR_BACKSPACE ||
 | 
						|
      Char == CHAR_LINEFEED ||
 | 
						|
      Char == CHAR_CARRIAGE_RETURN ||
 | 
						|
      Char == CHAR_TAB ) {
 | 
						|
    return TRUE;
 | 
						|
  }
 | 
						|
 | 
						|
  return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
VOID
 | 
						|
EFIAPI
 | 
						|
WaitForKeyEvent (
 | 
						|
  IN EFI_EVENT          Event,
 | 
						|
  IN VOID               *Context
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (SerialPortPoll ())  {
 | 
						|
    gBS->SignalEvent (Event);
 | 
						|
  }
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TextInReset (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
 | 
						|
  IN BOOLEAN                        ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ReadKeyStroke (
 | 
						|
  IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
 | 
						|
  OUT EFI_INPUT_KEY                 *Key
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8             Char;
 | 
						|
  
 | 
						|
  if (!SerialPortPoll ()) {
 | 
						|
    return EFI_NOT_READY;
 | 
						|
  }
 | 
						|
  
 | 
						|
  SerialPortRead ((UINT8 *)&Char, 1);
 | 
						|
  
 | 
						|
  //
 | 
						|
  // Check for ESC sequence. This code is not techincally correct VT100 code.
 | 
						|
  // An illegal ESC sequence represents an ESC and the characters that follow.
 | 
						|
  // This code will eat one or two chars after an escape. This is done to 
 | 
						|
  // prevent some complex FIFOing of the data. It is good enough to get
 | 
						|
  // the arrow and delete keys working
 | 
						|
  //
 | 
						|
  Key->UnicodeChar = 0;
 | 
						|
  Key->ScanCode    = SCAN_NULL;
 | 
						|
  if (Char == 0x1b) {
 | 
						|
    SerialPortRead ((UINT8 *)&Char, 1);
 | 
						|
    if (Char == '[') {
 | 
						|
      SerialPortRead ((UINT8 *)&Char, 1);
 | 
						|
      switch (Char) {
 | 
						|
      case 'A':
 | 
						|
        Key->ScanCode = SCAN_UP;
 | 
						|
        break;
 | 
						|
      case 'B':
 | 
						|
        Key->ScanCode = SCAN_DOWN;
 | 
						|
        break;
 | 
						|
      case 'C':
 | 
						|
        Key->ScanCode = SCAN_RIGHT;
 | 
						|
        break;
 | 
						|
      case 'D':
 | 
						|
        Key->ScanCode = SCAN_LEFT;
 | 
						|
        break;
 | 
						|
      case 'H':
 | 
						|
        Key->ScanCode = SCAN_HOME;
 | 
						|
        break;
 | 
						|
      case 'K':
 | 
						|
      case 'F': // PC ANSI 
 | 
						|
        Key->ScanCode = SCAN_END;
 | 
						|
        break;
 | 
						|
      case '@':
 | 
						|
      case 'L':
 | 
						|
        Key->ScanCode = SCAN_INSERT;
 | 
						|
        break;
 | 
						|
      case 'P':
 | 
						|
      case 'X': // PC ANSI 
 | 
						|
        Key->ScanCode = SCAN_DELETE;
 | 
						|
        break;
 | 
						|
      case 'U':
 | 
						|
      case '/':
 | 
						|
      case 'G': // PC ANSI
 | 
						|
        Key->ScanCode = SCAN_PAGE_DOWN;
 | 
						|
        break;
 | 
						|
      case 'V':
 | 
						|
      case '?':
 | 
						|
      case 'I': // PC ANSI
 | 
						|
        Key->ScanCode = SCAN_PAGE_UP;
 | 
						|
        break;
 | 
						|
 | 
						|
      // PCANSI that does not conflict with VT100
 | 
						|
      case 'M':
 | 
						|
        Key->ScanCode = SCAN_F1;
 | 
						|
        break;
 | 
						|
      case 'N':
 | 
						|
        Key->ScanCode = SCAN_F2;
 | 
						|
        break;
 | 
						|
      case 'O':
 | 
						|
        Key->ScanCode = SCAN_F3;
 | 
						|
        break;
 | 
						|
      case 'Q':
 | 
						|
        Key->ScanCode = SCAN_F5;
 | 
						|
        break;
 | 
						|
      case 'R':
 | 
						|
        Key->ScanCode = SCAN_F6;
 | 
						|
        break;
 | 
						|
      case 'S':
 | 
						|
        Key->ScanCode = SCAN_F7;
 | 
						|
        break;
 | 
						|
      case 'T':
 | 
						|
        Key->ScanCode = SCAN_F8;
 | 
						|
        break;
 | 
						|
 | 
						|
      default:
 | 
						|
        Key->UnicodeChar = Char;
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    } else if (Char == '0') {
 | 
						|
      SerialPortRead ((UINT8 *)&Char, 1);
 | 
						|
      switch (Char) {
 | 
						|
      case 'P':
 | 
						|
        Key->ScanCode = SCAN_F1;
 | 
						|
        break;
 | 
						|
      case 'Q':
 | 
						|
        Key->ScanCode = SCAN_F2;
 | 
						|
        break;
 | 
						|
      case 'w':
 | 
						|
        Key->ScanCode = SCAN_F3;
 | 
						|
        break;
 | 
						|
      case 'x':
 | 
						|
        Key->ScanCode = SCAN_F4;
 | 
						|
        break;
 | 
						|
      case 't':
 | 
						|
        Key->ScanCode = SCAN_F5;
 | 
						|
        break;
 | 
						|
      case 'u':
 | 
						|
        Key->ScanCode = SCAN_F6;
 | 
						|
        break;
 | 
						|
      case 'q':
 | 
						|
        Key->ScanCode = SCAN_F7;
 | 
						|
        break;
 | 
						|
      case 'r':
 | 
						|
        Key->ScanCode = SCAN_F8;
 | 
						|
        break;
 | 
						|
      case 'p':
 | 
						|
        Key->ScanCode = SCAN_F9;
 | 
						|
        break;
 | 
						|
      case 'm':
 | 
						|
        Key->ScanCode = SCAN_F10;
 | 
						|
        break;
 | 
						|
      default :
 | 
						|
        break;
 | 
						|
      }
 | 
						|
    }
 | 
						|
  } else if (Char < ' ') {
 | 
						|
    if ((Char == CHAR_BACKSPACE) || 
 | 
						|
        (Char == CHAR_TAB)       || 
 | 
						|
        (Char == CHAR_LINEFEED)  || 
 | 
						|
        (Char == CHAR_CARRIAGE_RETURN)) {
 | 
						|
      // Only let through EFI required control characters
 | 
						|
      Key->UnicodeChar = (CHAR16)Char;  
 | 
						|
    }
 | 
						|
  } else if (Char == 0x7f) {
 | 
						|
    Key->ScanCode = SCAN_DELETE;
 | 
						|
  } else {
 | 
						|
    Key->UnicodeChar = (CHAR16)Char;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TextOutReset (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN BOOLEAN                          ExtendedVerification
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  This->SetAttribute(
 | 
						|
        This,
 | 
						|
        EFI_TEXT_ATTR(This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)
 | 
						|
        );
 | 
						|
 | 
						|
  Status = This->SetMode (This, 0);
 | 
						|
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
CHAR8 *
 | 
						|
EFIAPI
 | 
						|
SafeUnicodeStrToAsciiStr (
 | 
						|
  IN      CONST CHAR16                *Source,
 | 
						|
  OUT     CHAR8                       *Destination
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8                               *ReturnValue;
 | 
						|
 | 
						|
  ASSERT (Destination != NULL);
 | 
						|
 | 
						|
  //
 | 
						|
  // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
 | 
						|
  // Length tests are performed inside StrLen().
 | 
						|
  //
 | 
						|
  ASSERT (StrSize (Source) != 0);
 | 
						|
 | 
						|
  //
 | 
						|
  // Source and Destination should not overlap
 | 
						|
  //
 | 
						|
  ASSERT ((UINTN) ((CHAR16 *) Destination -  Source) > StrLen (Source));
 | 
						|
  ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source));
 | 
						|
 | 
						|
 | 
						|
  ReturnValue = Destination;
 | 
						|
  while (*Source != '\0') {
 | 
						|
    //
 | 
						|
    // If any non-ascii characters in Source then replace it with '?'.
 | 
						|
    //
 | 
						|
    if (*Source < 0x80) {
 | 
						|
      *Destination = (CHAR8) *Source;
 | 
						|
    } else {
 | 
						|
      *Destination = '?';
 | 
						|
 | 
						|
      //Surrogate pair check.
 | 
						|
      if ((*Source >= 0xD800) && (*Source <= 0xDFFF)) {
 | 
						|
        Source++;
 | 
						|
      }
 | 
						|
    }
 | 
						|
 | 
						|
    Destination++;
 | 
						|
    Source++;
 | 
						|
  }
 | 
						|
 | 
						|
  *Destination = '\0';
 | 
						|
 | 
						|
  //
 | 
						|
  // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
 | 
						|
  // Length tests are performed inside AsciiStrLen().
 | 
						|
  //
 | 
						|
  ASSERT (AsciiStrSize (ReturnValue) != 0);
 | 
						|
 | 
						|
  return ReturnValue;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
OutputString (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN CHAR16                           *String
 | 
						|
  )
 | 
						|
{
 | 
						|
  UINTN Size          = StrLen(String) + 1;
 | 
						|
  CHAR8 *OutputString = AllocatePool(Size);
 | 
						|
  
 | 
						|
  //If there is any non-ascii characters in String buffer then replace it with '?'
 | 
						|
  //Eventually, UnicodeStrToAsciiStr API should be fixed.
 | 
						|
  SafeUnicodeStrToAsciiStr(String, OutputString);  
 | 
						|
  SerialPortWrite ((UINT8 *)OutputString, Size - 1);
 | 
						|
 | 
						|
  FreePool(OutputString);
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
TestString (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN CHAR16                           *String
 | 
						|
  )
 | 
						|
{
 | 
						|
  CHAR8           Character;
 | 
						|
 | 
						|
  for ( ; *String != CHAR_NULL; String++) {
 | 
						|
    Character = (CHAR8)*String;
 | 
						|
    if (!(TextOutIsValidAscii (Character) || TextOutIsValidEfiCntlChar (Character))) {
 | 
						|
      return EFI_UNSUPPORTED;
 | 
						|
    }
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
QueryMode (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN UINTN                            ModeNumber,
 | 
						|
  OUT UINTN                          *Columns,
 | 
						|
  OUT UINTN                          *Rows
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (This->Mode->MaxMode > 1) {
 | 
						|
    return EFI_DEVICE_ERROR;
 | 
						|
  }
 | 
						|
 | 
						|
  if (ModeNumber == 0) {
 | 
						|
    *Columns  = MODE0_COLUMN_COUNT;
 | 
						|
    *Rows     = MODE0_ROW_COUNT;
 | 
						|
    return EFI_SUCCESS;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_UNSUPPORTED;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetMode (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This,
 | 
						|
  IN UINTN                              ModeNumber
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (ModeNumber != 0) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  This->Mode->Mode = 0;
 | 
						|
  This->ClearScreen (This);
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetAttribute(
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This,
 | 
						|
  IN UINTN                              Attribute
 | 
						|
  )
 | 
						|
{
 | 
						|
  This->Mode->Attribute = (INT32)Attribute;
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
ClearScreen (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS    Status;
 | 
						|
 | 
						|
  Status = This->SetCursorPosition (This, 0, 0);
 | 
						|
  return Status;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SetCursorPosition (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This,
 | 
						|
  IN UINTN                              Column,
 | 
						|
  IN UINTN                              Row
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_SIMPLE_TEXT_OUTPUT_MODE       *Mode;
 | 
						|
  EFI_STATUS                        Status;
 | 
						|
  UINTN                             MaxColumn;
 | 
						|
  UINTN                             MaxRow;
 | 
						|
 | 
						|
  Mode = This->Mode;
 | 
						|
 | 
						|
  Status = This->QueryMode(
 | 
						|
                  This,
 | 
						|
                  Mode->Mode,
 | 
						|
                  &MaxColumn,
 | 
						|
                  &MaxRow 
 | 
						|
                  );
 | 
						|
  if (EFI_ERROR(Status)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  if ((Column >= MaxColumn) || (Row >= MaxRow)) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  Mode->CursorColumn = (INT32)Column;
 | 
						|
  Mode->CursorRow = (INT32)Row;
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
EnableCursor (
 | 
						|
  IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
 | 
						|
  IN BOOLEAN                          Enable
 | 
						|
  )
 | 
						|
{
 | 
						|
  if (!Enable) {
 | 
						|
    return EFI_UNSUPPORTED;
 | 
						|
  }
 | 
						|
 | 
						|
  return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
SimpleTextInOutEntryPoint (
 | 
						|
  IN EFI_HANDLE         ImageHandle,
 | 
						|
  IN EFI_SYSTEM_TABLE   *SystemTable
 | 
						|
  )
 | 
						|
{
 | 
						|
  EFI_STATUS            Status;
 | 
						|
 | 
						|
  Status = gBS->CreateEvent (
 | 
						|
                  EVT_NOTIFY_WAIT,
 | 
						|
                  TPL_NOTIFY,
 | 
						|
                  WaitForKeyEvent,
 | 
						|
                  NULL,
 | 
						|
                  &mSimpleTextIn.WaitForKey
 | 
						|
                  );
 | 
						|
  ASSERT_EFI_ERROR (Status);
 | 
						|
  
 | 
						|
  Status = gBS->InstallMultipleProtocolInterfaces(
 | 
						|
                  &mInstallHandle,
 | 
						|
                  &gEfiSimpleTextInProtocolGuid,   &mSimpleTextIn,
 | 
						|
                  &gEfiSimpleTextOutProtocolGuid,  &mSimpleTextOut,
 | 
						|
                  &gEfiDevicePathProtocolGuid,     &mDevicePath,
 | 
						|
                  NULL
 | 
						|
                  );
 | 
						|
  if (!EFI_ERROR (Status)) {
 | 
						|
    gST->ConOut = &mSimpleTextOut;
 | 
						|
    gST->ConIn = &mSimpleTextIn;
 | 
						|
  }
 | 
						|
  
 | 
						|
  return Status;
 | 
						|
}
 |