Blame view
lib/efi_selftest/efi_selftest_events.c
5.17 KB
83d290c56
|
1 |
// SPDX-License-Identifier: GPL-2.0+ |
bd126692d
|
2 3 4 5 6 |
/* * efi_selftest_events * * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de> * |
bd126692d
|
7 8 9 10 11 12 13 14 15 |
* This unit test uses timer events to check the implementation * of the following boottime services: * CreateEvent, CloseEvent, WaitForEvent, CheckEvent, SetTimer. */ #include <efi_selftest.h> static struct efi_event *event_notify; static struct efi_event *event_wait; |
e67e7249c
|
16 |
static unsigned int timer_ticks; |
bd126692d
|
17 18 19 |
static struct efi_boot_services *boottime; /* |
d8b2216c8
|
20 |
* Notification function, increments the notification count if parameter |
e67e7249c
|
21 |
* context is provided. |
bd126692d
|
22 23 |
* * @event notified event |
e67e7249c
|
24 |
* @context pointer to the notification count |
bd126692d
|
25 26 27 |
*/ static void EFIAPI notify(struct efi_event *event, void *context) { |
e67e7249c
|
28 29 30 31 |
unsigned int *count = context; if (count) ++*count; |
bd126692d
|
32 33 34 35 36 37 38 39 40 41 |
} /* * 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 |
e67e7249c
|
42 |
* @return: EFI_ST_SUCCESS for success |
bd126692d
|
43 44 45 46 47 48 49 50 51 |
*/ static int setup(const efi_handle_t handle, const struct efi_system_table *systable) { efi_status_t ret; boottime = systable->boottime; ret = boottime->create_event(EVT_TIMER | EVT_NOTIFY_SIGNAL, |
e67e7249c
|
52 |
TPL_CALLBACK, notify, (void *)&timer_ticks, |
bd126692d
|
53 54 55 56 |
&event_notify); if (ret != EFI_SUCCESS) { efi_st_error("could not create event "); |
e67e7249c
|
57 |
return EFI_ST_FAILURE; |
bd126692d
|
58 59 60 61 62 63 |
} 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 "); |
e67e7249c
|
64 |
return EFI_ST_FAILURE; |
bd126692d
|
65 |
} |
e67e7249c
|
66 |
return EFI_ST_SUCCESS; |
bd126692d
|
67 68 69 70 71 72 |
} /* * Tear down unit test. * * Close the events created in setup. |
e67e7249c
|
73 74 |
* * @return: EFI_ST_SUCCESS for success |
bd126692d
|
75 76 77 78 79 80 81 82 83 84 85 |
*/ static int teardown(void) { efi_status_t ret; if (event_notify) { ret = boottime->close_event(event_notify); event_notify = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event "); |
e67e7249c
|
86 |
return EFI_ST_FAILURE; |
bd126692d
|
87 88 89 90 91 92 93 94 |
} } if (event_wait) { ret = boottime->close_event(event_wait); event_wait = NULL; if (ret != EFI_SUCCESS) { efi_st_error("could not close event "); |
e67e7249c
|
95 |
return EFI_ST_FAILURE; |
bd126692d
|
96 97 |
} } |
e67e7249c
|
98 |
return EFI_ST_SUCCESS; |
bd126692d
|
99 100 101 102 103 104 105 106 107 108 |
} /* * Execute unit test. * * Run a 10 ms periodic timer and check that it is called 10 times * while waiting for 100 ms single shot timer. * * Run a 100 ms single shot timer and check that it is called once * while waiting for 100 ms periodic timer for two periods. |
e67e7249c
|
109 110 |
* * @return: EFI_ST_SUCCESS for success |
bd126692d
|
111 112 113 |
*/ static int execute(void) { |
f5a2a9389
|
114 |
efi_uintn_t index; |
bd126692d
|
115 116 117 |
efi_status_t ret; /* Set 10 ms timer */ |
e67e7249c
|
118 |
timer_ticks = 0; |
bd126692d
|
119 120 121 122 |
ret = boottime->set_timer(event_notify, EFI_TIMER_PERIODIC, 100000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer "); |
e67e7249c
|
123 |
return EFI_ST_FAILURE; |
bd126692d
|
124 125 126 127 128 129 |
} /* Set 100 ms timer */ ret = boottime->set_timer(event_wait, EFI_TIMER_RELATIVE, 1000000); if (ret != EFI_SUCCESS) { efi_st_error("Could not set timer "); |
e67e7249c
|
130 |
return EFI_ST_FAILURE; |
bd126692d
|
131 |
} |
e67e7249c
|
132 |
/* Set some arbitrary non-zero value to make change detectable. */ |
bd126692d
|
133 134 135 136 137 |
index = 5; ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event "); |
e67e7249c
|
138 |
return EFI_ST_FAILURE; |
bd126692d
|
139 140 141 142 143 144 145 |
} ret = boottime->check_event(event_wait); if (ret != EFI_NOT_READY) { efi_st_error("Signaled state was not cleared. "); efi_st_printf("ret = %u ", (unsigned int)ret); |
e67e7249c
|
146 |
return EFI_ST_FAILURE; |
bd126692d
|
147 148 149 150 |
} if (index != 0) { efi_st_error("WaitForEvent returned wrong index "); |
e67e7249c
|
151 |
return EFI_ST_FAILURE; |
bd126692d
|
152 |
} |
e67e7249c
|
153 |
if (timer_ticks < 8 || timer_ticks > 12) { |
ad50dcf8c
|
154 155 |
efi_st_printf("Notification count periodic: %u ", timer_ticks); |
bd126692d
|
156 157 |
efi_st_error("Incorrect timing of events "); |
e67e7249c
|
158 |
return EFI_ST_FAILURE; |
bd126692d
|
159 160 |
} ret = boottime->set_timer(event_notify, EFI_TIMER_STOP, 0); |
1309a159c
|
161 |
if (ret != EFI_SUCCESS) { |
bd126692d
|
162 163 |
efi_st_error("Could not cancel timer "); |
e67e7249c
|
164 |
return EFI_ST_FAILURE; |
bd126692d
|
165 166 |
} /* Set 10 ms timer */ |
e67e7249c
|
167 |
timer_ticks = 0; |
bd126692d
|
168 |
ret = boottime->set_timer(event_notify, EFI_TIMER_RELATIVE, 100000); |
1309a159c
|
169 |
if (ret != EFI_SUCCESS) { |
bd126692d
|
170 171 |
efi_st_error("Could not set timer "); |
e67e7249c
|
172 |
return EFI_ST_FAILURE; |
bd126692d
|
173 174 175 |
} /* Set 100 ms timer */ ret = boottime->set_timer(event_wait, EFI_TIMER_PERIODIC, 1000000); |
1309a159c
|
176 |
if (ret != EFI_SUCCESS) { |
bd126692d
|
177 178 |
efi_st_error("Could not set timer "); |
e67e7249c
|
179 |
return EFI_ST_FAILURE; |
bd126692d
|
180 181 182 183 184 |
} ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event "); |
e67e7249c
|
185 |
return EFI_ST_FAILURE; |
bd126692d
|
186 |
} |
e67e7249c
|
187 |
if (timer_ticks != 1) { |
ad50dcf8c
|
188 189 190 |
efi_st_printf("Notification count single shot: %u ", timer_ticks); |
bd126692d
|
191 192 |
efi_st_error("Single shot timer failed "); |
e67e7249c
|
193 |
return EFI_ST_FAILURE; |
bd126692d
|
194 195 196 197 198 |
} ret = boottime->wait_for_event(1, &event_wait, &index); if (ret != EFI_SUCCESS) { efi_st_error("Could not wait for event "); |
e67e7249c
|
199 |
return EFI_ST_FAILURE; |
bd126692d
|
200 |
} |
e67e7249c
|
201 |
if (timer_ticks != 1) { |
ad50dcf8c
|
202 203 204 |
efi_st_printf("Notification count stopped timer: %u ", timer_ticks); |
bd126692d
|
205 206 |
efi_st_error("Stopped timer fired "); |
e67e7249c
|
207 |
return EFI_ST_FAILURE; |
bd126692d
|
208 209 |
} ret = boottime->set_timer(event_wait, EFI_TIMER_STOP, 0); |
abe994633
|
210 |
if (ret != EFI_SUCCESS) { |
bd126692d
|
211 212 |
efi_st_error("Could not cancel timer "); |
e67e7249c
|
213 |
return EFI_ST_FAILURE; |
bd126692d
|
214 |
} |
e67e7249c
|
215 |
return EFI_ST_SUCCESS; |
bd126692d
|
216 217 218 219 220 221 222 223 224 |
} EFI_UNIT_TEST(events) = { .name = "event services", .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT, .setup = setup, .execute = execute, .teardown = teardown, }; |