1 // SPDX-License-Identifier: GPL-2.0+
3 * efi_selftest_manageprotocols
5 * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
7 * This unit test checks the following protocol services:
8 * InstallProtocolInterface, UninstallProtocolInterface,
9 * InstallMultipleProtocolsInterfaces, UninstallMultipleProtocolsInterfaces,
10 * HandleProtocol, ProtocolsPerHandle,
11 * LocateHandle, LocateHandleBuffer.
14 #include <efi_selftest.h>
17 * The test currently does not actually call the interface function.
18 * So this is just a dummy structure.
21 void (EFIAPI
* inc
)(void);
24 static struct efi_boot_services
*boottime
;
25 static efi_guid_t guid1
=
26 EFI_GUID(0x2e7ca819, 0x21d3, 0x0a3a,
27 0xf7, 0x91, 0x82, 0x1f, 0x7a, 0x83, 0x67, 0xaf);
28 static efi_guid_t guid2
=
29 EFI_GUID(0xf909f2bb, 0x90a8, 0x0d77,
30 0x94, 0x0c, 0x3e, 0xa8, 0xea, 0x38, 0xd6, 0x6f);
31 static efi_guid_t guid3
=
32 EFI_GUID(0x06d641a3, 0xf4e7, 0xe0c9,
33 0xe7, 0x8d, 0x41, 0x2d, 0x72, 0xa6, 0xb1, 0x24);
34 static efi_handle_t handle1
;
35 static efi_handle_t handle2
;
36 static struct interface interface1
;
37 static struct interface interface2
;
38 static struct interface interface3
;
39 static struct interface interface4
;
42 * Find a handle in an array.
44 * @handle: handle to find
45 * @count: number of entries in the array
46 * @buffer: array to search
48 efi_status_t
find_in_buffer(efi_handle_t handle
, size_t count
,
53 for (i
= 0; i
< count
; ++i
) {
54 if (buffer
[i
] == handle
)
63 * Create two handles and install two out of three protocol interfaces on each
73 * @handle: handle of the loaded image
74 * @systable: system table
76 static int setup(const efi_handle_t img_handle
,
77 const struct efi_system_table
*systable
)
82 boottime
= systable
->boottime
;
84 ret
= boottime
->install_protocol_interface(&handle1
, &guid3
,
87 if (ret
!= EFI_SUCCESS
) {
88 efi_st_error("InstallProtocolInterface failed\n");
89 return EFI_ST_FAILURE
;
92 efi_st_error("InstallProtocolInterface failed to create handle\n");
93 return EFI_ST_FAILURE
;
96 ret
= boottime
->install_protocol_interface(&handle1
, &guid1
,
99 if (ret
!= EFI_SUCCESS
) {
100 efi_st_error("InstallProtocolInterface failed\n");
101 return EFI_ST_FAILURE
;
103 if (handle
!= handle1
) {
104 efi_st_error("InstallProtocolInterface failed to use handle\n");
105 return EFI_ST_FAILURE
;
107 ret
= boottime
->install_multiple_protocol_interfaces(&handle2
,
108 &guid1
, &interface4
, &guid2
, &interface2
, NULL
);
109 if (ret
!= EFI_SUCCESS
) {
110 efi_st_error("InstallMultipleProtocolInterfaces failed\n");
111 return EFI_ST_FAILURE
;
113 if (!handle2
|| handle1
== handle2
) {
114 efi_st_error("InstallMultipleProtocolInterfaces failed to create handle\n");
115 return EFI_ST_FAILURE
;
118 return EFI_ST_SUCCESS
;
122 * Tear down unit test.
125 static int teardown(void)
127 return EFI_ST_SUCCESS
;
134 static int execute(void)
136 struct interface
*interface
;
138 efi_handle_t
*buffer
;
140 efi_uintn_t count
= 0;
141 efi_guid_t
**prot_buffer
;
142 efi_uintn_t prot_count
;
145 * Test HandleProtocol
147 ret
= boottime
->handle_protocol(handle1
, &guid3
, (void **)&interface
);
148 if (ret
!= EFI_SUCCESS
) {
149 efi_st_error("HandleProtocol failed to retrieve interface\n");
150 return EFI_ST_FAILURE
;
152 if (interface
!= &interface3
) {
153 efi_st_error("HandleProtocol returned wrong interface\n");
154 return EFI_ST_FAILURE
;
156 ret
= boottime
->handle_protocol(handle1
, &guid2
, (void **)&interface
);
157 if (ret
== EFI_SUCCESS
) {
158 efi_st_error("HandleProtocol returned not installed interface\n");
159 return EFI_ST_FAILURE
;
163 * Test LocateHandleBuffer with AllHandles
165 ret
= boottime
->locate_handle_buffer(ALL_HANDLES
, NULL
, NULL
,
167 if (ret
!= EFI_SUCCESS
) {
168 efi_st_error("LocateHandleBuffer with AllHandles failed\n");
169 return EFI_ST_FAILURE
;
172 ret
= find_in_buffer(handle1
, count
, buffer
);
173 if (ret
!= EFI_SUCCESS
) {
174 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
175 return EFI_ST_FAILURE
;
177 ret
= find_in_buffer(handle2
, count
, buffer
);
178 if (ret
!= EFI_SUCCESS
) {
179 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
180 return EFI_ST_FAILURE
;
183 ret
= boottime
->free_pool(buffer
);
184 if (ret
!= EFI_SUCCESS
) {
185 efi_st_error("FreePool failed\n");
186 return EFI_ST_FAILURE
;
190 * Test error handling in UninstallMultipleProtocols
192 * These are the installed protocol interfaces on handle 2:
197 * Try to uninstall more protocols than there are installed. This
198 * should return an error EFI_INVALID_PARAMETER. All deleted protocols
199 * should be reinstalled.
201 ret
= boottime
->uninstall_multiple_protocol_interfaces(
207 if (ret
!= EFI_INVALID_PARAMETER
) {
209 efi_st_error("UninstallMultipleProtocolInterfaces did not catch error\n");
210 return EFI_ST_FAILURE
;
214 * Test LocateHandleBuffer with ByProtocol
216 * These are the handles with a guid1 protocol interface installed:
221 ret
= boottime
->locate_handle_buffer(BY_PROTOCOL
, &guid1
, NULL
,
223 if (ret
!= EFI_SUCCESS
) {
224 efi_st_error("LocateHandleBuffer failed to locate new handles\n");
225 return EFI_ST_FAILURE
;
228 efi_st_error("UninstallMultipleProtocolInterfaces deleted handle\n");
229 return EFI_ST_FAILURE
;
231 ret
= find_in_buffer(handle1
, count
, buffer
);
232 if (ret
!= EFI_SUCCESS
) {
233 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
234 return EFI_ST_FAILURE
;
236 ret
= find_in_buffer(handle2
, count
, buffer
);
237 if (ret
!= EFI_SUCCESS
) {
238 efi_st_error("LocateHandleBuffer failed to locate new handle\n");
239 return EFI_ST_FAILURE
;
241 /* Clear the buffer, we are reusing it it the next step. */
242 boottime
->set_mem(buffer
, sizeof(efi_handle_t
) * buffer_size
, 0);
245 * Test LocateHandle with ByProtocol
247 count
= buffer_size
* sizeof(efi_handle_t
);
248 ret
= boottime
->locate_handle(BY_PROTOCOL
, &guid1
, NULL
,
250 if (ret
!= EFI_SUCCESS
) {
251 efi_st_error("LocateHandle with ByProtocol failed\n");
252 return EFI_ST_FAILURE
;
254 if (count
/ sizeof(efi_handle_t
) != 2) {
255 efi_st_error("LocateHandle failed to locate new handles\n");
256 return EFI_ST_FAILURE
;
259 ret
= find_in_buffer(handle1
, count
, buffer
);
260 if (ret
!= EFI_SUCCESS
) {
261 efi_st_error("LocateHandle failed to locate new handles\n");
262 return EFI_ST_FAILURE
;
264 ret
= find_in_buffer(handle2
, count
, buffer
);
265 if (ret
!= EFI_SUCCESS
) {
266 efi_st_error("LocateHandle failed to locate new handles\n");
267 return EFI_ST_FAILURE
;
270 ret
= boottime
->free_pool(buffer
);
271 if (ret
!= EFI_SUCCESS
) {
272 efi_st_error("FreePool failed\n");
273 return EFI_ST_FAILURE
;
277 * Test LocateProtocol
279 ret
= boottime
->locate_protocol(&guid1
, NULL
, (void **)&interface
);
280 if (ret
!= EFI_SUCCESS
) {
281 efi_st_error("LocateProtocol failed\n");
282 return EFI_ST_FAILURE
;
284 if (interface
!= &interface1
&& interface
!= &interface4
) {
285 efi_st_error("LocateProtocol failed to locate protocol\n");
286 return EFI_ST_FAILURE
;
290 * Test UninstallMultipleProtocols
292 ret
= boottime
->uninstall_multiple_protocol_interfaces(
297 if (ret
!= EFI_SUCCESS
) {
298 efi_st_error("UninstallMultipleProtocolInterfaces failed\n");
299 return EFI_ST_FAILURE
;
302 * Check that the protocols are really uninstalled.
305 ret
= boottime
->locate_handle_buffer(BY_PROTOCOL
, &guid1
, NULL
,
307 if (ret
!= EFI_SUCCESS
) {
308 efi_st_error("LocateHandleBuffer failed\n");
309 return EFI_ST_FAILURE
;
312 efi_st_error("UninstallMultipleProtocolInterfaces failed to uninstall protocols\n");
313 return EFI_ST_FAILURE
;
315 ret
= find_in_buffer(handle1
, count
, buffer
);
316 if (ret
!= EFI_SUCCESS
) {
317 efi_st_error("Failed to locate new handle\n");
318 return EFI_ST_FAILURE
;
320 boottime
->set_mem(buffer
, sizeof(efi_handle_t
) * buffer_size
, 0);
323 * Test ProtocolsPerHandle
325 ret
= boottime
->protocols_per_handle(handle1
,
326 &prot_buffer
, &prot_count
);
327 if (ret
!= EFI_SUCCESS
) {
328 efi_st_error("Failed to get protocols per handle\n");
329 return EFI_ST_FAILURE
;
331 if (prot_count
!= 2) {
332 efi_st_error("Failed to get protocols per handle\n");
333 return EFI_ST_FAILURE
;
335 if (memcmp(prot_buffer
[0], &guid1
, 16) &&
336 memcmp(prot_buffer
[1], &guid1
, 16)) {
337 efi_st_error("Failed to get protocols per handle\n");
338 return EFI_ST_FAILURE
;
340 if (memcmp(prot_buffer
[0], &guid3
, 16) &&
341 memcmp(prot_buffer
[1], &guid3
, 16)) {
342 efi_st_error("Failed to get protocols per handle\n");
343 return EFI_ST_FAILURE
;
346 ret
= boottime
->free_pool(prot_buffer
);
347 if (ret
!= EFI_SUCCESS
) {
348 efi_st_error("FreePool failed\n");
349 return EFI_ST_FAILURE
;
353 * Uninstall remaining protocols
355 ret
= boottime
->uninstall_protocol_interface(handle1
, &guid1
,
357 if (ret
!= EFI_SUCCESS
) {
358 efi_st_error("UninstallProtocolInterface failed\n");
359 return EFI_ST_FAILURE
;
361 ret
= boottime
->handle_protocol(handle1
, &guid1
, (void **)&interface
);
362 if (ret
== EFI_SUCCESS
) {
363 efi_st_error("UninstallProtocolInterface failed\n");
364 return EFI_ST_FAILURE
;
366 ret
= boottime
->uninstall_protocol_interface(handle1
, &guid3
,
368 if (ret
!= EFI_SUCCESS
) {
369 efi_st_error("UninstallProtocolInterface failed\n");
370 return EFI_ST_FAILURE
;
373 return EFI_ST_SUCCESS
;
376 EFI_UNIT_TEST(protserv
) = {
377 .name
= "manage protocols",
378 .phase
= EFI_EXECUTE_BEFORE_BOOTTIME_EXIT
,
381 .teardown
= teardown
,