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 
32 /*
33  * Count child controllers
34  *
35  * @handle	handle on which child controllers are installed
36  * @protocol	protocol for which the child controlles where installed
37  * @count	number of child controllers
38  * @return	status code
39  */
40 static efi_status_t count_child_controllers(efi_handle_t handle,
41 					    efi_guid_t *protocol,
42 					    efi_uintn_t *count)
43 {
44 	efi_status_t ret;
45 	efi_uintn_t entry_count;
46 	struct efi_open_protocol_info_entry *entry_buffer;
47 
48 	*count = 0;
49 	ret = boottime->open_protocol_information(handle, protocol,
50 						  &entry_buffer, &entry_count);
51 	if (ret != EFI_SUCCESS)
52 		return ret;
53 	if (!entry_count)
54 		return EFI_SUCCESS;
55 	while (entry_count) {
56 		if (entry_buffer[--entry_count].attributes &
57 		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
58 			++*count;
59 	}
60 	ret = boottime->free_pool(entry_buffer);
61 	if (ret != EFI_SUCCESS)
62 		efi_st_error("Cannot free buffer\n");
63 	return ret;
64 }
65 
66 /*
67  * Check if the driver supports the controller.
68  *
69  * @this			driver binding protocol
70  * @controller_handle		handle of the controller
71  * @remaining_device_path	path specifying the child controller
72  * @return			status code
73  */
74 static efi_status_t EFIAPI supported(
75 		struct efi_driver_binding_protocol *this,
76 		efi_handle_t controller_handle,
77 		struct efi_device_path *remaining_device_path)
78 {
79 	efi_status_t ret;
80 	void *interface;
81 
82 	ret = boottime->open_protocol(
83 			controller_handle, &guid_controller,
84 			&interface, handle_driver,
85 			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
86 	switch (ret) {
87 	case EFI_ACCESS_DENIED:
88 	case EFI_ALREADY_STARTED:
89 		return ret;
90 	case EFI_SUCCESS:
91 		break;
92 	default:
93 		return EFI_UNSUPPORTED;
94 	}
95 	ret = boottime->close_protocol(
96 				controller_handle, &guid_controller,
97 				handle_driver, controller_handle);
98 	if (ret != EFI_SUCCESS)
99 		ret = EFI_UNSUPPORTED;
100 	return ret;
101 }
102 
103 /*
104  * Create child controllers and attach driver.
105  *
106  * @this			driver binding protocol
107  * @controller_handle		handle of the controller
108  * @remaining_device_path	path specifying the child controller
109  * @return			status code
110  */
111 static efi_status_t EFIAPI start(
112 		struct efi_driver_binding_protocol *this,
113 		efi_handle_t controller_handle,
114 		struct efi_device_path *remaining_device_path)
115 {
116 	size_t i;
117 	efi_status_t ret;
118 	void *interface;
119 
120 	/* Attach driver to controller */
121 	ret = boottime->open_protocol(
122 			controller_handle, &guid_controller,
123 			&interface, handle_driver,
124 			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
125 	switch (ret) {
126 	case EFI_ACCESS_DENIED:
127 	case EFI_ALREADY_STARTED:
128 		return ret;
129 	case EFI_SUCCESS:
130 		break;
131 	default:
132 		return EFI_UNSUPPORTED;
133 	}
134 
135 	/* Create child controllers */
136 	for (i = 0; i < NUMBER_OF_CHILD_CONTROLLERS; ++i) {
137 		ret = boottime->install_protocol_interface(
138 			&handle_child_controller[i], &guid_child_controller,
139 			EFI_NATIVE_INTERFACE, NULL);
140 		if (ret != EFI_SUCCESS) {
141 			efi_st_error("InstallProtocolInterface failed\n");
142 			return EFI_ST_FAILURE;
143 		}
144 		ret = boottime->open_protocol(
145 			controller_handle, &guid_controller,
146 			&interface, handle_child_controller[i],
147 			handle_child_controller[i],
148 			EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER);
149 		if (ret != EFI_SUCCESS) {
150 			efi_st_error("OpenProtocol failed\n");
151 			return EFI_ST_FAILURE;
152 		}
153 	}
154 	return ret;
155 }
156 
157 /*
158  * Remove a single child controller from the parent controller.
159  *
160  * @controller_handle	parent controller
161  * @child_handle	child controller
162  * @return		status code
163  */
164 static efi_status_t disconnect_child(efi_handle_t controller_handle,
165 				     efi_handle_t child_handle)
166 {
167 	efi_status_t ret;
168 
169 	ret = boottime->close_protocol(
170 				controller_handle, &guid_controller,
171 				child_handle, child_handle);
172 	if (ret != EFI_SUCCESS) {
173 		efi_st_error("Cannot close protocol\n");
174 		return ret;
175 	}
176 	ret = boottime->uninstall_protocol_interface(
177 				child_handle, &guid_child_controller, NULL);
178 	if (ret != EFI_SUCCESS) {
179 		efi_st_error("Cannot uninstall protocol interface\n");
180 		return ret;
181 	}
182 	return ret;
183 }
184 
185 /*
186  * Remove child controllers and disconnect the controller.
187  *
188  * @this			driver binding protocol
189  * @controller_handle		handle of the controller
190  * @number_of_children		number of child controllers to remove
191  * @child_handle_buffer		handles of the child controllers to remove
192  * @return			status code
193  */
194 static efi_status_t EFIAPI stop(
195 		struct efi_driver_binding_protocol *this,
196 		efi_handle_t controller_handle,
197 		size_t number_of_children,
198 		efi_handle_t *child_handle_buffer)
199 {
200 	efi_status_t ret;
201 	efi_uintn_t count;
202 	struct efi_open_protocol_info_entry *entry_buffer;
203 
204 	/* Destroy provided child controllers */
205 	if (number_of_children) {
206 		efi_uintn_t i;
207 
208 		for (i = 0; i < number_of_children; ++i) {
209 			ret = disconnect_child(controller_handle,
210 					       child_handle_buffer[i]);
211 			if (ret != EFI_SUCCESS)
212 				return ret;
213 		}
214 		return EFI_SUCCESS;
215 	}
216 
217 	/* Destroy all children */
218 	ret = boottime->open_protocol_information(
219 					controller_handle, &guid_controller,
220 					&entry_buffer, &count);
221 	if (ret != EFI_SUCCESS) {
222 		efi_st_error("OpenProtocolInformation failed\n");
223 		return ret;
224 	}
225 	while (count) {
226 		if (entry_buffer[--count].attributes &
227 		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
228 			ret = disconnect_child(
229 					controller_handle,
230 					entry_buffer[count].agent_handle);
231 			if (ret != EFI_SUCCESS)
232 				return ret;
233 		}
234 	}
235 	ret = boottime->free_pool(entry_buffer);
236 	if (ret != EFI_SUCCESS)
237 		efi_st_error("Cannot free buffer\n");
238 
239 	/* Detach driver from controller */
240 	ret = boottime->close_protocol(
241 			controller_handle, &guid_controller,
242 			handle_driver, controller_handle);
243 	if (ret != EFI_SUCCESS) {
244 		efi_st_error("Cannot close protocol\n");
245 		return ret;
246 	}
247 	return EFI_SUCCESS;
248 }
249 
250 /* Driver binding protocol interface */
251 static struct efi_driver_binding_protocol binding_interface = {
252 	supported,
253 	start,
254 	stop,
255 	0xffffffff,
256 	NULL,
257 	NULL,
258 	};
259 
260 /*
261  * Setup unit test.
262  *
263  * @handle	handle of the loaded image
264  * @systable	system table
265  */
266 static int setup(const efi_handle_t img_handle,
267 		 const struct efi_system_table *systable)
268 {
269 	efi_status_t ret;
270 
271 	boottime = systable->boottime;
272 
273 	/* Create controller handle */
274 	ret = boottime->install_protocol_interface(
275 			&handle_controller, &guid_controller,
276 			EFI_NATIVE_INTERFACE, &interface1);
277 	if (ret != EFI_SUCCESS) {
278 		efi_st_error("InstallProtocolInterface failed\n");
279 		return EFI_ST_FAILURE;
280 	}
281 	/* Create driver handle */
282 	ret = boottime->install_protocol_interface(
283 			&handle_driver,  &guid_driver_binding_protocol,
284 			EFI_NATIVE_INTERFACE, &binding_interface);
285 	if (ret != EFI_SUCCESS) {
286 		efi_st_error("InstallProtocolInterface failed\n");
287 		return EFI_ST_FAILURE;
288 	}
289 
290 	return EFI_ST_SUCCESS;
291 }
292 
293 /*
294  * Execute unit test.
295  *
296  * The number of child controllers is checked after each of the following
297  * actions:
298  *
299  * Connect a controller to a driver.
300  * Disconnect and destroy a child controller.
301  * Disconnect and destroy the remaining child controllers.
302  *
303  * Connect a controller to a driver.
304  * Reinstall the driver protocol on the controller.
305  * Uninstall the driver protocol from the controller.
306  */
307 static int execute(void)
308 {
309 	efi_status_t ret;
310 	efi_uintn_t count;
311 
312 	/* Connect controller to driver */
313 	ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
314 	if (ret != EFI_SUCCESS) {
315 		efi_st_error("Failed to connect controller\n");
316 		return EFI_ST_FAILURE;
317 	}
318 	/* Check number of child controllers */
319 	ret = count_child_controllers(handle_controller, &guid_controller,
320 				      &count);
321 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
322 		efi_st_error("Number of children %u != %u\n",
323 			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
324 	}
325 	/* Destroy second child controller */
326 	ret = boottime->disconnect_controller(handle_controller,
327 					      handle_driver,
328 					      handle_child_controller[1]);
329 	if (ret != EFI_SUCCESS) {
330 		efi_st_error("Failed to disconnect child controller\n");
331 		return EFI_ST_FAILURE;
332 	}
333 	/* Check number of child controllers */
334 	ret = count_child_controllers(handle_controller, &guid_controller,
335 				      &count);
336 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS - 1) {
337 		efi_st_error("Destroying single child controller failed\n");
338 		return EFI_ST_FAILURE;
339 	}
340 	/* Destroy remaining child controllers and disconnect controller */
341 	ret = boottime->disconnect_controller(handle_controller, NULL, NULL);
342 	if (ret != EFI_SUCCESS) {
343 		efi_st_error("Failed to disconnect controller\n");
344 		return EFI_ST_FAILURE;
345 	}
346 	/* Check number of child controllers */
347 	ret = count_child_controllers(handle_controller, &guid_controller,
348 				      &count);
349 	if (ret != EFI_SUCCESS || count) {
350 		efi_st_error("Destroying child controllers failed\n");
351 		return EFI_ST_FAILURE;
352 	}
353 
354 	/* Connect controller to driver */
355 	ret = boottime->connect_controller(handle_controller, NULL, NULL, 1);
356 	if (ret != EFI_SUCCESS) {
357 		efi_st_error("Failed to connect controller\n");
358 		return EFI_ST_FAILURE;
359 	}
360 	/* Check number of child controllers */
361 	ret = count_child_controllers(handle_controller, &guid_controller,
362 				      &count);
363 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
364 		efi_st_error("Number of children %u != %u\n",
365 			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
366 	}
367 	/* Try to uninstall controller protocol using the wrong interface */
368 	ret = boottime->uninstall_protocol_interface(handle_controller,
369 						     &guid_controller,
370 						     &interface2);
371 	if (ret == EFI_SUCCESS) {
372 		efi_st_error(
373 			"Interface not checked when uninstalling protocol\n");
374 		return EFI_ST_FAILURE;
375 	}
376 	/* Reinstall controller protocol */
377 	ret = boottime->reinstall_protocol_interface(handle_controller,
378 						     &guid_controller,
379 						     &interface1,
380 						     &interface2);
381 	if (ret != EFI_SUCCESS) {
382 		efi_st_error("Failed to reinstall protocols\n");
383 		return EFI_ST_FAILURE;
384 	}
385 	/* Check number of child controllers */
386 	ret = count_child_controllers(handle_controller, &guid_controller,
387 				      &count);
388 	if (ret != EFI_SUCCESS || count != NUMBER_OF_CHILD_CONTROLLERS) {
389 		efi_st_error("Number of children %u != %u\n",
390 			     (unsigned int)count, NUMBER_OF_CHILD_CONTROLLERS);
391 	}
392 	/* Uninstall controller protocol */
393 	ret = boottime->uninstall_protocol_interface(handle_controller,
394 						     &guid_controller,
395 						     &interface2);
396 	if (ret != EFI_SUCCESS) {
397 		efi_st_error("Failed to uninstall protocols\n");
398 		return EFI_ST_FAILURE;
399 	}
400 	/* Check number of child controllers */
401 	ret = count_child_controllers(handle_controller, &guid_controller,
402 				      &count);
403 	if (ret == EFI_SUCCESS)
404 		efi_st_error("Uninstall failed\n");
405 	return EFI_ST_SUCCESS;
406 }
407 
408 EFI_UNIT_TEST(controllers) = {
409 	.name = "controllers",
410 	.phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
411 	.setup = setup,
412 	.execute = execute,
413 };
414