2 Simple Console that sits on a SerialLib.
4 Copyright (c) 2008-2009, Apple Inc. All rights reserved.
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 Symbols used in table below
18 ===========================
24 +=========+======+===========+==========+==========+
25 | | EFI | UEFI 2.0 | | |
26 | | Scan | | VT100+ | |
27 | KEY | Code | PC ANSI | VTUTF8 | VT100 |
28 +=========+======+===========+==========+==========+
30 | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
31 | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
32 | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
33 | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
34 | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
35 | END | 0x06 | ESC [ F | ESC k | ESC [ K |
36 | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
37 | | | ESC [ L | | ESC [ L |
38 | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
39 | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
41 | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
43 | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
44 | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
45 | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
46 | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
47 | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
48 | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
49 | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
50 | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
51 | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
52 | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
53 | Escape | 0x17 | ESC | ESC | ESC |
54 | F11 | 0x15 | | ESC ! | |
55 | F12 | 0x16 | | ESC @ | |
56 +=========+======+===========+==========+==========+
61 #include <Library/UefiLib.h>
62 #include <Library/UefiBootServicesTableLib.h>
63 #include <Library/BaseLib.h>
64 #include <Library/MemoryAllocationLib.h>
65 #include <Library/DebugLib.h>
66 #include <Library/SerialPortLib.h>
68 #include <Protocol/SerialIo.h>
69 #include <Protocol/SimpleTextIn.h>
70 #include <Protocol/SimpleTextOut.h>
73 #define MODE0_COLUMN_COUNT 80
74 #define MODE0_ROW_COUNT 25
80 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
81 IN BOOLEAN ExtendedVerification
88 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
89 OUT EFI_INPUT_KEY
*Key
96 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
97 IN BOOLEAN ExtendedVerification
102 SafeUnicodeStrToAsciiStr (
103 IN CONST CHAR16
*Source
,
104 OUT CHAR8
*Destination
110 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
118 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
126 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
136 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
144 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
152 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
159 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
168 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
173 EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn
= {
179 EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode
= {
182 EFI_TEXT_ATTR( EFI_LIGHTGRAY
, EFI_BLACK
),
188 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut
= {
201 EFI_HANDLE mInstallHandle
= NULL
;
206 TextOutIsValidAscii (
211 // valid ASCII code lies in the extent of 0x20 - 0x7F
213 if ((Ascii
>= 0x20) && (Ascii
<= 0x7F)) {
222 TextOutIsValidEfiCntlChar (
227 // only support four control characters.
229 if (Char
== CHAR_NULL
||
230 Char
== CHAR_BACKSPACE
||
231 Char
== CHAR_LINEFEED
||
232 Char
== CHAR_CARRIAGE_RETURN
||
248 if (SerialPortPoll ()) {
249 gBS
->SignalEvent (Event
);
257 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
258 IN BOOLEAN ExtendedVerification
268 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
269 OUT EFI_INPUT_KEY
*Key
274 SerialPortRead ((UINT8
*)&Char
, 1);
277 // Check for ESC sequence. This code is not techincally correct VT100 code.
278 // An illegal ESC sequence represents an ESC and the characters that follow.
279 // This code will eat one or two chars after an escape. This is done to
280 // prevent some complex FIFOing of the data. It is good enough to get
281 // the arrow and delete keys working
283 Key
->UnicodeChar
= 0;
284 Key
->ScanCode
= SCAN_NULL
;
286 SerialPortRead ((UINT8
*)&Char
, 1);
288 SerialPortRead ((UINT8
*)&Char
, 1);
291 Key
->ScanCode
= SCAN_UP
;
294 Key
->ScanCode
= SCAN_DOWN
;
297 Key
->ScanCode
= SCAN_RIGHT
;
300 Key
->ScanCode
= SCAN_LEFT
;
303 Key
->ScanCode
= SCAN_HOME
;
307 Key
->ScanCode
= SCAN_END
;
311 Key
->ScanCode
= SCAN_INSERT
;
315 Key
->ScanCode
= SCAN_DELETE
;
320 Key
->ScanCode
= SCAN_PAGE_DOWN
;
325 Key
->ScanCode
= SCAN_PAGE_UP
;
328 // PCANSI that does not conflict with VT100
330 Key
->ScanCode
= SCAN_F1
;
333 Key
->ScanCode
= SCAN_F2
;
336 Key
->ScanCode
= SCAN_F3
;
339 Key
->ScanCode
= SCAN_F5
;
342 Key
->ScanCode
= SCAN_F6
;
345 Key
->ScanCode
= SCAN_F7
;
348 Key
->ScanCode
= SCAN_F8
;
352 Key
->UnicodeChar
= Char
;
355 } else if (Char
== '0') {
356 SerialPortRead ((UINT8
*)&Char
, 1);
359 Key
->ScanCode
= SCAN_F1
;
362 Key
->ScanCode
= SCAN_F2
;
365 Key
->ScanCode
= SCAN_F3
;
368 Key
->ScanCode
= SCAN_F4
;
371 Key
->ScanCode
= SCAN_F5
;
374 Key
->ScanCode
= SCAN_F6
;
377 Key
->ScanCode
= SCAN_F7
;
380 Key
->ScanCode
= SCAN_F8
;
383 Key
->ScanCode
= SCAN_F9
;
386 Key
->ScanCode
= SCAN_F10
;
392 } else if (Char
< ' ') {
393 if ((Char
== CHAR_BACKSPACE
) ||
394 (Char
== CHAR_TAB
) ||
395 (Char
== CHAR_LINEFEED
) ||
396 (Char
== CHAR_CARRIAGE_RETURN
)) {
397 // Only let through EFI required control characters
398 Key
->UnicodeChar
= (CHAR16
)Char
;
400 } else if (Char
== 0x7f) {
401 Key
->ScanCode
= SCAN_DELETE
;
403 Key
->UnicodeChar
= (CHAR16
)Char
;
413 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
414 IN BOOLEAN ExtendedVerification
421 EFI_TEXT_ATTR(This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
)
424 Status
= This
->SetMode (This
, 0);
431 SafeUnicodeStrToAsciiStr (
432 IN CONST CHAR16
*Source
,
433 OUT CHAR8
*Destination
438 ASSERT (Destination
!= NULL
);
441 // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
442 // Length tests are performed inside StrLen().
444 ASSERT (StrSize (Source
) != 0);
447 // Source and Destination should not overlap
449 ASSERT ((UINTN
) ((CHAR16
*) Destination
- Source
) > StrLen (Source
));
450 ASSERT ((UINTN
) ((CHAR8
*) Source
- Destination
) > StrLen (Source
));
453 ReturnValue
= Destination
;
454 while (*Source
!= '\0') {
456 // If any non-ascii characters in Source then replace it with '?'.
458 if (*Source
< 0x80) {
459 *Destination
= (CHAR8
) *Source
;
463 //Surrogate pair check.
464 if ((*Source
>= 0xD800) && (*Source
<= 0xDFFF)) {
476 // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
477 // Length tests are performed inside AsciiStrLen().
479 ASSERT (AsciiStrSize (ReturnValue
) != 0);
487 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
491 UINTN Size
= StrLen(String
) + 1;
492 CHAR8
*OutputString
= AllocatePool(Size
);
494 //If there is any non-ascii characters in String buffer then replace it with '?'
495 //Eventually, UnicodeStrToAsciiStr API should be fixed.
496 SafeUnicodeStrToAsciiStr(String
, OutputString
);
497 SerialPortWrite ((UINT8
*)OutputString
, Size
- 1);
499 FreePool(OutputString
);
508 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
514 for ( ; *String
!= CHAR_NULL
; String
++) {
515 Character
= (CHAR8
)*String
;
516 if (!(TextOutIsValidAscii (Character
) || TextOutIsValidEfiCntlChar (Character
))) {
517 return EFI_UNSUPPORTED
;
528 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
534 if (This
->Mode
->MaxMode
> 1) {
535 return EFI_DEVICE_ERROR
;
538 if (ModeNumber
== 0) {
539 *Columns
= MODE0_COLUMN_COUNT
;
540 *Rows
= MODE0_ROW_COUNT
;
544 return EFI_UNSUPPORTED
;
551 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
555 if (ModeNumber
!= 0) {
556 return EFI_UNSUPPORTED
;
559 This
->Mode
->Mode
= 0;
560 This
->ClearScreen (This
);
568 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
572 This
->Mode
->Attribute
= (INT32
)Attribute
;
580 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
585 Status
= This
->SetCursorPosition (This
, 0, 0);
593 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
598 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
605 Status
= This
->QueryMode(
611 if (EFI_ERROR(Status
)) {
612 return EFI_UNSUPPORTED
;
615 if ((Column
>= MaxColumn
) || (Row
>= MaxRow
)) {
616 return EFI_UNSUPPORTED
;
619 Mode
->CursorColumn
= (INT32
)Column
;
620 Mode
->CursorRow
= (INT32
)Row
;
629 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
634 return EFI_UNSUPPORTED
;
643 SimpleTextInOutEntryPoint (
644 IN EFI_HANDLE ImageHandle
,
645 IN EFI_SYSTEM_TABLE
*SystemTable
650 Status
= gBS
->CreateEvent (
655 &mSimpleTextIn
.WaitForKey
657 ASSERT_EFI_ERROR (Status
);
659 Status
= gBS
->InstallMultipleProtocolInterfaces(
661 &gEfiSimpleTextInProtocolGuid
, &mSimpleTextIn
,
662 &gEfiSimpleTextOutProtocolGuid
, &mSimpleTextOut
,
665 if (!EFI_ERROR (Status
)) {
666 gST
->ConOut
= &mSimpleTextOut
;
667 gST
->ConIn
= &mSimpleTextIn
;