efi_console.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * EFI application console interface
  4. *
  5. * Copyright (c) 2016 Alexander Graf
  6. */
  7. #include <common.h>
  8. #include <charset.h>
  9. #include <malloc.h>
  10. #include <time.h>
  11. #include <dm/device.h>
  12. #include <efi_loader.h>
  13. #include <env.h>
  14. #include <stdio_dev.h>
  15. #include <video_console.h>
  16. #define EFI_COUT_MODE_2 2
  17. #define EFI_MAX_COUT_MODE 3
  18. struct cout_mode {
  19. unsigned long columns;
  20. unsigned long rows;
  21. int present;
  22. };
  23. static struct cout_mode efi_cout_modes[] = {
  24. /* EFI Mode 0 is 80x25 and always present */
  25. {
  26. .columns = 80,
  27. .rows = 25,
  28. .present = 1,
  29. },
  30. /* EFI Mode 1 is always 80x50 */
  31. {
  32. .columns = 80,
  33. .rows = 50,
  34. .present = 0,
  35. },
  36. /* Value are unknown until we query the console */
  37. {
  38. .columns = 0,
  39. .rows = 0,
  40. .present = 0,
  41. },
  42. };
  43. const efi_guid_t efi_guid_text_input_ex_protocol =
  44. EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
  45. const efi_guid_t efi_guid_text_input_protocol =
  46. EFI_SIMPLE_TEXT_INPUT_PROTOCOL_GUID;
  47. const efi_guid_t efi_guid_text_output_protocol =
  48. EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL_GUID;
  49. #define cESC '\x1b'
  50. #define ESC "\x1b"
  51. /* Default to mode 0 */
  52. static struct simple_text_output_mode efi_con_mode = {
  53. .max_mode = 1,
  54. .mode = 0,
  55. .attribute = 0,
  56. .cursor_column = 0,
  57. .cursor_row = 0,
  58. .cursor_visible = 1,
  59. };
  60. static int term_get_char(s32 *c)
  61. {
  62. u64 timeout;
  63. /* Wait up to 100 ms for a character */
  64. timeout = timer_get_us() + 100000;
  65. while (!tstc())
  66. if (timer_get_us() > timeout)
  67. return 1;
  68. *c = getc();
  69. return 0;
  70. }
  71. /*
  72. * Receive and parse a reply from the terminal.
  73. *
  74. * @n: array of return values
  75. * @num: number of return values expected
  76. * @end_char: character indicating end of terminal message
  77. * @return: non-zero indicates error
  78. */
  79. static int term_read_reply(int *n, int num, char end_char)
  80. {
  81. s32 c;
  82. int i = 0;
  83. if (term_get_char(&c) || c != cESC)
  84. return -1;
  85. if (term_get_char(&c) || c != '[')
  86. return -1;
  87. n[0] = 0;
  88. while (1) {
  89. if (!term_get_char(&c)) {
  90. if (c == ';') {
  91. i++;
  92. if (i >= num)
  93. return -1;
  94. n[i] = 0;
  95. continue;
  96. } else if (c == end_char) {
  97. break;
  98. } else if (c > '9' || c < '0') {
  99. return -1;
  100. }
  101. /* Read one more decimal position */
  102. n[i] *= 10;
  103. n[i] += c - '0';
  104. } else {
  105. return -1;
  106. }
  107. }
  108. if (i != num - 1)
  109. return -1;
  110. return 0;
  111. }
  112. static efi_status_t EFIAPI efi_cout_output_string(
  113. struct efi_simple_text_output_protocol *this,
  114. const efi_string_t string)
  115. {
  116. struct simple_text_output_mode *con = &efi_con_mode;
  117. struct cout_mode *mode = &efi_cout_modes[con->mode];
  118. char *buf, *pos;
  119. u16 *p;
  120. efi_status_t ret = EFI_SUCCESS;
  121. EFI_ENTRY("%p, %p", this, string);
  122. if (!this || !string) {
  123. ret = EFI_INVALID_PARAMETER;
  124. goto out;
  125. }
  126. buf = malloc(utf16_utf8_strlen(string) + 1);
  127. if (!buf) {
  128. ret = EFI_OUT_OF_RESOURCES;
  129. goto out;
  130. }
  131. pos = buf;
  132. utf16_utf8_strcpy(&pos, string);
  133. fputs(stdout, buf);
  134. free(buf);
  135. /*
  136. * Update the cursor position.
  137. *
  138. * The UEFI spec provides advance rules for U+0000, U+0008, U+000A,
  139. * and U000D. All other control characters are ignored. Any non-control
  140. * character increase the column by one.
  141. */
  142. for (p = string; *p; ++p) {
  143. switch (*p) {
  144. case '\b': /* U+0008, backspace */
  145. if (con->cursor_column)
  146. con->cursor_column--;
  147. break;
  148. case '\n': /* U+000A, newline */
  149. con->cursor_column = 0;
  150. con->cursor_row++;
  151. break;
  152. case '\r': /* U+000D, carriage-return */
  153. con->cursor_column = 0;
  154. break;
  155. case 0xd800 ... 0xdbff:
  156. /*
  157. * Ignore high surrogates, we do not want to count a
  158. * Unicode character twice.
  159. */
  160. break;
  161. default:
  162. /* Exclude control codes */
  163. if (*p > 0x1f)
  164. con->cursor_column++;
  165. break;
  166. }
  167. if (con->cursor_column >= mode->columns) {
  168. con->cursor_column = 0;
  169. con->cursor_row++;
  170. }
  171. /*
  172. * When we exceed the row count the terminal will scroll up one
  173. * line. We have to adjust the cursor position.
  174. */
  175. if (con->cursor_row >= mode->rows && con->cursor_row)
  176. con->cursor_row--;
  177. }
  178. out:
  179. return EFI_EXIT(ret);
  180. }
  181. static efi_status_t EFIAPI efi_cout_test_string(
  182. struct efi_simple_text_output_protocol *this,
  183. const efi_string_t string)
  184. {
  185. EFI_ENTRY("%p, %p", this, string);
  186. return EFI_EXIT(EFI_SUCCESS);
  187. }
  188. static bool cout_mode_matches(struct cout_mode *mode, int rows, int cols)
  189. {
  190. if (!mode->present)
  191. return false;
  192. return (mode->rows == rows) && (mode->columns == cols);
  193. }
  194. /**
  195. * query_console_serial() - query console size
  196. *
  197. * @rows: pointer to return number of rows
  198. * @cols: pointer to return number of columns
  199. * Returns: 0 on success
  200. */
  201. static int query_console_serial(int *rows, int *cols)
  202. {
  203. int ret = 0;
  204. int n[2];
  205. /* Empty input buffer */
  206. while (tstc())
  207. getc();
  208. /*
  209. * Not all terminals understand CSI [18t for querying the console size.
  210. * We should adhere to escape sequences documented in the console_codes
  211. * man page and the ECMA-48 standard.
  212. *
  213. * So here we follow a different approach. We position the cursor to the
  214. * bottom right and query its position. Before leaving the function we
  215. * restore the original cursor position.
  216. */
  217. printf(ESC "7" /* Save cursor position */
  218. ESC "[r" /* Set scrolling region to full window */
  219. ESC "[999;999H" /* Move to bottom right corner */
  220. ESC "[6n"); /* Query cursor position */
  221. /* Read {rows,cols} */
  222. if (term_read_reply(n, 2, 'R')) {
  223. ret = 1;
  224. goto out;
  225. }
  226. *cols = n[1];
  227. *rows = n[0];
  228. out:
  229. printf(ESC "8"); /* Restore cursor position */
  230. return ret;
  231. }
  232. /*
  233. * Update the mode table.
  234. *
  235. * By default the only mode available is 80x25. If the console has at least 50
  236. * lines, enable mode 80x50. If we can query the console size and it is neither
  237. * 80x25 nor 80x50, set it as an additional mode.
  238. */
  239. static void query_console_size(void)
  240. {
  241. const char *stdout_name = env_get("stdout");
  242. int rows = 25, cols = 80;
  243. if (stdout_name && !strcmp(stdout_name, "vidconsole") &&
  244. IS_ENABLED(CONFIG_DM_VIDEO)) {
  245. struct stdio_dev *stdout_dev =
  246. stdio_get_by_name("vidconsole");
  247. struct udevice *dev = stdout_dev->priv;
  248. struct vidconsole_priv *priv =
  249. dev_get_uclass_priv(dev);
  250. rows = priv->rows;
  251. cols = priv->cols;
  252. } else if (query_console_serial(&rows, &cols)) {
  253. return;
  254. }
  255. /* Test if we can have Mode 1 */
  256. if (cols >= 80 && rows >= 50) {
  257. efi_cout_modes[1].present = 1;
  258. efi_con_mode.max_mode = 2;
  259. }
  260. /*
  261. * Install our mode as mode 2 if it is different
  262. * than mode 0 or 1 and set it as the currently selected mode
  263. */
  264. if (!cout_mode_matches(&efi_cout_modes[0], rows, cols) &&
  265. !cout_mode_matches(&efi_cout_modes[1], rows, cols)) {
  266. efi_cout_modes[EFI_COUT_MODE_2].columns = cols;
  267. efi_cout_modes[EFI_COUT_MODE_2].rows = rows;
  268. efi_cout_modes[EFI_COUT_MODE_2].present = 1;
  269. efi_con_mode.max_mode = EFI_MAX_COUT_MODE;
  270. efi_con_mode.mode = EFI_COUT_MODE_2;
  271. }
  272. }
  273. static efi_status_t EFIAPI efi_cout_query_mode(
  274. struct efi_simple_text_output_protocol *this,
  275. unsigned long mode_number, unsigned long *columns,
  276. unsigned long *rows)
  277. {
  278. EFI_ENTRY("%p, %ld, %p, %p", this, mode_number, columns, rows);
  279. if (mode_number >= efi_con_mode.max_mode)
  280. return EFI_EXIT(EFI_UNSUPPORTED);
  281. if (efi_cout_modes[mode_number].present != 1)
  282. return EFI_EXIT(EFI_UNSUPPORTED);
  283. if (columns)
  284. *columns = efi_cout_modes[mode_number].columns;
  285. if (rows)
  286. *rows = efi_cout_modes[mode_number].rows;
  287. return EFI_EXIT(EFI_SUCCESS);
  288. }
  289. static const struct {
  290. unsigned int fg;
  291. unsigned int bg;
  292. } color[] = {
  293. { 30, 40 }, /* 0: black */
  294. { 34, 44 }, /* 1: blue */
  295. { 32, 42 }, /* 2: green */
  296. { 36, 46 }, /* 3: cyan */
  297. { 31, 41 }, /* 4: red */
  298. { 35, 45 }, /* 5: magenta */
  299. { 33, 43 }, /* 6: brown, map to yellow as EDK2 does*/
  300. { 37, 47 }, /* 7: light gray, map to white */
  301. };
  302. /* See EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL.SetAttribute(). */
  303. static efi_status_t EFIAPI efi_cout_set_attribute(
  304. struct efi_simple_text_output_protocol *this,
  305. unsigned long attribute)
  306. {
  307. unsigned int bold = EFI_ATTR_BOLD(attribute);
  308. unsigned int fg = EFI_ATTR_FG(attribute);
  309. unsigned int bg = EFI_ATTR_BG(attribute);
  310. EFI_ENTRY("%p, %lx", this, attribute);
  311. efi_con_mode.attribute = attribute;
  312. if (attribute)
  313. printf(ESC"[%u;%u;%um", bold, color[fg].fg, color[bg].bg);
  314. else
  315. printf(ESC"[0;37;40m");
  316. return EFI_EXIT(EFI_SUCCESS);
  317. }
  318. /**
  319. * efi_cout_clear_screen() - clear screen
  320. *
  321. * This function implements the ClearScreen service of the
  322. * EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. See the Unified Extensible Firmware
  323. * Interface (UEFI) specification for details.
  324. *
  325. * @this: pointer to the protocol instance
  326. * Return: status code
  327. */
  328. static efi_status_t EFIAPI efi_cout_clear_screen(
  329. struct efi_simple_text_output_protocol *this)
  330. {
  331. EFI_ENTRY("%p", this);
  332. /*
  333. * The Linux console wants both a clear and a home command. The video
  334. * uclass does not support <ESC>[H without coordinates, yet.
  335. */
  336. printf(ESC "[2J" ESC "[1;1H");
  337. efi_con_mode.cursor_column = 0;
  338. efi_con_mode.cursor_row = 0;
  339. return EFI_EXIT(EFI_SUCCESS);
  340. }
  341. static efi_status_t EFIAPI efi_cout_set_mode(
  342. struct efi_simple_text_output_protocol *this,
  343. unsigned long mode_number)
  344. {
  345. EFI_ENTRY("%p, %ld", this, mode_number);
  346. if (mode_number >= efi_con_mode.max_mode)
  347. return EFI_EXIT(EFI_UNSUPPORTED);
  348. if (!efi_cout_modes[mode_number].present)
  349. return EFI_EXIT(EFI_UNSUPPORTED);
  350. efi_con_mode.mode = mode_number;
  351. EFI_CALL(efi_cout_clear_screen(this));
  352. return EFI_EXIT(EFI_SUCCESS);
  353. }
  354. static efi_status_t EFIAPI efi_cout_reset(
  355. struct efi_simple_text_output_protocol *this,
  356. char extended_verification)
  357. {
  358. EFI_ENTRY("%p, %d", this, extended_verification);
  359. /* Clear screen */
  360. EFI_CALL(efi_cout_clear_screen(this));
  361. /* Set default colors */
  362. efi_con_mode.attribute = 0x07;
  363. printf(ESC "[0;37;40m");
  364. return EFI_EXIT(EFI_SUCCESS);
  365. }
  366. static efi_status_t EFIAPI efi_cout_set_cursor_position(
  367. struct efi_simple_text_output_protocol *this,
  368. unsigned long column, unsigned long row)
  369. {
  370. efi_status_t ret = EFI_SUCCESS;
  371. struct simple_text_output_mode *con = &efi_con_mode;
  372. struct cout_mode *mode = &efi_cout_modes[con->mode];
  373. EFI_ENTRY("%p, %ld, %ld", this, column, row);
  374. /* Check parameters */
  375. if (!this) {
  376. ret = EFI_INVALID_PARAMETER;
  377. goto out;
  378. }
  379. if (row >= mode->rows || column >= mode->columns) {
  380. ret = EFI_UNSUPPORTED;
  381. goto out;
  382. }
  383. /*
  384. * Set cursor position by sending CSI H.
  385. * EFI origin is [0, 0], terminal origin is [1, 1].
  386. */
  387. printf(ESC "[%d;%dH", (int)row + 1, (int)column + 1);
  388. efi_con_mode.cursor_column = column;
  389. efi_con_mode.cursor_row = row;
  390. out:
  391. return EFI_EXIT(ret);
  392. }
  393. static efi_status_t EFIAPI efi_cout_enable_cursor(
  394. struct efi_simple_text_output_protocol *this,
  395. bool enable)
  396. {
  397. EFI_ENTRY("%p, %d", this, enable);
  398. printf(ESC"[?25%c", enable ? 'h' : 'l');
  399. efi_con_mode.cursor_visible = !!enable;
  400. return EFI_EXIT(EFI_SUCCESS);
  401. }
  402. struct efi_simple_text_output_protocol efi_con_out = {
  403. .reset = efi_cout_reset,
  404. .output_string = efi_cout_output_string,
  405. .test_string = efi_cout_test_string,
  406. .query_mode = efi_cout_query_mode,
  407. .set_mode = efi_cout_set_mode,
  408. .set_attribute = efi_cout_set_attribute,
  409. .clear_screen = efi_cout_clear_screen,
  410. .set_cursor_position = efi_cout_set_cursor_position,
  411. .enable_cursor = efi_cout_enable_cursor,
  412. .mode = (void*)&efi_con_mode,
  413. };
  414. /**
  415. * struct efi_cin_notify_function - registered console input notify function
  416. *
  417. * @link: link to list
  418. * @key: key to notify
  419. * @function: function to call
  420. */
  421. struct efi_cin_notify_function {
  422. struct list_head link;
  423. struct efi_key_data key;
  424. efi_status_t (EFIAPI *function)
  425. (struct efi_key_data *key_data);
  426. };
  427. static bool key_available;
  428. static struct efi_key_data next_key;
  429. static LIST_HEAD(cin_notify_functions);
  430. /**
  431. * set_shift_mask() - set shift mask
  432. *
  433. * @mod: Xterm shift mask
  434. * @key_state: receives the state of the shift, alt, control, and logo keys
  435. */
  436. void set_shift_mask(int mod, struct efi_key_state *key_state)
  437. {
  438. key_state->key_shift_state = EFI_SHIFT_STATE_VALID;
  439. if (mod) {
  440. --mod;
  441. if (mod & 1)
  442. key_state->key_shift_state |= EFI_LEFT_SHIFT_PRESSED;
  443. if (mod & 2)
  444. key_state->key_shift_state |= EFI_LEFT_ALT_PRESSED;
  445. if (mod & 4)
  446. key_state->key_shift_state |= EFI_LEFT_CONTROL_PRESSED;
  447. if (!mod || (mod & 8))
  448. key_state->key_shift_state |= EFI_LEFT_LOGO_PRESSED;
  449. }
  450. }
  451. /**
  452. * analyze_modifiers() - analyze modifiers (shift, alt, ctrl) for function keys
  453. *
  454. * This gets called when we have already parsed CSI.
  455. *
  456. * @key_state: receives the state of the shift, alt, control, and logo keys
  457. * @return: the unmodified code
  458. */
  459. static int analyze_modifiers(struct efi_key_state *key_state)
  460. {
  461. int c, mod = 0, ret = 0;
  462. c = getc();
  463. if (c != ';') {
  464. ret = c;
  465. if (c == '~')
  466. goto out;
  467. c = getc();
  468. }
  469. for (;;) {
  470. switch (c) {
  471. case '0'...'9':
  472. mod *= 10;
  473. mod += c - '0';
  474. /* fall through */
  475. case ';':
  476. c = getc();
  477. break;
  478. default:
  479. goto out;
  480. }
  481. }
  482. out:
  483. set_shift_mask(mod, key_state);
  484. if (!ret)
  485. ret = c;
  486. return ret;
  487. }
  488. /**
  489. * efi_cin_read_key() - read a key from the console input
  490. *
  491. * @key: - key received
  492. * Return: - status code
  493. */
  494. static efi_status_t efi_cin_read_key(struct efi_key_data *key)
  495. {
  496. struct efi_input_key pressed_key = {
  497. .scan_code = 0,
  498. .unicode_char = 0,
  499. };
  500. s32 ch;
  501. if (console_read_unicode(&ch))
  502. return EFI_NOT_READY;
  503. key->key_state.key_shift_state = EFI_SHIFT_STATE_INVALID;
  504. key->key_state.key_toggle_state = EFI_TOGGLE_STATE_INVALID;
  505. /* We do not support multi-word codes */
  506. if (ch >= 0x10000)
  507. ch = '?';
  508. switch (ch) {
  509. case 0x1b:
  510. /*
  511. * Xterm Control Sequences
  512. * https://www.xfree86.org/4.8.0/ctlseqs.html
  513. */
  514. ch = getc();
  515. switch (ch) {
  516. case cESC: /* ESC */
  517. pressed_key.scan_code = 23;
  518. break;
  519. case 'O': /* F1 - F4, End */
  520. ch = getc();
  521. /* consider modifiers */
  522. if (ch == 'F') { /* End */
  523. pressed_key.scan_code = 6;
  524. break;
  525. } else if (ch < 'P') {
  526. set_shift_mask(ch - '0', &key->key_state);
  527. ch = getc();
  528. }
  529. pressed_key.scan_code = ch - 'P' + 11;
  530. break;
  531. case '[':
  532. ch = getc();
  533. switch (ch) {
  534. case 'A'...'D': /* up, down right, left */
  535. pressed_key.scan_code = ch - 'A' + 1;
  536. break;
  537. case 'F': /* End */
  538. pressed_key.scan_code = 6;
  539. break;
  540. case 'H': /* Home */
  541. pressed_key.scan_code = 5;
  542. break;
  543. case '1':
  544. ch = analyze_modifiers(&key->key_state);
  545. switch (ch) {
  546. case '1'...'5': /* F1 - F5 */
  547. pressed_key.scan_code = ch - '1' + 11;
  548. break;
  549. case '6'...'9': /* F5 - F8 */
  550. pressed_key.scan_code = ch - '6' + 15;
  551. break;
  552. case 'A'...'D': /* up, down right, left */
  553. pressed_key.scan_code = ch - 'A' + 1;
  554. break;
  555. case 'F': /* End */
  556. pressed_key.scan_code = 6;
  557. break;
  558. case 'H': /* Home */
  559. pressed_key.scan_code = 5;
  560. break;
  561. case '~': /* Home */
  562. pressed_key.scan_code = 5;
  563. break;
  564. }
  565. break;
  566. case '2':
  567. ch = analyze_modifiers(&key->key_state);
  568. switch (ch) {
  569. case '0'...'1': /* F9 - F10 */
  570. pressed_key.scan_code = ch - '0' + 19;
  571. break;
  572. case '3'...'4': /* F11 - F12 */
  573. pressed_key.scan_code = ch - '3' + 21;
  574. break;
  575. case '~': /* INS */
  576. pressed_key.scan_code = 7;
  577. break;
  578. }
  579. break;
  580. case '3': /* DEL */
  581. pressed_key.scan_code = 8;
  582. analyze_modifiers(&key->key_state);
  583. break;
  584. case '5': /* PG UP */
  585. pressed_key.scan_code = 9;
  586. analyze_modifiers(&key->key_state);
  587. break;
  588. case '6': /* PG DOWN */
  589. pressed_key.scan_code = 10;
  590. analyze_modifiers(&key->key_state);
  591. break;
  592. } /* [ */
  593. break;
  594. default:
  595. /* ALT key */
  596. set_shift_mask(3, &key->key_state);
  597. }
  598. break;
  599. case 0x7f:
  600. /* Backspace */
  601. ch = 0x08;
  602. }
  603. if (pressed_key.scan_code) {
  604. key->key_state.key_shift_state |= EFI_SHIFT_STATE_VALID;
  605. } else {
  606. pressed_key.unicode_char = ch;
  607. /*
  608. * Assume left control key for control characters typically
  609. * entered using the control key.
  610. */
  611. if (ch >= 0x01 && ch <= 0x1f) {
  612. key->key_state.key_shift_state |=
  613. EFI_SHIFT_STATE_VALID;
  614. switch (ch) {
  615. case 0x01 ... 0x07:
  616. case 0x0b ... 0x0c:
  617. case 0x0e ... 0x1f:
  618. key->key_state.key_shift_state |=
  619. EFI_LEFT_CONTROL_PRESSED;
  620. }
  621. }
  622. }
  623. key->key = pressed_key;
  624. return EFI_SUCCESS;
  625. }
  626. /**
  627. * efi_cin_notify() - notify registered functions
  628. */
  629. static void efi_cin_notify(void)
  630. {
  631. struct efi_cin_notify_function *item;
  632. list_for_each_entry(item, &cin_notify_functions, link) {
  633. bool match = true;
  634. /* We do not support toggle states */
  635. if (item->key.key.unicode_char || item->key.key.scan_code) {
  636. if (item->key.key.unicode_char !=
  637. next_key.key.unicode_char ||
  638. item->key.key.scan_code != next_key.key.scan_code)
  639. match = false;
  640. }
  641. if (item->key.key_state.key_shift_state &&
  642. item->key.key_state.key_shift_state !=
  643. next_key.key_state.key_shift_state)
  644. match = false;
  645. if (match)
  646. /* We don't bother about the return code */
  647. EFI_CALL(item->function(&next_key));
  648. }
  649. }
  650. /**
  651. * efi_cin_check() - check if keyboard input is available
  652. */
  653. static void efi_cin_check(void)
  654. {
  655. efi_status_t ret;
  656. if (key_available) {
  657. efi_signal_event(efi_con_in.wait_for_key);
  658. return;
  659. }
  660. if (tstc()) {
  661. ret = efi_cin_read_key(&next_key);
  662. if (ret == EFI_SUCCESS) {
  663. key_available = true;
  664. /* Notify registered functions */
  665. efi_cin_notify();
  666. /* Queue the wait for key event */
  667. if (key_available)
  668. efi_signal_event(efi_con_in.wait_for_key);
  669. }
  670. }
  671. }
  672. /**
  673. * efi_cin_empty_buffer() - empty input buffer
  674. */
  675. static void efi_cin_empty_buffer(void)
  676. {
  677. while (tstc())
  678. getc();
  679. key_available = false;
  680. }
  681. /**
  682. * efi_cin_reset_ex() - reset console input
  683. *
  684. * @this: - the extended simple text input protocol
  685. * @extended_verification: - extended verification
  686. *
  687. * This function implements the reset service of the
  688. * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  689. *
  690. * See the Unified Extensible Firmware Interface (UEFI) specification for
  691. * details.
  692. *
  693. * Return: old value of the task priority level
  694. */
  695. static efi_status_t EFIAPI efi_cin_reset_ex(
  696. struct efi_simple_text_input_ex_protocol *this,
  697. bool extended_verification)
  698. {
  699. efi_status_t ret = EFI_SUCCESS;
  700. EFI_ENTRY("%p, %d", this, extended_verification);
  701. /* Check parameters */
  702. if (!this) {
  703. ret = EFI_INVALID_PARAMETER;
  704. goto out;
  705. }
  706. efi_cin_empty_buffer();
  707. out:
  708. return EFI_EXIT(ret);
  709. }
  710. /**
  711. * efi_cin_read_key_stroke_ex() - read key stroke
  712. *
  713. * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
  714. * @key_data: key read from console
  715. * Return: status code
  716. *
  717. * This function implements the ReadKeyStrokeEx service of the
  718. * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  719. *
  720. * See the Unified Extensible Firmware Interface (UEFI) specification for
  721. * details.
  722. */
  723. static efi_status_t EFIAPI efi_cin_read_key_stroke_ex(
  724. struct efi_simple_text_input_ex_protocol *this,
  725. struct efi_key_data *key_data)
  726. {
  727. efi_status_t ret = EFI_SUCCESS;
  728. EFI_ENTRY("%p, %p", this, key_data);
  729. /* Check parameters */
  730. if (!this || !key_data) {
  731. ret = EFI_INVALID_PARAMETER;
  732. goto out;
  733. }
  734. /* We don't do interrupts, so check for timers cooperatively */
  735. efi_timer_check();
  736. /* Enable console input after ExitBootServices */
  737. efi_cin_check();
  738. if (!key_available) {
  739. ret = EFI_NOT_READY;
  740. goto out;
  741. }
  742. /*
  743. * CTRL+A - CTRL+Z have to be signaled as a - z.
  744. * SHIFT+CTRL+A - SHIFT+CTRL+Z have to be signaled as A - Z.
  745. */
  746. switch (next_key.key.unicode_char) {
  747. case 0x01 ... 0x07:
  748. case 0x0b ... 0x0c:
  749. case 0x0e ... 0x1a:
  750. if (!(next_key.key_state.key_toggle_state &
  751. EFI_CAPS_LOCK_ACTIVE) ^
  752. !(next_key.key_state.key_shift_state &
  753. (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED)))
  754. next_key.key.unicode_char += 0x40;
  755. else
  756. next_key.key.unicode_char += 0x60;
  757. }
  758. *key_data = next_key;
  759. key_available = false;
  760. efi_con_in.wait_for_key->is_signaled = false;
  761. out:
  762. return EFI_EXIT(ret);
  763. }
  764. /**
  765. * efi_cin_set_state() - set toggle key state
  766. *
  767. * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
  768. * @key_toggle_state: pointer to key toggle state
  769. * Return: status code
  770. *
  771. * This function implements the SetState service of the
  772. * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  773. *
  774. * See the Unified Extensible Firmware Interface (UEFI) specification for
  775. * details.
  776. */
  777. static efi_status_t EFIAPI efi_cin_set_state(
  778. struct efi_simple_text_input_ex_protocol *this,
  779. u8 *key_toggle_state)
  780. {
  781. EFI_ENTRY("%p, %p", this, key_toggle_state);
  782. /*
  783. * U-Boot supports multiple console input sources like serial and
  784. * net console for which a key toggle state cannot be set at all.
  785. *
  786. * According to the UEFI specification it is allowable to not implement
  787. * this service.
  788. */
  789. return EFI_EXIT(EFI_UNSUPPORTED);
  790. }
  791. /**
  792. * efi_cin_register_key_notify() - register key notification function
  793. *
  794. * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
  795. * @key_data: key to be notified
  796. * @key_notify_function: function to be called if the key is pressed
  797. * @notify_handle: handle for unregistering the notification
  798. * Return: status code
  799. *
  800. * This function implements the SetState service of the
  801. * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  802. *
  803. * See the Unified Extensible Firmware Interface (UEFI) specification for
  804. * details.
  805. */
  806. static efi_status_t EFIAPI efi_cin_register_key_notify(
  807. struct efi_simple_text_input_ex_protocol *this,
  808. struct efi_key_data *key_data,
  809. efi_status_t (EFIAPI *key_notify_function)(
  810. struct efi_key_data *key_data),
  811. void **notify_handle)
  812. {
  813. efi_status_t ret = EFI_SUCCESS;
  814. struct efi_cin_notify_function *notify_function;
  815. EFI_ENTRY("%p, %p, %p, %p",
  816. this, key_data, key_notify_function, notify_handle);
  817. /* Check parameters */
  818. if (!this || !key_data || !key_notify_function || !notify_handle) {
  819. ret = EFI_INVALID_PARAMETER;
  820. goto out;
  821. }
  822. EFI_PRINT("u+%04x, sc %04x, sh %08x, tg %02x\n",
  823. key_data->key.unicode_char,
  824. key_data->key.scan_code,
  825. key_data->key_state.key_shift_state,
  826. key_data->key_state.key_toggle_state);
  827. notify_function = calloc(1, sizeof(struct efi_cin_notify_function));
  828. if (!notify_function) {
  829. ret = EFI_OUT_OF_RESOURCES;
  830. goto out;
  831. }
  832. notify_function->key = *key_data;
  833. notify_function->function = key_notify_function;
  834. list_add_tail(&notify_function->link, &cin_notify_functions);
  835. *notify_handle = notify_function;
  836. out:
  837. return EFI_EXIT(ret);
  838. }
  839. /**
  840. * efi_cin_unregister_key_notify() - unregister key notification function
  841. *
  842. * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
  843. * @notification_handle: handle received when registering
  844. * Return: status code
  845. *
  846. * This function implements the SetState service of the
  847. * EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  848. *
  849. * See the Unified Extensible Firmware Interface (UEFI) specification for
  850. * details.
  851. */
  852. static efi_status_t EFIAPI efi_cin_unregister_key_notify(
  853. struct efi_simple_text_input_ex_protocol *this,
  854. void *notification_handle)
  855. {
  856. efi_status_t ret = EFI_INVALID_PARAMETER;
  857. struct efi_cin_notify_function *item, *notify_function =
  858. notification_handle;
  859. EFI_ENTRY("%p, %p", this, notification_handle);
  860. /* Check parameters */
  861. if (!this || !notification_handle)
  862. goto out;
  863. list_for_each_entry(item, &cin_notify_functions, link) {
  864. if (item == notify_function) {
  865. ret = EFI_SUCCESS;
  866. break;
  867. }
  868. }
  869. if (ret != EFI_SUCCESS)
  870. goto out;
  871. /* Remove the notify function */
  872. list_del(&notify_function->link);
  873. free(notify_function);
  874. out:
  875. return EFI_EXIT(ret);
  876. }
  877. /**
  878. * efi_cin_reset() - drain the input buffer
  879. *
  880. * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
  881. * @extended_verification: allow for exhaustive verification
  882. * Return: status code
  883. *
  884. * This function implements the Reset service of the
  885. * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
  886. *
  887. * See the Unified Extensible Firmware Interface (UEFI) specification for
  888. * details.
  889. */
  890. static efi_status_t EFIAPI efi_cin_reset
  891. (struct efi_simple_text_input_protocol *this,
  892. bool extended_verification)
  893. {
  894. efi_status_t ret = EFI_SUCCESS;
  895. EFI_ENTRY("%p, %d", this, extended_verification);
  896. /* Check parameters */
  897. if (!this) {
  898. ret = EFI_INVALID_PARAMETER;
  899. goto out;
  900. }
  901. efi_cin_empty_buffer();
  902. out:
  903. return EFI_EXIT(ret);
  904. }
  905. /**
  906. * efi_cin_read_key_stroke() - read key stroke
  907. *
  908. * @this: instance of the EFI_SIMPLE_TEXT_INPUT_PROTOCOL
  909. * @key: key read from console
  910. * Return: status code
  911. *
  912. * This function implements the ReadKeyStroke service of the
  913. * EFI_SIMPLE_TEXT_INPUT_PROTOCOL.
  914. *
  915. * See the Unified Extensible Firmware Interface (UEFI) specification for
  916. * details.
  917. */
  918. static efi_status_t EFIAPI efi_cin_read_key_stroke
  919. (struct efi_simple_text_input_protocol *this,
  920. struct efi_input_key *key)
  921. {
  922. efi_status_t ret = EFI_SUCCESS;
  923. EFI_ENTRY("%p, %p", this, key);
  924. /* Check parameters */
  925. if (!this || !key) {
  926. ret = EFI_INVALID_PARAMETER;
  927. goto out;
  928. }
  929. /* We don't do interrupts, so check for timers cooperatively */
  930. efi_timer_check();
  931. /* Enable console input after ExitBootServices */
  932. efi_cin_check();
  933. if (!key_available) {
  934. ret = EFI_NOT_READY;
  935. goto out;
  936. }
  937. *key = next_key.key;
  938. key_available = false;
  939. efi_con_in.wait_for_key->is_signaled = false;
  940. out:
  941. return EFI_EXIT(ret);
  942. }
  943. static struct efi_simple_text_input_ex_protocol efi_con_in_ex = {
  944. .reset = efi_cin_reset_ex,
  945. .read_key_stroke_ex = efi_cin_read_key_stroke_ex,
  946. .wait_for_key_ex = NULL,
  947. .set_state = efi_cin_set_state,
  948. .register_key_notify = efi_cin_register_key_notify,
  949. .unregister_key_notify = efi_cin_unregister_key_notify,
  950. };
  951. struct efi_simple_text_input_protocol efi_con_in = {
  952. .reset = efi_cin_reset,
  953. .read_key_stroke = efi_cin_read_key_stroke,
  954. .wait_for_key = NULL,
  955. };
  956. static struct efi_event *console_timer_event;
  957. /*
  958. * efi_console_timer_notify() - notify the console timer event
  959. *
  960. * @event: console timer event
  961. * @context: not used
  962. */
  963. static void EFIAPI efi_console_timer_notify(struct efi_event *event,
  964. void *context)
  965. {
  966. EFI_ENTRY("%p, %p", event, context);
  967. efi_cin_check();
  968. EFI_EXIT(EFI_SUCCESS);
  969. }
  970. /**
  971. * efi_key_notify() - notify the wait for key event
  972. *
  973. * @event: wait for key event
  974. * @context: not used
  975. */
  976. static void EFIAPI efi_key_notify(struct efi_event *event, void *context)
  977. {
  978. EFI_ENTRY("%p, %p", event, context);
  979. efi_cin_check();
  980. EFI_EXIT(EFI_SUCCESS);
  981. }
  982. /**
  983. * efi_console_register() - install the console protocols
  984. *
  985. * This function is called from do_bootefi_exec().
  986. *
  987. * Return: status code
  988. */
  989. efi_status_t efi_console_register(void)
  990. {
  991. efi_status_t r;
  992. efi_handle_t console_output_handle;
  993. efi_handle_t console_input_handle;
  994. /* Set up mode information */
  995. query_console_size();
  996. /* Create handles */
  997. r = efi_create_handle(&console_output_handle);
  998. if (r != EFI_SUCCESS)
  999. goto out_of_memory;
  1000. r = efi_add_protocol(console_output_handle,
  1001. &efi_guid_text_output_protocol, &efi_con_out);
  1002. if (r != EFI_SUCCESS)
  1003. goto out_of_memory;
  1004. systab.con_out_handle = console_output_handle;
  1005. systab.stderr_handle = console_output_handle;
  1006. r = efi_create_handle(&console_input_handle);
  1007. if (r != EFI_SUCCESS)
  1008. goto out_of_memory;
  1009. r = efi_add_protocol(console_input_handle,
  1010. &efi_guid_text_input_protocol, &efi_con_in);
  1011. if (r != EFI_SUCCESS)
  1012. goto out_of_memory;
  1013. systab.con_in_handle = console_input_handle;
  1014. r = efi_add_protocol(console_input_handle,
  1015. &efi_guid_text_input_ex_protocol, &efi_con_in_ex);
  1016. if (r != EFI_SUCCESS)
  1017. goto out_of_memory;
  1018. /* Create console events */
  1019. r = efi_create_event(EVT_NOTIFY_WAIT, TPL_CALLBACK, efi_key_notify,
  1020. NULL, NULL, &efi_con_in.wait_for_key);
  1021. if (r != EFI_SUCCESS) {
  1022. printf("ERROR: Failed to register WaitForKey event\n");
  1023. return r;
  1024. }
  1025. efi_con_in_ex.wait_for_key_ex = efi_con_in.wait_for_key;
  1026. r = efi_create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK,
  1027. efi_console_timer_notify, NULL, NULL,
  1028. &console_timer_event);
  1029. if (r != EFI_SUCCESS) {
  1030. printf("ERROR: Failed to register console event\n");
  1031. return r;
  1032. }
  1033. /* 5000 ns cycle is sufficient for 2 MBaud */
  1034. r = efi_set_timer(console_timer_event, EFI_TIMER_PERIODIC, 50);
  1035. if (r != EFI_SUCCESS)
  1036. printf("ERROR: Failed to set console timer\n");
  1037. return r;
  1038. out_of_memory:
  1039. printf("ERROR: Out of memory\n");
  1040. return r;
  1041. }