1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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
28
29
30
31
32
33
34static 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
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
45 const struct efi_device_path *node = efi_dp_last_node(dp);
46
47 if (!node || node->type == DEVICE_PATH_TYPE_MEDIA_DEVICE)
48 ret = EFI_UNSUPPORTED;
49 }
50 return ret;
51}
52
53
54
55
56
57
58
59
60
61static 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
76
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_close_protocol(controller_handle, bp->ops->protocol,
101 this->driver_binding_handle,
102 controller_handle);
103 if (r != EFI_SUCCESS)
104 ret = EFI_UNSUPPORTED;
105out:
106 return EFI_EXIT(ret);
107}
108
109
110
111
112
113
114
115
116
117static efi_status_t EFIAPI efi_uc_start(
118 struct efi_driver_binding_protocol *this,
119 efi_handle_t controller_handle,
120 struct efi_device_path *remaining_device_path)
121{
122 efi_status_t r, ret;
123 void *interface = NULL;
124 struct efi_driver_binding_extended_protocol *bp =
125 (struct efi_driver_binding_extended_protocol *)this;
126
127 EFI_ENTRY("%p, %p, %ls", this, controller_handle,
128 efi_dp_str(remaining_device_path));
129
130
131 ret = EFI_CALL(systab.boottime->open_protocol(
132 controller_handle, bp->ops->protocol,
133 &interface, this->driver_binding_handle,
134 controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
135 switch (ret) {
136 case EFI_ACCESS_DENIED:
137 case EFI_ALREADY_STARTED:
138 goto out;
139 case EFI_SUCCESS:
140 break;
141 default:
142 ret = EFI_UNSUPPORTED;
143 goto out;
144 }
145 ret = check_node_type(controller_handle);
146 if (ret != EFI_SUCCESS)
147 goto err;
148 ret = bp->ops->bind(bp, controller_handle, interface);
149 if (ret == EFI_SUCCESS)
150 goto out;
151
152err:
153 r = efi_close_protocol(controller_handle, bp->ops->protocol,
154 this->driver_binding_handle,
155 controller_handle);
156 if (r != EFI_SUCCESS)
157 EFI_PRINT("Failure to close handle\n");
158
159out:
160 return EFI_EXIT(ret);
161}
162
163
164
165
166
167
168
169
170
171static efi_status_t disconnect_child(efi_handle_t controller_handle,
172 efi_handle_t child_handle)
173{
174 efi_status_t ret;
175 efi_guid_t *guid_controller = NULL;
176 efi_guid_t *guid_child_controller = NULL;
177
178 ret = efi_close_protocol(controller_handle, guid_controller,
179 child_handle, child_handle);
180 if (ret != EFI_SUCCESS) {
181 EFI_PRINT("Cannot close protocol\n");
182 return ret;
183 }
184 ret = EFI_CALL(systab.boottime->uninstall_protocol_interface(
185 child_handle, guid_child_controller, NULL));
186 if (ret != EFI_SUCCESS) {
187 EFI_PRINT("Cannot uninstall protocol interface\n");
188 return ret;
189 }
190 return ret;
191}
192
193
194
195
196
197
198
199
200
201
202static efi_status_t EFIAPI efi_uc_stop(
203 struct efi_driver_binding_protocol *this,
204 efi_handle_t controller_handle,
205 size_t number_of_children,
206 efi_handle_t *child_handle_buffer)
207{
208 efi_status_t ret;
209 efi_uintn_t count;
210 struct efi_open_protocol_info_entry *entry_buffer;
211 struct efi_driver_binding_extended_protocol *bp =
212 (struct efi_driver_binding_extended_protocol *)this;
213
214 EFI_ENTRY("%p, %p, %zu, %p", this, controller_handle,
215 number_of_children, child_handle_buffer);
216
217
218 if (number_of_children) {
219 efi_uintn_t i;
220
221 for (i = 0; i < number_of_children; ++i) {
222 ret = disconnect_child(controller_handle,
223 child_handle_buffer[i]);
224 if (ret != EFI_SUCCESS)
225 goto out;
226 }
227 ret = EFI_SUCCESS;
228 goto out;
229 }
230
231
232 ret = EFI_CALL(systab.boottime->open_protocol_information(
233 controller_handle, bp->ops->protocol,
234 &entry_buffer, &count));
235 if (ret != EFI_SUCCESS)
236 goto out;
237 while (count) {
238 if (entry_buffer[--count].attributes &
239 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
240 ret = disconnect_child(
241 controller_handle,
242 entry_buffer[count].agent_handle);
243 if (ret != EFI_SUCCESS)
244 goto out;
245 }
246 }
247 ret = efi_free_pool(entry_buffer);
248 if (ret != EFI_SUCCESS)
249 log_err("Cannot free EFI memory pool\n");
250
251
252 ret = efi_close_protocol(controller_handle, bp->ops->protocol,
253 this->driver_binding_handle,
254 controller_handle);
255out:
256 return EFI_EXIT(ret);
257}
258
259
260
261
262
263
264
265static efi_status_t efi_add_driver(struct driver *drv)
266{
267 efi_status_t ret;
268 const struct efi_driver_ops *ops = drv->ops;
269 struct efi_driver_binding_extended_protocol *bp;
270
271 log_debug("Adding EFI driver '%s'\n", drv->name);
272 if (!ops->protocol) {
273 log_err("EFI protocol GUID missing for driver '%s'\n",
274 drv->name);
275 return EFI_INVALID_PARAMETER;
276 }
277 bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
278 if (!bp)
279 return EFI_OUT_OF_RESOURCES;
280
281 bp->bp.supported = efi_uc_supported;
282 bp->bp.start = efi_uc_start;
283 bp->bp.stop = efi_uc_stop;
284 bp->bp.version = 0xffffffff;
285 bp->ops = ops;
286
287 ret = efi_create_handle(&bp->bp.driver_binding_handle);
288 if (ret != EFI_SUCCESS) {
289 free(bp);
290 goto out;
291 }
292 bp->bp.image_handle = bp->bp.driver_binding_handle;
293 ret = efi_add_protocol(bp->bp.driver_binding_handle,
294 &efi_guid_driver_binding_protocol, bp);
295 if (ret != EFI_SUCCESS)
296 goto err;
297 if (ops->init) {
298 ret = ops->init(bp);
299 if (ret != EFI_SUCCESS)
300 goto err;
301 }
302out:
303 return ret;
304
305err:
306 efi_delete_handle(bp->bp.driver_binding_handle);
307 free(bp);
308 return ret;
309}
310
311
312
313
314
315
316
317
318efi_status_t efi_driver_init(void)
319{
320 struct driver *drv;
321 efi_status_t ret = EFI_SUCCESS;
322
323 log_debug("Initializing EFI driver framework\n");
324 for (drv = ll_entry_start(struct driver, driver);
325 drv < ll_entry_end(struct driver, driver); ++drv) {
326 if (drv->id == UCLASS_EFI_LOADER) {
327 ret = efi_add_driver(drv);
328 if (ret != EFI_SUCCESS) {
329 log_err("Failed to add EFI driver %s\n",
330 drv->name);
331 break;
332 }
333 }
334 }
335 return ret;
336}
337
338
339
340
341
342
343
344static int efi_uc_init(struct uclass *class)
345{
346 log_debug("Initializing UCLASS_EFI_LOADER\n");
347 return 0;
348}
349
350
351
352
353
354
355
356static int efi_uc_destroy(struct uclass *class)
357{
358 log_debug("Destroying UCLASS_EFI_LOADER\n");
359 return 0;
360}
361
362UCLASS_DRIVER(efi) = {
363 .name = "efi",
364 .id = UCLASS_EFI_LOADER,
365 .init = efi_uc_init,
366 .destroy = efi_uc_destroy,
367};
368