1 // SPDX-License-Identifier: GPL-2.0+
3 * efi_selftest_controllers
7 * This unit test checks the following protocol services:
8 * ConnectController, DisconnectController,
9 * InstallProtocol, ReinstallProtocol, UninstallProtocol,
10 * OpenProtocol, CloseProtcol, OpenProtocolInformation
13 #include <efi_selftest.h>
15 #define NUMBER_OF_CHILD_CONTROLLERS 4
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;
34 * Count child controllers
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
41 static efi_status_t count_child_controllers(efi_handle_t handle,
46 efi_uintn_t entry_count;
47 struct efi_open_protocol_info_entry *entry_buffer;
50 ret = boottime->open_protocol_information(handle, protocol,
51 &entry_buffer, &entry_count);
52 if (ret != EFI_SUCCESS)
57 if (entry_buffer[--entry_count].attributes &
58 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER)
61 ret = boottime->free_pool(entry_buffer);
62 if (ret != EFI_SUCCESS)
63 efi_st_error("Cannot free buffer\n");
68 * Check if the driver supports the controller.
70 * @this driver binding protocol
71 * @controller_handle handle of the controller
72 * @remaining_device_path path specifying the child controller
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)
83 ret = boottime->open_protocol(
84 controller_handle, &guid_controller,
85 &interface, handle_driver,
86 controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER);
88 case EFI_ACCESS_DENIED:
90 case EFI_ALREADY_STARTED:
94 return EFI_UNSUPPORTED;
96 ret = boottime->close_protocol(
97 controller_handle, &guid_controller,
98 handle_driver, controller_handle);
99 if (ret != EFI_SUCCESS)
100 ret = EFI_UNSUPPORTED;
105 * Create child controllers and attach driver.
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
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)
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);
127 case EFI_ACCESS_DENIED:
129 case EFI_ALREADY_STARTED:
133 return EFI_UNSUPPORTED;
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;
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;
161 * Remove a single child controller from the parent controller.
163 * @controller_handle parent controller
164 * @child_handle child controller
165 * Return: status code
167 static efi_status_t disconnect_child(efi_handle_t controller_handle,
168 efi_handle_t child_handle)
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");
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");
189 * Remove child controllers and disconnect the controller.
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
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)
205 struct efi_open_protocol_info_entry *entry_buffer;
207 /* Destroy provided child controllers */
208 if (number_of_children) {
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)
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");
229 if (entry_buffer[--count].attributes &
230 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
231 ret = disconnect_child(
233 entry_buffer[count].agent_handle);
234 if (ret != EFI_SUCCESS)
238 ret = boottime->free_pool(entry_buffer);
239 if (ret != EFI_SUCCESS)
240 efi_st_error("Cannot free buffer\n");
243 return EFI_DEVICE_ERROR;
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");
256 /* Driver binding protocol interface */
257 static struct efi_driver_binding_protocol binding_interface = {
269 * @handle handle of the loaded image
270 * @systable system table
272 static int setup(const efi_handle_t img_handle,
273 const struct efi_system_table *systable)
277 boottime = systable->boottime;
278 handle_controller = NULL;
279 handle_driver = NULL;
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;
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;
298 return EFI_ST_SUCCESS;
304 * The number of child controllers is checked after each of the following
307 * Connect a controller to a driver.
308 * Disconnect and destroy a child controller.
309 * Disconnect and destroy the remaining child controllers.
311 * Connect a controller to a driver.
312 * Reinstall the driver protocol on the controller.
313 * Uninstall the driver protocol from the controller.
315 static int execute(void)
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;
326 /* Check number of child controllers */
327 ret = count_child_controllers(handle_controller, &guid_controller,
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);
333 /* Destroy second child controller */
334 ret = boottime->disconnect_controller(handle_controller,
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;
341 /* Check number of child controllers */
342 ret = count_child_controllers(handle_controller, &guid_controller,
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;
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;
355 /* Check number of child controllers */
356 ret = count_child_controllers(handle_controller, &guid_controller,
358 if (ret != EFI_SUCCESS || count) {
359 efi_st_error("Destroying child controllers failed\n");
360 return EFI_ST_FAILURE;
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;
369 /* Check number of child controllers */
370 ret = count_child_controllers(handle_controller, &guid_controller,
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);
376 /* Try to uninstall controller protocol using the wrong interface */
377 ret = boottime->uninstall_protocol_interface(handle_controller,
380 if (ret == EFI_SUCCESS) {
382 "Interface not checked when uninstalling protocol\n");
383 return EFI_ST_FAILURE;
385 /* Reinstall controller protocol */
386 ret = boottime->reinstall_protocol_interface(handle_controller,
390 if (ret != EFI_SUCCESS) {
391 efi_st_error("Failed to reinstall protocols\n");
392 return EFI_ST_FAILURE;
394 /* Check number of child controllers */
395 ret = count_child_controllers(handle_controller, &guid_controller,
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);
402 allow_removal = false;
403 /* Try to uninstall controller protocol using the wrong interface */
404 ret = boottime->uninstall_protocol_interface(handle_controller,
407 if (ret != EFI_NOT_FOUND) {
408 efi_st_error("Interface not checked when uninstalling protocol\n");
409 return EFI_ST_FAILURE;
413 * Uninstall a protocol while Disconnect controller won't
416 ret = boottime->uninstall_protocol_interface(handle_controller,
419 if (ret != EFI_ACCESS_DENIED) {
420 efi_st_error("Uninstall protocol interface failed\n");
421 return EFI_ST_FAILURE;
424 * Check number of child controllers and make sure children have
427 ret = count_child_controllers(handle_controller, &guid_controller,
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);
434 allow_removal = true;
435 ret = boottime->uninstall_protocol_interface(handle_controller,
438 if (ret != EFI_SUCCESS) {
439 efi_st_error("Failed to uninstall protocols\n");
440 return EFI_ST_FAILURE;
442 /* Check number of child controllers */
443 ret = count_child_controllers(handle_controller, &guid_controller,
445 if (ret == EFI_SUCCESS || count) {
446 efi_st_error("Uninstall failed\n");
447 return EFI_ST_FAILURE;
450 return EFI_ST_SUCCESS;
454 * Tear down unit test.
457 static int teardown(void)
460 /* Uninstall binding protocol */
461 ret = boottime->uninstall_protocol_interface(handle_driver,
462 &guid_driver_binding_protocol,
464 if (ret != EFI_SUCCESS)
465 efi_st_error("Failed to uninstall protocols\n");
470 EFI_UNIT_TEST(controllers) = {
471 .name = "controllers",
472 .phase = EFI_EXECUTE_BEFORE_BOOTTIME_EXIT,
475 .teardown = teardown,