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 { MESSAGING_DEVICE_PATH
, MSG_UART_DP
, 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
,
523 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
527 Size
= StrLen(String
) + 1;
528 OutputString
= AllocatePool(Size
);
530 //If there is any non-ascii characters in String buffer then replace it with '?'
531 //Eventually, UnicodeStrToAsciiStr API should be fixed.
532 SafeUnicodeStrToAsciiStr(String
, OutputString
);
533 SerialPortWrite ((UINT8
*)OutputString
, Size
- 1);
536 // Parse each character of the string to output
537 // to update the cursor position information
541 Status
= This
->QueryMode (
547 if (EFI_ERROR (Status
)) {
551 for (; *String
!= CHAR_NULL
; String
++) {
555 if (Mode
->CursorColumn
> 0) {
556 Mode
->CursorColumn
--;
561 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
566 case CHAR_CARRIAGE_RETURN
:
567 Mode
->CursorColumn
= 0;
571 if (Mode
->CursorColumn
>= (INT32
) (MaxColumn
- 1)) {
572 // Move the cursor as if we print CHAR_CARRIAGE_RETURN & CHAR_LINE_FEED
574 if (Mode
->CursorRow
< (INT32
) (MaxRow
- 1)) {
577 // CHAR_CARIAGE_RETURN
578 Mode
->CursorColumn
= 0;
580 Mode
->CursorColumn
++;
586 FreePool(OutputString
);
595 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
601 for ( ; *String
!= CHAR_NULL
; String
++) {
602 Character
= (CHAR8
)*String
;
603 if (!(TextOutIsValidAscii (Character
) || TextOutIsValidEfiCntlChar (Character
))) {
604 return EFI_UNSUPPORTED
;
615 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
621 if (This
->Mode
->MaxMode
> 1) {
622 return EFI_DEVICE_ERROR
;
625 if (ModeNumber
== 0) {
626 *Columns
= MODE0_COLUMN_COUNT
;
627 *Rows
= MODE0_ROW_COUNT
;
631 return EFI_UNSUPPORTED
;
638 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
642 if (ModeNumber
!= 0) {
643 return EFI_UNSUPPORTED
;
646 This
->Mode
->Mode
= 0;
647 This
->ClearScreen (This
);
655 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
659 This
->Mode
->Attribute
= (INT32
)Attribute
;
667 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
672 Status
= This
->SetCursorPosition (This
, 0, 0);
680 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
685 EFI_SIMPLE_TEXT_OUTPUT_MODE
*Mode
;
692 Status
= This
->QueryMode(
698 if (EFI_ERROR(Status
)) {
699 return EFI_UNSUPPORTED
;
702 if ((Column
>= MaxColumn
) || (Row
>= MaxRow
)) {
703 return EFI_UNSUPPORTED
;
706 Mode
->CursorColumn
= (INT32
)Column
;
707 Mode
->CursorRow
= (INT32
)Row
;
716 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL
*This
,
721 return EFI_UNSUPPORTED
;
730 SimpleTextInOutEntryPoint (
731 IN EFI_HANDLE ImageHandle
,
732 IN EFI_SYSTEM_TABLE
*SystemTable
737 Status
= gBS
->CreateEvent (
742 &mSimpleTextIn
.WaitForKey
744 ASSERT_EFI_ERROR (Status
);
746 Status
= gBS
->InstallMultipleProtocolInterfaces(
748 &gEfiSimpleTextInProtocolGuid
, &mSimpleTextIn
,
749 &gEfiSimpleTextOutProtocolGuid
, &mSimpleTextOut
,
750 &gEfiDevicePathProtocolGuid
, &mDevicePath
,
753 if (!EFI_ERROR (Status
)) {
754 gST
->ConOut
= &mSimpleTextOut
;
755 gST
->ConIn
= &mSimpleTextIn
;