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