The UART device type and subtype were inccorect. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11729 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			760 lines
		
	
	
		
			17 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			760 lines
		
	
	
		
			17 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
 | |
|   },
 | |
|   {
 | |
|     { MESSAGING_DEVICE_PATH, MSG_UART_DP, 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;
 | |
|   CHAR8*                      OutputString;
 | |
|   EFI_STATUS                  Status;
 | |
|   EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
 | |
|   UINTN                       MaxColumn;
 | |
|   UINTN                       MaxRow;
 | |
|   
 | |
|   Size = StrLen(String) + 1;
 | |
|   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);
 | |
| 
 | |
|   //
 | |
|   // Parse each character of the string to output
 | |
|   // to update the cursor position information
 | |
|   //
 | |
|   Mode = This->Mode;
 | |
| 
 | |
|   Status = This->QueryMode (
 | |
|                    This,
 | |
|                    Mode->Mode,
 | |
|                    &MaxColumn,
 | |
|                    &MaxRow
 | |
|                    );
 | |
|   if (EFI_ERROR (Status)) {
 | |
|     return Status;
 | |
|   }
 | |
| 
 | |
|   for (; *String != CHAR_NULL; String++) {
 | |
| 
 | |
|     switch (*String) {
 | |
|     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)) {
 | |
|         // Move the cursor as if we print CHAR_CARRIAGE_RETURN & CHAR_LINE_FEED
 | |
|         // CHAR_LINEFEED
 | |
|         if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
 | |
|           Mode->CursorRow++;
 | |
|         }
 | |
|         // CHAR_CARIAGE_RETURN
 | |
|         Mode->CursorColumn = 0;
 | |
|       } else {
 | |
|         Mode->CursorColumn++;
 | |
|       }
 | |
|       break;
 | |
|     }
 | |
|   }
 | |
| 
 | |
|   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;
 | |
| }
 |