2 Simple Console that sits on a SerialLib.
4 Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
6 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>
67 #include <Library/PcdLib.h>
69 #include <Protocol/SerialIo.h>
70 #include <Protocol/SimpleTextIn.h>
71 #include <Protocol/SimpleTextOut.h>
72 #include <Protocol/DevicePath.h>
75 #define MODE0_COLUMN_COUNT 80
76 #define MODE0_ROW_COUNT 25
82 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
83 IN BOOLEAN ExtendedVerification
90 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
91 OUT EFI_INPUT_KEY
*Key
98 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
99 IN BOOLEAN ExtendedVerification
104 SafeUnicodeStrToAsciiStr (
105 IN CONST CHAR16
*Source
,
106 OUT CHAR8
*Destination
112 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
120 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
128 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
138 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
146 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
154 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
161 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
170 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
175 EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn
= {
181 EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode
= {
184 EFI_TEXT_ATTR( EFI_LIGHTGRAY
, EFI_BLACK
),
190 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut
= {
203 EFI_HANDLE mInstallHandle
= NULL
;
206 VENDOR_DEVICE_PATH Guid
;
207 UART_DEVICE_PATH Uart
;
208 EFI_DEVICE_PATH_PROTOCOL End
;
209 } SIMPLE_TEXT_OUT_DEVICE_PATH
;
211 SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath
= {
213 { HARDWARE_DEVICE_PATH
, HW_VENDOR_DP
, sizeof (VENDOR_DEVICE_PATH
), 0},
217 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, sizeof (UART_DEVICE_PATH
), 0},
219 FixedPcdGet64 (PcdUartDefaultBaudRate
), // BaudRate
220 FixedPcdGet8 (PcdUartDefaultDataBits
), // DataBits
221 FixedPcdGet8 (PcdUartDefaultParity
), // Parity (N)
222 FixedPcdGet8 (PcdUartDefaultStopBits
) // StopBits
224 { END_DEVICE_PATH_TYPE
, END_ENTIRE_DEVICE_PATH_SUBTYPE
, sizeof (EFI_DEVICE_PATH_PROTOCOL
), 0}
231 TextOutIsValidAscii (
236 // valid ASCII code lies in the extent of 0x20 - 0x7F
238 if ((Ascii
>= 0x20) && (Ascii
<= 0x7F)) {
247 TextOutIsValidEfiCntlChar (
252 // only support four control characters.
254 if (Char
== CHAR_NULL
||
255 Char
== CHAR_BACKSPACE
||
256 Char
== CHAR_LINEFEED
||
257 Char
== CHAR_CARRIAGE_RETURN
||
273 if (SerialPortPoll ()) {
274 gBS
->SignalEvent (Event
);
282 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
283 IN BOOLEAN ExtendedVerification
293 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL
*This
,
294 OUT EFI_INPUT_KEY
*Key
299 if (!SerialPortPoll ()) {
300 return EFI_NOT_READY
;
303 SerialPortRead ((UINT8
*)&Char
, 1);
306 // Check for ESC sequence. This code is not techincally correct VT100 code.
307 // An illegal ESC sequence represents an ESC and the characters that follow.
308 // This code will eat one or two chars after an escape. This is done to
309 // prevent some complex FIFOing of the data. It is good enough to get
310 // the arrow and delete keys working
312 Key
->UnicodeChar
= 0;
313 Key
->ScanCode
= SCAN_NULL
;
315 SerialPortRead ((UINT8
*)&Char
, 1);
317 SerialPortRead ((UINT8
*)&Char
, 1);
320 Key
->ScanCode
= SCAN_UP
;
323 Key
->ScanCode
= SCAN_DOWN
;
326 Key
->ScanCode
= SCAN_RIGHT
;
329 Key
->ScanCode
= SCAN_LEFT
;
332 Key
->ScanCode
= SCAN_HOME
;
336 Key
->ScanCode
= SCAN_END
;
340 Key
->ScanCode
= SCAN_INSERT
;
344 Key
->ScanCode
= SCAN_DELETE
;
349 Key
->ScanCode
= SCAN_PAGE_DOWN
;
354 Key
->ScanCode
= SCAN_PAGE_UP
;
357 // PCANSI that does not conflict with VT100
359 Key
->ScanCode
= SCAN_F1
;
362 Key
->ScanCode
= SCAN_F2
;
365 Key
->ScanCode
= SCAN_F3
;
368 Key
->ScanCode
= SCAN_F5
;
371 Key
->ScanCode
= SCAN_F6
;
374 Key
->ScanCode
= SCAN_F7
;
377 Key
->ScanCode
= SCAN_F8
;
381 Key
->UnicodeChar
= Char
;
384 } else if (Char
== '0') {
385 SerialPortRead ((UINT8
*)&Char
, 1);
388 Key
->ScanCode
= SCAN_F1
;
391 Key
->ScanCode
= SCAN_F2
;
394 Key
->ScanCode
= SCAN_F3
;
397 Key
->ScanCode
= SCAN_F4
;
400 Key
->ScanCode
= SCAN_F5
;
403 Key
->ScanCode
= SCAN_F6
;
406 Key
->ScanCode
= SCAN_F7
;
409 Key
->ScanCode
= SCAN_F8
;
412 Key
->ScanCode
= SCAN_F9
;
415 Key
->ScanCode
= SCAN_F10
;
421 } else if (Char
< ' ') {
422 if ((Char
== CHAR_BACKSPACE
) ||
423 (Char
== CHAR_TAB
) ||
424 (Char
== CHAR_LINEFEED
) ||
425 (Char
== CHAR_CARRIAGE_RETURN
)) {
426 // Only let through EFI required control characters
427 Key
->UnicodeChar
= (CHAR16
)Char
;
429 } else if (Char
== 0x7f) {
430 Key
->ScanCode
= SCAN_DELETE
;
432 Key
->UnicodeChar
= (CHAR16
)Char
;
442 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
443 IN BOOLEAN ExtendedVerification
450 EFI_TEXT_ATTR(This
->Mode
->Attribute
& 0x0F, EFI_BACKGROUND_BLACK
)
453 Status
= This
->SetMode (This
, 0);
460 SafeUnicodeStrToAsciiStr (
461 IN CONST CHAR16
*Source
,
462 OUT CHAR8
*Destination
467 ASSERT (Destination
!= NULL
);
470 // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
471 // Length tests are performed inside StrLen().
473 ASSERT (StrSize (Source
) != 0);
476 // Source and Destination should not overlap
478 ASSERT ((UINTN
) ((CHAR16
*) Destination
- Source
) > StrLen (Source
));
479 ASSERT ((UINTN
) ((CHAR8
*) Source
- Destination
) > StrLen (Source
));
482 ReturnValue
= Destination
;
483 while (*Source
!= '\0') {
485 // If any non-ascii characters in Source then replace it with '?'.
487 if (*Source
< 0x80) {
488 *Destination
= (CHAR8
) *Source
;
492 //Surrogate pair check.
493 if ((*Source
>= 0xD800) && (*Source
<= 0xDFFF)) {
505 // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
506 // Length tests are performed inside AsciiStrLen().
508 ASSERT (AsciiStrSize (ReturnValue
) != 0);
516 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
520 UINTN Size
= StrLen(String
) + 1;
521 CHAR8
*OutputString
= AllocatePool(Size
);
523 //If there is any non-ascii characters in String buffer then replace it with '?'
524 //Eventually, UnicodeStrToAsciiStr API should be fixed.
525 SafeUnicodeStrToAsciiStr(String
, OutputString
);
526 SerialPortWrite ((UINT8
*)OutputString
, Size
- 1);
528 FreePool(OutputString
);
537 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
543 for ( ; *String
!= CHAR_NULL
; String
++) {
544 Character
= (CHAR8
)*String
;
545 if (!(TextOutIsValidAscii (Character
) || TextOutIsValidEfiCntlChar (Character
))) {
546 return EFI_UNSUPPORTED
;
557 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
563 if (This
->Mode
->MaxMode
> 1) {
564 return EFI_DEVICE_ERROR
;
567 if (ModeNumber
== 0) {
568 *Columns
= MODE0_COLUMN_COUNT
;
569 *Rows
= MODE0_ROW_COUNT
;
573 return EFI_UNSUPPORTED
;
580 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
584 if (ModeNumber
!= 0) {
585 return EFI_UNSUPPORTED
;
588 This
->Mode
->Mode
= 0;
589 This
->ClearScreen (This
);
597 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
601 This
->Mode
->Attribute
= (INT32
)Attribute
;
609 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
614 Status
= This
->SetCursorPosition (This
, 0, 0);
622 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
627 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
634 Status
= This
->QueryMode(
640 if (EFI_ERROR(Status
)) {
641 return EFI_UNSUPPORTED
;
644 if ((Column
>= MaxColumn
) || (Row
>= MaxRow
)) {
645 return EFI_UNSUPPORTED
;
648 Mode
->CursorColumn
= (INT32
)Column
;
649 Mode
->CursorRow
= (INT32
)Row
;
658 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
663 return EFI_UNSUPPORTED
;
672 SimpleTextInOutEntryPoint (
673 IN EFI_HANDLE ImageHandle
,
674 IN EFI_SYSTEM_TABLE
*SystemTable
679 Status
= gBS
->CreateEvent (
684 &mSimpleTextIn
.WaitForKey
686 ASSERT_EFI_ERROR (Status
);
688 Status
= gBS
->InstallMultipleProtocolInterfaces(
690 &gEfiSimpleTextInProtocolGuid
, &mSimpleTextIn
,
691 &gEfiSimpleTextOutProtocolGuid
, &mSimpleTextOut
,
692 &gEfiDevicePathProtocolGuid
, &mDevicePath
,
695 if (!EFI_ERROR (Status
)) {
696 gST
->ConOut
= &mSimpleTextOut
;
697 gST
->ConIn
= &mSimpleTextIn
;