1 /** @file
2   Simple Console that sits on a SerialLib.
3 
4   Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
5 
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
10 
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.
13 
14 **/
15 
16 /*
17   Symbols used in table below
18 ===========================
19   ESC = 0x1B
20   CSI = 0x9B
21   DEL = 0x7f
22   ^   = CTRL
23 
24 +=========+======+===========+==========+==========+
25 |         | EFI  | UEFI 2.0  |          |          |
26 |         | Scan |           |  VT100+  |          |
27 |   KEY   | Code |  PC ANSI  |  VTUTF8  |   VT100  |
28 +=========+======+===========+==========+==========+
29 | NULL    | 0x00 |           |          |          |
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  |
40 |         |      |           |          | ESC [ ?  |
41 | PG DOWN | 0x0A | ESC [ G   | ESC /    | ESC [ U  |
42 |         |      |           |          | ESC [ /  |
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 +=========+======+===========+==========+==========+
57 
58 */
59 
60 #include <PiDxe.h>
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>
68 
69 #include <Protocol/SerialIo.h>
70 #include <Protocol/SimpleTextIn.h>
71 #include <Protocol/SimpleTextOut.h>
72 #include <Protocol/DevicePath.h>
73 
74 
75 #define MODE0_COLUMN_COUNT        80
76 #define MODE0_ROW_COUNT           25
77 
78 
79 EFI_STATUS
80 EFIAPI
81 TextInReset(
82   IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
83   IN BOOLEAN                        ExtendedVerification
84   );
85 
86 
87 EFI_STATUS
88 EFIAPI
89 ReadKeyStroke(
90   IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
91   OUT EFI_INPUT_KEY                 *Key
92   );
93 
94 
95 EFI_STATUS
96 EFIAPI
97 TextOutReset(
98   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
99   IN BOOLEAN                          ExtendedVerification
100   );
101 
102 CHAR8 *
103 EFIAPI
104 SafeUnicodeStrToAsciiStr (
105   IN      CONST CHAR16                *Source,
106   OUT     CHAR8                       *Destination
107   );
108 
109 EFI_STATUS
110 EFIAPI
111 OutputString (
112   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
113   IN CHAR16                           *String
114   );
115 
116 
117 EFI_STATUS
118 EFIAPI
119 TestString (
120   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
121   IN CHAR16                           *String
122   );
123 
124 
125 EFI_STATUS
126 EFIAPI
127 QueryMode (
128   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
129   IN UINTN                            ModeNumber,
130   OUT UINTN                           *Columns,
131   OUT UINTN                           *Rows
132   );
133 
134 
135 EFI_STATUS
136 EFIAPI
137 SetMode(
138   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
139   IN UINTN                            ModeNumber
140   );
141 
142 
143 EFI_STATUS
144 EFIAPI
145 SetAttribute(
146   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
147   IN UINTN                            Attribute
148   );
149 
150 
151 EFI_STATUS
152 EFIAPI
153 ClearScreen (
154   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This
155   );
156 
157 
158 EFI_STATUS
159 EFIAPI
160 SetCursorPosition (
161   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
162   IN UINTN                            Column,
163   IN UINTN                            Row
164   );
165 
166 
167 EFI_STATUS
168 EFIAPI
169 EnableCursor (
170   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
171   IN BOOLEAN                          Enable
172   );
173 
174 
175  EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = {
176   TextInReset,
177   ReadKeyStroke,
178   NULL
179 };
180 
181  EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode = {
182   1,
183   0,
184   EFI_TEXT_ATTR( EFI_LIGHTGRAY, EFI_BLACK ),
185   0,
186   0,
187   TRUE
188 };
189 
190 EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut = {
191   TextOutReset,
192   OutputString,
193   TestString,
194   QueryMode,
195   SetMode,
196   SetAttribute,
197   ClearScreen,
198   SetCursorPosition,
199   EnableCursor,
200   &mSimpleTextOutMode
201 };
202 
203 EFI_HANDLE           mInstallHandle = NULL;
204 
205 typedef struct {
206   VENDOR_DEVICE_PATH        Guid;
207   UART_DEVICE_PATH          Uart;
208   EFI_DEVICE_PATH_PROTOCOL  End;
209 } SIMPLE_TEXT_OUT_DEVICE_PATH;
210 
211 SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath = {
212   {
213     { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0} },
214     EFI_CALLER_ID_GUID
215   },
216   {
217     { MESSAGING_DEVICE_PATH, MSG_UART_DP, { sizeof (UART_DEVICE_PATH), 0} },
218     0,        // Reserved
219     FixedPcdGet64 (PcdUartDefaultBaudRate),   // BaudRate
220     FixedPcdGet8 (PcdUartDefaultDataBits),    // DataBits
221     FixedPcdGet8 (PcdUartDefaultParity),      // Parity (N)
222     FixedPcdGet8 (PcdUartDefaultStopBits)     // StopBits
223   },
224   { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0} }
225 };
226 
227 
228 
229 
230 BOOLEAN
TextOutIsValidAscii(IN CHAR16 Ascii)231 TextOutIsValidAscii (
232   IN CHAR16       Ascii
233   )
234 {
235   //
236   // valid ASCII code lies in the extent of 0x20 - 0x7F
237   //
238   if ((Ascii >= 0x20) && (Ascii <= 0x7F)) {
239     return TRUE;
240   }
241 
242   return FALSE;
243 }
244 
245 
246 BOOLEAN
TextOutIsValidEfiCntlChar(IN CHAR16 Char)247 TextOutIsValidEfiCntlChar (
248   IN CHAR16       Char
249   )
250 {
251   //
252   // only support four control characters.
253   //
254   if (Char == CHAR_NULL ||
255       Char == CHAR_BACKSPACE ||
256       Char == CHAR_LINEFEED ||
257       Char == CHAR_CARRIAGE_RETURN ||
258       Char == CHAR_TAB ) {
259     return TRUE;
260   }
261 
262   return FALSE;
263 }
264 
265 
266 VOID
267 EFIAPI
WaitForKeyEvent(IN EFI_EVENT Event,IN VOID * Context)268 WaitForKeyEvent (
269   IN EFI_EVENT          Event,
270   IN VOID               *Context
271   )
272 {
273   if (SerialPortPoll ())  {
274     gBS->SignalEvent (Event);
275   }
276 }
277 
278 
279 EFI_STATUS
280 EFIAPI
TextInReset(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * This,IN BOOLEAN ExtendedVerification)281 TextInReset (
282   IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
283   IN BOOLEAN                        ExtendedVerification
284   )
285 {
286   return EFI_SUCCESS;
287 }
288 
289 
290 EFI_STATUS
291 EFIAPI
ReadKeyStroke(IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL * This,OUT EFI_INPUT_KEY * Key)292 ReadKeyStroke (
293   IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
294   OUT EFI_INPUT_KEY                 *Key
295   )
296 {
297   CHAR8             Char;
298 
299   if (!SerialPortPoll ()) {
300     return EFI_NOT_READY;
301   }
302 
303   SerialPortRead ((UINT8 *)&Char, 1);
304 
305   //
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
311   //
312   Key->UnicodeChar = 0;
313   Key->ScanCode    = SCAN_NULL;
314   if (Char == 0x1b) {
315     SerialPortRead ((UINT8 *)&Char, 1);
316     if (Char == '[') {
317       SerialPortRead ((UINT8 *)&Char, 1);
318       switch (Char) {
319       case 'A':
320         Key->ScanCode = SCAN_UP;
321         break;
322       case 'B':
323         Key->ScanCode = SCAN_DOWN;
324         break;
325       case 'C':
326         Key->ScanCode = SCAN_RIGHT;
327         break;
328       case 'D':
329         Key->ScanCode = SCAN_LEFT;
330         break;
331       case 'H':
332         Key->ScanCode = SCAN_HOME;
333         break;
334       case 'K':
335       case 'F': // PC ANSI
336         Key->ScanCode = SCAN_END;
337         break;
338       case '@':
339       case 'L':
340         Key->ScanCode = SCAN_INSERT;
341         break;
342       case 'P':
343       case 'X': // PC ANSI
344         Key->ScanCode = SCAN_DELETE;
345         break;
346       case 'U':
347       case '/':
348       case 'G': // PC ANSI
349         Key->ScanCode = SCAN_PAGE_DOWN;
350         break;
351       case 'V':
352       case '?':
353       case 'I': // PC ANSI
354         Key->ScanCode = SCAN_PAGE_UP;
355         break;
356 
357       // PCANSI that does not conflict with VT100
358       case 'M':
359         Key->ScanCode = SCAN_F1;
360         break;
361       case 'N':
362         Key->ScanCode = SCAN_F2;
363         break;
364       case 'O':
365         Key->ScanCode = SCAN_F3;
366         break;
367       case 'Q':
368         Key->ScanCode = SCAN_F5;
369         break;
370       case 'R':
371         Key->ScanCode = SCAN_F6;
372         break;
373       case 'S':
374         Key->ScanCode = SCAN_F7;
375         break;
376       case 'T':
377         Key->ScanCode = SCAN_F8;
378         break;
379 
380       default:
381         Key->UnicodeChar = Char;
382         break;
383       }
384     } else if (Char == '0') {
385       SerialPortRead ((UINT8 *)&Char, 1);
386       switch (Char) {
387       case 'P':
388         Key->ScanCode = SCAN_F1;
389         break;
390       case 'Q':
391         Key->ScanCode = SCAN_F2;
392         break;
393       case 'w':
394         Key->ScanCode = SCAN_F3;
395         break;
396       case 'x':
397         Key->ScanCode = SCAN_F4;
398         break;
399       case 't':
400         Key->ScanCode = SCAN_F5;
401         break;
402       case 'u':
403         Key->ScanCode = SCAN_F6;
404         break;
405       case 'q':
406         Key->ScanCode = SCAN_F7;
407         break;
408       case 'r':
409         Key->ScanCode = SCAN_F8;
410         break;
411       case 'p':
412         Key->ScanCode = SCAN_F9;
413         break;
414       case 'm':
415         Key->ScanCode = SCAN_F10;
416         break;
417       default :
418         break;
419       }
420     }
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;
428     }
429   } else if (Char == 0x7f) {
430     Key->ScanCode = SCAN_DELETE;
431   } else {
432     Key->UnicodeChar = (CHAR16)Char;
433   }
434 
435   return EFI_SUCCESS;
436 }
437 
438 
439 EFI_STATUS
440 EFIAPI
TextOutReset(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN ExtendedVerification)441 TextOutReset (
442   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
443   IN BOOLEAN                          ExtendedVerification
444   )
445 {
446   EFI_STATUS            Status;
447 
448   This->SetAttribute(
449         This,
450         EFI_TEXT_ATTR(This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)
451         );
452 
453   Status = This->SetMode (This, 0);
454 
455   return Status;
456 }
457 
458 CHAR8 *
459 EFIAPI
SafeUnicodeStrToAsciiStr(IN CONST CHAR16 * Source,OUT CHAR8 * Destination)460 SafeUnicodeStrToAsciiStr (
461   IN      CONST CHAR16                *Source,
462   OUT     CHAR8                       *Destination
463   )
464 {
465   CHAR8                               *ReturnValue;
466 
467   ASSERT (Destination != NULL);
468 
469   //
470   // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
471   // Length tests are performed inside StrLen().
472   //
473   ASSERT (StrSize (Source) != 0);
474 
475   //
476   // Source and Destination should not overlap
477   //
478   ASSERT ((UINTN) ((CHAR16 *) Destination -  Source) > StrLen (Source));
479   ASSERT ((UINTN) ((CHAR8 *) Source - Destination) > StrLen (Source));
480 
481 
482   ReturnValue = Destination;
483   while (*Source != '\0') {
484     //
485     // If any non-ascii characters in Source then replace it with '?'.
486     //
487     if (*Source < 0x80) {
488       *Destination = (CHAR8) *Source;
489     } else {
490       *Destination = '?';
491 
492       //Surrogate pair check.
493       if ((*Source >= 0xD800) && (*Source <= 0xDFFF)) {
494         Source++;
495       }
496     }
497 
498     Destination++;
499     Source++;
500   }
501 
502   *Destination = '\0';
503 
504   //
505   // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
506   // Length tests are performed inside AsciiStrLen().
507   //
508   ASSERT (AsciiStrSize (ReturnValue) != 0);
509 
510   return ReturnValue;
511 }
512 
513 EFI_STATUS
514 EFIAPI
OutputString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * String)515 OutputString (
516   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
517   IN CHAR16                           *String
518   )
519 {
520   UINTN                       Size;
521   CHAR8*                      OutputString;
522   EFI_STATUS                  Status;
523   EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
524   UINTN                       MaxColumn;
525   UINTN                       MaxRow;
526 
527   Size = StrLen(String) + 1;
528   OutputString = AllocatePool(Size);
529 
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);
534 
535   //
536   // Parse each character of the string to output
537   // to update the cursor position information
538   //
539   Mode = This->Mode;
540 
541   Status = This->QueryMode (
542                    This,
543                    Mode->Mode,
544                    &MaxColumn,
545                    &MaxRow
546                    );
547   if (EFI_ERROR (Status)) {
548     return Status;
549   }
550 
551   for (; *String != CHAR_NULL; String++) {
552 
553     switch (*String) {
554     case CHAR_BACKSPACE:
555       if (Mode->CursorColumn > 0) {
556         Mode->CursorColumn--;
557       }
558       break;
559 
560     case CHAR_LINEFEED:
561       if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
562         Mode->CursorRow++;
563       }
564       break;
565 
566     case CHAR_CARRIAGE_RETURN:
567       Mode->CursorColumn = 0;
568       break;
569 
570     default:
571       if (Mode->CursorColumn >= (INT32) (MaxColumn - 1)) {
572         // Move the cursor as if we print CHAR_CARRIAGE_RETURN & CHAR_LINE_FEED
573         // CHAR_LINEFEED
574         if (Mode->CursorRow < (INT32) (MaxRow - 1)) {
575           Mode->CursorRow++;
576         }
577         // CHAR_CARIAGE_RETURN
578         Mode->CursorColumn = 0;
579       } else {
580         Mode->CursorColumn++;
581       }
582       break;
583     }
584   }
585 
586   FreePool(OutputString);
587 
588   return EFI_SUCCESS;
589 }
590 
591 
592 EFI_STATUS
593 EFIAPI
TestString(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN CHAR16 * String)594 TestString (
595   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
596   IN CHAR16                           *String
597   )
598 {
599   CHAR8           Character;
600 
601   for ( ; *String != CHAR_NULL; String++) {
602     Character = (CHAR8)*String;
603     if (!(TextOutIsValidAscii (Character) || TextOutIsValidEfiCntlChar (Character))) {
604       return EFI_UNSUPPORTED;
605     }
606   }
607 
608   return EFI_SUCCESS;
609 }
610 
611 
612 EFI_STATUS
613 EFIAPI
QueryMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber,OUT UINTN * Columns,OUT UINTN * Rows)614 QueryMode (
615   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
616   IN UINTN                            ModeNumber,
617   OUT UINTN                          *Columns,
618   OUT UINTN                          *Rows
619   )
620 {
621   if (This->Mode->MaxMode > 1) {
622     return EFI_DEVICE_ERROR;
623   }
624 
625   if (ModeNumber == 0) {
626     *Columns  = MODE0_COLUMN_COUNT;
627     *Rows     = MODE0_ROW_COUNT;
628     return EFI_SUCCESS;
629   }
630 
631   return EFI_UNSUPPORTED;
632 }
633 
634 
635 EFI_STATUS
636 EFIAPI
SetMode(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN ModeNumber)637 SetMode (
638   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This,
639   IN UINTN                              ModeNumber
640   )
641 {
642   if (ModeNumber != 0) {
643     return EFI_UNSUPPORTED;
644   }
645 
646   This->Mode->Mode = 0;
647   This->ClearScreen (This);
648   return EFI_SUCCESS;
649 }
650 
651 
652 EFI_STATUS
653 EFIAPI
SetAttribute(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Attribute)654 SetAttribute(
655   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This,
656   IN UINTN                              Attribute
657   )
658 {
659   This->Mode->Attribute = (INT32)Attribute;
660   return EFI_SUCCESS;
661 }
662 
663 
664 EFI_STATUS
665 EFIAPI
ClearScreen(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This)666 ClearScreen (
667   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This
668   )
669 {
670   EFI_STATUS    Status;
671 
672   Status = This->SetCursorPosition (This, 0, 0);
673   return Status;
674 }
675 
676 
677 EFI_STATUS
678 EFIAPI
SetCursorPosition(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN UINTN Column,IN UINTN Row)679 SetCursorPosition (
680   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL    *This,
681   IN UINTN                              Column,
682   IN UINTN                              Row
683   )
684 {
685   EFI_SIMPLE_TEXT_OUTPUT_MODE       *Mode;
686   EFI_STATUS                        Status;
687   UINTN                             MaxColumn;
688   UINTN                             MaxRow;
689 
690   Mode = This->Mode;
691 
692   Status = This->QueryMode(
693                   This,
694                   Mode->Mode,
695                   &MaxColumn,
696                   &MaxRow
697                   );
698   if (EFI_ERROR(Status)) {
699     return EFI_UNSUPPORTED;
700   }
701 
702   if ((Column >= MaxColumn) || (Row >= MaxRow)) {
703     return EFI_UNSUPPORTED;
704   }
705 
706   Mode->CursorColumn = (INT32)Column;
707   Mode->CursorRow = (INT32)Row;
708 
709   return EFI_SUCCESS;
710 }
711 
712 
713 EFI_STATUS
714 EFIAPI
EnableCursor(IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL * This,IN BOOLEAN Enable)715 EnableCursor (
716   IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL  *This,
717   IN BOOLEAN                          Enable
718   )
719 {
720   if (!Enable) {
721     return EFI_UNSUPPORTED;
722   }
723 
724   return EFI_SUCCESS;
725 }
726 
727 
728 EFI_STATUS
729 EFIAPI
SimpleTextInOutEntryPoint(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)730 SimpleTextInOutEntryPoint (
731   IN EFI_HANDLE         ImageHandle,
732   IN EFI_SYSTEM_TABLE   *SystemTable
733   )
734 {
735   EFI_STATUS            Status;
736 
737   Status = gBS->CreateEvent (
738                   EVT_NOTIFY_WAIT,
739                   TPL_NOTIFY,
740                   WaitForKeyEvent,
741                   NULL,
742                   &mSimpleTextIn.WaitForKey
743                   );
744   ASSERT_EFI_ERROR (Status);
745 
746   Status = gBS->InstallMultipleProtocolInterfaces(
747                   &mInstallHandle,
748                   &gEfiSimpleTextInProtocolGuid,   &mSimpleTextIn,
749                   &gEfiSimpleTextOutProtocolGuid,  &mSimpleTextOut,
750                   &gEfiDevicePathProtocolGuid,     &mDevicePath,
751                   NULL
752                   );
753   if (!EFI_ERROR (Status)) {
754     gST->ConOut = &mSimpleTextOut;
755     gST->ConIn = &mSimpleTextIn;
756   }
757 
758   return Status;
759 }
760