1 // SPDX-License-Identifier: GPL-2.0+
3 * Uclass for EFI drivers
5 * Copyright (c) 2017 Heinrich Schuchardt
7 * For each EFI driver the uclass
9 * - installs the driver binding protocol
11 * The uclass provides the bind, start, and stop entry points for the driver
14 * In supported() and bind() 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
22 #include <efi_driver.h>
27 * check_node_type() - check node type
29 * We do not support partitions as controller handles.
31 * @handle: handle to be checked
34 static efi_status_t check_node_type(efi_handle_t handle)
36 efi_status_t r, ret = EFI_SUCCESS;
37 const struct efi_device_path *dp;
39 /* Open the device path protocol */
40 r = EFI_CALL(systab.boottime->open_protocol(
41 handle, &efi_guid_device_path, (void **)&dp,
42 NULL, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL));
43 if (r == EFI_SUCCESS && dp) {
44 /* Get the last node */
45 const struct efi_device_path *node = efi_dp_last_node(dp);
46 /* We do not support partitions as controller */
47 if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE)
48 ret = EFI_UNSUPPORTED;
54 * efi_uc_supported() - check if the driver supports the controller
56 * @this: driver binding protocol
57 * @controller_handle: handle of the controller
58 * @remaining_device_path: path specifying the child controller
61 static efi_status_t EFIAPI efi_uc_supported(
62 struct efi_driver_binding_protocol *this,
63 efi_handle_t controller_handle,
64 struct efi_device_path *remaining_device_path)
68 struct efi_driver_binding_extended_protocol *bp =
69 (struct efi_driver_binding_extended_protocol *)this;
71 EFI_ENTRY("%p, %p, %ls", this, controller_handle,
72 efi_dp_str(remaining_device_path));
75 * U-Boot internal devices install protocols interfaces without calling
76 * ConnectController(). Hence we should not bind an extra driver.
78 if (controller_handle->dev) {
79 ret = EFI_UNSUPPORTED;
83 ret = EFI_CALL(systab.boottime->open_protocol(
84 controller_handle, bp->ops->protocol,
85 &interface, this->driver_binding_handle,
86 controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
88 case EFI_ACCESS_DENIED:
89 case EFI_ALREADY_STARTED:
94 ret = EFI_UNSUPPORTED;
98 ret = check_node_type(controller_handle);
100 r = EFI_CALL(systab.boottime->close_protocol(
101 controller_handle, bp->ops->protocol,
102 this->driver_binding_handle,
104 if (r != EFI_SUCCESS)
105 ret = EFI_UNSUPPORTED;
107 return EFI_EXIT(ret);
111 * efi_uc_start() - create child controllers and attach driver
113 * @this: driver binding protocol
114 * @controller_handle: handle of the controller
115 * @remaining_device_path: path specifying the child controller
116 * Return: status code
118 static efi_status_t EFIAPI efi_uc_start(
119 struct efi_driver_binding_protocol *this,
120 efi_handle_t controller_handle,
121 struct efi_device_path *remaining_device_path)
124 void *interface = NULL;
125 struct efi_driver_binding_extended_protocol *bp =
126 (struct efi_driver_binding_extended_protocol *)this;
128 EFI_ENTRY("%p, %p, %ls", this, controller_handle,
129 efi_dp_str(remaining_device_path));
131 /* Attach driver to controller */
132 ret = EFI_CALL(systab.boottime->open_protocol(
133 controller_handle, bp->ops->protocol,
134 &interface, this->driver_binding_handle,
135 controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
137 case EFI_ACCESS_DENIED:
138 case EFI_ALREADY_STARTED:
143 ret = EFI_UNSUPPORTED;
146 ret = check_node_type(controller_handle);
147 if (ret != EFI_SUCCESS)
149 ret = bp->ops->bind(controller_handle, interface);
150 if (ret == EFI_SUCCESS)
154 r = EFI_CALL(systab.boottime->close_protocol(
155 controller_handle, bp->ops->protocol,
156 this->driver_binding_handle,
158 if (r != EFI_SUCCESS)
159 EFI_PRINT("Failure to close handle\n");
162 return EFI_EXIT(ret);
166 * disconnect_child() - remove a single child controller from the parent
169 * @controller_handle: parent controller
170 * @child_handle: child controller
171 * Return: status code
173 static efi_status_t disconnect_child(efi_handle_t controller_handle,
174 efi_handle_t child_handle)
177 efi_guid_t *guid_controller = NULL;
178 efi_guid_t *guid_child_controller = NULL;
180 ret = EFI_CALL(systab.boottime->close_protocol(
181 controller_handle, guid_controller,
182 child_handle, child_handle));
183 if (ret != EFI_SUCCESS) {
184 EFI_PRINT("Cannot close protocol\n");
187 ret = EFI_CALL(systab.boottime->uninstall_protocol_interface(
188 child_handle, guid_child_controller, NULL));
189 if (ret != EFI_SUCCESS) {
190 EFI_PRINT("Cannot uninstall protocol interface\n");
197 * efi_uc_stop() - Remove child controllers and disconnect the controller
199 * @this: driver binding protocol
200 * @controller_handle: handle of the controller
201 * @number_of_children: number of child controllers to remove
202 * @child_handle_buffer: handles of the child controllers to remove
203 * Return: status code
205 static efi_status_t EFIAPI efi_uc_stop(
206 struct efi_driver_binding_protocol *this,
207 efi_handle_t controller_handle,
208 size_t number_of_children,
209 efi_handle_t *child_handle_buffer)
213 struct efi_open_protocol_info_entry *entry_buffer;
214 struct efi_driver_binding_extended_protocol *bp =
215 (struct efi_driver_binding_extended_protocol *)this;
217 EFI_ENTRY("%p, %p, %zu, %p", this, controller_handle,
218 number_of_children, child_handle_buffer);
220 /* Destroy provided child controllers */
221 if (number_of_children) {
224 for (i = 0; i < number_of_children; ++i) {
225 ret = disconnect_child(controller_handle,
226 child_handle_buffer[i]);
227 if (ret != EFI_SUCCESS)
233 /* Destroy all children */
234 ret = EFI_CALL(systab.boottime->open_protocol_information(
235 controller_handle, bp->ops->protocol,
236 &entry_buffer, &count));
237 if (ret != EFI_SUCCESS)
240 if (entry_buffer[--count].attributes &
241 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
242 ret = disconnect_child(
244 entry_buffer[count].agent_handle);
245 if (ret != EFI_SUCCESS)
249 ret = EFI_CALL(systab.boottime->free_pool(entry_buffer));
250 if (ret != EFI_SUCCESS)
251 log_err("Cannot free EFI memory pool\n");
253 /* Detach driver from controller */
254 ret = EFI_CALL(systab.boottime->close_protocol(
255 controller_handle, bp->ops->protocol,
256 this->driver_binding_handle, controller_handle));
258 return EFI_EXIT(ret);
262 * efi_add_driver() - add driver
264 * @drv: driver to add
265 * Return: status code
267 static efi_status_t efi_add_driver(struct driver *drv)
270 const struct efi_driver_ops *ops = drv->ops;
271 struct efi_driver_binding_extended_protocol *bp;
273 log_debug("Adding EFI driver '%s'\n", drv->name);
274 if (!ops->protocol) {
275 log_err("EFI protocol GUID missing for driver '%s'\n",
277 return EFI_INVALID_PARAMETER;
279 bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
281 return EFI_OUT_OF_RESOURCES;
283 bp->bp.supported = efi_uc_supported;
284 bp->bp.start = efi_uc_start;
285 bp->bp.stop = efi_uc_stop;
286 bp->bp.version = 0xffffffff;
289 ret = efi_create_handle(&bp->bp.driver_binding_handle);
290 if (ret != EFI_SUCCESS) {
294 bp->bp.image_handle = bp->bp.driver_binding_handle;
295 ret = efi_add_protocol(bp->bp.driver_binding_handle,
296 &efi_guid_driver_binding_protocol, bp);
297 if (ret != EFI_SUCCESS) {
298 efi_delete_handle(bp->bp.driver_binding_handle);
307 * efi_driver_init() - initialize the EFI drivers
309 * Called by efi_init_obj_list().
311 * Return: 0 = success, any other value will stop further execution
313 efi_status_t efi_driver_init(void)
316 efi_status_t ret = EFI_SUCCESS;
318 log_debug("Initializing EFI driver framework\n");
319 for (drv = ll_entry_start(struct driver, driver);
320 drv < ll_entry_end(struct driver, driver); ++drv) {
321 if (drv->id == UCLASS_EFI_LOADER) {
322 ret = efi_add_driver(drv);
323 if (ret != EFI_SUCCESS) {
324 log_err("Failed to add EFI driver %s\n",
334 * efi_uc_init() - initialize the EFI uclass
336 * @class: the EFI uclass
337 * Return: 0 = success
339 static int efi_uc_init(struct uclass *class)
341 log_debug("Initializing UCLASS_EFI_LOADER\n");
346 * efi_uc_destroy() - destroy the EFI uclass
348 * @class: the EFI uclass
349 * Return: 0 = success
351 static int efi_uc_destroy(struct uclass *class)
353 log_debug("Destroying UCLASS_EFI_LOADER\n");
357 UCLASS_DRIVER(efi) = {
359 .id = UCLASS_EFI_LOADER,
361 .destroy = efi_uc_destroy,