1 /* 2 * efi_selftest_events 3 * 4 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> 5 * 6 * SPDX-License-Identifier: GPL-2.0+ 7 * 8 * This unit test checks that the notification function of an 9 * EVT_SIGNAL_EXIT_BOOT_SERVICES event is called exactly once. 10 */ 11 12 #include <efi_selftest.h> 13 14 static struct efi_boot_services *boottime; 15 static struct efi_event *event_notify; 16 static unsigned int counter; 17 18 /* 19 * Notification function, increments a counter. 20 * 21 * @event notified event 22 * @context pointer to the counter 23 */ 24 static void EFIAPI notify(struct efi_event *event, void *context) 25 { 26 if (!context) 27 return; 28 ++*(unsigned int *)context; 29 } 30 31 /* 32 * Setup unit test. 33 * 34 * Create an EVT_SIGNAL_EXIT_BOOT_SERVICES event. 35 * 36 * @handle: handle of the loaded image 37 * @systable: system table 38 */ 39 static int setup(const efi_handle_t handle, 40 const struct efi_system_table *systable) 41 { 42 efi_status_t ret; 43 44 boottime = systable->boottime; 45 46 counter = 0; 47 ret = boottime->create_event(EVT_SIGNAL_EXIT_BOOT_SERVICES, 48 TPL_CALLBACK, notify, (void *)&counter, 49 &event_notify); 50 if (ret != EFI_SUCCESS) { 51 efi_st_error("could not create event\n"); 52 return 1; 53 } 54 return 0; 55 } 56 57 /* 58 * Tear down unit test. 59 * 60 * Close the event created in setup. 61 */ 62 static int teardown(void) 63 { 64 efi_status_t ret; 65 66 if (event_notify) { 67 ret = boottime->close_event(event_notify); 68 event_notify = NULL; 69 if (ret != EFI_SUCCESS) { 70 efi_st_error("could not close event\n"); 71 return 1; 72 } 73 } 74 return 0; 75 } 76 77 /* 78 * Execute unit test. 79 * 80 * Check that the notification function of the EVT_SIGNAL_EXIT_BOOT_SERVICES 81 * event has been called. 82 * 83 * Call ExitBootServices again and check that the notification function is 84 * not called again. 85 */ 86 static int execute(void) 87 { 88 if (counter != 1) { 89 efi_st_error("ExitBootServices was not notified"); 90 return 1; 91 } 92 efi_st_exit_boot_services(); 93 if (counter != 1) { 94 efi_st_error("ExitBootServices was notified twice"); 95 return 1; 96 } 97 return 0; 98 } 99 100 EFI_UNIT_TEST(exitbootservices) = { 101 .name = "ExitBootServices", 102 .phase = EFI_SETUP_BEFORE_BOOTTIME_EXIT, 103 .setup = setup, 104 .execute = execute, 105 .teardown = teardown, 106 }; 107