1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3  * efi_selftest_controllers
4  *
5  * Copyright (c) 2017 Heinrich Schuchardt <xypron.glpk@gmx.de>
6  *
7  * This unit test checks the following protocol services:
8  * ConnectController, DisconnectController,
9  * InstallProtocol, ReinstallProtocol, UninstallProtocol,
10  * OpenProtocol, CloseProtcol, OpenProtocolInformation
11  */
12 
13 #include <efi_selftest.h>
14 
15 #define NUMBER_OF_CHILD_CONTROLLERS 4
16 
17 static int interface1 = 1;
18 static int interface2 = 2;
19 static struct efi_boot_services *boottime;
20 const efi_guid_t guid_driver_binding_protocol =
21 			EFI_DRIVER_BINDING_PROTOCOL_GUID;
22 static efi_guid_t guid_controller =
23 	EFI_GUID(0xe6ab1d96, 0x6bff, 0xdb42,
24 		 0xaa, 0x05, 0xc8, 0x1f, 0x7f, 0x45, 0x26, 0x34);
25 static efi_guid_t guid_child_controller =
26 	EFI_GUID(0x1d41f6f5, 0x2c41, 0xddfb,
27 		 0xe2, 0x9b, 0xb8, 0x0e, 0x2e, 0xe8, 0x3a, 0x85);
28 static efi_handle_t handle_controller;
29 static efi_handle_t handle_child_controller[NUMBER_OF_CHILD_CONTROLLERS];
30 static efi_handle_t handle_driver;
31 static bool allow_removal;
32 
33 /*
34  * Count child controllers
35  *
36  * @handle	handle on which child controllers are installed
37  * @protocol	protocol for which the child controllers were installed
38  * @count	number of child controllers
39  * Return:	status code
40  */
count_child_controllers(efi_handle_t handle,efi_guid_t * protocol,efi_uintn_t * count)41 static efi_status_t count_child_controllers(efi_handle_t handle,
42 					    efi_guid_t *protocol,
43 					    efi_uintn_t *count)
44 {
45 	efi_status_t ret;
46 	efi_uintn_t entry_count;
47 	struct efi_open_protocol_info_entry *entry_buffer;
48 
49 	*count = 0;
50 	ret = boottime->open_protocol_information(handle, protocol,
51 						  &entry_buffer, &entry_count);
52 	if (ret != EFI_SUCCESS)
53 		return ret;
54 	if (!entry_count)
55 		return EFI_SUCCESS;
56 	while (entry_count) {
57 		if (entry_buffer[--entry_count].attributes &
58 		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
59 			++*count;
60 	}
61 	ret = boottime->free_pool(entry_buffer);
62 	if (ret != EFI_SUCCESS)
63 		efi_st_error("Cannot free buffer\n");
64 	return ret;
65 }
66 
67 /*
68  * Check if the driver supports the controller.
69  *
70  * @this			driver binding protocol
71  * @controller_handle		handle of the controller
72  * @remaining_device_path	path specifying the child controller
73  * Return:			status code
74  */
supported(struct efi_driver_binding_protocol * this,efi_handle_t controller_handle,struct efi_device_path * remaining_device_path)75 static efi_status_t EFIAPI supported(
76 		struct efi_driver_binding_protocol *this,
77 		efi_handle_t controller_handle,
78 		struct efi_device_path *remaining_device_path)
79 {
80 	efi_status_t ret;
81 	void *interface;
82 
83 	ret = boottime->open_protocol(
84 			controller_handle, &guid_controller,
85 			&interface, handle_driver,
86 			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
87 	switch (ret) {
88 	case EFI_ACCESS_DENIED:
89 		return ret;
90 	case EFI_ALREADY_STARTED:
91 	case EFI_SUCCESS:
92 		break;
93 	default:
94 		return EFI_UNSUPPORTED;
95 	}
96 	ret = boottime->close_protocol(
97 				controller_handle, &guid_controller,
98 				handle_driver, controller_handle);
99 	if (ret != EFI_SUCCESS)
100 		ret = EFI_UNSUPPORTED;
101 	return ret;
102 }
103 
104 /*
105  * Create child controllers and attach driver.
106  *
107  * @this			driver binding protocol
108  * @controller_handle		handle of the controller
109  * @remaining_device_path	path specifying the child controller
110  * Return:			status code
111  */
start(struct efi_driver_binding_protocol * this,efi_handle_t controller_handle,struct efi_device_path * remaining_device_path)112 static efi_status_t EFIAPI start(
113 		struct efi_driver_binding_protocol *this,
114 		efi_handle_t controller_handle,
115 		struct efi_device_path *remaining_device_path)
116 {
117 	size_t i;
118 	efi_status_t ret;
119 	void *interface;
120 
121 	/* Attach driver to controller */
122 	ret = boottime->open_protocol(
123 			controller_handle, &guid_controller,
124 			&interface, handle_driver,
125 			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
126 	switch (ret) {
127 	case EFI_ACCESS_DENIED:
128 		return ret;
129 	case EFI_ALREADY_STARTED:
130 	case EFI_SUCCESS:
131 		break;
132 	default:
133 		return EFI_UNSUPPORTED;
134 	}
135 
136 	/* Create child controllers */
137 	for (i = 0; i < NUMBER_OF_CHILD_CONTROLLERS; ++i) {
138 		/* Creating a new handle for the child controller */
139 		handle_child_controller[i] = 0;
140 		ret = boottime->install_protocol_interface(
141 			&handle_child_controller[i], &guid_child_controller,
142 			EFI_NATIVE_INTERFACE, NULL);
143 		if (ret != EFI_SUCCESS) {
144 			efi_st_error("InstallProtocolInterface failed\n");
145 			return EFI_ST_FAILURE;
146 		}
147 		ret = boottime->open_protocol(
148 			controller_handle, &guid_controller,
149 			&interface, handle_child_controller[i],
150 			handle_child_controller[i],
151 			EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
152 		if (ret != EFI_SUCCESS) {
153 			efi_st_error("OpenProtocol failed\n");
154 			return EFI_ST_FAILURE;
155 		}
156 	}
157 	return ret;
158 }
159 
160 /*
161  * Remove a single child controller from the parent controller.
162  *
163  * @controller_handle	parent controller
164  * @child_handle	child controller
165  * Return:		status code
166  */
disconnect_child(efi_handle_t controller_handle,efi_handle_t child_handle)167 static efi_status_t disconnect_child(efi_handle_t controller_handle,
168 				     efi_handle_t child_handle)
169 {
170 	efi_status_t ret;
171 
172 	ret = boottime->close_protocol(
173 				controller_handle, &guid_controller,
174 				child_handle, child_handle);
175 	if (ret != EFI_SUCCESS) {
176 		efi_st_error("Cannot close protocol\n");
177 		return ret;
178 	}
179 	ret = boottime->uninstall_protocol_interface(
180 				child_handle, &guid_child_controller, NULL);
181 	if (ret != EFI_SUCCESS) {
182 		efi_st_error("Cannot uninstall protocol interface\n");
183 		return ret;
184 	}
185 	return ret;
186 }
187 
188 /*
189  * Remove child controllers and disconnect the controller.
190  *
191  * @this			driver binding protocol
192  * @controller_handle		handle of the controller
193  * @number_of_children		number of child controllers to remove
194  * @child_handle_buffer		handles of the child controllers to remove
195  * Return:			status code
196  */
stop(struct efi_driver_binding_protocol * this,efi_handle_t controller_handle,size_t number_of_children,efi_handle_t * child_handle_buffer)197 static efi_status_t EFIAPI stop(
198 		struct efi_driver_binding_protocol *this,
199 		efi_handle_t controller_handle,
200 		size_t number_of_children,
201 		efi_handle_t *child_handle_buffer)
202 {
203 	efi_status_t ret;
204 	efi_uintn_t count;
205 	struct efi_open_protocol_info_entry *entry_buffer;
206 
207 	/* Destroy provided child controllers */
208 	if (number_of_children) {
209 		efi_uintn_t i;
210 
211 		for (i = 0; i < number_of_children; ++i) {
212 			ret = disconnect_child(controller_handle,
213 					       child_handle_buffer[i]);
214 			if (ret != EFI_SUCCESS)
215 				return ret;
216 		}
217 		return EFI_SUCCESS;
218 	}
219 
220 	/* Destroy all children */
221 	ret = boottime->open_protocol_information(
222 					controller_handle, &guid_controller,
223 					&entry_buffer, &count);
224 	if (ret != EFI_SUCCESS) {
225 		efi_st_error("OpenProtocolInformation failed\n");
226 		return ret;
227 	}
228 	while (count) {
229 		if (entry_buffer[--count].attributes &
230 		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
231 			ret = disconnect_child(
232 					controller_handle,
233 					entry_buffer[count].agent_handle);
234 			if (ret != EFI_SUCCESS)
235 				return ret;
236 		}
237 	}
238 	ret = boottime->free_pool(entry_buffer);
239 	if (ret != EFI_SUCCESS)
240 		efi_st_error("Cannot free buffer\n");
241 
242 	if (!allow_removal)
243 		return EFI_DEVICE_ERROR;
244 
245 	/* Detach driver from controller */
246 	ret = boottime->close_protocol(
247 			controller_handle, &guid_controller,
248 			handle_driver, controller_handle);
249 	if (ret != EFI_SUCCESS) {
250 		efi_st_error("Cannot close protocol\n");
251 		return ret;
252 	}
253 	return EFI_SUCCESS;
254 }
255 
256 /* Driver binding protocol interface */
257 static struct efi_driver_binding_protocol binding_interface = {
258 	supported,
259 	start,
260 	stop,
261 	0xffffffff,
262 	NULL,
263 	NULL,
264 	};
265 
266 /*
267  * Setup unit test.
268  *
269  * @handle	handle of the loaded image
270  * @systable	system table
271  */
setup(const efi_handle_t img_handle,const struct efi_system_table * systable)272 static int setup(const efi_handle_t img_handle,
273 		 const struct efi_system_table *systable)
274 {
275 	efi_status_t ret;
276 
277 	boottime = systable->boottime;
278 	handle_controller =  NULL;
279 	handle_driver = NULL;
280 
281 	/* Create controller handle */
282 	ret = boottime->install_protocol_interface(
283 			&handle_controller, &guid_controller,
284 			EFI_NATIVE_INTERFACE, &interface1);
285 	if (ret != EFI_SUCCESS) {
286 		efi_st_error("InstallProtocolInterface failed\n");
287 		return EFI_ST_FAILURE;
288 	}
289 	/* Create driver handle */
290 	ret = boottime->install_protocol_interface(
291 			&handle_driver,  &guid_driver_binding_protocol,
292 			EFI_NATIVE_INTERFACE, &binding_interface);
293 	if (ret != EFI_SUCCESS) {
294 		efi_st_error("InstallProtocolInterface failed\n");
295 		return EFI_ST_FAILURE;
296 	}
297 
298 	return EFI_ST_SUCCESS;
299 }
300 
301 /*
302  * Execute unit test.
303  *
304  * The number of child controllers is checked after each of the following
305  * actions:
306  *
307  * Connect a controller to a driver.
308  * Disconnect and destroy a child controller.
309  * Disconnect and destroy the remaining child controllers.
310  *
311  * Connect a controller to a driver.
312  * Reinstall the driver protocol on the controller.
313  * Uninstall the driver protocol from the controller.
314  */
execute(void)315 static int execute(void)
316 {
317 	efi_status_t ret;
318 	efi_uintn_t count;
319 
320 	/* Connect controller to driver */
321 	ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
322 	if (ret != EFI_SUCCESS) {
323 		efi_st_error("Failed to connect controller\n");
324 		return EFI_ST_FAILURE;
325 	}
326 	/* Check number of child controllers */
327 	ret = count_child_controllers(handle_controller, &guid_controller,
328 				      &count);
329 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
330 		efi_st_error("Number of children %u != %u\n",
331 			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
332 	}
333 	/* Destroy second child controller */
334 	ret = boottime->disconnect_controller(handle_controller,
335 					      handle_driver,
336 					      handle_child_controller[1]);
337 	if (ret != EFI_SUCCESS) {
338 		efi_st_error("Failed to disconnect child controller\n");
339 		return EFI_ST_FAILURE;
340 	}
341 	/* Check number of child controllers */
342 	ret = count_child_controllers(handle_controller, &guid_controller,
343 				      &count);
344 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS - 1) {
345 		efi_st_error("Destroying single child controller failed\n");
346 		return EFI_ST_FAILURE;
347 	}
348 	/* Destroy remaining child controllers and disconnect controller */
349 	allow_removal = true;
350 	ret = boottime->disconnect_controller(handle_controller, NULL, NULL);
351 	if (ret != EFI_SUCCESS) {
352 		efi_st_error("Failed to disconnect controller\n");
353 		return EFI_ST_FAILURE;
354 	}
355 	/* Check number of child controllers */
356 	ret = count_child_controllers(handle_controller, &guid_controller,
357 				      &count);
358 	if (ret != EFI_SUCCESS || count) {
359 		efi_st_error("Destroying child controllers failed\n");
360 		return EFI_ST_FAILURE;
361 	}
362 
363 	/* Connect controller to driver */
364 	ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
365 	if (ret != EFI_SUCCESS) {
366 		efi_st_error("Failed to connect controller\n");
367 		return EFI_ST_FAILURE;
368 	}
369 	/* Check number of child controllers */
370 	ret = count_child_controllers(handle_controller, &guid_controller,
371 				      &count);
372 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
373 		efi_st_error("Number of children %u != %u\n",
374 			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
375 	}
376 	/* Try to uninstall controller protocol using the wrong interface */
377 	ret = boottime->uninstall_protocol_interface(handle_controller,
378 						     &guid_controller,
379 						     &interface2);
380 	if (ret == EFI_SUCCESS) {
381 		efi_st_error(
382 			"Interface not checked when uninstalling protocol\n");
383 		return EFI_ST_FAILURE;
384 	}
385 	/* Reinstall controller protocol */
386 	ret = boottime->reinstall_protocol_interface(handle_controller,
387 						     &guid_controller,
388 						     &interface1,
389 						     &interface2);
390 	if (ret != EFI_SUCCESS) {
391 		efi_st_error("Failed to reinstall protocols\n");
392 		return EFI_ST_FAILURE;
393 	}
394 	/* Check number of child controllers */
395 	ret = count_child_controllers(handle_controller, &guid_controller,
396 				      &count);
397 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
398 		efi_st_error("Number of children %u != %u\n",
399 			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
400 	}
401 
402 	allow_removal = false;
403 	/* Try to uninstall controller protocol using the wrong interface */
404 	ret = boottime->uninstall_protocol_interface(handle_controller,
405 						     &guid_controller,
406 						     &interface1);
407 	if (ret != EFI_NOT_FOUND) {
408 		efi_st_error("Interface not checked when uninstalling protocol\n");
409 		return EFI_ST_FAILURE;
410 	}
411 
412 	/*
413 	 * Uninstall a protocol while Disconnect controller won't
414 	 * allow it.
415 	 */
416 	ret = boottime->uninstall_protocol_interface(handle_controller,
417 						     &guid_controller,
418 						     &interface2);
419 	if (ret != EFI_ACCESS_DENIED) {
420 		efi_st_error("Uninstall protocol interface failed\n");
421 		return EFI_ST_FAILURE;
422 	}
423 	/*
424 	 * Check number of child controllers and make sure children have
425 	 * been reconnected
426 	 */
427 	ret = count_child_controllers(handle_controller, &guid_controller,
428 				      &count);
429 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
430 		efi_st_error("Number of children %u != %u\n",
431 			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
432 	}
433 
434 	allow_removal = true;
435 	ret = boottime->uninstall_protocol_interface(handle_controller,
436 						     &guid_controller,
437 						     &interface2);
438 	if (ret != EFI_SUCCESS) {
439 		efi_st_error("Failed to uninstall protocols\n");
440 		return EFI_ST_FAILURE;
441 	}
442 	/* Check number of child controllers */
443 	ret = count_child_controllers(handle_controller, &guid_controller,
444 				      &count);
445 	if (ret == EFI_SUCCESS || count) {
446 		efi_st_error("Uninstall failed\n");
447 		return EFI_ST_FAILURE;
448 	}
449 
450 	return EFI_ST_SUCCESS;
451 }
452 
453   /*
454    * Tear down unit test.
455    *
456    */
teardown(void)457 static int teardown(void)
458 {
459 	efi_status_t ret;
460 	/* Uninstall binding protocol */
461 	ret = boottime->uninstall_protocol_interface(handle_driver,
462 						     &guid_driver_binding_protocol,
463 						     &binding_interface);
464 	if (ret != EFI_SUCCESS)
465 		efi_st_error("Failed to uninstall protocols\n");
466 
467 	return ret;
468 }
469 
470 EFI_UNIT_TEST(controllers) = {
471 	.name = "controllers",
472 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
473 	.setup = setup,
474 	.execute = execute,
475 	.teardown = teardown,
476 };
477