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 <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  */
check_node_type(efi_handle_t handle)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  */
efi_uc_supported(struct efi_driver_binding_protocol * this,efi_handle_t controller_handle,struct efi_device_path * remaining_device_path)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 	ret = EFI_CALL(systab.boottime->open_protocol(
75 			controller_handle, bp->ops->protocol,
76 			&interface, this->driver_binding_handle,
77 			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
78 	switch (ret) {
79 	case EFI_ACCESS_DENIED:
80 	case EFI_ALREADY_STARTED:
81 		goto out;
82 	case EFI_SUCCESS:
83 		break;
84 	default:
85 		ret = EFI_UNSUPPORTED;
86 		goto out;
87 	}
88 
89 	ret = check_node_type(controller_handle);
90 
91 	r = EFI_CALL(systab.boottime->close_protocol(
92 				controller_handle, bp->ops->protocol,
93 				this->driver_binding_handle,
94 				controller_handle));
95 	if (r != EFI_SUCCESS)
96 		ret = EFI_UNSUPPORTED;
97 out:
98 	return EFI_EXIT(ret);
99 }
100 
101 /**
102  * efi_uc_start() - create child controllers and attach driver
103  *
104  * @this:			driver binding protocol
105  * @controller_handle:		handle of the controller
106  * @remaining_device_path:	path specifying the child controller
107  * Return:			status code
108  */
efi_uc_start(struct efi_driver_binding_protocol * this,efi_handle_t controller_handle,struct efi_device_path * remaining_device_path)109 static efi_status_t EFIAPI efi_uc_start(
110 		struct efi_driver_binding_protocol *this,
111 		efi_handle_t controller_handle,
112 		struct efi_device_path *remaining_device_path)
113 {
114 	efi_status_t r, ret;
115 	void *interface = NULL;
116 	struct efi_driver_binding_extended_protocol *bp =
117 			(struct efi_driver_binding_extended_protocol *)this;
118 
119 	EFI_ENTRY("%p, %p, %ls", this, controller_handle,
120 		  efi_dp_str(remaining_device_path));
121 
122 	/* Attach driver to controller */
123 	ret = EFI_CALL(systab.boottime->open_protocol(
124 			controller_handle, bp->ops->protocol,
125 			&interface, this->driver_binding_handle,
126 			controller_handle, EFI_OPEN_PROTOCOL_BY_DRIVER));
127 	switch (ret) {
128 	case EFI_ACCESS_DENIED:
129 	case EFI_ALREADY_STARTED:
130 		goto out;
131 	case EFI_SUCCESS:
132 		break;
133 	default:
134 		ret =  EFI_UNSUPPORTED;
135 		goto out;
136 	}
137 	ret = check_node_type(controller_handle);
138 	if (ret != EFI_SUCCESS) {
139 		r = EFI_CALL(systab.boottime->close_protocol(
140 				controller_handle, bp->ops->protocol,
141 				this->driver_binding_handle,
142 				controller_handle));
143 		if (r != EFI_SUCCESS)
144 			EFI_PRINT("Failure to close handle\n");
145 		goto out;
146 	}
147 
148 	/* TODO: driver specific stuff */
149 	bp->ops->bind(controller_handle, interface);
150 
151 out:
152 	return EFI_EXIT(ret);
153 }
154 
155 /**
156  * disconnect_child() - remove a single child controller from the parent
157  *			controller
158  *
159  * @controller_handle:	parent controller
160  * @child_handle:	child controller
161  * Return:		status code
162  */
disconnect_child(efi_handle_t controller_handle,efi_handle_t child_handle)163 static efi_status_t disconnect_child(efi_handle_t controller_handle,
164 				     efi_handle_t child_handle)
165 {
166 	efi_status_t ret;
167 	efi_guid_t *guid_controller = NULL;
168 	efi_guid_t *guid_child_controller = NULL;
169 
170 	ret = EFI_CALL(systab.boottime->close_protocol(
171 				controller_handle, guid_controller,
172 				child_handle, child_handle));
173 	if (ret != EFI_SUCCESS) {
174 		EFI_PRINT("Cannot close protocol\n");
175 		return ret;
176 	}
177 	ret = EFI_CALL(systab.boottime->uninstall_protocol_interface(
178 				child_handle, guid_child_controller, NULL));
179 	if (ret != EFI_SUCCESS) {
180 		EFI_PRINT("Cannot uninstall protocol interface\n");
181 		return ret;
182 	}
183 	return ret;
184 }
185 
186 /**
187  * efi_uc_stop() - Remove child controllers and disconnect the controller
188  *
189  * @this:			driver binding protocol
190  * @controller_handle:		handle of the controller
191  * @number_of_children:		number of child controllers to remove
192  * @child_handle_buffer:	handles of the child controllers to remove
193  * Return:			status code
194  */
efi_uc_stop(struct efi_driver_binding_protocol * this,efi_handle_t controller_handle,size_t number_of_children,efi_handle_t * child_handle_buffer)195 static efi_status_t EFIAPI efi_uc_stop(
196 		struct efi_driver_binding_protocol *this,
197 		efi_handle_t controller_handle,
198 		size_t number_of_children,
199 		efi_handle_t *child_handle_buffer)
200 {
201 	efi_status_t ret;
202 	efi_uintn_t count;
203 	struct efi_open_protocol_info_entry *entry_buffer;
204 	struct efi_driver_binding_extended_protocol *bp =
205 			(struct efi_driver_binding_extended_protocol *)this;
206 
207 	EFI_ENTRY("%p, %p, %zu, %p", this, controller_handle,
208 		  number_of_children, child_handle_buffer);
209 
210 	/* Destroy provided child controllers */
211 	if (number_of_children) {
212 		efi_uintn_t i;
213 
214 		for (i = 0; i < number_of_children; ++i) {
215 			ret = disconnect_child(controller_handle,
216 					       child_handle_buffer[i]);
217 			if (ret != EFI_SUCCESS)
218 				return ret;
219 		}
220 		return EFI_SUCCESS;
221 	}
222 
223 	/* Destroy all children */
224 	ret = EFI_CALL(systab.boottime->open_protocol_information(
225 					controller_handle, bp->ops->protocol,
226 					&entry_buffer, &count));
227 	if (ret != EFI_SUCCESS)
228 		goto out;
229 	while (count) {
230 		if (entry_buffer[--count].attributes &
231 		    EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) {
232 			ret = disconnect_child(
233 					controller_handle,
234 					entry_buffer[count].agent_handle);
235 			if (ret != EFI_SUCCESS)
236 				goto out;
237 		}
238 	}
239 	ret = EFI_CALL(systab.boottime->free_pool(entry_buffer));
240 	if (ret != EFI_SUCCESS)
241 		log_err("Cannot free EFI memory pool\n");
242 
243 	/* Detach driver from controller */
244 	ret = EFI_CALL(systab.boottime->close_protocol(
245 			controller_handle, bp->ops->protocol,
246 			this->driver_binding_handle, controller_handle));
247 out:
248 	return EFI_EXIT(ret);
249 }
250 
251 /**
252  * efi_add_driver() - add driver
253  *
254  * @drv:		driver to add
255  * Return:		status code
256  */
efi_add_driver(struct driver * drv)257 static efi_status_t efi_add_driver(struct driver *drv)
258 {
259 	efi_status_t ret;
260 	const struct efi_driver_ops *ops = drv->ops;
261 	struct efi_driver_binding_extended_protocol *bp;
262 
263 	log_debug("Adding EFI driver '%s'\n", drv->name);
264 	if (!ops->protocol) {
265 		log_err("EFI protocol GUID missing for driver '%s'\n",
266 			drv->name);
267 		return EFI_INVALID_PARAMETER;
268 	}
269 	bp = calloc(1, sizeof(struct efi_driver_binding_extended_protocol));
270 	if (!bp)
271 		return EFI_OUT_OF_RESOURCES;
272 
273 	bp->bp.supported = efi_uc_supported;
274 	bp->bp.start = efi_uc_start;
275 	bp->bp.stop = efi_uc_stop;
276 	bp->bp.version = 0xffffffff;
277 	bp->ops = drv->ops;
278 
279 	ret = efi_create_handle(&bp->bp.driver_binding_handle);
280 	if (ret != EFI_SUCCESS) {
281 		free(bp);
282 		goto out;
283 	}
284 	bp->bp.image_handle = bp->bp.driver_binding_handle;
285 	ret = efi_add_protocol(bp->bp.driver_binding_handle,
286 			       &efi_guid_driver_binding_protocol, bp);
287 	if (ret != EFI_SUCCESS) {
288 		efi_delete_handle(bp->bp.driver_binding_handle);
289 		free(bp);
290 		goto out;
291 	}
292 out:
293 	return ret;
294 }
295 
296 /**
297  * efi_driver_init() - initialize the EFI drivers
298  *
299  * Called by efi_init_obj_list().
300  *
301  * Return:	0 = success, any other value will stop further execution
302  */
efi_driver_init(void)303 efi_status_t efi_driver_init(void)
304 {
305 	struct driver *drv;
306 	efi_status_t ret = EFI_SUCCESS;
307 
308 	log_debug("Initializing EFI driver framework\n");
309 	for (drv = ll_entry_start(struct driver, driver);
310 	     drv < ll_entry_end(struct driver, driver); ++drv) {
311 		if (drv->id == UCLASS_EFI) {
312 			ret = efi_add_driver(drv);
313 			if (ret != EFI_SUCCESS) {
314 				log_err("Failed to add EFI driver %s\n",
315 					drv->name);
316 				break;
317 			}
318 		}
319 	}
320 	return ret;
321 }
322 
323 /**
324  * efi_uc_init() - initialize the EFI uclass
325  *
326  * @class:	the EFI uclass
327  * Return:	0 = success
328  */
efi_uc_init(struct uclass * class)329 static int efi_uc_init(struct uclass *class)
330 {
331 	log_debug("Initializing UCLASS_EFI\n");
332 	return 0;
333 }
334 
335 /**
336  * efi_uc_destroy() - destroy the EFI uclass
337  *
338  * @class:	the EFI uclass
339  * Return:	0 = success
340  */
efi_uc_destroy(struct uclass * class)341 static int efi_uc_destroy(struct uclass *class)
342 {
343 	log_debug("Destroying UCLASS_EFI\n");
344 	return 0;
345 }
346 
347 UCLASS_DRIVER(efi) = {
348 	.name		= "efi",
349 	.id		= UCLASS_EFI,
350 	.init		= efi_uc_init,
351 	.destroy	= efi_uc_destroy,
352 };
353