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