1 /* SPDX-License-Identifier: GPL-2.0+ */
2 /*
3  * Copyright 2021 Google LLC
4  * Written by Simon Glass <sjg@chromium.org>
5  */
6 
7 #ifndef __bootdev_h
8 #define __bootdev_h
9 
10 #include <dm/uclass-id.h>
11 #include <linux/list.h>
12 
13 struct bootflow;
14 struct bootflow_iter;
15 struct bootstd_priv;
16 struct udevice;
17 
18 /**
19  * enum bootdev_prio_t - priority of each bootdev
20  *
21  * These values are associated with each bootdev and set up by the driver.
22  *
23  * Smallest value is the highest priority. By default, bootdevs are scanned from
24  * highest to lowest priority
25  *
26  * BOOTDEVP_0_NONE: Invalid value, do not use
27  * @BOOTDEVP_6_PRE_SCAN: Scan bootdevs with this priority always, before
28  * starting any bootflow scan
29  * @BOOTDEVP_2_INTERNAL_FAST: Internal devices which don't need scanning and
30  * generally very quick to access, e.g. less than 100ms
31  * @BOOTDEVP_3_INTERNAL_SLOW: Internal devices which don't need scanning but
32  * take a significant fraction of a second to access
33  * @BOOTDEVP_4_SCAN_FAST: Extenal devices which need scanning or bus
34  * enumeration to find, but this enumeration happens quickly, typically under
35  * 100ms
36  * @BOOTDEVP_5_SCAN_SLOW: Extenal devices which need scanning or bus
37  * enumeration to find. The enumeration takes significant fraction of a second
38  * to complete
39  * @BOOTDEVP_6_NET_BASE: Basic network devices which are quickly and easily
40  * available. Typically used for an internal Ethernet device
41  * @BOOTDEVP_7_NET_FALLBACK: Secondary network devices which require extra time
42  * to start up, or are less desirable. Typically used for secondary Ethernet
43  * devices. Note that USB ethernet devices are found during USB enumeration,
44  * so do not use this priority
45  */
46 enum bootdev_prio_t {
47 	BOOTDEVP_0_NONE,
48 	BOOTDEVP_1_PRE_SCAN,
49 	BOOTDEVP_2_INTERNAL_FAST,
50 	BOOTDEVP_3_INTERNAL_SLOW,
51 	BOOTDEVP_4_SCAN_FAST,
52 	BOOTDEVP_5_SCAN_SLOW,
53 	BOOTDEVP_6_NET_BASE,
54 	BOOTDEVP_7_NET_FALLBACK,
55 
56 	BOOTDEVP_COUNT,
57 };
58 
59 struct bootdev_hunter;
60 
61 /**
62  * bootdev_hunter_func - function to probe for bootdevs of a given type
63  *
64  * This should hunt around for bootdevs of the given type, binding them as it
65  * finds them. This may involve bus enumeration, etc.
66  *
67  * @info: Info structure describing this hunter
68  * @show: true to show information from the hunter
69  * Returns: 0 if OK, -ENOENT on device not found, otherwise -ve on error
70  */
71 typedef int (*bootdev_hunter_func)(struct bootdev_hunter *info, bool show);
72 
73 /**
74  * struct bootdev_hunter - information about how to hunt for bootdevs
75  *
76  * @prio: Scanning priority of this hunter
77  * @uclass: Uclass ID for the media associated with this bootdev
78  * @drv: bootdev driver for the things found by this hunter
79  * @hunt: Function to call to hunt for bootdevs of this type (NULL if none)
80  *
81  * Some bootdevs are not visible until other devices are enumerated. For
82  * example, USB bootdevs only appear when the USB bus is enumerated.
83  *
84  * On the other hand, we don't always want to enumerate all the buses just to
85  * find the first valid bootdev. Ideally we want to work through them in
86  * priority order, so that the fastest bootdevs are discovered first.
87  *
88  * This struct holds information about the bootdev so we can determine the probe
89  * order and how to hunt for bootdevs of this type
90  */
91 struct bootdev_hunter {
92 	enum bootdev_prio_t prio;
93 	enum uclass_id uclass;
94 	struct driver *drv;
95 	bootdev_hunter_func hunt;
96 };
97 
98 /* declare a new bootdev hunter */
99 #define BOOTDEV_HUNTER(__name)						\
100 	ll_entry_declare(struct bootdev_hunter, __name, bootdev_hunter)
101 
102 /* access a bootdev hunter by name */
103 #define BOOTDEV_HUNTER_GET(__name)						\
104 	ll_entry_get(struct bootdev_hunter, __name, bootdev_hunter)
105 
106 /**
107  * struct bootdev_uc_plat - uclass information about a bootdev
108  *
109  * This is attached to each device in the bootdev uclass and accessible via
110  * dev_get_uclass_plat(dev)
111  *
112  * @piro: Priority of this bootdev
113  */
114 struct bootdev_uc_plat {
115 	enum bootdev_prio_t prio;
116 };
117 
118 /** struct bootdev_ops - Operations for the bootdev uclass */
119 struct bootdev_ops {
120 	/**
121 	 * get_bootflow() - get a bootflow (optional)
122 	 *
123 	 * If this is NULL then the default implementaton is used, which is
124 	 * default_get_bootflow()
125 	 *
126 	 * @dev:	Bootflow device to check
127 	 * @iter:	Provides current dev, part, method to get. Should update
128 	 *	max_part if there is a partition table. Should update state,
129 	 *	subdir, fname, buf, size according to progress
130 	 * @bflow:	Updated bootflow if found
131 	 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this
132 	 *	device, -ENOSYS if this device doesn't support bootflows,
133 	 *	other -ve value on other error
134 	 */
135 	int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter,
136 			    struct bootflow *bflow);
137 };
138 
139 #define bootdev_get_ops(dev)  ((struct bootdev_ops *)(dev)->driver->ops)
140 
141 /**
142  * bootdev_get_bootflow() - get a bootflow
143  *
144  * @dev:	Bootflow device to check
145  * @iter:	Provides current  part, method to get
146  * @bflow:	Returns bootflow if found
147  * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this device,
148  *	-ENOSYS if this device doesn't support bootflows, other -ve value on
149  *	other error
150  */
151 int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
152 			 struct bootflow *bflow);
153 
154 /**
155  * bootdev_bind() - Bind a new named bootdev device
156  *
157  * @parent:	Parent of the new device
158  * @drv_name:	Driver name to use for the bootdev device
159  * @name:	Name for the device (parent name is prepended)
160  * @devp:	the new device (which has not been probed)
161  */
162 int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name,
163 		 struct udevice **devp);
164 
165 /**
166  * bootdev_find_in_blk() - Find a bootdev in a block device
167  *
168  * @dev: Bootflow device associated with this block device
169  * @blk: Block device to search
170  * @iter:	Provides current dev, part, method to get. Should update
171  *	max_part if there is a partition table
172  * @bflow: On entry, provides information about the partition and device to
173  *	check. On exit, returns bootflow if found
174  * Return: 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error
175  */
176 int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk,
177 			struct bootflow_iter *iter, struct bootflow *bflow);
178 
179 /**
180  * bootdev_list() - List all available bootdevs
181  *
182  * @probe: true to probe devices, false to leave them as is
183  */
184 void bootdev_list(bool probe);
185 
186 /**
187  * bootdev_first_bootflow() - Get the first bootflow from a bootdev
188  *
189  * Returns the first bootflow attached to a bootdev
190  *
191  * @dev: bootdev device
192  * @bflowp: Returns a pointer to the bootflow
193  * Return: 0 if found, -ENOENT if there are no bootflows
194  */
195 int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp);
196 
197 /**
198  * bootdev_next_bootflow() - Get the next bootflow from a bootdev
199  *
200  * Returns the next bootflow attached to a bootdev
201  *
202  * @bflowp: On entry, the last bootflow returned , e.g. from
203  *	bootdev_first_bootflow()
204  * Return: 0 if found, -ENOENT if there are no more bootflows
205  */
206 int bootdev_next_bootflow(struct bootflow **bflowp);
207 
208 /**
209  * bootdev_find_by_label() - Look up a bootdev by label
210  *
211  * Each bootdev has a label which contains the media-uclass name and a number,
212  * e.g. 'mmc2'. This looks up the label and returns the associated bootdev
213  *
214  * The lookup is performed based on the media device's sequence number. So for
215  * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2.
216  *
217  * @label: Label to look up (e.g. "mmc1" or "mmc0")
218  * @devp: Returns the bootdev device found, or NULL if none (note it does not
219  *	return the media device, but its bootdev child)
220  * @method_flagsp: If non-NULL, returns any flags implied by the label
221  * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
222  * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
223  * -ENOENT if there is no device with that number
224  */
225 int bootdev_find_by_label(const char *label, struct udevice **devp,
226 			  int *method_flagsp);
227 
228 /**
229  * bootdev_find_by_any() - Find a bootdev by name, label or sequence
230  *
231  * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find
232  * @devp: returns the device found, on success
233  * @method_flagsp: If non-NULL, returns any flags implied by the label
234  * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
235  * Return: 0 if OK, -EPFNOSUPPORT if the uclass is not supported by this board,
236  * -ENOENT if there is no device with that number
237  */
238 int bootdev_find_by_any(const char *name, struct udevice **devp,
239 			int *method_flagsp);
240 
241 /**
242  * bootdev_setup_iter() - Set up iteration through bootdevs
243  *
244  * This sets up the an interation, based on the provided device or label. If
245  * neither is provided, the iteration is based on the priority of each bootdev,
246  * the * bootdev-order property in the bootstd node (or the boot_targets env
247  * var).
248  *
249  * @iter: Iterator to update with the order
250  * @label: label to scan, or NULL to scan all
251  * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single)
252  *	device to scan. Returns the first device to use, which is the passed-in
253  *	@devp if it was non-NULL
254  * @method_flagsp: If non-NULL, returns any flags implied by the label
255  * (enum bootflow_meth_flags_t), 0 if none
256  * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve
257  *	on other error
258  */
259 int bootdev_setup_iter(struct bootflow_iter *iter, const char *label,
260 		       struct udevice **devp, int *method_flagsp);
261 
262 /**
263  * bootdev_list_hunters() - List the available bootdev hunters
264  *
265  * These provide a way to find new bootdevs by enumerating buses, etc. This
266  * function lists the available hunters
267  *
268  * @std: Pointer to bootstd private info
269  */
270 void bootdev_list_hunters(struct bootstd_priv *std);
271 
272 /**
273  * bootdev_hunt() - Hunt for bootdevs matching a particular spec
274  *
275  * This runs the selected hunter (or all if @spec is NULL) to try to find new
276  * bootdevs.
277  *
278  * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must
279  * match a uclass name so that the hunter can be determined. Any trailing number
280  * is ignored
281  * @show: true to show each hunter before using it
282  * Returns: 0 if OK, -ve on error
283  */
284 int bootdev_hunt(const char *spec, bool show);
285 
286 /**
287  * bootdev_hunt_prio() - Hunt for bootdevs of a particular priority
288  *
289  * This runs all hunters which can find bootdevs of the given priority.
290  *
291  * @prio: Priority to use
292  * @show: true to show each hunter as it is used
293  * Returns: 0 if OK, -ve on error
294  */
295 int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show);
296 
297 /**
298  * bootdev_unhunt() - Mark a device as needing to be hunted again
299  *
300  * @id: uclass ID to update
301  * Return: 0 if done, -EALREADY if already in this state, -ENOENT if no hunter
302  * found for that uclass
303  */
304 int bootdev_unhunt(enum uclass_id id);
305 
306 /**
307  * bootdev_hunt_and_find_by_label() - Hunt for bootdevs by label
308  *
309  * Runs the hunter for the label, then tries to find the bootdev, possible
310  * created by the hunter
311  *
312  * @label: Label to look up (e.g. "mmc1" or "mmc0")
313  * @devp: Returns the bootdev device found, or NULL if none (note it does not
314  *	return the media device, but its bootdev child)
315  * @method_flagsp: If non-NULL, returns any flags implied by the label
316  * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails
317  * Return: 0 if OK, -EINVAL if the uclass is not supported by this board,
318  * -ENOENT if there is no device with that number
319  */
320 int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp,
321 				   int *method_flagsp);
322 
323 /**
324  * bootdev_next_label() - Move to the next bootdev in the label sequence
325  *
326  * Looks through the remaining labels until it finds one that matches a bootdev.
327  * Bootdev scanners are used as needed. For example a label "mmc1" results in
328  * running the "mmc" bootdrv.
329  *
330  * @iter: Interation info, containing iter->cur_label
331  * @devp: New bootdev found, if any was found
332  * @method_flagsp: If non-NULL, returns any flags implied by the label
333  * (enum bootflow_meth_flags_t), 0 if none
334  * Returns 0 if OK, -ENODEV if no bootdev was found
335  */
336 int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp,
337 		       int *method_flagsp);
338 
339 /**
340  * bootdev_next_prio() - Find the next bootdev in priority order
341  *
342  * This moves @devp to the next bootdev with the current priority. If there is
343  * none, then it moves to the next priority and scans for new bootdevs there.
344  *
345  * @iter: Interation info, containing iter->cur_prio
346  * @devp: On entry this is the previous bootdev that was considered. On exit
347  *	this is the new bootdev, if any was found
348  * Returns 0 on success (*devp is updated), -ENODEV if there are no more
349  * bootdevs at any priority
350  */
351 int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp);
352 
353 #if CONFIG_IS_ENABLED(BOOTSTD)
354 /**
355  * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated)
356  *
357  * Please use bootdev_setup_for_sibling_blk() instead since it supports multiple
358  * (child) block devices for each media device.
359  *
360  * Creates a bootdev device as a child of @parent. This should be called from
361  * the driver's bind() method or its uclass' post_bind() method.
362  *
363  * If a child bootdev already exists, this function does nothing
364  *
365  * @parent: Parent device (e.g. MMC or Ethernet)
366  * @drv_name: Name of bootdev driver to bind
367  * Return: 0 if OK, -ve on error
368  */
369 int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name);
370 
371 #if CONFIG_IS_ENABLED(BOOTSTD)
372 /**
373  * bootdev_setup_for_sibling_blk() - Bind a new bootdev device for a blk device
374  *
375  * Creates a bootdev device as a sibling of @blk. This should be called from
376  * the driver's bind() method or its uclass' post_bind() method, at the same
377  * time as the bould device is bound
378  *
379  * If a device of the same name already exists, this function does nothing
380  *
381  * @parent: Parent device (e.g. MMC or Ethernet)
382  * @drv_name: Name of bootdev driver to bind
383  * Return: 0 if OK, -ve on error
384  */
385 int bootdev_setup_for_sibling_blk(struct udevice *blk, const char *drv_name);
386 #else
bootdev_setup_for_sibling_blk(struct udevice * blk,const char * drv_name)387 static int bootdev_setup_for_sibling_blk(struct udevice *blk,
388 					 const char *drv_name)
389 {
390 	return 0;
391 }
392 #endif
393 
394 /**
395  * bootdev_get_sibling_blk() - Locate the block device for a bootdev
396  *
397  * @dev: bootdev to check
398  * @blkp: returns associated block device
399  * Return: 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other
400  *	error
401  */
402 int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp);
403 
404 /**
405  * bootdev_get_from_blk() - Get the bootdev given a block device
406  *
407  * @blk: Block device to check
408  * @bootdebp: Returns the bootdev found, if any
409  * Return 0 if OK, -ve on error
410  */
411 int bootdev_get_from_blk(struct udevice *blk, struct udevice **bootdevp);
412 
413 /**
414  * bootdev_unbind_dev() - Unbind a bootdev device
415  *
416  * Remove and unbind a bootdev device which is a child of @parent. This should
417  * be called from the driver's unbind() method or its uclass' post_bind()
418  * method.
419  *
420  * @parent: Parent device (e.g. MMC or Ethernet)
421  * Return: 0 if OK, -ve on error
422  */
423 int bootdev_unbind_dev(struct udevice *parent);
424 #else
bootdev_setup_for_dev(struct udevice * parent,const char * drv_name)425 static inline int bootdev_setup_for_dev(struct udevice *parent,
426 					const char *drv_name)
427 {
428 	return 0;
429 }
430 
bootdev_setup_for_sibling_blk(struct udevice * blk,const char * drv_name)431 static inline int bootdev_setup_for_sibling_blk(struct udevice *blk,
432 						const char *drv_name)
433 {
434 	return 0;
435 }
436 
bootdev_unbind_dev(struct udevice * parent)437 static inline int bootdev_unbind_dev(struct udevice *parent)
438 {
439 	return 0;
440 }
441 #endif
442 
443 #endif
444