]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - EmbeddedPkg/SimpleTextInOutSerial/SimpleTextInOut.c
Cleanup SerailIO drivers to have a device path and use PCD settings for various stuff...
[mirror_edk2.git] / EmbeddedPkg / SimpleTextInOutSerial / SimpleTextInOut.c
... / ...
CommitLineData
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
79EFI_STATUS\r
80EFIAPI\r
81TextInReset(\r
82 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
83 IN BOOLEAN ExtendedVerification\r
84 );\r
85\r
86\r
87EFI_STATUS\r
88EFIAPI\r
89ReadKeyStroke(\r
90 IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,\r
91 OUT EFI_INPUT_KEY *Key\r
92 );\r
93\r
94\r
95EFI_STATUS\r
96EFIAPI\r
97TextOutReset(\r
98 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
99 IN BOOLEAN ExtendedVerification\r
100 );\r
101\r
102CHAR8 *\r
103EFIAPI\r
104SafeUnicodeStrToAsciiStr (\r
105 IN CONST CHAR16 *Source,\r
106 OUT CHAR8 *Destination\r
107 );\r
108\r
109EFI_STATUS\r
110EFIAPI\r
111OutputString (\r
112 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
113 IN CHAR16 *String\r
114 );\r
115\r
116\r
117EFI_STATUS\r
118EFIAPI\r
119TestString (\r
120 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
121 IN CHAR16 *String\r
122 );\r
123\r
124\r
125EFI_STATUS\r
126EFIAPI\r
127QueryMode (\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
135EFI_STATUS\r
136EFIAPI\r
137SetMode(\r
138 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
139 IN UINTN ModeNumber\r
140 );\r
141\r
142\r
143EFI_STATUS\r
144EFIAPI\r
145SetAttribute(\r
146 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,\r
147 IN UINTN Attribute\r
148 );\r
149\r
150\r
151EFI_STATUS\r
152EFIAPI\r
153ClearScreen (\r
154 IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This\r
155 );\r
156\r
157\r
158EFI_STATUS\r
159EFIAPI\r
160SetCursorPosition (\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
167EFI_STATUS\r
168EFIAPI\r
169EnableCursor (\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
190EFI_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
203EFI_HANDLE mInstallHandle = NULL;\r
204\r
205typedef 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
211SIMPLE_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
230BOOLEAN\r
231TextOutIsValidAscii (\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
246BOOLEAN\r
247TextOutIsValidEfiCntlChar (\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
266VOID\r
267EFIAPI\r
268WaitForKeyEvent (\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
279EFI_STATUS\r
280EFIAPI\r
281TextInReset (\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
290EFI_STATUS\r
291EFIAPI\r
292ReadKeyStroke (\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
439EFI_STATUS\r
440EFIAPI\r
441TextOutReset (\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
458CHAR8 *\r
459EFIAPI\r
460SafeUnicodeStrToAsciiStr (\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
513EFI_STATUS\r
514EFIAPI\r
515OutputString (\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
534EFI_STATUS\r
535EFIAPI\r
536TestString (\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
554EFI_STATUS\r
555EFIAPI\r
556QueryMode (\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
577EFI_STATUS\r
578EFIAPI\r
579SetMode (\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
594EFI_STATUS\r
595EFIAPI\r
596SetAttribute(\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
606EFI_STATUS\r
607EFIAPI\r
608ClearScreen (\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
619EFI_STATUS\r
620EFIAPI\r
621SetCursorPosition (\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
655EFI_STATUS\r
656EFIAPI\r
657EnableCursor (\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
670EFI_STATUS\r
671EFIAPI\r
672SimpleTextInOutEntryPoint (\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