1 // SPDX-License-Identifier: GPL-2.0+
3 * efi_selftest_register_notify
5 * Copyright (c) 2019 Heinrich Schuchardt <xypron.glpk@gmx.de>
7 * This unit test checks the following protocol services:
8 * InstallProtocolInterface, UninstallProtocolInterface,
9 * RegisterProtocolNotify, CreateEvent, CloseEvent.
12 #include <efi_selftest.h>
15 * The test currently does not actually call the interface function.
16 * So this is just a dummy structure.
19 void (EFIAPI * inc)(void);
23 void *registration_key;
24 efi_uintn_t notify_count;
25 efi_uintn_t handle_count;
26 efi_handle_t *handles;
29 static struct efi_boot_services *boottime;
30 static efi_guid_t guid1 =
31 EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
32 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
33 static efi_guid_t guid2 =
34 EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
35 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
36 static struct context context;
37 static struct efi_event *event;
40 * Notification function, increments the notification count if parameter
41 * context is provided.
43 * @event notified event
44 * @context pointer to the notification count
46 static void EFIAPI notify(struct efi_event *event, void *context)
48 struct context *cp = context;
53 ret = boottime->locate_handle_buffer(BY_REGISTER_NOTIFY, NULL,
57 if (ret != EFI_SUCCESS)
64 * @handle: handle of the loaded image
65 * @systable: system table
67 static int setup(const efi_handle_t img_handle,
68 const struct efi_system_table *systable)
72 boottime = systable->boottime;
74 ret = boottime->create_event(EVT_NOTIFY_SIGNAL,
75 TPL_CALLBACK, notify, &context,
77 if (ret != EFI_SUCCESS) {
78 efi_st_error("could not create event\n");
79 return EFI_ST_FAILURE;
82 ret = boottime->register_protocol_notify(&guid1, event,
83 &context.registration_key);
84 if (ret != EFI_SUCCESS) {
85 efi_st_error("could not register event\n");
86 return EFI_ST_FAILURE;
89 return EFI_ST_SUCCESS;
93 * Tear down unit test.
96 static int teardown(void)
101 ret = boottime->close_event(event);
103 if (ret != EFI_SUCCESS) {
104 efi_st_error("could not close event\n");
105 return EFI_ST_FAILURE;
109 return EFI_ST_SUCCESS;
116 static int execute(void)
119 efi_handle_t handle1 = NULL, handle2 = NULL;
120 struct interface interface1, interface2;
122 ret = boottime->install_protocol_interface(&handle1, &guid1,
123 EFI_NATIVE_INTERFACE,
125 if (ret != EFI_SUCCESS) {
126 efi_st_error("could not install interface\n");
127 return EFI_ST_FAILURE;
129 if (!context.notify_count) {
130 efi_st_error("install was not notified\n");
131 return EFI_ST_FAILURE;
133 if (context.notify_count > 1) {
134 efi_st_error("install was notified too often\n");
135 return EFI_ST_FAILURE;
137 if (context.handle_count != 1) {
138 efi_st_error("LocateHandle failed\n");
139 return EFI_ST_FAILURE;
141 ret = boottime->free_pool(context.handles);
142 if (ret != EFI_SUCCESS) {
143 efi_st_error("FreePool failed\n");
144 return EFI_ST_FAILURE;
146 context.notify_count = 0;
147 ret = boottime->install_protocol_interface(&handle1, &guid2,
148 EFI_NATIVE_INTERFACE,
150 if (ret != EFI_SUCCESS) {
151 efi_st_error("could not install interface\n");
152 return EFI_ST_FAILURE;
154 if (context.notify_count) {
155 efi_st_error("wrong protocol was notified\n");
156 return EFI_ST_FAILURE;
158 context.notify_count = 0;
159 ret = boottime->reinstall_protocol_interface(handle1, &guid1,
160 &interface1, &interface2);
161 if (ret != EFI_SUCCESS) {
162 efi_st_error("could not reinstall interface\n");
163 return EFI_ST_FAILURE;
165 if (!context.notify_count) {
166 efi_st_error("reinstall was not notified\n");
167 return EFI_ST_FAILURE;
169 if (context.notify_count > 1) {
170 efi_st_error("reinstall was notified too often\n");
171 return EFI_ST_FAILURE;
173 if (context.handle_count != 1) {
174 efi_st_error("LocateHandle failed\n");
175 return EFI_ST_FAILURE;
177 ret = boottime->free_pool(context.handles);
178 if (ret != EFI_SUCCESS) {
179 efi_st_error("FreePool failed\n");
180 return EFI_ST_FAILURE;
182 context.notify_count = 0;
183 ret = boottime->install_protocol_interface(&handle2, &guid1,
184 EFI_NATIVE_INTERFACE,
186 if (ret != EFI_SUCCESS) {
187 efi_st_error("could not install interface\n");
188 return EFI_ST_FAILURE;
190 if (!context.notify_count) {
191 efi_st_error("install was not notified\n");
192 return EFI_ST_FAILURE;
194 if (context.notify_count > 1) {
195 efi_st_error("install was notified too often\n");
196 return EFI_ST_FAILURE;
198 if (context.handle_count != 2) {
199 efi_st_error("LocateHandle failed\n");
200 return EFI_ST_FAILURE;
202 ret = boottime->free_pool(context.handles);
203 if (ret != EFI_SUCCESS) {
204 efi_st_error("FreePool failed\n");
205 return EFI_ST_FAILURE;
208 ret = boottime->uninstall_multiple_protocol_interfaces
209 (handle1, &guid1, &interface2,
210 &guid2, &interface1, NULL);
211 if (ret != EFI_SUCCESS) {
212 efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
213 return EFI_ST_FAILURE;
215 ret = boottime->uninstall_multiple_protocol_interfaces
216 (handle2, &guid1, &interface1, NULL);
217 if (ret != EFI_SUCCESS) {
218 efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
219 return EFI_ST_FAILURE;
222 return EFI_ST_SUCCESS;
225 EFI_UNIT_TEST(regprotnot) = {
226 .name = "register protocol notify",
227 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
230 .teardown = teardown,