SimpleTextInOut.c 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735
  1. /** @file
  2. Simple Console that sits on a SerialLib.
  3. Copyright (c) 2008 - 2009, Apple Inc. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. /*
  7. Symbols used in table below
  8. ===========================
  9. ESC = 0x1B
  10. CSI = 0x9B
  11. DEL = 0x7f
  12. ^ = CTRL
  13. +=========+======+===========+==========+==========+
  14. | | EFI | UEFI 2.0 | | |
  15. | | Scan | | VT100+ | |
  16. | KEY | Code | PC ANSI | VTUTF8 | VT100 |
  17. +=========+======+===========+==========+==========+
  18. | NULL | 0x00 | | | |
  19. | UP | 0x01 | ESC [ A | ESC [ A | ESC [ A |
  20. | DOWN | 0x02 | ESC [ B | ESC [ B | ESC [ B |
  21. | RIGHT | 0x03 | ESC [ C | ESC [ C | ESC [ C |
  22. | LEFT | 0x04 | ESC [ D | ESC [ D | ESC [ D |
  23. | HOME | 0x05 | ESC [ H | ESC h | ESC [ H |
  24. | END | 0x06 | ESC [ F | ESC k | ESC [ K |
  25. | INSERT | 0x07 | ESC [ @ | ESC + | ESC [ @ |
  26. | | | ESC [ L | | ESC [ L |
  27. | DELETE | 0x08 | ESC [ X | ESC - | ESC [ P |
  28. | PG UP | 0x09 | ESC [ I | ESC ? | ESC [ V |
  29. | | | | | ESC [ ? |
  30. | PG DOWN | 0x0A | ESC [ G | ESC / | ESC [ U |
  31. | | | | | ESC [ / |
  32. | F1 | 0x0B | ESC [ M | ESC 1 | ESC O P |
  33. | F2 | 0x0C | ESC [ N | ESC 2 | ESC O Q |
  34. | F3 | 0x0D | ESC [ O | ESC 3 | ESC O w |
  35. | F4 | 0x0E | ESC [ P | ESC 4 | ESC O x |
  36. | F5 | 0x0F | ESC [ Q | ESC 5 | ESC O t |
  37. | F6 | 0x10 | ESC [ R | ESC 6 | ESC O u |
  38. | F7 | 0x11 | ESC [ S | ESC 7 | ESC O q |
  39. | F8 | 0x12 | ESC [ T | ESC 8 | ESC O r |
  40. | F9 | 0x13 | ESC [ U | ESC 9 | ESC O p |
  41. | F10 | 0x14 | ESC [ V | ESC 0 | ESC O M |
  42. | Escape | 0x17 | ESC | ESC | ESC |
  43. | F11 | 0x15 | | ESC ! | |
  44. | F12 | 0x16 | | ESC @ | |
  45. +=========+======+===========+==========+==========+
  46. */
  47. #include <PiDxe.h>
  48. #include <Library/UefiLib.h>
  49. #include <Library/UefiBootServicesTableLib.h>
  50. #include <Library/BaseLib.h>
  51. #include <Library/MemoryAllocationLib.h>
  52. #include <Library/DebugLib.h>
  53. #include <Library/SerialPortLib.h>
  54. #include <Library/PcdLib.h>
  55. #include <Protocol/SerialIo.h>
  56. #include <Protocol/SimpleTextIn.h>
  57. #include <Protocol/SimpleTextOut.h>
  58. #include <Protocol/DevicePath.h>
  59. #define MODE0_COLUMN_COUNT 80
  60. #define MODE0_ROW_COUNT 25
  61. EFI_STATUS
  62. EFIAPI
  63. TextInReset (
  64. IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
  65. IN BOOLEAN ExtendedVerification
  66. );
  67. EFI_STATUS
  68. EFIAPI
  69. ReadKeyStroke (
  70. IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
  71. OUT EFI_INPUT_KEY *Key
  72. );
  73. EFI_STATUS
  74. EFIAPI
  75. TextOutReset (
  76. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  77. IN BOOLEAN ExtendedVerification
  78. );
  79. CHAR8 *
  80. EFIAPI
  81. SafeUnicodeStrToAsciiStr (
  82. IN CONST CHAR16 *Source,
  83. OUT CHAR8 *Destination
  84. );
  85. EFI_STATUS
  86. EFIAPI
  87. OutputString (
  88. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  89. IN CHAR16 *String
  90. );
  91. EFI_STATUS
  92. EFIAPI
  93. TestString (
  94. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  95. IN CHAR16 *String
  96. );
  97. EFI_STATUS
  98. EFIAPI
  99. QueryMode (
  100. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  101. IN UINTN ModeNumber,
  102. OUT UINTN *Columns,
  103. OUT UINTN *Rows
  104. );
  105. EFI_STATUS
  106. EFIAPI
  107. SetMode (
  108. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  109. IN UINTN ModeNumber
  110. );
  111. EFI_STATUS
  112. EFIAPI
  113. SetAttribute (
  114. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  115. IN UINTN Attribute
  116. );
  117. EFI_STATUS
  118. EFIAPI
  119. ClearScreen (
  120. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
  121. );
  122. EFI_STATUS
  123. EFIAPI
  124. SetCursorPosition (
  125. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  126. IN UINTN Column,
  127. IN UINTN Row
  128. );
  129. EFI_STATUS
  130. EFIAPI
  131. EnableCursor (
  132. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  133. IN BOOLEAN Enable
  134. );
  135. EFI_SIMPLE_TEXT_INPUT_PROTOCOL mSimpleTextIn = {
  136. TextInReset,
  137. ReadKeyStroke,
  138. NULL
  139. };
  140. EFI_SIMPLE_TEXT_OUTPUT_MODE mSimpleTextOutMode = {
  141. 1,
  142. 0,
  143. EFI_TEXT_ATTR (EFI_LIGHTGRAY,EFI_BLACK),
  144. 0,
  145. 0,
  146. TRUE
  147. };
  148. EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL mSimpleTextOut = {
  149. TextOutReset,
  150. OutputString,
  151. TestString,
  152. QueryMode,
  153. SetMode,
  154. SetAttribute,
  155. ClearScreen,
  156. SetCursorPosition,
  157. EnableCursor,
  158. &mSimpleTextOutMode
  159. };
  160. EFI_HANDLE mInstallHandle = NULL;
  161. typedef struct {
  162. VENDOR_DEVICE_PATH Guid;
  163. UART_DEVICE_PATH Uart;
  164. EFI_DEVICE_PATH_PROTOCOL End;
  165. } SIMPLE_TEXT_OUT_DEVICE_PATH;
  166. SIMPLE_TEXT_OUT_DEVICE_PATH mDevicePath = {
  167. {
  168. { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 }
  169. },
  170. EFI_CALLER_ID_GUID
  171. },
  172. {
  173. { MESSAGING_DEVICE_PATH, MSG_UART_DP, { sizeof (UART_DEVICE_PATH), 0 }
  174. },
  175. 0, // Reserved
  176. FixedPcdGet64 (PcdUartDefaultBaudRate), // BaudRate
  177. FixedPcdGet8 (PcdUartDefaultDataBits), // DataBits
  178. FixedPcdGet8 (PcdUartDefaultParity), // Parity (N)
  179. FixedPcdGet8 (PcdUartDefaultStopBits) // StopBits
  180. },
  181. { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 }
  182. }
  183. };
  184. BOOLEAN
  185. TextOutIsValidAscii (
  186. IN CHAR16 Ascii
  187. )
  188. {
  189. //
  190. // valid ASCII code lies in the extent of 0x20 - 0x7F
  191. //
  192. if ((Ascii >= 0x20) && (Ascii <= 0x7F)) {
  193. return TRUE;
  194. }
  195. return FALSE;
  196. }
  197. BOOLEAN
  198. TextOutIsValidEfiCntlChar (
  199. IN CHAR16 Char
  200. )
  201. {
  202. //
  203. // only support four control characters.
  204. //
  205. if ((Char == CHAR_NULL) ||
  206. (Char == CHAR_BACKSPACE) ||
  207. (Char == CHAR_LINEFEED) ||
  208. (Char == CHAR_CARRIAGE_RETURN) ||
  209. (Char == CHAR_TAB))
  210. {
  211. return TRUE;
  212. }
  213. return FALSE;
  214. }
  215. VOID
  216. EFIAPI
  217. WaitForKeyEvent (
  218. IN EFI_EVENT Event,
  219. IN VOID *Context
  220. )
  221. {
  222. if (SerialPortPoll ()) {
  223. gBS->SignalEvent (Event);
  224. }
  225. }
  226. EFI_STATUS
  227. EFIAPI
  228. TextInReset (
  229. IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
  230. IN BOOLEAN ExtendedVerification
  231. )
  232. {
  233. return EFI_SUCCESS;
  234. }
  235. EFI_STATUS
  236. EFIAPI
  237. ReadKeyStroke (
  238. IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This,
  239. OUT EFI_INPUT_KEY *Key
  240. )
  241. {
  242. CHAR8 Char;
  243. if (!SerialPortPoll ()) {
  244. return EFI_NOT_READY;
  245. }
  246. SerialPortRead ((UINT8 *)&Char, 1);
  247. //
  248. // Check for ESC sequence. This code is not technically correct VT100 code.
  249. // An illegal ESC sequence represents an ESC and the characters that follow.
  250. // This code will eat one or two chars after an escape. This is done to
  251. // prevent some complex FIFOing of the data. It is good enough to get
  252. // the arrow and delete keys working
  253. //
  254. Key->UnicodeChar = 0;
  255. Key->ScanCode = SCAN_NULL;
  256. if (Char == 0x1b) {
  257. SerialPortRead ((UINT8 *)&Char, 1);
  258. if (Char == '[') {
  259. SerialPortRead ((UINT8 *)&Char, 1);
  260. switch (Char) {
  261. case 'A':
  262. Key->ScanCode = SCAN_UP;
  263. break;
  264. case 'B':
  265. Key->ScanCode = SCAN_DOWN;
  266. break;
  267. case 'C':
  268. Key->ScanCode = SCAN_RIGHT;
  269. break;
  270. case 'D':
  271. Key->ScanCode = SCAN_LEFT;
  272. break;
  273. case 'H':
  274. Key->ScanCode = SCAN_HOME;
  275. break;
  276. case 'K':
  277. case 'F': // PC ANSI
  278. Key->ScanCode = SCAN_END;
  279. break;
  280. case '@':
  281. case 'L':
  282. Key->ScanCode = SCAN_INSERT;
  283. break;
  284. case 'P':
  285. case 'X': // PC ANSI
  286. Key->ScanCode = SCAN_DELETE;
  287. break;
  288. case 'U':
  289. case '/':
  290. case 'G': // PC ANSI
  291. Key->ScanCode = SCAN_PAGE_DOWN;
  292. break;
  293. case 'V':
  294. case '?':
  295. case 'I': // PC ANSI
  296. Key->ScanCode = SCAN_PAGE_UP;
  297. break;
  298. // PCANSI that does not conflict with VT100
  299. case 'M':
  300. Key->ScanCode = SCAN_F1;
  301. break;
  302. case 'N':
  303. Key->ScanCode = SCAN_F2;
  304. break;
  305. case 'O':
  306. Key->ScanCode = SCAN_F3;
  307. break;
  308. case 'Q':
  309. Key->ScanCode = SCAN_F5;
  310. break;
  311. case 'R':
  312. Key->ScanCode = SCAN_F6;
  313. break;
  314. case 'S':
  315. Key->ScanCode = SCAN_F7;
  316. break;
  317. case 'T':
  318. Key->ScanCode = SCAN_F8;
  319. break;
  320. default:
  321. Key->UnicodeChar = Char;
  322. break;
  323. }
  324. } else if (Char == '0') {
  325. SerialPortRead ((UINT8 *)&Char, 1);
  326. switch (Char) {
  327. case 'P':
  328. Key->ScanCode = SCAN_F1;
  329. break;
  330. case 'Q':
  331. Key->ScanCode = SCAN_F2;
  332. break;
  333. case 'w':
  334. Key->ScanCode = SCAN_F3;
  335. break;
  336. case 'x':
  337. Key->ScanCode = SCAN_F4;
  338. break;
  339. case 't':
  340. Key->ScanCode = SCAN_F5;
  341. break;
  342. case 'u':
  343. Key->ScanCode = SCAN_F6;
  344. break;
  345. case 'q':
  346. Key->ScanCode = SCAN_F7;
  347. break;
  348. case 'r':
  349. Key->ScanCode = SCAN_F8;
  350. break;
  351. case 'p':
  352. Key->ScanCode = SCAN_F9;
  353. break;
  354. case 'm':
  355. Key->ScanCode = SCAN_F10;
  356. break;
  357. default:
  358. break;
  359. }
  360. }
  361. } else if (Char < ' ') {
  362. if ((Char == CHAR_BACKSPACE) ||
  363. (Char == CHAR_TAB) ||
  364. (Char == CHAR_LINEFEED) ||
  365. (Char == CHAR_CARRIAGE_RETURN))
  366. {
  367. // Only let through EFI required control characters
  368. Key->UnicodeChar = (CHAR16)Char;
  369. }
  370. } else if (Char == 0x7f) {
  371. Key->ScanCode = SCAN_DELETE;
  372. } else {
  373. Key->UnicodeChar = (CHAR16)Char;
  374. }
  375. return EFI_SUCCESS;
  376. }
  377. EFI_STATUS
  378. EFIAPI
  379. TextOutReset (
  380. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  381. IN BOOLEAN ExtendedVerification
  382. )
  383. {
  384. EFI_STATUS Status;
  385. This->SetAttribute (
  386. This,
  387. EFI_TEXT_ATTR (This->Mode->Attribute & 0x0F, EFI_BACKGROUND_BLACK)
  388. );
  389. Status = This->SetMode (This, 0);
  390. return Status;
  391. }
  392. CHAR8 *
  393. EFIAPI
  394. SafeUnicodeStrToAsciiStr (
  395. IN CONST CHAR16 *Source,
  396. OUT CHAR8 *Destination
  397. )
  398. {
  399. CHAR8 *ReturnValue;
  400. ASSERT (Destination != NULL);
  401. //
  402. // ASSERT if Source is long than PcdMaximumUnicodeStringLength.
  403. // Length tests are performed inside StrLen().
  404. //
  405. ASSERT (StrSize (Source) != 0);
  406. //
  407. // Source and Destination should not overlap
  408. //
  409. ASSERT ((UINTN)((CHAR16 *)Destination - Source) > StrLen (Source));
  410. ASSERT ((UINTN)((CHAR8 *)Source - Destination) > StrLen (Source));
  411. ReturnValue = Destination;
  412. while (*Source != '\0') {
  413. //
  414. // If any non-ascii characters in Source then replace it with '?'.
  415. //
  416. if (*Source < 0x80) {
  417. *Destination = (CHAR8)*Source;
  418. } else {
  419. *Destination = '?';
  420. // Surrogate pair check.
  421. if ((*Source >= 0xD800) && (*Source <= 0xDFFF)) {
  422. Source++;
  423. }
  424. }
  425. Destination++;
  426. Source++;
  427. }
  428. *Destination = '\0';
  429. //
  430. // ASSERT Original Destination is less long than PcdMaximumAsciiStringLength.
  431. // Length tests are performed inside AsciiStrLen().
  432. //
  433. ASSERT (AsciiStrSize (ReturnValue) != 0);
  434. return ReturnValue;
  435. }
  436. EFI_STATUS
  437. EFIAPI
  438. OutputString (
  439. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  440. IN CHAR16 *String
  441. )
  442. {
  443. UINTN Size;
  444. CHAR8 *OutputString;
  445. EFI_STATUS Status;
  446. EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
  447. UINTN MaxColumn;
  448. UINTN MaxRow;
  449. Size = StrLen (String) + 1;
  450. OutputString = AllocatePool (Size);
  451. // If there is any non-ascii characters in String buffer then replace it with '?'
  452. // Eventually, UnicodeStrToAsciiStr API should be fixed.
  453. SafeUnicodeStrToAsciiStr (String, OutputString);
  454. SerialPortWrite ((UINT8 *)OutputString, Size - 1);
  455. //
  456. // Parse each character of the string to output
  457. // to update the cursor position information
  458. //
  459. Mode = This->Mode;
  460. Status = This->QueryMode (
  461. This,
  462. Mode->Mode,
  463. &MaxColumn,
  464. &MaxRow
  465. );
  466. if (EFI_ERROR (Status)) {
  467. return Status;
  468. }
  469. for ( ; *String != CHAR_NULL; String++) {
  470. switch (*String) {
  471. case CHAR_BACKSPACE:
  472. if (Mode->CursorColumn > 0) {
  473. Mode->CursorColumn--;
  474. }
  475. break;
  476. case CHAR_LINEFEED:
  477. if (Mode->CursorRow < (INT32)(MaxRow - 1)) {
  478. Mode->CursorRow++;
  479. }
  480. break;
  481. case CHAR_CARRIAGE_RETURN:
  482. Mode->CursorColumn = 0;
  483. break;
  484. default:
  485. if (Mode->CursorColumn >= (INT32)(MaxColumn - 1)) {
  486. // Move the cursor as if we print CHAR_CARRIAGE_RETURN & CHAR_LINE_FEED
  487. // CHAR_LINEFEED
  488. if (Mode->CursorRow < (INT32)(MaxRow - 1)) {
  489. Mode->CursorRow++;
  490. }
  491. // CHAR_CARIAGE_RETURN
  492. Mode->CursorColumn = 0;
  493. } else {
  494. Mode->CursorColumn++;
  495. }
  496. break;
  497. }
  498. }
  499. FreePool (OutputString);
  500. return EFI_SUCCESS;
  501. }
  502. EFI_STATUS
  503. EFIAPI
  504. TestString (
  505. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  506. IN CHAR16 *String
  507. )
  508. {
  509. CHAR8 Character;
  510. for ( ; *String != CHAR_NULL; String++) {
  511. Character = (CHAR8)*String;
  512. if (!(TextOutIsValidAscii (Character) || TextOutIsValidEfiCntlChar (Character))) {
  513. return EFI_UNSUPPORTED;
  514. }
  515. }
  516. return EFI_SUCCESS;
  517. }
  518. EFI_STATUS
  519. EFIAPI
  520. QueryMode (
  521. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  522. IN UINTN ModeNumber,
  523. OUT UINTN *Columns,
  524. OUT UINTN *Rows
  525. )
  526. {
  527. if (This->Mode->MaxMode > 1) {
  528. return EFI_DEVICE_ERROR;
  529. }
  530. if (ModeNumber == 0) {
  531. *Columns = MODE0_COLUMN_COUNT;
  532. *Rows = MODE0_ROW_COUNT;
  533. return EFI_SUCCESS;
  534. }
  535. return EFI_UNSUPPORTED;
  536. }
  537. EFI_STATUS
  538. EFIAPI
  539. SetMode (
  540. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  541. IN UINTN ModeNumber
  542. )
  543. {
  544. if (ModeNumber != 0) {
  545. return EFI_UNSUPPORTED;
  546. }
  547. This->Mode->Mode = 0;
  548. This->ClearScreen (This);
  549. return EFI_SUCCESS;
  550. }
  551. EFI_STATUS
  552. EFIAPI
  553. SetAttribute (
  554. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  555. IN UINTN Attribute
  556. )
  557. {
  558. This->Mode->Attribute = (INT32)Attribute;
  559. return EFI_SUCCESS;
  560. }
  561. EFI_STATUS
  562. EFIAPI
  563. ClearScreen (
  564. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This
  565. )
  566. {
  567. EFI_STATUS Status;
  568. Status = This->SetCursorPosition (This, 0, 0);
  569. return Status;
  570. }
  571. EFI_STATUS
  572. EFIAPI
  573. SetCursorPosition (
  574. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  575. IN UINTN Column,
  576. IN UINTN Row
  577. )
  578. {
  579. EFI_SIMPLE_TEXT_OUTPUT_MODE *Mode;
  580. EFI_STATUS Status;
  581. UINTN MaxColumn;
  582. UINTN MaxRow;
  583. Mode = This->Mode;
  584. Status = This->QueryMode (
  585. This,
  586. Mode->Mode,
  587. &MaxColumn,
  588. &MaxRow
  589. );
  590. if (EFI_ERROR (Status)) {
  591. return EFI_UNSUPPORTED;
  592. }
  593. if ((Column >= MaxColumn) || (Row >= MaxRow)) {
  594. return EFI_UNSUPPORTED;
  595. }
  596. Mode->CursorColumn = (INT32)Column;
  597. Mode->CursorRow = (INT32)Row;
  598. return EFI_SUCCESS;
  599. }
  600. EFI_STATUS
  601. EFIAPI
  602. EnableCursor (
  603. IN EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *This,
  604. IN BOOLEAN Enable
  605. )
  606. {
  607. if (!Enable) {
  608. return EFI_UNSUPPORTED;
  609. }
  610. return EFI_SUCCESS;
  611. }
  612. EFI_STATUS
  613. EFIAPI
  614. SimpleTextInOutEntryPoint (
  615. IN EFI_HANDLE ImageHandle,
  616. IN EFI_SYSTEM_TABLE *SystemTable
  617. )
  618. {
  619. EFI_STATUS Status;
  620. Status = gBS->CreateEvent (
  621. EVT_NOTIFY_WAIT,
  622. TPL_NOTIFY,
  623. WaitForKeyEvent,
  624. NULL,
  625. &mSimpleTextIn.WaitForKey
  626. );
  627. ASSERT_EFI_ERROR (Status);
  628. Status = gBS->InstallMultipleProtocolInterfaces (
  629. &mInstallHandle,
  630. &gEfiSimpleTextInProtocolGuid,
  631. &mSimpleTextIn,
  632. &gEfiSimpleTextOutProtocolGuid,
  633. &mSimpleTextOut,
  634. &gEfiDevicePathProtocolGuid,
  635. &mDevicePath,
  636. NULL
  637. );
  638. if (!EFI_ERROR (Status)) {
  639. gST->ConOut = &mSimpleTextOut;
  640. gST->ConIn = &mSimpleTextIn;
  641. }
  642. return Status;
  643. }