diff options
Diffstat (limited to 'lib/efi_selftest/efi_selftest.c')
| -rw-r--r-- | lib/efi_selftest/efi_selftest.c | 153 | 
1 files changed, 119 insertions, 34 deletions
| diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c index 45d8d3d384c..4e5a12c47ca 100644 --- a/lib/efi_selftest/efi_selftest.c +++ b/lib/efi_selftest/efi_selftest.c @@ -9,6 +9,13 @@  #include <efi_selftest.h>  #include <vsprintf.h> +/* + * Constants for test step bitmap + */ +#define EFI_ST_SETUP	1 +#define EFI_ST_EXECUTE	2 +#define EFI_ST_TEARDOWN	4 +  static const struct efi_system_table *systable;  static const struct efi_boot_services *boottime;  static const struct efi_runtime_services *runtime; @@ -25,9 +32,9 @@ static u16 reset_message[] = L"Selftest completed";   */  void efi_st_exit_boot_services(void)  { -	unsigned long  map_size = 0; -	unsigned long  map_key; -	unsigned long desc_size; +	efi_uintn_t map_size = 0; +	efi_uintn_t map_key; +	efi_uintn_t desc_size;  	u32 desc_version;  	efi_status_t ret;  	struct efi_mem_desc *memory_map; @@ -134,6 +141,70 @@ static int teardown(struct efi_unit_test *test, unsigned int *failures)  }  /* + * Check that a test exists. + * + * @testname:	name of the test + * @return:	test + */ +static struct efi_unit_test *find_test(const u16 *testname) +{ +	struct efi_unit_test *test; + +	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); +	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { +		if (!efi_st_strcmp_16_8(testname, test->name)) +			return test; +	} +	efi_st_printf("\nTest '%ps' not found\n", testname); +	return NULL; +} + +/* + * List all available tests. + */ +static void list_all_tests(void) +{ +	struct efi_unit_test *test; + +	/* List all tests */ +	efi_st_printf("\nAvailable tests:\n"); +	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); +	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { +		efi_st_printf("'%s'%s\n", test->name, +			      test->on_request ? " - on request" : ""); +	} +} + +/* + * Execute test steps of one phase. + * + * @testname	name of a single selected test or NULL + * @phase	test phase + * @steps	steps to execute + * failures	returns EFI_ST_SUCCESS if all test steps succeeded + */ +void efi_st_do_tests(const u16 *testname, unsigned int phase, +		     unsigned int steps, unsigned int *failures) +{ +	struct efi_unit_test *test; + +	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); +	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { +		if (testname ? +		    efi_st_strcmp_16_8(testname, test->name) : test->on_request) +			continue; +		if (test->phase != phase) +			continue; +		if (steps & EFI_ST_SETUP) +			setup(test, failures); +		if (steps & EFI_ST_EXECUTE) +			execute(test, failures); +		if (steps & EFI_ST_TEARDOWN) +			teardown(test, failures); +	} +} + +/*   * Execute selftest of the EFI API   *   * This is the main entry point of the EFI selftest application. @@ -153,8 +224,10 @@ static int teardown(struct efi_unit_test *test, unsigned int *failures)  efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,  				 struct efi_system_table *systab)  { -	struct efi_unit_test *test;  	unsigned int failures = 0; +	const u16 *testname = NULL; +	struct efi_loaded_image *loaded_image; +	efi_status_t ret;  	systable = systab;  	boottime = systable->boottime; @@ -163,47 +236,59 @@ efi_status_t EFIAPI efi_selftest(efi_handle_t image_handle,  	con_out = systable->con_out;  	con_in = systable->con_in; -	efi_st_printf("\nTesting EFI API implementation\n"); +	ret = boottime->handle_protocol(image_handle, &efi_guid_loaded_image, +					(void **)&loaded_image); +	if (ret != EFI_SUCCESS) { +		efi_st_error("Cannot open loaded image protocol\n"); +		return ret; +	} -	efi_st_printf("\nNumber of tests to execute: %u\n", -		      ll_entry_count(struct efi_unit_test, efi_unit_test)); +	if (loaded_image->load_options) +		testname = (u16 *)loaded_image->load_options; -	/* Execute boottime tests */ -	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); -	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { -		if (test->phase == EFI_EXECUTE_BEFORE_BOOTTIME_EXIT) { -			setup(test, &failures); -			execute(test, &failures); -			teardown(test, &failures); +	if (testname) { +		if (!efi_st_strcmp_16_8(testname, "list") || +		    !find_test(testname)) { +			list_all_tests(); +			/* +			 * TODO: +			 * Once the Exit boottime service is correctly +			 * implemented we should call +			 *   boottime->exit(image_handle, EFI_SUCCESS, 0, NULL); +			 * here, cf. +			 * https://lists.denx.de/pipermail/u-boot/2017-October/308720.html +			 */ +			return EFI_SUCCESS;  		}  	} +	efi_st_printf("\nTesting EFI API implementation\n"); + +	if (testname) +		efi_st_printf("\nSelected test: '%ps'\n", testname); +	else +		efi_st_printf("\nNumber of tests to execute: %u\n", +			      ll_entry_count(struct efi_unit_test, +					     efi_unit_test)); + +	/* Execute boottime tests */ +	efi_st_do_tests(testname, EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, +			EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN, +			&failures); +  	/* Execute mixed tests */ -	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); -	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { -		if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT) -			setup(test, &failures); -	} +	efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT, +			EFI_ST_SETUP, &failures);  	efi_st_exit_boot_services(); -	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); -	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { -		if (test->phase == EFI_SETUP_BEFORE_BOOTTIME_EXIT) { -			execute(test, &failures); -			teardown(test, &failures); -		} -	} +	efi_st_do_tests(testname, EFI_SETUP_BEFORE_BOOTTIME_EXIT, +			EFI_ST_EXECUTE | EFI_ST_TEARDOWN, &failures);  	/* Execute runtime tests */ -	for (test = ll_entry_start(struct efi_unit_test, efi_unit_test); -	     test < ll_entry_end(struct efi_unit_test, efi_unit_test); ++test) { -		if (test->phase == EFI_SETUP_AFTER_BOOTTIME_EXIT) { -			setup(test, &failures); -			execute(test, &failures); -			teardown(test, &failures); -		} -	} +	efi_st_do_tests(testname, EFI_SETUP_AFTER_BOOTTIME_EXIT, +			EFI_ST_SETUP | EFI_ST_EXECUTE | EFI_ST_TEARDOWN, +			&failures);  	/* Give feedback */  	efi_st_printf("\nSummary: %u failures\n\n", failures); | 
