efi_driver: fix error handling
[platform/kernel/u-boot.git] / lib / efi_driver / efi_uclass.c
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 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
17  * controllers.
18  */
19
20 #include <common.h>
21 #include <dm.h>
22 #include <efi_driver.h>
23 #include <log.h>
24 #include <malloc.h>
25
26 /**
27  * check_node_type() - check node type
28  *
29  * We do not support partitions as controller handles.
30  *
31  * @handle:     handle to be checked
32  * Return:      status code
33  */
34 static efi_status_t check_node_type(efi_handle_t handle)
35 {
36         efi_status_t r, ret = EFI_SUCCESS;
37         const struct efi_device_path *dp;
38
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;
49         }
50         return ret;
51 }
52
53 /**
54  * efi_uc_supported() - check if the driver supports the controller
55  *
56  * @this:                       driver binding protocol
57  * @controller_handle:          handle of the controller
58  * @remaining_device_path:      path specifying the child controller
59  * Return:                      status code
60  */
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)
65 {
66         efi_status_t r, ret;
67         void *interface;
68         struct efi_driver_binding_extended_protocol *bp =
69                         (struct efi_driver_binding_extended_protocol *)this;
70
71         EFI_ENTRY("%p, %p, %ls", this, controller_handle,
72                   efi_dp_str(remaining_device_path));
73
74         /*
75          * U-Boot internal devices install protocols interfaces without calling
76          * ConnectController(). Hence we should not bind an extra driver.
77          */
78         if (controller_handle->dev) {
79                 ret = EFI_UNSUPPORTED;
80                 goto out;
81         }
82
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));
87         switch (ret) {
88         case EFI_ACCESS_DENIED:
89         case EFI_ALREADY_STARTED:
90                 goto out;
91         case EFI_SUCCESS:
92                 break;
93         default:
94                 ret = EFI_UNSUPPORTED;
95                 goto out;
96         }
97
98         ret = check_node_type(controller_handle);
99
100         r = EFI_CALL(systab.boottime->close_protocol(
101                                 controller_handle, bp->ops->protocol,
102                                 this->driver_binding_handle,
103                                 controller_handle));
104         if (r != EFI_SUCCESS)
105                 ret = EFI_UNSUPPORTED;
106 out:
107         return EFI_EXIT(ret);
108 }
109
110 /**
111  * efi_uc_start() - create child controllers and attach driver
112  *
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
117  */
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)
122 {
123         efi_status_t r, ret;
124         void *interface = NULL;
125         struct efi_driver_binding_extended_protocol *bp =
126                         (struct efi_driver_binding_extended_protocol *)this;
127
128         EFI_ENTRY("%p, %p, %ls", this, controller_handle,
129                   efi_dp_str(remaining_device_path));
130
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));
136         switch (ret) {
137         case EFI_ACCESS_DENIED:
138         case EFI_ALREADY_STARTED:
139                 goto out;
140         case EFI_SUCCESS:
141                 break;
142         default:
143                 ret =  EFI_UNSUPPORTED;
144                 goto out;
145         }
146         ret = check_node_type(controller_handle);
147         if (ret != EFI_SUCCESS)
148                 goto err;
149         ret = bp->ops->bind(controller_handle, interface);
150         if (ret == EFI_SUCCESS)
151                 goto out;
152
153 err:
154         r = EFI_CALL(systab.boottime->close_protocol(
155                         controller_handle, bp->ops->protocol,
156                         this->driver_binding_handle,
157                         controller_handle));
158         if (r != EFI_SUCCESS)
159                 EFI_PRINT("Failure to close handle\n");
160
161 out:
162         return EFI_EXIT(ret);
163 }
164
165 /**
166  * disconnect_child() - remove a single child controller from the parent
167  *                      controller
168  *
169  * @controller_handle:  parent controller
170  * @child_handle:       child controller
171  * Return:              status code
172  */
173 static efi_status_t disconnect_child(efi_handle_t controller_handle,
174                                      efi_handle_t child_handle)
175 {
176         efi_status_t ret;
177         efi_guid_t *guid_controller = NULL;
178         efi_guid_t *guid_child_controller = NULL;
179
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");
185                 return ret;
186         }
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");
191                 return ret;
192         }
193         return ret;
194 }
195
196 /**
197  * efi_uc_stop() - Remove child controllers and disconnect the controller
198  *
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
204  */
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)
210 {
211         efi_status_t ret;
212         efi_uintn_t count;
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;
216
217         EFI_ENTRY("%p, %p, %zu, %p", this, controller_handle,
218                   number_of_children, child_handle_buffer);
219
220         /* Destroy provided child controllers */
221         if (number_of_children) {
222                 efi_uintn_t i;
223
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)
228                                 return ret;
229                 }
230                 return EFI_SUCCESS;
231         }
232
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)
238                 goto out;
239         while (count) {
240                 if (entry_buffer[--count].attributes &
241                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
242                         ret = disconnect_child(
243                                         controller_handle,
244                                         entry_buffer[count].agent_handle);
245                         if (ret != EFI_SUCCESS)
246                                 goto out;
247                 }
248         }
249         ret = EFI_CALL(systab.boottime->free_pool(entry_buffer));
250         if (ret != EFI_SUCCESS)
251                 log_err("Cannot free EFI memory pool\n");
252
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));
257 out:
258         return EFI_EXIT(ret);
259 }
260
261 /**
262  * efi_add_driver() - add driver
263  *
264  * @drv:                driver to add
265  * Return:              status code
266  */
267 static efi_status_t efi_add_driver(struct driver *drv)
268 {
269         efi_status_t ret;
270         const struct efi_driver_ops *ops = drv->ops;
271         struct efi_driver_binding_extended_protocol *bp;
272
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",
276                         drv->name);
277                 return EFI_INVALID_PARAMETER;
278         }
279         bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
280         if (!bp)
281                 return EFI_OUT_OF_RESOURCES;
282
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;
287         bp->ops = drv->ops;
288
289         ret = efi_create_handle(&bp->bp.driver_binding_handle);
290         if (ret != EFI_SUCCESS) {
291                 free(bp);
292                 goto out;
293         }
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);
299                 free(bp);
300                 goto out;
301         }
302 out:
303         return ret;
304 }
305
306 /**
307  * efi_driver_init() - initialize the EFI drivers
308  *
309  * Called by efi_init_obj_list().
310  *
311  * Return:      0 = success, any other value will stop further execution
312  */
313 efi_status_t efi_driver_init(void)
314 {
315         struct driver *drv;
316         efi_status_t ret = EFI_SUCCESS;
317
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",
325                                         drv->name);
326                                 break;
327                         }
328                 }
329         }
330         return ret;
331 }
332
333 /**
334  * efi_uc_init() - initialize the EFI uclass
335  *
336  * @class:      the EFI uclass
337  * Return:      0 = success
338  */
339 static int efi_uc_init(struct uclass *class)
340 {
341         log_debug("Initializing UCLASS_EFI_LOADER\n");
342         return 0;
343 }
344
345 /**
346  * efi_uc_destroy() - destroy the EFI uclass
347  *
348  * @class:      the EFI uclass
349  * Return:      0 = success
350  */
351 static int efi_uc_destroy(struct uclass *class)
352 {
353         log_debug("Destroying UCLASS_EFI_LOADER\n");
354         return 0;
355 }
356
357 UCLASS_DRIVER(efi) = {
358         .name           = "efi",
359         .id             = UCLASS_EFI_LOADER,
360         .init           = efi_uc_init,
361         .destroy        = efi_uc_destroy,
362 };