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