xref: /openbmc/u-boot/lib/efi_selftest/efi_selftest_textinputex.c (revision 0ae8dcfef7c890330c62bb34c724126ffc169bef)
13394f200SHeinrich Schuchardt // SPDX-License-Identifier: GPL-2.0+
23394f200SHeinrich Schuchardt /*
33394f200SHeinrich Schuchardt  * efi_selftest_textinput
43394f200SHeinrich Schuchardt  *
53394f200SHeinrich Schuchardt  * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de>
63394f200SHeinrich Schuchardt  *
73394f200SHeinrich Schuchardt  * Provides a unit test for the EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL.
83394f200SHeinrich Schuchardt  * The unicode character and the scan code are printed for text
93394f200SHeinrich Schuchardt  * input. To run the test:
103394f200SHeinrich Schuchardt  *
113394f200SHeinrich Schuchardt  *	setenv efi_selftest extended text input
123394f200SHeinrich Schuchardt  *	bootefi selftest
133394f200SHeinrich Schuchardt  */
143394f200SHeinrich Schuchardt 
153394f200SHeinrich Schuchardt #include <efi_selftest.h>
163394f200SHeinrich Schuchardt 
173394f200SHeinrich Schuchardt static const efi_guid_t text_input_ex_protocol_guid =
183394f200SHeinrich Schuchardt 		EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL_GUID;
193394f200SHeinrich Schuchardt 
203394f200SHeinrich Schuchardt static struct efi_simple_text_input_ex_protocol *con_in_ex;
213394f200SHeinrich Schuchardt 
223394f200SHeinrich Schuchardt static struct efi_boot_services *boottime;
233394f200SHeinrich Schuchardt 
246dec8739SHeinrich Schuchardt static void *efi_key_notify_handle;
256dec8739SHeinrich Schuchardt static bool efi_running;
266dec8739SHeinrich Schuchardt 
276dec8739SHeinrich Schuchardt /**
286dec8739SHeinrich Schuchardt  * efi_key_notify_function() - key notification function
296dec8739SHeinrich Schuchardt  *
306dec8739SHeinrich Schuchardt  * This function is called when the registered key is hit.
316dec8739SHeinrich Schuchardt  *
326dec8739SHeinrich Schuchardt  * @key_data:		next key
336dec8739SHeinrich Schuchardt  * Return:		status code
346dec8739SHeinrich Schuchardt  */
efi_key_notify_function(struct efi_key_data * key_data)356dec8739SHeinrich Schuchardt static efi_status_t EFIAPI efi_key_notify_function
366dec8739SHeinrich Schuchardt 				(struct efi_key_data *key_data)
376dec8739SHeinrich Schuchardt {
386dec8739SHeinrich Schuchardt 	efi_running = false;
396dec8739SHeinrich Schuchardt 
406dec8739SHeinrich Schuchardt 	return EFI_SUCCESS;
416dec8739SHeinrich Schuchardt }
426dec8739SHeinrich Schuchardt 
433394f200SHeinrich Schuchardt /*
443394f200SHeinrich Schuchardt  * Setup unit test.
453394f200SHeinrich Schuchardt  *
463394f200SHeinrich Schuchardt  * @handle:	handle of the loaded image
473394f200SHeinrich Schuchardt  * @systable:	system table
483394f200SHeinrich Schuchardt  * @return:	EFI_ST_SUCCESS for success
493394f200SHeinrich Schuchardt  */
setup(const efi_handle_t handle,const struct efi_system_table * systable)503394f200SHeinrich Schuchardt static int setup(const efi_handle_t handle,
513394f200SHeinrich Schuchardt 		 const struct efi_system_table *systable)
523394f200SHeinrich Schuchardt {
533394f200SHeinrich Schuchardt 	efi_status_t ret;
546dec8739SHeinrich Schuchardt 	struct efi_key_data key_data = {
556dec8739SHeinrich Schuchardt 		.key = {
566dec8739SHeinrich Schuchardt 			.scan_code = 0,
576dec8739SHeinrich Schuchardt 			.unicode_char = 0x18
586dec8739SHeinrich Schuchardt 		},
596dec8739SHeinrich Schuchardt 		.key_state = {
606dec8739SHeinrich Schuchardt 			.key_shift_state = EFI_SHIFT_STATE_VALID |
616dec8739SHeinrich Schuchardt 					   EFI_LEFT_CONTROL_PRESSED,
626dec8739SHeinrich Schuchardt 			.key_toggle_state = EFI_TOGGLE_STATE_INVALID,
636dec8739SHeinrich Schuchardt 		},
646dec8739SHeinrich Schuchardt 	};
653394f200SHeinrich Schuchardt 
663394f200SHeinrich Schuchardt 	boottime = systable->boottime;
673394f200SHeinrich Schuchardt 
683394f200SHeinrich Schuchardt 	ret = boottime->locate_protocol(&text_input_ex_protocol_guid, NULL,
693394f200SHeinrich Schuchardt 					(void **)&con_in_ex);
703394f200SHeinrich Schuchardt 	if (ret != EFI_SUCCESS) {
713394f200SHeinrich Schuchardt 		con_in_ex = NULL;
723394f200SHeinrich Schuchardt 		efi_st_error
733394f200SHeinrich Schuchardt 			("Extended text input protocol is not available.\n");
743394f200SHeinrich Schuchardt 		return EFI_ST_FAILURE;
753394f200SHeinrich Schuchardt 	}
763394f200SHeinrich Schuchardt 
776dec8739SHeinrich Schuchardt 	ret = con_in_ex->register_key_notify(con_in_ex, &key_data,
786dec8739SHeinrich Schuchardt 					     efi_key_notify_function,
796dec8739SHeinrich Schuchardt 					     &efi_key_notify_handle);
806dec8739SHeinrich Schuchardt 	if (ret != EFI_SUCCESS) {
816dec8739SHeinrich Schuchardt 		efi_key_notify_handle = NULL;
826dec8739SHeinrich Schuchardt 		efi_st_error
836dec8739SHeinrich Schuchardt 			("Notify function could not be registered.\n");
846dec8739SHeinrich Schuchardt 		return EFI_ST_FAILURE;
856dec8739SHeinrich Schuchardt 	}
866dec8739SHeinrich Schuchardt 	efi_running = true;
876dec8739SHeinrich Schuchardt 
883394f200SHeinrich Schuchardt 	return EFI_ST_SUCCESS;
893394f200SHeinrich Schuchardt }
903394f200SHeinrich Schuchardt 
913394f200SHeinrich Schuchardt /*
926dec8739SHeinrich Schuchardt  * Tear down unit test.
936dec8739SHeinrich Schuchardt  *
946dec8739SHeinrich Schuchardt  * Unregister notify function.
956dec8739SHeinrich Schuchardt  *
966dec8739SHeinrich Schuchardt  * @return:	EFI_ST_SUCCESS for success
976dec8739SHeinrich Schuchardt  */
teardown(void)986dec8739SHeinrich Schuchardt static int teardown(void)
996dec8739SHeinrich Schuchardt {
1006dec8739SHeinrich Schuchardt 	efi_status_t ret;
1016dec8739SHeinrich Schuchardt 
1026dec8739SHeinrich Schuchardt 	ret = con_in_ex->unregister_key_notify
1036dec8739SHeinrich Schuchardt 			(con_in_ex, efi_key_notify_handle);
1046dec8739SHeinrich Schuchardt 	if (ret != EFI_SUCCESS) {
1056dec8739SHeinrich Schuchardt 		efi_st_error
1066dec8739SHeinrich Schuchardt 			("Notify function could not be registered.\n");
1076dec8739SHeinrich Schuchardt 		return EFI_ST_FAILURE;
1086dec8739SHeinrich Schuchardt 	}
1096dec8739SHeinrich Schuchardt 
1106dec8739SHeinrich Schuchardt 	return EFI_ST_SUCCESS;
1116dec8739SHeinrich Schuchardt }
1126dec8739SHeinrich Schuchardt /*
1133394f200SHeinrich Schuchardt  * Execute unit test.
1143394f200SHeinrich Schuchardt  *
1153394f200SHeinrich Schuchardt  * @return:	EFI_ST_SUCCESS for success
1163394f200SHeinrich Schuchardt  */
execute(void)1173394f200SHeinrich Schuchardt static int execute(void)
1183394f200SHeinrich Schuchardt {
119*e1020386SHeinrich Schuchardt 	struct efi_key_data input_key = { {0, 0}, {0, 0} };
1203394f200SHeinrich Schuchardt 	efi_status_t ret;
1213394f200SHeinrich Schuchardt 	efi_uintn_t index;
1223394f200SHeinrich Schuchardt 
1233394f200SHeinrich Schuchardt 	if (!con_in_ex) {
1243394f200SHeinrich Schuchardt 		efi_st_printf("Setup failed\n");
1253394f200SHeinrich Schuchardt 		return EFI_ST_FAILURE;
1263394f200SHeinrich Schuchardt 	}
1273394f200SHeinrich Schuchardt 
1283394f200SHeinrich Schuchardt 	/* Drain the console input */
1293394f200SHeinrich Schuchardt 	ret = con_in_ex->reset(con_in_ex, true);
1303394f200SHeinrich Schuchardt 	if (ret != EFI_SUCCESS) {
1313394f200SHeinrich Schuchardt 		efi_st_error("Reset failed\n");
1323394f200SHeinrich Schuchardt 		return EFI_ST_FAILURE;
1333394f200SHeinrich Schuchardt 	}
1343394f200SHeinrich Schuchardt 	ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
1353394f200SHeinrich Schuchardt 	if (ret != EFI_NOT_READY) {
1363394f200SHeinrich Schuchardt 		efi_st_error("Empty buffer not reported\n");
1373394f200SHeinrich Schuchardt 		return EFI_ST_FAILURE;
1383394f200SHeinrich Schuchardt 	}
1393394f200SHeinrich Schuchardt 
1403394f200SHeinrich Schuchardt 	efi_st_printf("Waiting for your input\n");
1416dec8739SHeinrich Schuchardt 	efi_st_printf("To terminate type 'CTRL+x'\n");
1423394f200SHeinrich Schuchardt 
1436dec8739SHeinrich Schuchardt 	while (efi_running) {
1443394f200SHeinrich Schuchardt 		/* Wait for next key */
1453394f200SHeinrich Schuchardt 		ret = boottime->wait_for_event(1, &con_in_ex->wait_for_key_ex,
1463394f200SHeinrich Schuchardt 					       &index);
1473394f200SHeinrich Schuchardt 		if (ret != EFI_ST_SUCCESS) {
1483394f200SHeinrich Schuchardt 			efi_st_error("WaitForEvent failed\n");
1493394f200SHeinrich Schuchardt 			return EFI_ST_FAILURE;
1503394f200SHeinrich Schuchardt 		}
1513394f200SHeinrich Schuchardt 		ret = con_in_ex->read_key_stroke_ex(con_in_ex, &input_key);
1523394f200SHeinrich Schuchardt 		if (ret != EFI_SUCCESS) {
1533394f200SHeinrich Schuchardt 			efi_st_error("ReadKeyStroke failed\n");
1543394f200SHeinrich Schuchardt 			return EFI_ST_FAILURE;
1553394f200SHeinrich Schuchardt 		}
1563394f200SHeinrich Schuchardt 
1573394f200SHeinrich Schuchardt 		/* Allow 5 minutes until time out */
1583394f200SHeinrich Schuchardt 		boottime->set_watchdog_timer(300, 0, 0, NULL);
1593394f200SHeinrich Schuchardt 
1603394f200SHeinrich Schuchardt 		efi_st_printf("Unicode char %u (%ps), scan code %u (",
1613394f200SHeinrich Schuchardt 			      (unsigned int)input_key.key.unicode_char,
1623394f200SHeinrich Schuchardt 			      efi_st_translate_char(input_key.key.unicode_char),
1633394f200SHeinrich Schuchardt 			      (unsigned int)input_key.key.scan_code);
1643394f200SHeinrich Schuchardt 		if (input_key.key_state.key_shift_state &
1653394f200SHeinrich Schuchardt 		    EFI_SHIFT_STATE_VALID) {
1663394f200SHeinrich Schuchardt 			if (input_key.key_state.key_shift_state &
1673394f200SHeinrich Schuchardt 			    (EFI_LEFT_SHIFT_PRESSED | EFI_RIGHT_SHIFT_PRESSED))
1683394f200SHeinrich Schuchardt 				efi_st_printf("SHIFT+");
1693394f200SHeinrich Schuchardt 			if (input_key.key_state.key_shift_state &
1703394f200SHeinrich Schuchardt 			    (EFI_LEFT_ALT_PRESSED | EFI_RIGHT_ALT_PRESSED))
1713394f200SHeinrich Schuchardt 				efi_st_printf("ALT+");
1723394f200SHeinrich Schuchardt 			if (input_key.key_state.key_shift_state &
1733394f200SHeinrich Schuchardt 			    (EFI_LEFT_CONTROL_PRESSED |
1743394f200SHeinrich Schuchardt 			     EFI_RIGHT_CONTROL_PRESSED))
1753394f200SHeinrich Schuchardt 				efi_st_printf("CTRL+");
1763394f200SHeinrich Schuchardt 			if (input_key.key_state.key_shift_state &
1773394f200SHeinrich Schuchardt 			    (EFI_LEFT_LOGO_PRESSED | EFI_RIGHT_LOGO_PRESSED))
1783394f200SHeinrich Schuchardt 				efi_st_printf("META+");
1793394f200SHeinrich Schuchardt 			if (input_key.key_state.key_shift_state ==
1803394f200SHeinrich Schuchardt 			    EFI_SHIFT_STATE_VALID)
1813394f200SHeinrich Schuchardt 				efi_st_printf("+");
1823394f200SHeinrich Schuchardt 		}
1833394f200SHeinrich Schuchardt 
1843394f200SHeinrich Schuchardt 		efi_st_printf("%ps)\n",
1853394f200SHeinrich Schuchardt 			      efi_st_translate_code(input_key.key.scan_code));
1863394f200SHeinrich Schuchardt 
1876dec8739SHeinrich Schuchardt 	}
1883394f200SHeinrich Schuchardt 	return EFI_ST_SUCCESS;
1893394f200SHeinrich Schuchardt }
1903394f200SHeinrich Schuchardt 
1913394f200SHeinrich Schuchardt EFI_UNIT_TEST(textinputex) = {
1923394f200SHeinrich Schuchardt 	.name = "extended text input",
1933394f200SHeinrich Schuchardt 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
1943394f200SHeinrich Schuchardt 	.setup = setup,
1953394f200SHeinrich Schuchardt 	.execute = execute,
1966dec8739SHeinrich Schuchardt 	.teardown = teardown,
1973394f200SHeinrich Schuchardt 	.on_request = true,
1983394f200SHeinrich Schuchardt };
199