1 // SPDX-License-Identifier: GPL-2.0+ 2 /* 3 * Uclass for EFI drivers 4 * 5 * Copyright (c) 2017 Heinrich Schuchardt 6 * 7 * For each EFI driver the uclass 8 * - creates a handle 9 * - installs the driver binding protocol 10 * 11 * The uclass provides the bind, start, and stop entry points for the driver 12 * binding protocol. 13 * 14 * In bind() and stop() it checks if the controller implements the protocol 15 * supported by the EFI driver. In the start() function it calls the bind() 16 * function of the EFI driver. In the stop() function it destroys the child 17 * controllers. 18 */ 19 20 #include <efi_driver.h> 21 22 /* 23 * Check node type. We do not support partitions as controller handles. 24 * 25 * @handle handle to be checked 26 * @return status code 27 */ 28 static efi_status_t check_node_type(efi_handle_t handle) 29 { 30 efi_status_t r, ret = EFI_SUCCESS; 31 const struct efi_device_path *dp; 32 33 /* Open the device path protocol */ 34 r = EFI_CALL(systab.boottime->open_protocol( 35 handle, &efi_guid_device_path, (void **)&dp, 36 NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL)); 37 if (r == EFI_SUCCESS && dp) { 38 /* Get the last node */ 39 const struct efi_device_path *node = efi_dp_last_node(dp); 40 /* We do not support partitions as controller */ 41 if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE) 42 ret = EFI_UNSUPPORTED; 43 } 44 return ret; 45 } 46 47 /* 48 * Check if the driver supports the controller. 49 * 50 * @this driver binding protocol 51 * @controller_handle handle of the controller 52 * @remaining_device_path path specifying the child controller 53 * @return status code 54 */ 55 static efi_status_t EFIAPI efi_uc_supported( 56 struct efi_driver_binding_protocol *this, 57 efi_handle_t controller_handle, 58 struct efi_device_path *remaining_device_path) 59 { 60 efi_status_t r, ret; 61 void *interface; 62 struct efi_driver_binding_extended_protocol *bp = 63 (struct efi_driver_binding_extended_protocol *)this; 64 65 EFI_ENTRY("%p, %p, %ls", this, controller_handle, 66 efi_dp_str(remaining_device_path)); 67 68 ret = EFI_CALL(systab.boottime->open_protocol( 69 controller_handle, bp->ops->protocol, 70 &interface, this->driver_binding_handle, 71 controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)); 72 switch (ret) { 73 case EFI_ACCESS_DENIED: 74 case EFI_ALREADY_STARTED: 75 goto out; 76 case EFI_SUCCESS: 77 break; 78 default: 79 ret = EFI_UNSUPPORTED; 80 goto out; 81 } 82 83 ret = check_node_type(controller_handle); 84 85 r = EFI_CALL(systab.boottime->close_protocol( 86 controller_handle, bp->ops->protocol, 87 this->driver_binding_handle, 88 controller_handle)); 89 if (r != EFI_SUCCESS) 90 ret = EFI_UNSUPPORTED; 91 out: 92 return EFI_EXIT(ret); 93 } 94 95 /* 96 * Create child controllers and attach driver. 97 * 98 * @this driver binding protocol 99 * @controller_handle handle of the controller 100 * @remaining_device_path path specifying the child controller 101 * @return status code 102 */ 103 static efi_status_t EFIAPI efi_uc_start( 104 struct efi_driver_binding_protocol *this, 105 efi_handle_t controller_handle, 106 struct efi_device_path *remaining_device_path) 107 { 108 efi_status_t r, ret; 109 void *interface = NULL; 110 struct efi_driver_binding_extended_protocol *bp = 111 (struct efi_driver_binding_extended_protocol *)this; 112 113 EFI_ENTRY("%p, %pUl, %ls", this, controller_handle, 114 efi_dp_str(remaining_device_path)); 115 116 /* Attach driver to controller */ 117 ret = EFI_CALL(systab.boottime->open_protocol( 118 controller_handle, bp->ops->protocol, 119 &interface, this->driver_binding_handle, 120 controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER)); 121 switch (ret) { 122 case EFI_ACCESS_DENIED: 123 case EFI_ALREADY_STARTED: 124 goto out; 125 case EFI_SUCCESS: 126 break; 127 default: 128 ret = EFI_UNSUPPORTED; 129 goto out; 130 } 131 ret = check_node_type(controller_handle); 132 if (ret != EFI_SUCCESS) { 133 r = EFI_CALL(systab.boottime->close_protocol( 134 controller_handle, bp->ops->protocol, 135 this->driver_binding_handle, 136 controller_handle)); 137 if (r != EFI_SUCCESS) 138 EFI_PRINT("Failure to close handle\n"); 139 goto out; 140 } 141 142 /* TODO: driver specific stuff */ 143 bp->ops->bind(controller_handle, interface); 144 145 out: 146 return EFI_EXIT(ret); 147 } 148 149 /* 150 * Remove a single child controller from the parent controller. 151 * 152 * @controller_handle parent controller 153 * @child_handle child controller 154 * @return status code 155 */ 156 static efi_status_t disconnect_child(efi_handle_t controller_handle, 157 efi_handle_t child_handle) 158 { 159 efi_status_t ret; 160 efi_guid_t *guid_controller = NULL; 161 efi_guid_t *guid_child_controller = NULL; 162 163 ret = EFI_CALL(systab.boottime->close_protocol( 164 controller_handle, guid_controller, 165 child_handle, child_handle)); 166 if (ret != EFI_SUCCESS) { 167 EFI_PRINT("Cannot close protocol\n"); 168 return ret; 169 } 170 ret = EFI_CALL(systab.boottime->uninstall_protocol_interface( 171 child_handle, guid_child_controller, NULL)); 172 if (ret != EFI_SUCCESS) { 173 EFI_PRINT("Cannot uninstall protocol interface\n"); 174 return ret; 175 } 176 return ret; 177 } 178 179 /* 180 * Remove child controllers and disconnect the controller. 181 * 182 * @this driver binding protocol 183 * @controller_handle handle of the controller 184 * @number_of_children number of child controllers to remove 185 * @child_handle_buffer handles of the child controllers to remove 186 * @return status code 187 */ 188 static efi_status_t EFIAPI efi_uc_stop( 189 struct efi_driver_binding_protocol *this, 190 efi_handle_t controller_handle, 191 size_t number_of_children, 192 efi_handle_t *child_handle_buffer) 193 { 194 efi_status_t ret; 195 efi_uintn_t count; 196 struct efi_open_protocol_info_entry *entry_buffer; 197 efi_guid_t *guid_controller = NULL; 198 199 EFI_ENTRY("%p, %pUl, %zu, %p", this, controller_handle, 200 number_of_children, child_handle_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 = EFI_CALL(systab.boottime->open_protocol_information( 217 controller_handle, guid_controller, 218 &entry_buffer, &count)); 219 if (ret != EFI_SUCCESS) 220 goto out; 221 while (count) { 222 if (entry_buffer[--count].attributes & 223 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) { 224 ret = disconnect_child( 225 controller_handle, 226 entry_buffer[count].agent_handle); 227 if (ret != EFI_SUCCESS) 228 goto out; 229 } 230 } 231 ret = EFI_CALL(systab.boottime->free_pool(entry_buffer)); 232 if (ret != EFI_SUCCESS) 233 printf("%s(%u) %s: ERROR: Cannot free pool\n", 234 __FILE__, __LINE__, __func__); 235 236 /* Detach driver from controller */ 237 ret = EFI_CALL(systab.boottime->close_protocol( 238 controller_handle, guid_controller, 239 this->driver_binding_handle, controller_handle)); 240 out: 241 return EFI_EXIT(ret); 242 } 243 244 static efi_status_t efi_add_driver(struct driver *drv) 245 { 246 efi_status_t ret; 247 const struct efi_driver_ops *ops = drv->ops; 248 struct efi_driver_binding_extended_protocol *bp; 249 250 debug("EFI: Adding driver '%s'\n", drv->name); 251 if (!ops->protocol) { 252 printf("EFI: ERROR: protocol GUID missing for driver '%s'\n", 253 drv->name); 254 return EFI_INVALID_PARAMETER; 255 } 256 bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol)); 257 if (!bp) 258 return EFI_OUT_OF_RESOURCES; 259 260 bp->bp.supported = efi_uc_supported; 261 bp->bp.start = efi_uc_start; 262 bp->bp.stop = efi_uc_stop; 263 bp->bp.version = 0xffffffff; 264 bp->ops = drv->ops; 265 266 ret = efi_create_handle(&bp->bp.driver_binding_handle); 267 if (ret != EFI_SUCCESS) { 268 free(bp); 269 goto out; 270 } 271 bp->bp.image_handle = bp->bp.driver_binding_handle; 272 ret = efi_add_protocol(bp->bp.driver_binding_handle, 273 &efi_guid_driver_binding_protocol, bp); 274 if (ret != EFI_SUCCESS) { 275 efi_delete_handle(bp->bp.driver_binding_handle); 276 free(bp); 277 goto out; 278 } 279 out: 280 return ret; 281 } 282 283 /* 284 * Initialize the EFI drivers. 285 * Called by board_init_r(). 286 * 287 * @return 0 = success, any other value will stop further execution 288 */ 289 efi_status_t efi_driver_init(void) 290 { 291 struct driver *drv; 292 efi_status_t ret = EFI_SUCCESS; 293 294 /* Save 'gd' pointer */ 295 efi_save_gd(); 296 297 debug("EFI: Initializing EFI driver framework\n"); 298 for (drv = ll_entry_start(struct driver, driver); 299 drv < ll_entry_end(struct driver, driver); ++drv) { 300 if (drv->id == UCLASS_EFI) { 301 ret = efi_add_driver(drv); 302 if (ret != EFI_SUCCESS) { 303 printf("EFI: ERROR: failed to add driver %s\n", 304 drv->name); 305 break; 306 } 307 } 308 } 309 return ret; 310 } 311 312 static int efi_uc_init(struct uclass *class) 313 { 314 printf("EFI: Initializing UCLASS_EFI\n"); 315 return 0; 316 } 317 318 static int efi_uc_destroy(struct uclass *class) 319 { 320 printf("Destroying UCLASS_EFI\n"); 321 return 0; 322 } 323 324 UCLASS_DRIVER(efi) = { 325 .name = "efi", 326 .id = UCLASS_EFI, 327 .init = efi_uc_init, 328 .destroy = efi_uc_destroy, 329 }; 330