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