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