2 Simple Console that sits on a SerialLib.
\r
4 Copyright (c) 2008-2009, Apple Inc. All rights reserved.
\r
6 All rights reserved. This program and the accompanying materials
\r
7 are licensed and made available under the terms and conditions of the BSD License
\r
8 which accompanies this distribution. The full text of the license may be found at
\r
9 http://opensource.org/licenses/bsd-license.php
\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
\r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
\r
17 Symbols used in table below
\r
18 ===========================
\r
24 +=========+======+===========+==========+==========+
\r
25 | | EFI | UEFI 2.0 | | |
\r
26 | | Scan | | VT100+ | |
\r
27 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
\r
28 +=========+======+===========+==========+==========+
\r
29 | NULL | 0x00 | | | |
\r
30 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
\r
31 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
\r
32 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
\r
33 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
\r
34 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
\r
35 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
\r
36 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
\r
37 | | | ESC [ L | | ESC [ L |
\r
38 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
\r
39 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
\r
41 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
\r
43 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
\r
44 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
\r
45 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
\r
46 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
\r
47 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
\r
48 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
\r
49 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
\r
50 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
\r
51 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
\r
52 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
\r
53 | Escape | 0x17 | ESC | ESC | ESC |
\r
54 | F11 | 0x15 | | ESC ! | |
\r
55 | F12 | 0x16 | | ESC @ | |
\r
56 +=========+======+===========+==========+==========+
\r
61 #include <Library/UefiLib.h>
\r
62 #include <Library/UefiBootServicesTableLib.h>
\r
63 #include <Library/BaseLib.h>
\r
64 #include <Library/MemoryAllocationLib.h>
\r
65 #include <Library/DebugLib.h>
\r
66 #include <Library/SerialPortLib.h>
\r
67 #include <Library/PcdLib.h>
\r
69 #include <Protocol/SerialIo.h>
\r
70 #include <Protocol/SimpleTextIn.h>
\r
71 #include <Protocol/SimpleTextOut.h>
\r
72 #include <Protocol/DevicePath.h>
\r
75 #define MODE0_COLUMN_COUNT 80
\r
76 #define MODE0_ROW_COUNT 25
\r
82 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
83 IN BOOLEAN ExtendedVerification
\r
90 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
91 OUT EFI_INPUT_KEY *Key
\r
98 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
99 IN BOOLEAN ExtendedVerification
\r
104 SafeUnicodeStrToAsciiStr (
\r
105 IN CONST CHAR16 *Source,
\r
106 OUT CHAR8 *Destination
\r
112 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
120 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
128 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
129 IN UINTN ModeNumber,
\r
130 OUT UINTN *Columns,
\r
138 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
139 IN UINTN ModeNumber
\r
146 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
154 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
\r
160 SetCursorPosition (
\r
161 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
170 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
175 EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = {
\r
181 EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode = {
\r
184 EFI_TEXT_ATTR( EFI_LIGHTGRAY, EFI_BLACK ),
\r
190 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut = {
\r
200 &mSimpleTextOutMode
\r
203 EFI_HANDLE mInstallHandle = NULL;
\r
206 VENDOR_DEVICE_PATH Guid;
\r
207 UART_DEVICE_PATH Uart;
\r
208 EFI_DEVICE_PATH_PROTOCOL End;
\r
209 } SIMPLE_TEXT_OUT_DEVICE_PATH;
\r
211 SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath = {
\r
213 { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, sizeof (VENDOR_DEVICE_PATH), 0},
\r
217 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (UART_DEVICE_PATH), 0},
\r
219 FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
\r
220 FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
\r
221 FixedPcdGet8 (PcdUartDefaultParity), // Parity (N)
\r
222 FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
\r
224 { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, sizeof (EFI_DEVICE_PATH_PROTOCOL), 0}
\r
231 TextOutIsValidAscii (
\r
236 // valid ASCII code lies in the extent of 0x20 - 0x7F
\r
238 if ((Ascii >= 0x20) && (Ascii <= 0x7F)) {
\r
247 TextOutIsValidEfiCntlChar (
\r
252 // only support four control characters.
\r
254 if (Char == CHAR_NULL ||
\r
255 Char == CHAR_BACKSPACE ||
\r
256 Char == CHAR_LINEFEED ||
\r
257 Char == CHAR_CARRIAGE_RETURN ||
\r
258 Char == CHAR_TAB ) {
\r
269 IN EFI_EVENT Event,
\r
273 if (SerialPortPoll ()) {
\r
274 gBS->SignalEvent (Event);
\r
282 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
283 IN BOOLEAN ExtendedVerification
\r
286 return EFI_SUCCESS;
\r
293 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
\r
294 OUT EFI_INPUT_KEY *Key
\r
299 if (!SerialPortPoll ()) {
\r
300 return EFI_NOT_READY;
\r
303 SerialPortRead ((UINT8 *)&Char, 1);
\r
306 // Check for ESC sequence. This code is not techincally correct VT100 code.
\r
307 // An illegal ESC sequence represents an ESC and the characters that follow.
\r
308 // This code will eat one or two chars after an escape. This is done to
\r
309 // prevent some complex FIFOing of the data. It is good enough to get
\r
310 // the arrow and delete keys working
\r
312 Key->UnicodeChar = 0;
\r
313 Key->ScanCode = SCAN_NULL;
\r
314 if (Char == 0x1b) {
\r
315 SerialPortRead ((UINT8 *)&Char, 1);
\r
317 SerialPortRead ((UINT8 *)&Char, 1);
\r
320 Key->ScanCode = SCAN_UP;
\r
323 Key->ScanCode = SCAN_DOWN;
\r
326 Key->ScanCode = SCAN_RIGHT;
\r
329 Key->ScanCode = SCAN_LEFT;
\r
332 Key->ScanCode = SCAN_HOME;
\r
335 case 'F': // PC ANSI
\r
336 Key->ScanCode = SCAN_END;
\r
340 Key->ScanCode = SCAN_INSERT;
\r
343 case 'X': // PC ANSI
\r
344 Key->ScanCode = SCAN_DELETE;
\r
348 case 'G': // PC ANSI
\r
349 Key->ScanCode = SCAN_PAGE_DOWN;
\r
353 case 'I': // PC ANSI
\r
354 Key->ScanCode = SCAN_PAGE_UP;
\r
357 // PCANSI that does not conflict with VT100
\r
359 Key->ScanCode = SCAN_F1;
\r
362 Key->ScanCode = SCAN_F2;
\r
365 Key->ScanCode = SCAN_F3;
\r
368 Key->ScanCode = SCAN_F5;
\r
371 Key->ScanCode = SCAN_F6;
\r
374 Key->ScanCode = SCAN_F7;
\r
377 Key->ScanCode = SCAN_F8;
\r
381 Key->UnicodeChar = Char;
\r
384 } else if (Char == '0') {
\r
385 SerialPortRead ((UINT8 *)&Char, 1);
\r
388 Key->ScanCode = SCAN_F1;
\r
391 Key->ScanCode = SCAN_F2;
\r
394 Key->ScanCode = SCAN_F3;
\r
397 Key->ScanCode = SCAN_F4;
\r
400 Key->ScanCode = SCAN_F5;
\r
403 Key->ScanCode = SCAN_F6;
\r
406 Key->ScanCode = SCAN_F7;
\r
409 Key->ScanCode = SCAN_F8;
\r
412 Key->ScanCode = SCAN_F9;
\r
415 Key->ScanCode = SCAN_F10;
\r
421 } else if (Char < ' ') {
\r
422 if ((Char == CHAR_BACKSPACE) ||
\r
423 (Char == CHAR_TAB) ||
\r
424 (Char == CHAR_LINEFEED) ||
\r
425 (Char == CHAR_CARRIAGE_RETURN)) {
\r
426 // Only let through EFI required control characters
\r
427 Key->UnicodeChar = (CHAR16)Char;
\r
429 } else if (Char == 0x7f) {
\r
430 Key->ScanCode = SCAN_DELETE;
\r
432 Key->UnicodeChar = (CHAR16)Char;
\r
435 return EFI_SUCCESS;
\r
442 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
443 IN BOOLEAN ExtendedVerification
\r
448 This->SetAttribute(
\r
450 EFI_TEXT_ATTR(This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)
\r
453 Status = This->SetMode (This, 0);
\r
460 SafeUnicodeStrToAsciiStr (
\r
461 IN CONST CHAR16 *Source,
\r
462 OUT CHAR8 *Destination
\r
465 CHAR8 *ReturnValue;
\r
467 ASSERT (Destination != NULL);
\r
470 // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
\r
471 // Length tests are performed inside StrLen().
\r
473 ASSERT (StrSize (Source) != 0);
\r
476 // Source and Destination should not overlap
\r
478 ASSERT ((UINTN) ((CHAR16 *) Destination - Source) > StrLen (Source));
\r
479 ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source));
\r
482 ReturnValue = Destination;
\r
483 while (*Source != '\0') {
\r
485 // If any non-ascii characters in Source then replace it with '?'.
\r
487 if (*Source < 0x80) {
\r
488 *Destination = (CHAR8) *Source;
\r
490 *Destination = '?';
\r
492 //Surrogate pair check.
\r
493 if ((*Source >= 0xD800) && (*Source <= 0xDFFF)) {
\r
502 *Destination = '\0';
\r
505 // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
\r
506 // Length tests are performed inside AsciiStrLen().
\r
508 ASSERT (AsciiStrSize (ReturnValue) != 0);
\r
510 return ReturnValue;
\r
516 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
520 UINTN Size = StrLen(String) + 1;
\r
521 CHAR8 *OutputString = AllocatePool(Size);
\r
523 //If there is any non-ascii characters in String buffer then replace it with '?'
\r
524 //Eventually, UnicodeStrToAsciiStr API should be fixed.
\r
525 SafeUnicodeStrToAsciiStr(String, OutputString);
\r
526 SerialPortWrite ((UINT8 *)OutputString, Size - 1);
\r
528 FreePool(OutputString);
\r
530 return EFI_SUCCESS;
\r
537 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
543 for ( ; *String != CHAR_NULL; String++) {
\r
544 Character = (CHAR8)*String;
\r
545 if (!(TextOutIsValidAscii (Character) || TextOutIsValidEfiCntlChar (Character))) {
\r
546 return EFI_UNSUPPORTED;
\r
550 return EFI_SUCCESS;
\r
557 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
558 IN UINTN ModeNumber,
\r
559 OUT UINTN *Columns,
\r
563 if (This->Mode->MaxMode > 1) {
\r
564 return EFI_DEVICE_ERROR;
\r
567 if (ModeNumber == 0) {
\r
568 *Columns = MODE0_COLUMN_COUNT;
\r
569 *Rows = MODE0_ROW_COUNT;
\r
570 return EFI_SUCCESS;
\r
573 return EFI_UNSUPPORTED;
\r
580 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
581 IN UINTN ModeNumber
\r
584 if (ModeNumber != 0) {
\r
585 return EFI_UNSUPPORTED;
\r
588 This->Mode->Mode = 0;
\r
589 This->ClearScreen (This);
\r
590 return EFI_SUCCESS;
\r
597 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
601 This->Mode->Attribute = (INT32)Attribute;
\r
602 return EFI_SUCCESS;
\r
609 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
\r
614 Status = This->SetCursorPosition (This, 0, 0);
\r
621 SetCursorPosition (
\r
622 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
627 EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
\r
634 Status = This->QueryMode(
\r
640 if (EFI_ERROR(Status)) {
\r
641 return EFI_UNSUPPORTED;
\r
644 if ((Column >= MaxColumn) || (Row >= MaxRow)) {
\r
645 return EFI_UNSUPPORTED;
\r
648 Mode->CursorColumn = (INT32)Column;
\r
649 Mode->CursorRow = (INT32)Row;
\r
651 return EFI_SUCCESS;
\r
658 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
\r
663 return EFI_UNSUPPORTED;
\r
666 return EFI_SUCCESS;
\r
672 SimpleTextInOutEntryPoint (
\r
673 IN EFI_HANDLE ImageHandle,
\r
674 IN EFI_SYSTEM_TABLE *SystemTable
\r
679 Status = gBS->CreateEvent (
\r
684 &mSimpleTextIn.WaitForKey
\r
686 ASSERT_EFI_ERROR (Status);
\r
688 Status = gBS->InstallMultipleProtocolInterfaces(
\r
690 &gEfiSimpleTextInProtocolGuid, &mSimpleTextIn,
\r
691 &gEfiSimpleTextOutProtocolGuid, &mSimpleTextOut,
\r
692 &gEfiDevicePathProtocolGuid, &mDevicePath,
\r
695 if (!EFI_ERROR (Status)) {
\r
696 gST->ConOut = &mSimpleTextOut;
\r
697 gST->ConIn = &mSimpleTextIn;
\r