diff options
Diffstat (limited to 'lib/efi_selftest')
-rw-r--r-- | lib/efi_selftest/Makefile | 22 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest.c | 153 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_console.c | 10 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_devicepath.c | 390 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_events.c | 2 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_gop.c | 95 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_manageprotocols.c | 354 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_snp.c | 2 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_textoutput.c | 53 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_tpl.c | 4 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_util.c | 11 | ||||
-rw-r--r-- | lib/efi_selftest/efi_selftest_watchdog.c | 231 |
12 files changed, 1272 insertions, 55 deletions
diff --git a/lib/efi_selftest/Makefile b/lib/efi_selftest/Makefile index e446046e02..837e86228e 100644 --- a/lib/efi_selftest/Makefile +++ b/lib/efi_selftest/Makefile @@ -7,26 +7,16 @@ # This file only gets included with CONFIG_EFI_LOADER set, so all # object inclusion implicitly depends on it -CFLAGS_efi_selftest.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_console.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_console.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_events.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_events.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_exitbootservices.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_exitbootservices.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_snp.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_snp.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_tpl.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_tpl.o := $(CFLAGS_NON_EFI) -CFLAGS_efi_selftest_util.o := $(CFLAGS_EFI) -CFLAGS_REMOVE_efi_selftest_util.o := $(CFLAGS_NON_EFI) - obj-$(CONFIG_CMD_BOOTEFI_SELFTEST) += \ efi_selftest.o \ efi_selftest_console.o \ +efi_selftest_devicepath.o \ efi_selftest_events.o \ efi_selftest_exitbootservices.o \ +efi_selftest_gop.o \ +efi_selftest_manageprotocols.o \ efi_selftest_snp.o \ +efi_selftest_textoutput.o \ efi_selftest_tpl.o \ -efi_selftest_util.o +efi_selftest_util.o \ +efi_selftest_watchdog.o diff --git a/lib/efi_selftest/efi_selftest.c b/lib/efi_selftest/efi_selftest.c index 45d8d3d384..4e5a12c47c 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); diff --git a/lib/efi_selftest/efi_selftest_console.c b/lib/efi_selftest/efi_selftest_console.c index 840e2290c6..6a7fd20da5 100644 --- a/lib/efi_selftest/efi_selftest_console.c +++ b/lib/efi_selftest/efi_selftest_console.c @@ -142,6 +142,7 @@ void efi_st_printf(const char *fmt, ...) const char *c; u16 *pos = buf; const char *s; + const u16 *u; va_start(args, fmt); @@ -179,9 +180,18 @@ void efi_st_printf(const char *fmt, ...) case 'p': ++c; switch (*c) { + /* MAC address */ case 'm': mac(va_arg(args, void*), &pos); break; + + /* u16 string */ + case 's': + u = va_arg(args, u16*); + /* Ensure string fits into buffer */ + for (; *u && pos < buf + 120; ++u) + *pos++ = *u; + break; default: --c; pointer(va_arg(args, void*), &pos); diff --git a/lib/efi_selftest/efi_selftest_devicepath.c b/lib/efi_selftest/efi_selftest_devicepath.c new file mode 100644 index 0000000000..1ab54ebb37 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_devicepath.c @@ -0,0 +1,390 @@ +/* + * efi_selftest_devicepath + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This unit test checks the following protocol services: + * DevicePathToText + */ + +#include <efi_selftest.h> + +static struct efi_boot_services *boottime; + +static efi_handle_t handle1; +static efi_handle_t handle2; +static efi_handle_t handle3; + +struct interface { + void (EFIAPI * inc)(void); +} interface; + +static efi_guid_t guid_device_path = DEVICE_PATH_GUID; + +static efi_guid_t guid_device_path_to_text_protocol = + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; + +static efi_guid_t guid_protocol = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0x7d); + +static efi_guid_t guid_vendor1 = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xb1); + +static efi_guid_t guid_vendor2 = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xa2); + +static efi_guid_t guid_vendor3 = + EFI_GUID(0xdbca4c98, 0x6cb0, 0x694d, + 0x08, 0x72, 0x81, 0x9c, 0x65, 0x0c, 0xbb, 0xc3); + +static u8 *dp1; +static u8 *dp2; +static u8 *dp3; + +struct efi_device_path_to_text_protocol *device_path_to_text; + +/* + * Setup unit test. + * + * Create three handles. Install a new protocol on two of them and + * provice device paths. + * + * handle1 + * guid interface + * handle2 + * guid interface + * handle3 + * + * @handle: handle of the loaded image + * @systable: system table + */ +static int setup(const efi_handle_t img_handle, + const struct efi_system_table *systable) +{ + struct efi_device_path_vendor vendor_node; + struct efi_device_path end_node; + efi_status_t ret; + + boottime = systable->boottime; + + ret = boottime->locate_protocol(&guid_device_path_to_text_protocol, + NULL, (void **)&device_path_to_text); + if (ret != EFI_SUCCESS) { + device_path_to_text = NULL; + efi_st_error( + "Device path to text protocol is not available.\n"); + return EFI_ST_FAILURE; + } + + ret = boottime->allocate_pool(EFI_LOADER_DATA, + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path), + (void **)&dp1); + if (ret != EFI_SUCCESS) + goto out_of_memory; + + ret = boottime->allocate_pool(EFI_LOADER_DATA, 2 * + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path), + (void **)&dp2); + if (ret != EFI_SUCCESS) + goto out_of_memory; + + ret = boottime->allocate_pool(EFI_LOADER_DATA, 3 * + sizeof(struct efi_device_path_vendor) + + sizeof(struct efi_device_path), + (void **)&dp3); + if (ret != EFI_SUCCESS) + goto out_of_memory; + + vendor_node.dp.type = DEVICE_PATH_TYPE_HARDWARE_DEVICE; + vendor_node.dp.sub_type = DEVICE_PATH_SUB_TYPE_VENDOR; + vendor_node.dp.length = sizeof(struct efi_device_path_vendor); + + boottime->copy_mem(&vendor_node.guid, &guid_vendor1, + sizeof(efi_guid_t)); + boottime->copy_mem(dp1, &vendor_node, + sizeof(struct efi_device_path_vendor)); + boottime->copy_mem(dp2, &vendor_node, + sizeof(struct efi_device_path_vendor)); + boottime->copy_mem(dp3, &vendor_node, + sizeof(struct efi_device_path_vendor)); + + boottime->copy_mem(&vendor_node.guid, &guid_vendor2, + sizeof(efi_guid_t)); + boottime->copy_mem(dp2 + sizeof(struct efi_device_path_vendor), + &vendor_node, sizeof(struct efi_device_path_vendor)); + boottime->copy_mem(dp3 + sizeof(struct efi_device_path_vendor), + &vendor_node, sizeof(struct efi_device_path_vendor)); + + boottime->copy_mem(&vendor_node.guid, &guid_vendor3, + sizeof(efi_guid_t)); + boottime->copy_mem(dp3 + 2 * sizeof(struct efi_device_path_vendor), + &vendor_node, sizeof(struct efi_device_path_vendor)); + + end_node.type = DEVICE_PATH_TYPE_END; + end_node.sub_type = DEVICE_PATH_SUB_TYPE_END; + end_node.length = sizeof(struct efi_device_path); + boottime->copy_mem(dp1 + sizeof(struct efi_device_path_vendor), + &end_node, sizeof(struct efi_device_path)); + boottime->copy_mem(dp2 + 2 * sizeof(struct efi_device_path_vendor), + &end_node, sizeof(struct efi_device_path)); + boottime->copy_mem(dp3 + 3 * sizeof(struct efi_device_path_vendor), + &end_node, sizeof(struct efi_device_path)); + + ret = boottime->install_protocol_interface(&handle1, + &guid_device_path, + EFI_NATIVE_INTERFACE, + dp1); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle1, + &guid_protocol, + EFI_NATIVE_INTERFACE, + &interface); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle2, + &guid_device_path, + EFI_NATIVE_INTERFACE, + dp2); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle2, + &guid_protocol, + EFI_NATIVE_INTERFACE, + &interface); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_protocol_interface(&handle3, + &guid_device_path, + EFI_NATIVE_INTERFACE, + dp3); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; + +out_of_memory: + efi_st_error("Out of memory\n"); + return EFI_ST_FAILURE; +} + +/* + * Tear down unit test. + * + */ +static int teardown(void) +{ + efi_status_t ret; + + ret = boottime->uninstall_protocol_interface(&handle1, + &guid_device_path, + dp1); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle1, + &guid_protocol, + &interface); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle2, + &guid_device_path, + dp2); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle2, + &guid_protocol, + &interface); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + ret = boottime->uninstall_protocol_interface(&handle3, + &guid_device_path, + dp3); + if (ret != EFI_SUCCESS) + efi_st_todo("UninstallProtocolInterface failed\n"); + if (dp1) { + ret = boottime->free_pool(dp1); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } + if (dp2) { + ret = boottime->free_pool(dp2); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } + if (dp3) { + ret = boottime->free_pool(dp3); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + } + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + */ +static int execute(void) +{ + struct efi_device_path *remaining_dp; + void *handle; + /* + * This device path node ends with the letter 't' of 'u-boot'. + * The following '.bin' does not belong to the node but is + * helps to test the correct truncation. + */ + struct { + struct efi_device_path dp; + u16 text[12]; + } __packed dp_node = { + { DEVICE_PATH_TYPE_MEDIA_DEVICE, + DEVICE_PATH_SUB_TYPE_FILE_PATH, + sizeof(struct efi_device_path) + 12}, + L"u-boot.bin", + }; + u16 *string; + efi_status_t ret; + efi_uintn_t i, no_handles; + efi_handle_t *handles; + struct efi_device_path *dp; + + /* Display all available device paths */ + ret = boottime->locate_handle_buffer(BY_PROTOCOL, + &guid_device_path, + NULL, &no_handles, &handles); + if (ret != EFI_SUCCESS) { + efi_st_error("Cannot retrieve device path protocols.\n"); + return EFI_ST_FAILURE; + } + + efi_st_printf("Installed device path protocols:\n"); + for (i = 0; i < no_handles; ++i) { + ret = boottime->open_protocol(handles[i], &guid_device_path, + (void **)&dp, NULL, NULL, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + if (ret != EFI_SUCCESS) { + efi_st_error("Cannot open device path protocol.\n"); + return EFI_ST_FAILURE; + } + string = device_path_to_text->convert_device_path_to_text( + dp, true, false); + if (!string) { + efi_st_error("ConvertDevicePathToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("%ps\n", string); + ret = boottime->free_pool(string); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + ret = boottime->close_protocol(handles[i], &guid_device_path, + NULL, NULL); + if (ret != EFI_SUCCESS) + efi_st_todo("Cannot close device path protocol.\n"); + } + ret = boottime->free_pool(handles); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("\n"); + + /* Test ConvertDevicePathToText */ + string = device_path_to_text->convert_device_path_to_text( + (struct efi_device_path *)dp2, true, false); + if (!string) { + efi_st_error("ConvertDevicePathToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("dp2: %ps\n", string); + if (efi_st_strcmp_16_8( + string, + "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbb1)/VenHw(dbca4c98-6cb0-694d-0872-819c650cbba2)") + ) { + efi_st_error("Incorrect text from ConvertDevicePathToText\n"); + return EFI_ST_FAILURE; + } + + ret = boottime->free_pool(string); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + + /* Test ConvertDeviceNodeToText */ + string = device_path_to_text->convert_device_node_to_text( + (struct efi_device_path *)&dp_node, true, false); + if (!string) { + efi_st_error("ConvertDeviceNodeToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("dp_node: %ps\n", string); + ret = boottime->free_pool(string); + if (ret != EFI_SUCCESS) { + efi_st_error("FreePool failed\n"); + return EFI_ST_FAILURE; + } + if (efi_st_strcmp_16_8(string, "u-boot")) { + efi_st_error( + "Incorrect conversion by ConvertDeviceNodeToText\n"); + return EFI_ST_FAILURE; + } + + /* Test LocateDevicePath */ + remaining_dp = (struct efi_device_path *)dp3; + ret = boottime->locate_device_path(&guid_protocol, &remaining_dp, + &handle); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateDevicePath failed\n"); + return EFI_ST_FAILURE; + } + if (handle != handle2) { + efi_st_error("LocateDevicePath returned wrong handle\n"); + return EFI_ST_FAILURE; + } + string = device_path_to_text->convert_device_path_to_text(remaining_dp, + true, false); + if (!string) { + efi_st_error("ConvertDevicePathToText failed\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("remaining device path: %ps\n", string); + if (efi_st_strcmp_16_8(string, + "/VenHw(dbca4c98-6cb0-694d-0872-819c650cbbc3)") + ) { + efi_st_error("LocateDevicePath: wrong remaining device path\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(devicepath) = { + .name = "device path", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/lib/efi_selftest/efi_selftest_events.c b/lib/efi_selftest/efi_selftest_events.c index 081f31257f..ad9490bd25 100644 --- a/lib/efi_selftest/efi_selftest_events.c +++ b/lib/efi_selftest/efi_selftest_events.c @@ -108,7 +108,7 @@ static int teardown(void) */ static int execute(void) { - size_t index; + efi_uintn_t index; efi_status_t ret; /* Set 10 ms timer */ diff --git a/lib/efi_selftest/efi_selftest_gop.c b/lib/efi_selftest/efi_selftest_gop.c new file mode 100644 index 0000000000..2a0553b115 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_gop.c @@ -0,0 +1,95 @@ +/* + * efi_selftest_gop + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Test the graphical output protocol. + */ + +#include <efi_selftest.h> + +static struct efi_boot_services *boottime; +static efi_guid_t efi_gop_guid = EFI_GOP_GUID; +static struct efi_gop *gop; + +/* + * Setup unit test. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + efi_status_t ret; + + boottime = systable->boottime; + + ret = boottime->locate_protocol(&efi_gop_guid, NULL, (void **)&gop); + if (ret != EFI_SUCCESS) { + gop = NULL; + efi_st_printf("Graphical output protocol is not available.\n"); + } + + return EFI_ST_SUCCESS; +} + +/* + * Tear down unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int teardown(void) +{ + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + efi_status_t ret; + u32 i, max_mode; + efi_uintn_t size; + struct efi_gop_mode_info *info; + + if (!gop) + return EFI_ST_SUCCESS; + + if (!gop->mode) { + efi_st_error("EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE missing\n"); + return EFI_ST_FAILURE; + } + max_mode = gop->mode->max_mode; + if (!max_mode) { + efi_st_error("No graphical mode available\n"); + return EFI_ST_FAILURE; + } + efi_st_printf("Number of available modes: %u\n", max_mode); + + for (i = 0; i < max_mode; ++i) { + ret = gop->query_mode(gop, i, &size, &info); + if (ret != EFI_SUCCESS) { + efi_st_printf("Could not query mode %u\n", i); + return EFI_ST_FAILURE; + } + efi_st_printf("Mode %u: %u x %u\n", + i, info->width, info->height); + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(gop) = { + .name = "graphical output", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/lib/efi_selftest/efi_selftest_manageprotocols.c b/lib/efi_selftest/efi_selftest_manageprotocols.c new file mode 100644 index 0000000000..f20f1528d4 --- /dev/null +++ b/lib/efi_selftest/efi_selftest_manageprotocols.c @@ -0,0 +1,354 @@ +/* + * efi_selftest_manageprotocols + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * This unit test checks the following protocol services: + * InstallProtocolInterface, UninstallProtocolInterface, + * InstallMultipleProtocolsInterfaces, UninstallMultipleProtocolsInterfaces, + * HandleProtocol, ProtocolsPerHandle, + * LocateHandle, LocateHandleBuffer. + */ + +#include <efi_selftest.h> + +/* + * The test currently does not actually call the interface function. + * So this is just a dummy structure. + */ +struct interface { + void (EFIAPI * inc)(void); +}; + +static struct efi_boot_services *boottime; +static efi_guid_t guid1 = + EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a, + 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf); +static efi_guid_t guid2 = + EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77, + 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f); +static efi_guid_t guid3 = + EFI_GUID(0x06d641a3, 0xf4e7, 0xe0c9, + 0xe7, 0x8d, 0x41, 0x2d, 0x72, 0xa6, 0xb1, 0x24); +static efi_handle_t handle1; +static efi_handle_t handle2; +static struct interface interface1; +static struct interface interface2; +static struct interface interface3; +static struct interface interface4; + +/* + * Find a handle in an array. + * + * @handle: handle to find + * @count: number of entries in the array + * @buffer: array to search + */ +efi_status_t find_in_buffer(efi_handle_t handle, size_t count, + efi_handle_t *buffer) +{ + size_t i; + + for (i = 0; i < count; ++i) { + if (buffer[i] == handle) + return EFI_SUCCESS; + } + return EFI_NOT_FOUND; +} + +/* + * Setup unit test. + * + * Create two handles and install two out of three protocol interfaces on each + * of them: + * + * handle1 + * guid1 interface1 + * guid3 interface3 + * handle2 + * guid1 interface4 + * guid2 interface2 + * + * @handle: handle of the loaded image + * @systable: system table + */ +static int setup(const efi_handle_t img_handle, + const struct efi_system_table *systable) +{ + efi_status_t ret; + efi_handle_t handle; + + boottime = systable->boottime; + + ret = boottime->install_protocol_interface(&handle1, &guid3, + EFI_NATIVE_INTERFACE, + &interface3); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + if (!handle1) { + efi_st_error("InstallProtocolInterface failed to create handle\n"); + return EFI_ST_FAILURE; + } + handle = handle1; + ret = boottime->install_protocol_interface(&handle1, &guid1, + EFI_NATIVE_INTERFACE, + &interface1); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallProtocolInterface failed\n"); + return EFI_ST_FAILURE; + } + if (handle != handle1) { + efi_st_error("InstallProtocolInterface failed to use handle\n"); + return EFI_ST_FAILURE; + } + ret = boottime->install_multiple_protocol_interfaces(&handle2, + &guid1, &interface4, &guid2, &interface2, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("InstallMultipleProtocolInterfaces failed\n"); + return EFI_ST_FAILURE; + } + if (!handle2 || handle1 == handle2) { + efi_st_error("InstallMultipleProtocolInterfaces failed to create handle\n"); + return EFI_ST_FAILURE; + } + + return EFI_ST_SUCCESS; +} + +/* + * Tear down unit test. + * + */ +static int teardown(void) +{ + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + */ +static int execute(void) +{ + struct interface *interface; + efi_status_t ret; + efi_handle_t *buffer; + size_t buffer_size; + efi_uintn_t count = 0; + efi_guid_t **prot_buffer; + efi_uintn_t prot_count; + + /* + * Test HandleProtocol + */ + ret = boottime->handle_protocol(handle1, &guid3, (void **)&interface); + if (ret != EFI_SUCCESS) { + efi_st_error("HandleProtocol failed to retrieve interface\n"); + return EFI_ST_FAILURE; + } + if (interface != &interface3) { + efi_st_error("HandleProtocol returned wrong interface\n"); + return EFI_ST_FAILURE; + } + ret = boottime->handle_protocol(handle1, &guid2, (void **)&interface); + if (ret == EFI_SUCCESS) { + efi_st_error("HandleProtocol returned not installed interface\n"); + return EFI_ST_FAILURE; + } + + /* + * Test LocateHandleBuffer with AllHandles + */ + ret = boottime->locate_handle_buffer(ALL_HANDLES, NULL, NULL, + &count, &buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer with AllHandles failed\n"); + return EFI_ST_FAILURE; + } + buffer_size = count; + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle2, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test error handling in UninstallMultipleProtocols + * + * Try to uninstall more protocols than there are installed. + */ + ret = boottime->uninstall_multiple_protocol_interfaces( + handle2, + &guid1, &interface4, + &guid2, &interface2, + &guid3, &interface3, + NULL); + if (ret == EFI_SUCCESS) { + efi_st_todo("UninstallMultipleProtocolInterfaces did not catch error\n"); + return EFI_ST_FAILURE; + } + + /* + * Test LocateHandleBuffer with ByProtocol + */ + count = buffer_size; + ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL, + &count, &buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + if (count != 2) { + efi_st_error("LocateHandleBuffer failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle2, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test LocateHandle with ByProtocol + */ + count = buffer_size * sizeof(efi_handle_t); + ret = boottime->locate_handle(BY_PROTOCOL, &guid1, NULL, + &count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandle with ByProtocol failed\n"); + return EFI_ST_FAILURE; + } + if (count / sizeof(efi_handle_t) != 2) { + efi_st_error("LocateHandle failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + buffer_size = count; + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandle failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + ret = find_in_buffer(handle2, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandle failed to locate new handles\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test LocateProtocol + */ + ret = boottime->locate_protocol(&guid1, NULL, (void **)&interface); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateProtocol failed\n"); + return EFI_ST_FAILURE; + } + if (interface != &interface1 && interface != &interface4) { + efi_st_error("LocateProtocol failed to locate protocol\n"); + return EFI_ST_FAILURE; + } + + /* + * Test UninstallMultipleProtocols + */ + ret = boottime->uninstall_multiple_protocol_interfaces( + handle2, + &guid1, &interface4, + &guid2, &interface2, + NULL); + if (ret != EFI_SUCCESS) { + efi_st_todo("UninstallMultipleProtocolInterfaces failed\n"); + /* This test is known to fail due to missing implementation */ + } + /* + * Check that the protocols are really uninstalled. + */ + count = buffer_size; + ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL, + &count, &buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("LocateHandleBuffer failed\n"); + return EFI_ST_FAILURE; + } + if (count != 1) { + efi_st_todo("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n"); + /* This test is known to fail due to missing implementation */ + } + ret = find_in_buffer(handle1, count, buffer); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to locate new handle\n"); + return EFI_ST_FAILURE; + } + boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0); + + /* + * Test ProtocolsPerHandle + */ + ret = boottime->protocols_per_handle(handle1, + &prot_buffer, &prot_count); + if (ret != EFI_SUCCESS) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + if (prot_count != 2) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(prot_buffer[0], &guid1, 16) && + efi_st_memcmp(prot_buffer[1], &guid1, 16)) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + if (efi_st_memcmp(prot_buffer[0], &guid3, 16) && + efi_st_memcmp(prot_buffer[1], &guid3, 16)) { + efi_st_error("Failed to get protocols per handle\n"); + return EFI_ST_FAILURE; + } + + /* + * Uninstall remaining protocols + */ + ret = boottime->uninstall_protocol_interface(handle1, &guid1, + &interface1); + if (ret != EFI_SUCCESS) { + efi_st_todo("UninstallProtocolInterface failed\n"); + /* This test is known to fail due to missing implementation */ + } + ret = boottime->handle_protocol(handle1, &guid1, (void **)&interface); + if (ret == EFI_SUCCESS) { + efi_st_todo("UninstallProtocolInterface failed\n"); + /* This test is known to fail due to missing implementation */ + } + ret = boottime->uninstall_protocol_interface(handle1, &guid3, + &interface1); + if (ret != EFI_SUCCESS) { + efi_st_todo("UninstallProtocolInterface failed\n"); + /* This test is known to fail due to missing implementation */ + } + + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(protserv) = { + .name = "manage protocols", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup, + .execute = execute, + .teardown = teardown, +}; diff --git a/lib/efi_selftest/efi_selftest_snp.c b/lib/efi_selftest/efi_selftest_snp.c index bdd6ce20da..cc0705fb59 100644 --- a/lib/efi_selftest/efi_selftest_snp.c +++ b/lib/efi_selftest/efi_selftest_snp.c @@ -260,7 +260,7 @@ static int execute(void) { efi_status_t ret; struct efi_event *events[2]; - size_t index; + efi_uintn_t index; union { struct dhcp p; u8 b[PKTSIZE]; diff --git a/lib/efi_selftest/efi_selftest_textoutput.c b/lib/efi_selftest/efi_selftest_textoutput.c new file mode 100644 index 0000000000..6e8c90cc8b --- /dev/null +++ b/lib/efi_selftest/efi_selftest_textoutput.c @@ -0,0 +1,53 @@ +/* + * efi_selftest_textoutput + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * Test the EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL. + * + * The following services are tested: + * OutputString, TestString, SetAttribute. + */ + +#include <efi_selftest.h> + +/* + * Execute unit test. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + size_t foreground; + size_t background; + size_t attrib; + efi_status_t ret; + + /* SetAttribute */ + efi_st_printf("\nColor palette\n"); + for (foreground = 0; foreground < 0x10; ++foreground) { + for (background = 0; background < 0x80; background += 0x10) { + attrib = foreground | background; + con_out->set_attribute(con_out, attrib); + efi_st_printf("%p", (void *)attrib); + } + con_out->set_attribute(con_out, 0); + efi_st_printf("\n"); + } + /* TestString */ + ret = con_out->test_string(con_out, + L" !\"#$%&'()*+,-./0-9:;<=>?@A-Z[\\]^_`a-z{|}~\n"); + if (ret != EFI_ST_SUCCESS) { + efi_st_error("TestString failed for ANSI characters\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(textoutput) = { + .name = "text output", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .execute = execute, +}; diff --git a/lib/efi_selftest/efi_selftest_tpl.c b/lib/efi_selftest/efi_selftest_tpl.c index ddb67ed268..6ea0bb7177 100644 --- a/lib/efi_selftest/efi_selftest_tpl.c +++ b/lib/efi_selftest/efi_selftest_tpl.c @@ -111,9 +111,9 @@ static int teardown(void) */ static int execute(void) { - size_t index; + efi_uintn_t index; efi_status_t ret; - UINTN old_tpl; + efi_uintn_t old_tpl; /* Set 10 ms timer */ notification_count = 0; diff --git a/lib/efi_selftest/efi_selftest_util.c b/lib/efi_selftest/efi_selftest_util.c index 5cffe383d8..1b17bf4d4b 100644 --- a/lib/efi_selftest/efi_selftest_util.c +++ b/lib/efi_selftest/efi_selftest_util.c @@ -21,5 +21,14 @@ int efi_st_memcmp(const void *buf1, const void *buf2, size_t length) ++pos1; ++pos2; } - return EFI_ST_SUCCESS; + return 0; +} + +int efi_st_strcmp_16_8(const u16 *buf1, const char *buf2) +{ + for (; *buf1 || *buf2; ++buf1, ++buf2) { + if (*buf1 != *buf2) + return *buf1 - *buf2; + } + return 0; } diff --git a/lib/efi_selftest/efi_selftest_watchdog.c b/lib/efi_selftest/efi_selftest_watchdog.c new file mode 100644 index 0000000000..e4af38407f --- /dev/null +++ b/lib/efi_selftest/efi_selftest_watchdog.c @@ -0,0 +1,231 @@ +/* + * efi_selftest_watchdog + * + * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> + * + * SPDX-License-Identifier: GPL-2.0+ + * + * The 'watchdog timer' unit test checks that the watchdog timer + * will not cause a system restart during the timeout period after + * a timer reset. + * + * The 'watchdog reboot' unit test checks that the watchdog timer + * actually reboots the system after a timeout. The test is only + * executed on explicit request. Use the following commands: + * + * setenv efi_selftest watchdog reboot + * bootefi selftest + */ + +#include <efi_selftest.h> + +/* + * This is the communication structure for the notification function. + */ +struct notify_context { + /* Status code returned when resetting watchdog */ + efi_status_t status; + /* Number of invocations of the notification function */ + unsigned int timer_ticks; +}; + +static struct efi_event *event_notify; +static struct efi_event *event_wait; +static struct efi_boot_services *boottime; +static struct notify_context notification_context; +static bool watchdog_reset; + +/* + * Notification function, increments the notfication count if parameter + * context is provided. + * + * @event notified event + * @context pointer to the timeout + */ +static void EFIAPI notify(struct efi_event *event, void *context) +{ + struct notify_context *notify_context = context; + efi_status_t ret = EFI_SUCCESS; + + if (!notify_context) + return; + + /* Reset watchdog timer to one second */ + ret = boottime->set_watchdog_timer(1, 0, 0, NULL); + if (ret != EFI_SUCCESS) + notify_context->status = ret; + /* Count number of calls */ + notify_context->timer_ticks++; +} + +/* + * Setup unit test. + * + * Create two timer events. + * One with EVT_NOTIFY_SIGNAL, the other with EVT_NOTIFY_WAIT. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + efi_status_t ret; + + boottime = systable->boottime; + + notification_context.status = EFI_SUCCESS; + notification_context.timer_ticks = 0; + ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_CALLBACK, notify, + (void *)¬ification_context, + &event_notify); + if (ret != EFI_SUCCESS) { + efi_st_error("could not create event\n"); + return EFI_ST_FAILURE; + } + ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_WAIT, + TPL_CALLBACK, notify, NULL, &event_wait); + if (ret != EFI_SUCCESS) { + efi_st_error("could not create event\n"); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +/* + * Execute the test resetting the watchdog in a timely manner. No reboot occurs. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup_timer(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + watchdog_reset = true; + return setup(handle, systable); +} + +/* + * Execute the test without resetting the watchdog. A system reboot occurs. + * + * @handle: handle of the loaded image + * @systable: system table + * @return: EFI_ST_SUCCESS for success + */ +static int setup_reboot(const efi_handle_t handle, + const struct efi_system_table *systable) +{ + watchdog_reset = false; + return setup(handle, systable); +} + +/* + * Tear down unit test. + * + * Close the events created in setup. + * + * @return: EFI_ST_SUCCESS for success + */ +static int teardown(void) +{ + efi_status_t ret; + + /* Set the watchdog timer to the five minute default value */ + ret = boottime->set_watchdog_timer(300, 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Setting watchdog timer failed\n"); + return EFI_ST_FAILURE; + } + if (event_notify) { + ret = boottime->close_event(event_notify); + event_notify = NULL; + if (ret != EFI_SUCCESS) { + efi_st_error("Could not close event\n"); + return EFI_ST_FAILURE; + } + } + if (event_wait) { + ret = boottime->close_event(event_wait); + event_wait = NULL; + if (ret != EFI_SUCCESS) { + efi_st_error("Could not close event\n"); + return EFI_ST_FAILURE; + } + } + return EFI_ST_SUCCESS; +} + +/* + * Execute unit test. + * + * Run a 600 ms periodic timer that resets the watchdog to one second + * on every timer tick. + * + * Run a 1350 ms single shot timer and check that the 600ms timer has + * been called 2 times. + * + * @return: EFI_ST_SUCCESS for success + */ +static int execute(void) +{ + size_t index; + efi_status_t ret; + + /* Set the watchdog timeout to one second */ + ret = boottime->set_watchdog_timer(1, 0, 0, NULL); + if (ret != EFI_SUCCESS) { + efi_st_error("Setting watchdog timer failed\n"); + return EFI_ST_FAILURE; + } + if (watchdog_reset) { + /* Set 600 ms timer */ + ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, + 6000000); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not set timer\n"); + return EFI_ST_FAILURE; + } + } + /* Set 1350 ms timer */ + ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 13500000); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not set timer\n"); + return EFI_ST_FAILURE; + } + + ret = boottime->wait_for_event(1, &event_wait, &index); + if (ret != EFI_SUCCESS) { + efi_st_error("Could not wait for event\n"); + return EFI_ST_FAILURE; + } + if (notification_context.status != EFI_SUCCESS) { + efi_st_error("Setting watchdog timer failed\n"); + return EFI_ST_FAILURE; + } + if (notification_context.timer_ticks != 2) { + efi_st_error("The timer was called %u times, expected 2.\n", + notification_context.timer_ticks); + return EFI_ST_FAILURE; + } + return EFI_ST_SUCCESS; +} + +EFI_UNIT_TEST(watchdog1) = { + .name = "watchdog timer", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup_timer, + .execute = execute, + .teardown = teardown, +}; + +EFI_UNIT_TEST(watchdog2) = { + .name = "watchdog reboot", + .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, + .setup = setup_reboot, + .execute = execute, + .teardown = teardown, + .on_request = true, +}; |