efi_selftest_textinputex.c 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139
  1. // SPDX-License-Identifier: GPL-2.0+
  2. /*
  3. * efi_selftest_textinput
  4. *
  5. * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
  6. *
  7. * Provides a unit test for the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
  8. * The unicode character and the scan code are printed for text
  9. * input. To run the test:
  10. *
  11. * setenv efi_selftest extended text input
  12. * bootefi selftest
  13. */
  14. #include <efi_selftest.h>
  15. static const efi_guid_t text_input_ex_protocol_guid =
  16. EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
  17. static struct efi_simple_text_input_ex_protocol *con_in_ex;
  18. static struct efi_boot_services *boottime;
  19. /*
  20. * Setup unit test.
  21. *
  22. * @handle: handle of the loaded image
  23. * @systable: system table
  24. * @return: EFI_ST_SUCCESS for success
  25. */
  26. static int setup(const efi_handle_t handle,
  27. const struct efi_system_table *systable)
  28. {
  29. efi_status_t ret;
  30. boottime = systable->boottime;
  31. ret = boottime->locate_protocol(&text_input_ex_protocol_guid, NULL,
  32. (void **)&con_in_ex);
  33. if (ret != EFI_SUCCESS) {
  34. con_in_ex = NULL;
  35. efi_st_error
  36. ("Extended text input protocol is not available.\n");
  37. return EFI_ST_FAILURE;
  38. }
  39. return EFI_ST_SUCCESS;
  40. }
  41. /*
  42. * Execute unit test.
  43. *
  44. * @return: EFI_ST_SUCCESS for success
  45. */
  46. static int execute(void)
  47. {
  48. struct efi_key_data input_key = {0,};
  49. efi_status_t ret;
  50. efi_uintn_t index;
  51. if (!con_in_ex) {
  52. efi_st_printf("Setup failed\n");
  53. return EFI_ST_FAILURE;
  54. }
  55. /* Drain the console input */
  56. ret = con_in_ex->reset(con_in_ex, true);
  57. if (ret != EFI_SUCCESS) {
  58. efi_st_error("Reset failed\n");
  59. return EFI_ST_FAILURE;
  60. }
  61. ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
  62. if (ret != EFI_NOT_READY) {
  63. efi_st_error("Empty buffer not reported\n");
  64. return EFI_ST_FAILURE;
  65. }
  66. efi_st_printf("Waiting for your input\n");
  67. efi_st_printf("To terminate type 'x'\n");
  68. for (;;) {
  69. /* Wait for next key */
  70. ret = boottime->wait_for_event(1, &con_in_ex->wait_for_key_ex,
  71. &index);
  72. if (ret != EFI_ST_SUCCESS) {
  73. efi_st_error("WaitForEvent failed\n");
  74. return EFI_ST_FAILURE;
  75. }
  76. ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
  77. if (ret != EFI_SUCCESS) {
  78. efi_st_error("ReadKeyStroke failed\n");
  79. return EFI_ST_FAILURE;
  80. }
  81. /* Allow 5 minutes until time out */
  82. boottime->set_watchdog_timer(300, 0, 0, NULL);
  83. efi_st_printf("Unicode char %u (%ps), scan code %u (",
  84. (unsigned int)input_key.key.unicode_char,
  85. efi_st_translate_char(input_key.key.unicode_char),
  86. (unsigned int)input_key.key.scan_code);
  87. if (input_key.key_state.key_shift_state &
  88. EFI_SHIFT_STATE_VALID) {
  89. if (input_key.key_state.key_shift_state &
  90. (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED))
  91. efi_st_printf("SHIFT+");
  92. if (input_key.key_state.key_shift_state &
  93. (EFI_LEFT_ALT_PRESSED | EFI_RIGHT_ALT_PRESSED))
  94. efi_st_printf("ALT+");
  95. if (input_key.key_state.key_shift_state &
  96. (EFI_LEFT_CONTROL_PRESSED |
  97. EFI_RIGHT_CONTROL_PRESSED))
  98. efi_st_printf("CTRL+");
  99. if (input_key.key_state.key_shift_state &
  100. (EFI_LEFT_LOGO_PRESSED | EFI_RIGHT_LOGO_PRESSED))
  101. efi_st_printf("META+");
  102. if (input_key.key_state.key_shift_state ==
  103. EFI_SHIFT_STATE_VALID)
  104. efi_st_printf("+");
  105. }
  106. efi_st_printf("%ps)\n",
  107. efi_st_translate_code(input_key.key.scan_code));
  108. switch (input_key.key.unicode_char) {
  109. case 'x':
  110. case 'X':
  111. return EFI_ST_SUCCESS;
  112. }
  113. }
  114. }
  115. EFI_UNIT_TEST(textinputex) = {
  116. .name = "extended text input",
  117. .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
  118. .setup = setup,
  119. .execute = execute,
  120. .on_request = true,
  121. };