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