blob: 097b2ae35456116abfabe1370bdad07c90cf0c1c [file] [log] [blame]
Tom Rini10e47792018-05-06 17:58:06 -04001// SPDX-License-Identifier: GPL-2.0+
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +01002/*
3 * efi_selftest_manageprotocols
4 *
5 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
6 *
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +01007 * This unit test checks the following protocol services:
8 * InstallProtocolInterface, UninstallProtocolInterface,
9 * InstallMultipleProtocolsInterfaces, UninstallMultipleProtocolsInterfaces,
10 * HandleProtocol, ProtocolsPerHandle,
11 * LocateHandle, LocateHandleBuffer.
12 */
13
14#include <efi_selftest.h>
15
16/*
17 * The test currently does not actually call the interface function.
18 * So this is just a dummy structure.
19 */
20struct interface {
21 void (EFIAPI * inc)(void);
22};
23
24static struct efi_boot_services *boottime;
25static efi_guid_t guid1 =
26 EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
27 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
28static efi_guid_t guid2 =
29 EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
30 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
31static efi_guid_t guid3 =
32 EFI_GUID(0x06d641a3, 0xf4e7, 0xe0c9,
33 0xe7, 0x8d, 0x41, 0x2d, 0x72, 0xa6, 0xb1, 0x24);
34static efi_handle_t handle1;
35static efi_handle_t handle2;
36static struct interface interface1;
37static struct interface interface2;
38static struct interface interface3;
39static struct interface interface4;
40
41/*
42 * Find a handle in an array.
43 *
44 * @handle: handle to find
45 * @count: number of entries in the array
46 * @buffer: array to search
47 */
48efi_status_t find_in_buffer(efi_handle_t handle, size_t count,
49 efi_handle_t *buffer)
50{
51 size_t i;
52
53 for (i = 0; i < count; ++i) {
54 if (buffer[i] == handle)
55 return EFI_SUCCESS;
56 }
57 return EFI_NOT_FOUND;
58}
59
60/*
61 * Setup unit test.
62 *
63 * Create two handles and install two out of three protocol interfaces on each
64 * of them:
65 *
66 * handle1
67 * guid1 interface1
68 * guid3 interface3
69 * handle2
70 * guid1 interface4
71 * guid2 interface2
72 *
73 * @handle: handle of the loaded image
74 * @systable: system table
75 */
76static int setup(const efi_handle_t img_handle,
77 const struct efi_system_table *systable)
78{
79 efi_status_t ret;
80 efi_handle_t handle;
81
Ilias Apalodimas0c57c4c2023-06-13 16:23:06 +030082 handle1 = NULL;
83 handle2 = NULL;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +010084 boottime = systable->boottime;
85
86 ret = boottime->install_protocol_interface(&handle1, &guid3,
87 EFI_NATIVE_INTERFACE,
88 &interface3);
89 if (ret != EFI_SUCCESS) {
90 efi_st_error("InstallProtocolInterface failed\n");
91 return EFI_ST_FAILURE;
92 }
93 if (!handle1) {
94 efi_st_error("InstallProtocolInterface failed to create handle\n");
95 return EFI_ST_FAILURE;
96 }
97 handle = handle1;
98 ret = boottime->install_protocol_interface(&handle1, &guid1,
99 EFI_NATIVE_INTERFACE,
100 &interface1);
101 if (ret != EFI_SUCCESS) {
102 efi_st_error("InstallProtocolInterface failed\n");
103 return EFI_ST_FAILURE;
104 }
105 if (handle != handle1) {
106 efi_st_error("InstallProtocolInterface failed to use handle\n");
107 return EFI_ST_FAILURE;
108 }
109 ret = boottime->install_multiple_protocol_interfaces(&handle2,
110 &guid1, &interface4, &guid2, &interface2, NULL);
111 if (ret != EFI_SUCCESS) {
112 efi_st_error("InstallMultipleProtocolInterfaces failed\n");
113 return EFI_ST_FAILURE;
114 }
115 if (!handle2 || handle1 == handle2) {
116 efi_st_error("InstallMultipleProtocolInterfaces failed to create handle\n");
117 return EFI_ST_FAILURE;
118 }
119
120 return EFI_ST_SUCCESS;
121}
122
123/*
124 * Tear down unit test.
125 *
126 */
127static int teardown(void)
128{
129 return EFI_ST_SUCCESS;
130}
131
132/*
133 * Execute unit test.
134 *
135 */
136static int execute(void)
137{
138 struct interface *interface;
139 efi_status_t ret;
140 efi_handle_t *buffer;
141 size_t buffer_size;
Heinrich Schuchardt798a4412017-11-06 21:17:48 +0100142 efi_uintn_t count = 0;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100143 efi_guid_t **prot_buffer;
Heinrich Schuchardt798a4412017-11-06 21:17:48 +0100144 efi_uintn_t prot_count;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100145
146 /*
147 * Test HandleProtocol
148 */
149 ret = boottime->handle_protocol(handle1, &guid3, (void **)&interface);
150 if (ret != EFI_SUCCESS) {
151 efi_st_error("HandleProtocol failed to retrieve interface\n");
152 return EFI_ST_FAILURE;
153 }
154 if (interface != &interface3) {
155 efi_st_error("HandleProtocol returned wrong interface\n");
156 return EFI_ST_FAILURE;
157 }
158 ret = boottime->handle_protocol(handle1, &guid2, (void **)&interface);
159 if (ret == EFI_SUCCESS) {
160 efi_st_error("HandleProtocol returned not installed interface\n");
161 return EFI_ST_FAILURE;
162 }
163
164 /*
165 * Test LocateHandleBuffer with AllHandles
166 */
167 ret = boottime->locate_handle_buffer(ALL_HANDLES, NULL, NULL,
168 &count, &buffer);
169 if (ret != EFI_SUCCESS) {
170 efi_st_error("LocateHandleBuffer with AllHandles failed\n");
171 return EFI_ST_FAILURE;
172 }
173 buffer_size = count;
174 ret = find_in_buffer(handle1, count, buffer);
175 if (ret != EFI_SUCCESS) {
176 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
177 return EFI_ST_FAILURE;
178 }
179 ret = find_in_buffer(handle2, count, buffer);
180 if (ret != EFI_SUCCESS) {
181 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
182 return EFI_ST_FAILURE;
183 }
Heinrich Schuchardt653517a2018-08-26 14:58:16 +0200184 /* Release buffer */
185 ret = boottime->free_pool(buffer);
186 if (ret != EFI_SUCCESS) {
187 efi_st_error("FreePool failed\n");
188 return EFI_ST_FAILURE;
189 }
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100190
191 /*
192 * Test error handling in UninstallMultipleProtocols
193 *
Heinrich Schuchardt1c76eda2018-09-24 19:57:27 +0200194 * These are the installed protocol interfaces on handle 2:
195 *
196 * guid1 interface4
197 * guid2 interface2
198 *
199 * Try to uninstall more protocols than there are installed. This
200 * should return an error EFI_INVALID_PARAMETER. All deleted protocols
201 * should be reinstalled.
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100202 */
203 ret = boottime->uninstall_multiple_protocol_interfaces(
204 handle2,
205 &guid1, &interface4,
206 &guid2, &interface2,
207 &guid3, &interface3,
208 NULL);
Heinrich Schuchardt1c76eda2018-09-24 19:57:27 +0200209 if (ret != EFI_INVALID_PARAMETER) {
210 printf("%lx", ret);
Heinrich Schuchardt4ba37042018-01-11 08:16:06 +0100211 efi_st_error("UninstallMultipleProtocolInterfaces did not catch error\n");
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100212 return EFI_ST_FAILURE;
213 }
214
215 /*
216 * Test LocateHandleBuffer with ByProtocol
Heinrich Schuchardt1c76eda2018-09-24 19:57:27 +0200217 *
218 * These are the handles with a guid1 protocol interface installed:
219 *
220 * handle1, handle2
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100221 */
222 count = buffer_size;
223 ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
224 &count, &buffer);
225 if (ret != EFI_SUCCESS) {
226 efi_st_error("LocateHandleBuffer failed to locate new handles\n");
227 return EFI_ST_FAILURE;
228 }
229 if (count != 2) {
Heinrich Schuchardt1c76eda2018-09-24 19:57:27 +0200230 efi_st_error("UninstallMultipleProtocolInterfaces deleted handle\n");
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100231 return EFI_ST_FAILURE;
232 }
233 ret = find_in_buffer(handle1, count, buffer);
234 if (ret != EFI_SUCCESS) {
235 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
236 return EFI_ST_FAILURE;
237 }
238 ret = find_in_buffer(handle2, count, buffer);
239 if (ret != EFI_SUCCESS) {
240 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
241 return EFI_ST_FAILURE;
242 }
Heinrich Schuchardt653517a2018-08-26 14:58:16 +0200243 /* Clear the buffer, we are reusing it it the next step. */
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100244 boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
245
246 /*
247 * Test LocateHandle with ByProtocol
248 */
249 count = buffer_size * sizeof(efi_handle_t);
250 ret = boottime->locate_handle(BY_PROTOCOL, &guid1, NULL,
251 &count, buffer);
252 if (ret != EFI_SUCCESS) {
253 efi_st_error("LocateHandle with ByProtocol failed\n");
254 return EFI_ST_FAILURE;
255 }
256 if (count / sizeof(efi_handle_t) != 2) {
257 efi_st_error("LocateHandle failed to locate new handles\n");
258 return EFI_ST_FAILURE;
259 }
260 buffer_size = count;
261 ret = find_in_buffer(handle1, count, buffer);
262 if (ret != EFI_SUCCESS) {
263 efi_st_error("LocateHandle failed to locate new handles\n");
264 return EFI_ST_FAILURE;
265 }
266 ret = find_in_buffer(handle2, count, buffer);
267 if (ret != EFI_SUCCESS) {
268 efi_st_error("LocateHandle failed to locate new handles\n");
269 return EFI_ST_FAILURE;
270 }
Heinrich Schuchardt653517a2018-08-26 14:58:16 +0200271 /* Release buffer */
272 ret = boottime->free_pool(buffer);
273 if (ret != EFI_SUCCESS) {
274 efi_st_error("FreePool failed\n");
275 return EFI_ST_FAILURE;
276 }
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100277
278 /*
279 * Test LocateProtocol
280 */
281 ret = boottime->locate_protocol(&guid1, NULL, (void **)&interface);
282 if (ret != EFI_SUCCESS) {
283 efi_st_error("LocateProtocol failed\n");
284 return EFI_ST_FAILURE;
285 }
286 if (interface != &interface1 && interface != &interface4) {
287 efi_st_error("LocateProtocol failed to locate protocol\n");
288 return EFI_ST_FAILURE;
289 }
290
291 /*
292 * Test UninstallMultipleProtocols
293 */
294 ret = boottime->uninstall_multiple_protocol_interfaces(
295 handle2,
296 &guid1, &interface4,
297 &guid2, &interface2,
298 NULL);
299 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt4ba37042018-01-11 08:16:06 +0100300 efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
301 return EFI_ST_FAILURE;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100302 }
303 /*
304 * Check that the protocols are really uninstalled.
305 */
306 count = buffer_size;
307 ret = boottime->locate_handle_buffer(BY_PROTOCOL, &guid1, NULL,
308 &count, &buffer);
309 if (ret != EFI_SUCCESS) {
310 efi_st_error("LocateHandleBuffer failed\n");
311 return EFI_ST_FAILURE;
312 }
313 if (count != 1) {
Heinrich Schuchardt4ba37042018-01-11 08:16:06 +0100314 efi_st_error("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n");
315 return EFI_ST_FAILURE;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100316 }
317 ret = find_in_buffer(handle1, count, buffer);
318 if (ret != EFI_SUCCESS) {
319 efi_st_error("Failed to locate new handle\n");
320 return EFI_ST_FAILURE;
321 }
322 boottime->set_mem(buffer, sizeof(efi_handle_t) * buffer_size, 0);
323
324 /*
325 * Test ProtocolsPerHandle
326 */
327 ret = boottime->protocols_per_handle(handle1,
328 &prot_buffer, &prot_count);
329 if (ret != EFI_SUCCESS) {
330 efi_st_error("Failed to get protocols per handle\n");
331 return EFI_ST_FAILURE;
332 }
333 if (prot_count != 2) {
334 efi_st_error("Failed to get protocols per handle\n");
335 return EFI_ST_FAILURE;
336 }
Heinrich Schuchardt5f946662019-05-04 19:48:38 +0200337 if (memcmp(prot_buffer[0], &guid1, 16) &&
338 memcmp(prot_buffer[1], &guid1, 16)) {
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100339 efi_st_error("Failed to get protocols per handle\n");
340 return EFI_ST_FAILURE;
341 }
Heinrich Schuchardt5f946662019-05-04 19:48:38 +0200342 if (memcmp(prot_buffer[0], &guid3, 16) &&
343 memcmp(prot_buffer[1], &guid3, 16)) {
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100344 efi_st_error("Failed to get protocols per handle\n");
345 return EFI_ST_FAILURE;
346 }
Heinrich Schuchardt653517a2018-08-26 14:58:16 +0200347 /* Release buffer */
348 ret = boottime->free_pool(prot_buffer);
349 if (ret != EFI_SUCCESS) {
350 efi_st_error("FreePool failed\n");
351 return EFI_ST_FAILURE;
352 }
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100353
354 /*
355 * Uninstall remaining protocols
356 */
357 ret = boottime->uninstall_protocol_interface(handle1, &guid1,
358 &interface1);
359 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt4ba37042018-01-11 08:16:06 +0100360 efi_st_error("UninstallProtocolInterface failed\n");
361 return EFI_ST_FAILURE;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100362 }
363 ret = boottime->handle_protocol(handle1, &guid1, (void **)&interface);
364 if (ret == EFI_SUCCESS) {
Heinrich Schuchardt4ba37042018-01-11 08:16:06 +0100365 efi_st_error("UninstallProtocolInterface failed\n");
366 return EFI_ST_FAILURE;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100367 }
368 ret = boottime->uninstall_protocol_interface(handle1, &guid3,
Heinrich Schuchardtdc05b702018-05-11 12:09:20 +0200369 &interface3);
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100370 if (ret != EFI_SUCCESS) {
Heinrich Schuchardt4ba37042018-01-11 08:16:06 +0100371 efi_st_error("UninstallProtocolInterface failed\n");
372 return EFI_ST_FAILURE;
Heinrich Schuchardtc53591c2017-11-06 21:17:43 +0100373 }
374
375 return EFI_ST_SUCCESS;
376}
377
378EFI_UNIT_TEST(protserv) = {
379 .name = "manage protocols",
380 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
381 .setup = setup,
382 .execute = execute,
383 .teardown = teardown,
384};