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