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 13struct bootflow; 14struct bootflow_iter; 15struct bootstd_priv; 16struct 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 */ 46enum 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 59struct 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 */ 71typedef 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 */ 91struct 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 * @bootflows: List of available bootflows for this bootdev 113 * @piro: Priority of this bootdev 114 */ 115struct bootdev_uc_plat { 116 struct list_head bootflow_head; 117 enum bootdev_prio_t prio; 118}; 119 120/** struct bootdev_ops - Operations for the bootdev uclass */ 121struct bootdev_ops { 122 /** 123 * get_bootflow() - get a bootflow (optional) 124 * 125 * If this is NULL then the default implementaton is used, which is 126 * default_get_bootflow() 127 * 128 * @dev: Bootflow device to check 129 * @iter: Provides current dev, part, method to get. Should update 130 * max_part if there is a partition table. Should update state, 131 * subdir, fname, buf, size according to progress 132 * @bflow: Updated bootflow if found 133 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this 134 * device, -ENOSYS if this device doesn't support bootflows, 135 * other -ve value on other error 136 */ 137 int (*get_bootflow)(struct udevice *dev, struct bootflow_iter *iter, 138 struct bootflow *bflow); 139}; 140 141#define bootdev_get_ops(dev) ((struct bootdev_ops *)(dev)->driver->ops) 142 143/** 144 * bootdev_get_bootflow() - get a bootflow 145 * 146 * @dev: Bootflow device to check 147 * @iter: Provides current part, method to get 148 * @bflow: Returns bootflow if found 149 * Return: 0 if OK, -ESHUTDOWN if there are no more bootflows on this device, 150 * -ENOSYS if this device doesn't support bootflows, other -ve value on 151 * other error 152 */ 153int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, 154 struct bootflow *bflow); 155 156/** 157 * bootdev_bind() - Bind a new named bootdev device 158 * 159 * @parent: Parent of the new device 160 * @drv_name: Driver name to use for the bootdev device 161 * @name: Name for the device (parent name is prepended) 162 * @devp: the new device (which has not been probed) 163 */ 164int bootdev_bind(struct udevice *parent, const char *drv_name, const char *name, 165 struct udevice **devp); 166 167/** 168 * bootdev_find_in_blk() - Find a bootdev in a block device 169 * 170 * @dev: Bootflow device associated with this block device 171 * @blk: Block device to search 172 * @iter: Provides current dev, part, method to get. Should update 173 * max_part if there is a partition table 174 * @bflow: On entry, provides information about the partition and device to 175 * check. On exit, returns bootflow if found 176 * Return: 0 if found, -ESHUTDOWN if no more bootflows, other -ve on error 177 */ 178int bootdev_find_in_blk(struct udevice *dev, struct udevice *blk, 179 struct bootflow_iter *iter, struct bootflow *bflow); 180 181/** 182 * bootdev_list() - List all available bootdevs 183 * 184 * @probe: true to probe devices, false to leave them as is 185 */ 186void bootdev_list(bool probe); 187 188/** 189 * bootdev_clear_bootflows() - Clear bootflows from a bootdev 190 * 191 * Each bootdev maintains a list of discovered bootflows. This provides a 192 * way to clear it. These bootflows are removed from the global list too. 193 * 194 * @dev: bootdev device to update 195 */ 196void bootdev_clear_bootflows(struct udevice *dev); 197 198/** 199 * bootdev_add_bootflow() - Add a bootflow to the bootdev's list 200 * 201 * All fields in @bflow must be set up. Note that @bflow->dev is used to add the 202 * bootflow to that device. 203 * 204 * @dev: Bootdev device to add to 205 * @bflow: Bootflow to add. Note that fields within bflow must be allocated 206 * since this function takes over ownership of these. This functions makes 207 * a copy of @bflow itself (without allocating its fields again), so the 208 * caller must dispose of the memory used by the @bflow pointer itself 209 * Return: 0 if OK, -ENOMEM if out of memory 210 */ 211int bootdev_add_bootflow(struct bootflow *bflow); 212 213/** 214 * bootdev_first_bootflow() - Get the first bootflow from a bootdev 215 * 216 * Returns the first bootflow attached to a bootdev 217 * 218 * @dev: bootdev device 219 * @bflowp: Returns a pointer to the bootflow 220 * Return: 0 if found, -ENOENT if there are no bootflows 221 */ 222int bootdev_first_bootflow(struct udevice *dev, struct bootflow **bflowp); 223 224/** 225 * bootdev_next_bootflow() - Get the next bootflow from a bootdev 226 * 227 * Returns the next bootflow attached to a bootdev 228 * 229 * @bflowp: On entry, the last bootflow returned , e.g. from 230 * bootdev_first_bootflow() 231 * Return: 0 if found, -ENOENT if there are no more bootflows 232 */ 233int bootdev_next_bootflow(struct bootflow **bflowp); 234 235/** 236 * bootdev_find_by_label() - Look up a bootdev by label 237 * 238 * Each bootdev has a label which contains the media-uclass name and a number, 239 * e.g. 'mmc2'. This looks up the label and returns the associated bootdev 240 * 241 * The lookup is performed based on the media device's sequence number. So for 242 * 'mmc2' this looks for a device in UCLASS_MMC with a dev_seq() of 2. 243 * 244 * @label: Label to look up (e.g. "mmc1" or "mmc0") 245 * @devp: Returns the bootdev device found, or NULL if none (note it does not 246 * return the media device, but its bootdev child) 247 * @method_flagsp: If non-NULL, returns any flags implied by the label 248 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails 249 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board, 250 * -ENOENT if there is no device with that number 251 */ 252int bootdev_find_by_label(const char *label, struct udevice **devp, 253 int *method_flagsp); 254 255/** 256 * bootdev_find_by_any() - Find a bootdev by name, label or sequence 257 * 258 * @name: name (e.g. "mmc2.bootdev"), label ("mmc2"), or sequence ("2") to find 259 * @devp: returns the device found, on success 260 * @method_flagsp: If non-NULL, returns any flags implied by the label 261 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails 262 * Return: 0 if OK, -EPFNOSUPPORT if the uclass is not supported by this board, 263 * -ENOENT if there is no device with that number 264 */ 265int bootdev_find_by_any(const char *name, struct udevice **devp, 266 int *method_flagsp); 267 268/** 269 * bootdev_setup_iter() - Set up iteration through bootdevs 270 * 271 * This sets up the an interation, based on the provided device or label. If 272 * neither is provided, the iteration is based on the priority of each bootdev, 273 * the * bootdev-order property in the bootstd node (or the boot_targets env 274 * var). 275 * 276 * @iter: Iterator to update with the order 277 * @label: label to scan, or NULL to scan all 278 * @devp: On entry, *devp is NULL to scan all, otherwise this is the (single) 279 * device to scan. Returns the first device to use, which is the passed-in 280 * @devp if it was non-NULL 281 * @method_flagsp: If non-NULL, returns any flags implied by the label 282 * (enum bootflow_meth_flags_t), 0 if none 283 * Return: 0 if OK, -ENOENT if no bootdevs, -ENOMEM if out of memory, other -ve 284 * on other error 285 */ 286int bootdev_setup_iter(struct bootflow_iter *iter, const char *label, 287 struct udevice **devp, int *method_flagsp); 288 289/** 290 * bootdev_list_hunters() - List the available bootdev hunters 291 * 292 * These provide a way to find new bootdevs by enumerating buses, etc. This 293 * function lists the available hunters 294 * 295 * @std: Pointer to bootstd private info 296 */ 297void bootdev_list_hunters(struct bootstd_priv *std); 298 299/** 300 * bootdev_hunt() - Hunt for bootdevs matching a particular spec 301 * 302 * This runs the selected hunter (or all if @spec is NULL) to try to find new 303 * bootdevs. 304 * 305 * @spec: Spec to match, e.g. "mmc0", or NULL for any. If provided, this must 306 * match a uclass name so that the hunter can be determined. Any trailing number 307 * is ignored 308 * @show: true to show each hunter before using it 309 * Returns: 0 if OK, -ve on error 310 */ 311int bootdev_hunt(const char *spec, bool show); 312 313/** 314 * bootdev_hunt_prio() - Hunt for bootdevs of a particular priority 315 * 316 * This runs all hunters which can find bootdevs of the given priority. 317 * 318 * @prio: Priority to use 319 * @show: true to show each hunter as it is used 320 * Returns: 0 if OK, -ve on error 321 */ 322int bootdev_hunt_prio(enum bootdev_prio_t prio, bool show); 323 324/** 325 * bootdev_unhunt() - Mark a device as needing to be hunted again 326 * 327 * @id: uclass ID to update 328 * Return: 0 if done, -EALREADY if already in this state, -ENOENT if no hunter 329 * found for that uclass 330 */ 331int bootdev_unhunt(enum uclass_id id); 332 333/** 334 * bootdev_hunt_and_find_by_label() - Hunt for bootdevs by label 335 * 336 * Runs the hunter for the label, then tries to find the bootdev, possible 337 * created by the hunter 338 * 339 * @label: Label to look up (e.g. "mmc1" or "mmc0") 340 * @devp: Returns the bootdev device found, or NULL if none (note it does not 341 * return the media device, but its bootdev child) 342 * @method_flagsp: If non-NULL, returns any flags implied by the label 343 * (enum bootflow_meth_flags_t), 0 if none. Unset if function fails 344 * Return: 0 if OK, -EINVAL if the uclass is not supported by this board, 345 * -ENOENT if there is no device with that number 346 */ 347int bootdev_hunt_and_find_by_label(const char *label, struct udevice **devp, 348 int *method_flagsp); 349 350/** 351 * bootdev_next_label() - Move to the next bootdev in the label sequence 352 * 353 * Looks through the remaining labels until it finds one that matches a bootdev. 354 * Bootdev scanners are used as needed. For example a label "mmc1" results in 355 * running the "mmc" bootdrv. 356 * 357 * @iter: Interation info, containing iter->cur_label 358 * @devp: New bootdev found, if any was found 359 * @method_flagsp: If non-NULL, returns any flags implied by the label 360 * (enum bootflow_meth_flags_t), 0 if none 361 * Returns 0 if OK, -ENODEV if no bootdev was found 362 */ 363int bootdev_next_label(struct bootflow_iter *iter, struct udevice **devp, 364 int *method_flagsp); 365 366/** 367 * bootdev_next_prio() - Find the next bootdev in priority order 368 * 369 * This moves @devp to the next bootdev with the current priority. If there is 370 * none, then it moves to the next priority and scans for new bootdevs there. 371 * 372 * @iter: Interation info, containing iter->cur_prio 373 * @devp: On entry this is the previous bootdev that was considered. On exit 374 * this is the new bootdev, if any was found 375 * Returns 0 on success (*devp is updated), -ENODEV if there are no more 376 * bootdevs at any priority 377 */ 378int bootdev_next_prio(struct bootflow_iter *iter, struct udevice **devp); 379 380#if CONFIG_IS_ENABLED(BOOTSTD) 381/** 382 * bootdev_setup_for_dev() - Bind a new bootdev device (deprecated) 383 * 384 * Please use bootdev_setup_for_sibling_blk() instead since it supports multiple 385 * (child) block devices for each media device. 386 * 387 * Creates a bootdev device as a child of @parent. This should be called from 388 * the driver's bind() method or its uclass' post_bind() method. 389 * 390 * If a child bootdev already exists, this function does nothing 391 * 392 * @parent: Parent device (e.g. MMC or Ethernet) 393 * @drv_name: Name of bootdev driver to bind 394 * Return: 0 if OK, -ve on error 395 */ 396int bootdev_setup_for_dev(struct udevice *parent, const char *drv_name); 397 398/** 399 * bootdev_setup_for_sibling_blk() - Bind a new bootdev device for a blk device 400 * 401 * Creates a bootdev device as a sibling of @blk. This should be called from 402 * the driver's bind() method or its uclass' post_bind() method, at the same 403 * time as the bould device is bound 404 * 405 * If a device of the same name already exists, this function does nothing 406 * 407 * @parent: Parent device (e.g. MMC or Ethernet) 408 * @drv_name: Name of bootdev driver to bind 409 * Return: 0 if OK, -ve on error 410 */ 411int bootdev_setup_for_sibling_blk(struct udevice *blk, const char *drv_name); 412 413/** 414 * bootdev_get_sibling_blk() - Locate the block device for a bootdev 415 * 416 * @dev: bootdev to check 417 * @blkp: returns associated block device 418 * Return: 0 if OK, -EINVAL if @dev is not a bootdev device, other -ve on other 419 * error 420 */ 421int bootdev_get_sibling_blk(struct udevice *dev, struct udevice **blkp); 422 423/** 424 * bootdev_unbind_dev() - Unbind a bootdev device 425 * 426 * Remove and unbind a bootdev device which is a child of @parent. This should 427 * be called from the driver's unbind() method or its uclass' post_bind() 428 * method. 429 * 430 * @parent: Parent device (e.g. MMC or Ethernet) 431 * Return: 0 if OK, -ve on error 432 */ 433int bootdev_unbind_dev(struct udevice *parent); 434#else 435static inline int bootdev_setup_for_dev(struct udevice *parent, 436 const char *drv_name) 437{ 438 return 0; 439} 440 441static inline int bootdev_setup_for_sibling_blk(struct udevice *blk, 442 const char *drv_name) 443{ 444 return 0; 445} 446 447static inline int bootdev_unbind_dev(struct udevice *parent) 448{ 449 return 0; 450} 451#endif 452 453#endif 454