"Das U-Boot" Source Tree
at master 852 lines 36 kB view raw
1.. SPDX-License-Identifier: GPL-2.0+: 2 3Standard Boot Overview 4====================== 5 6Introduction 7------------ 8 9Standard boot provides a built-in way for U-Boot to automatically boot 10an Operating System without custom scripting and other customisation. It 11introduces the following concepts: 12 13 - bootdev - a device which can hold or access a distro (e.g. MMC, Ethernet) 14 - bootmeth - a method to scan a bootdev to find bootflows (e.g. distro boot) 15 - bootflow - a description of how to boot (provided by the distro) 16 17For Linux, the distro (Linux distribution, e.g. Debian, Fedora) is responsible 18for creating a bootflow for each kernel combination that it wants to offer. 19These bootflows are stored on media so they can be discovered by U-Boot. This 20feature is typically called `distro boot` (see :doc:`../distro`) because it is 21a way for distributions to boot on any hardware. 22 23Traditionally U-Boot has relied on scripts to implement this feature. See 24distro_bootcmd_ for details. This is done because U-Boot has no native support 25for scanning devices. While the scripts work remarkably well, they can be hard 26to understand and extend, and the feature does not include tests. They are also 27making it difficult to move away from ad-hoc CONFIGs, since they are implemented 28using the environment and a lot of #defines. 29 30Standard boot is a generalisation of distro boot. It provides a more built-in 31way to boot with U-Boot. The feature is extensible to different Operating 32Systems (such as Chromium OS) and devices (beyond just block and network 33devices). It supports EFI boot and EFI bootmgr too. 34 35Finally, standard boot supports the operation of :doc:`../vbe`. 36 37Bootflow 38-------- 39 40A bootflow is a file that describes how to boot a distro. Conceptually there can 41be different formats for that file but at present U-Boot only supports the 42BootLoaderSpec_ format which looks something like this:: 43 44 menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. 45 menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. 46 menu hidden 47 48 label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) 49 kernel /vmlinuz-5.3.7-301.fc31.armv7hl 50 append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB 51 fdtdir /dtb-5.3.7-301.fc31.armv7hl/ 52 initrd /initramfs-5.3.7-301.fc31.armv7hl.img 53 54As you can see it specifies a kernel, a ramdisk (initrd) and a directory from 55which to load Device Tree files. The details are described in distro_bootcmd_. 56 57The bootflow is provided by the distro. It is not part of U-Boot. U-Boot's job 58is simply to interpret the file and carry out the instructions. This allows 59distros to boot on essentially any device supported by U-Boot. 60 61Typically the first available bootflow is selected and booted. If that fails, 62then the next one is tried. 63 64 65Bootdev 66------- 67 68Where does U-Boot find the media that holds the operating systems? That is the 69job of bootdev. A bootdev is simply a layer on top of a media device (such as 70MMC, NVMe). The bootdev accesses the device, including partitions and 71filesystems that might contain things related to an operating system. 72 73For example, an MMC bootdev provides access to the individual partitions on the 74MMC device. It scans through these to find filesystems with the boot flag set, 75then provides a list of these for consideration. 76 77Some bootdevs are not visible until a bus is enumerated, e.g. flash sticks 78attached via USB. To deal with this, each bootdev has an associated 'hunter' 79which can hunt for bootdevs of a particular uclass type. For example, the SCSI 80bootdev scans the SCSI bus looking for devices, creating a bootdev for each 81Logical Unit Number (LUN) that it finds. 82 83 84Bootmeth 85-------- 86 87Once the list of filesystems is provided, how does U-Boot find the bootflow 88files in these filesystems? That is the job of bootmeth. Each boot method has 89its own way of doing this. 90 91For example, the distro bootmeth simply looks through the provided filesystem 92for a file called `extlinux/extlinux.conf`. This files constitutes a bootflow. 93If the distro bootmeth is used on multiple partitions it may produce multiple 94bootflows. 95 96Note: it is possible to have a bootmeth that uses a partition or a whole device 97directly, but it is more common to use a filesystem. 98For example, the Android bootmeth uses a whole device. 99 100Note that some bootmeths are 'global', meaning that they select the bootdev 101themselves. Examples include VBE and EFI boot manager. In this case, they 102provide a `read_bootflow()` method which checks whatever bootdevs it likes, then 103returns the bootflow, if found. Some of these bootmeths may be very slow, if 104they scan a lot of devices. 105 106The extlinux bootmeth also allows for bootmeth specific configuration to be 107set. A bootmeth that wishes to support this provides the `set_property()` 108method. This allows string properties and values to be passed to the bootmeth. 109It is up to the bootmeth to determine what action to take when this method is 110called. 111 112 113Boot process 114------------ 115 116U-Boot tries to use the 'lazy init' approach wherever possible and distro boot 117is no exception. The algorithm is:: 118 119 while (get next bootdev) 120 while (get next bootmeth) 121 while (get next bootflow) 122 try to boot it 123 124So U-Boot works its way through the bootdevs, trying each bootmeth in turn to 125obtain bootflows, until it either boots or exhausts the available options. 126 127Instead of 500 lines of #defines and a 4KB boot script, all that is needed is 128the following command:: 129 130 bootflow scan -lb 131 132which scans for available bootflows, optionally listing each find it finds (-l) 133and trying to boot it (-b). 134 135When global bootmeths are available, these are typically checked before the 136above bootdev scanning. 137 138 139Controlling ordering 140-------------------- 141 142By default, faster bootdevs (or those which are assumed to be faster) are used 143first, since they are more likely to be able to boot the device quickly. 144 145Several options are available to control the ordering of boot scanning: 146 147 148boot_targets 149~~~~~~~~~~~~ 150 151This environment variable can be used to control the list of bootdevs searched 152and their ordering, for example:: 153 154 setenv boot_targets "mmc0 mmc1 usb pxe" 155 156Entries may be removed or re-ordered in this list to affect the boot order. If 157the variable is empty, the default ordering is used, based on the priority of 158bootdevs and their sequence numbers. 159 160 161bootmeths 162~~~~~~~~~ 163 164By default bootmeths are checked in name order. Use `bootmeth list` to see the 165ordering. Note that the `extlinux` and `script` bootmeth is first, to preserve the behaviour 166used by the old distro scripts. 167 168This environment variable can be used to control the list of bootmeths used and 169their ordering for example:: 170 171 setenv bootmeths "extlinux efi" 172 173Entries may be removed or re-ordered in this list to affect the order the 174bootmeths are tried on each bootdev. If the variable is empty, the default 175ordering is used, based on the bootmeth sequence numbers, which can be 176controlled by aliases. 177 178The :ref:`usage/cmd/bootmeth:bootmeth command` (`bootmeth order`) operates in 179the same way as setting this variable. 180 181Bootdev uclass 182-------------- 183 184The bootdev uclass provides a simple API call to obtain a bootflow from a 185device:: 186 187 int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, 188 struct bootflow *bflow); 189 190This takes an iterator which indicates the bootdev, partition and bootmeth to 191use. It returns a bootflow. This is the core of the bootdev implementation. The 192bootdev drivers that implement this differ depending on the media they are 193reading from, but each is responsible for returning a valid bootflow if 194available. 195 196A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this 197function for each media device uclass, in a few lines of code. For many types 198of bootdevs, the `get_bootflow` member can be NULL, indicating that the default 199handler is used. This is called `default_get_bootflow()` and it only works with 200block devices. 201 202 203Bootdev drivers 204--------------- 205 206A bootdev driver is typically fairly simple. Here is one for MMC:: 207 208 static int mmc_bootdev_bind(struct udevice *dev) 209 { 210 struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); 211 212 ucp->prio = BOOTDEVP_2_INTERNAL_FAST; 213 214 return 0; 215 } 216 217 struct bootdev_ops mmc_bootdev_ops = { 218 }; 219 220 static const struct udevice_id mmc_bootdev_ids[] = { 221 { .compatible = "u-boot,bootdev-mmc" }, 222 { } 223 }; 224 225 U_BOOT_DRIVER(mmc_bootdev) = { 226 .name = "mmc_bootdev", 227 .id = UCLASS_BOOTDEV, 228 .ops = &mmc_bootdev_ops, 229 .bind = mmc_bootdev_bind, 230 .of_match = mmc_bootdev_ids, 231 }; 232 233You may notice that the `get_bootflow` memory is not provided, so is NULL. This 234means that `default_get_bootflow()` is used. This simply obtains the 235block device and calls a bootdev helper function to do the rest. The 236implementation of `bootdev_find_in_blk()` checks the partition table, and 237attempts to read a file from a filesystem on the partition number given by the 238`@iter->part` parameter. If there are any bootable partitions in the table, 239then only bootable partitions are considered. 240 241Each bootdev has a priority, which indicates the order in which it is used, 242if `boot_targets` is not used. Faster bootdevs are used first, since they are 243more likely to be able to boot the device quickly. 244 245 246Environment Variables 247--------------------- 248 249Various environment variables are used by standard boot. These allow the board 250to control where things are placed when booting the OS. You should ensure that 251your boards sets values for these. 252 253fdtfile 254 Name of the flattened device tree (FDT) file to load, e.g. 255 "rockchip/rk3399-rockpro64.dtb" 256 257fdt_addr_r 258 Address at which to load the FDT, e.g. 0x01f00000 259 260fdtoverlay_addr_r (needed if overlays are used) 261 Address at which to load the overlay for the FDT, e.g. 0x02000000 262 263kernel_addr_r 264 Address at which to load the kernel, e.g. 0x02080000 265 266kernel_comp_addr_r 267 Address to which to decompress the kernel, e.g. 0x08000000 268 269kernel_comp_size 270 Size of available space for decompressed kernel, e.g. 0x2000000 271 272pxefile_addr_r 273 Address at which to load the PXE file, e.g. 0x00600000 274 275ramdisk_addr_r 276 Address at which to load the ramdisk, e.g. 0x06000000 277 278scriptaddr 279 Address at which to load the U-Boot script, e.g. 0x00500000 280 281script_offset_f 282 SPI flash offset from which to load the U-Boot script, e.g. 0xffe000 283 284script_size_f 285 Size of the script to load, e.g. 0x2000 286 287vendor_boot_comp_addr_r 288 Address to which to load the vendor_boot Android image, e.g. 0xe0000000 289 290Some variables are set by script bootmeth: 291 292devtype 293 Device type being used for boot, e.g. mmc 294 295devnum 296 Device number being used for boot, e.g. 1 297 298distro_bootpart 299 Partition being used for boot, e.g. 2 300 301prefix 302 Directory containing the script 303 304mmc_bootdev 305 Device number being used for boot (e.g. 1). This is only used by MMC on 306 sunxi boards. 307 308 309Device hierarchy 310---------------- 311 312A bootdev device is a child of the media device. In this example, you can see 313that the bootdev is a sibling of the block device and both are children of 314media device:: 315 316 mmc 0 [ + ] bcm2835-sdhost | |-- mmc@7e202000 317 blk 0 [ + ] mmc_blk | | |-- mmc@7e202000.blk 318 bootdev 0 [ ] mmc_bootdev | | `-- mmc@7e202000.bootdev 319 mmc 1 [ + ] sdhci-bcm2835 | |-- sdhci@7e300000 320 blk 1 [ ] mmc_blk | | |-- sdhci@7e300000.blk 321 bootdev 1 [ ] mmc_bootdev | | `-- sdhci@7e300000.bootdev 322 323The bootdev device is typically created automatically in the media uclass' 324`post_bind()` method by calling `bootdev_setup_for_dev()` or 325`bootdev_setup_for_sibling_blk()`. The code typically something like this:: 326 327 /* dev is the Ethernet device */ 328 ret = bootdev_setup_for_dev(dev, "eth_bootdev"); 329 if (ret) 330 return log_msg_ret("bootdev", ret); 331 332or:: 333 334 /* blk is the block device (child of MMC device) 335 ret = bootdev_setup_for_sibling_blk(blk, "mmc_bootdev"); 336 if (ret) 337 return log_msg_ret("bootdev", ret); 338 339 340Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev` 341is the Ethernet device. This function is safe to call even if standard boot is 342not enabled, since it does nothing in that case. It can be added to all uclasses 343which implement suitable media. 344 345 346The bootstd device 347------------------ 348 349Standard boot requires a single instance of the bootstd device to make things 350work. This includes global information about the state of standard boot. See 351`struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`. 352 353Within the Device Tree, if you add bootmeth devices, they should be children of 354the bootstd device. See `arch/sandbox/dts/test.dts` for an example of this. 355 356 357.. _`Automatic Devices`: 358 359Automatic devices 360----------------- 361 362It is possible to define all the required devices in the Device Tree manually, 363but it is not necessary. The bootstd uclass includes a `dm_scan_other()` 364function which creates the bootstd device if not found. If no bootmeth devices 365are found at all, it creates one for each available bootmeth driver. 366 367If your Device Tree has any bootmeth device it must have all of them that you 368want to use, since no bootmeth devices will be created automatically in that 369case. 370 371 372Using devicetree 373---------------- 374 375If a bootdev is complicated or needs configuration information, it can be 376added to the Device Tree as a child of the media device. For example, imagine a 377bootdev which reads a bootflow from SPI flash. The Device Tree fragment might 378look like this:: 379 380 spi@0 { 381 flash@0 { 382 reg = <0>; 383 compatible = "spansion,m25p16", "jedec,spi-nor"; 384 spi-max-frequency = <40000000>; 385 386 bootdev { 387 compatible = "u-boot,sf-bootdev"; 388 offset = <0x2000>; 389 size = <0x1000>; 390 }; 391 }; 392 }; 393 394The `sf-bootdev` driver can implement a way to read from the SPI flash, using 395the offset and size provided, and return that bootflow file back to the caller. 396When distro boot wants to read the kernel it calls distro_getfile() which must 397provide a way to read from the SPI flash. See `distro_boot()` at distro_boot_ 398for more details. 399 400Of course this is all internal to U-Boot. All the distro sees is another way 401to boot. 402 403 404Configuration 405------------- 406 407Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG 408option also. For example, `CONFIG_BOOTMETH_EXTLINUX` enables support for 409booting from a disk using an `extlinux.conf` file. 410 411To enable all features of standard boot, use `CONFIG_BOOTSTD_FULL`. This 412includes the full set of commands, more error messages when things go wrong and 413bootmeth ordering with the bootmeths environment variable. 414 415You should probably also enable `CONFIG_BOOTSTD_DEFAULTS`, which provides 416several filesystem and network features (if `CONFIG_NET` is enabled) so that 417a good selection of boot options is available. 418 419Some devicetree properties are supported in the bootstd node when 420`CONFIG_BOOTSTD_FULL` is enabled: 421 422 filename-prefixes 423 List of prefixes to use when searching for files on block devices. This 424 defaults to {"/", "/boot/"} if not provided. 425 426 bootdev-order 427 Lists the bootdev ordering to use. Note that the deprecated 428 `boot_targets` environment variable overrides this, if present. 429 430 theme (subnode) 431 Sets the theme to use for menus. See :doc:`/develop/expo`. 432 433Available bootmeth drivers 434-------------------------- 435 436Bootmeth drivers are provided for booting from various media: 437 438 - :doc:`Android <android>` bootflow (boot image v4) 439 - :doc:`ChromiumOS <cros>` ChromiumOS boot from a disk 440 - EFI boot using bootefi from disk 441 - EFI boot using boot manager 442 - :doc:`extlinux / syslinux <extlinux>` boot from a storage device 443 - :doc:`extlinux / syslinux <extlinux>` boot from a network (PXE) 444 - :doc:`sandbox <sandbox>` used only for testing 445 - :doc:`U-Boot scripts <script>` from disk, network or SPI flash 446 - :doc:`QFW <qfw>`: QEMU firmware interface 447 - :doc:`VBE </develop/vbe>`: Verified Boot for Embedded 448 449Each driver is controlled by a Kconfig option. If no bootmeth driver is 450selected by a compatible string in the devicetree, all available bootmeth 451drivers are bound automatically. 452 453Command interface 454----------------- 455 456Four commands are available: 457 458`bootdev` 459 Allows listing of available bootdevs, selecting a particular one and 460 getting information about it. See :doc:`/usage/cmd/bootdev` 461 462`bootflow` 463 Allows scanning one or more bootdevs for bootflows, listing available 464 bootflows, selecting one, obtaining information about it and booting it. 465 See :doc:`/usage/cmd/bootflow` 466 467`bootmeth` 468 Allow listing of available bootmethds, setting the order in which they are 469 tried and bootmeth specific configuration. See :doc:`/usage/cmd/bootmeth` 470 471`bootstd` 472 Allow access to standard boot itself, so far only for listing images across 473 all bootflows. See :doc:`/usage/cmd/bootstd` 474 475Images 476------ 477 478Standard boot keeps track of images which can or have been loaded. These are 479kept in a list attached to each bootflow. They can be listed using the 480``bootstd images`` command (see :doc:`/usage/cmd/bootstd`). 481 482For now most bootmeths load their images when scanning. Over time, some may 483adjust to load them only when needed, but in this case the images will still 484be visible. 485 486Once a bootflow has been selected, images for those that are not selected can 487potentially be dropped from the memory map. For now, this is not implemented. 488 489 490.. _BootflowStates: 491 492Bootflow states 493--------------- 494 495Here is a list of states that a bootflow can be in: 496 497======= ======================================================================= 498State Meaning 499======= ======================================================================= 500base Starting-out state, indicates that no media/partition was found. For an 501 SD card socket it may indicate that the card is not inserted. 502media Media was found (e.g. SD card is inserted) but no partition information 503 was found. It might lack a partition table or have a read error. 504part Partition was found but a filesystem could not be read. This could be 505 because the partition does not hold a filesystem or the filesystem is 506 very corrupted. 507fs Filesystem was found but the file could not be read. It could be 508 missing or in the wrong subdirectory. 509file File was found and its size detected, but it could not be read. This 510 could indicate filesystem corruption. 511ready File was loaded and is ready for use. In this state the bootflow is 512 ready to be booted. 513======= ======================================================================= 514 515 516Migrating from distro_boot 517-------------------------- 518 519To migrate from distro_boot: 520 521#. Update your board header files to remove the BOOTENV and BOOT_TARGET_xxx 522 defines. Standard boot finds available boot devices automatically. 523 524#. Remove the "boot_targets" variable unless you need it. Standard boot uses a 525 default order from fastest to slowest, which generally matches the order used 526 by boards. 527 528#. Make sure that CONFIG_BOOTSTD_DEFAULTS is enabled by your board, so it can 529 boot common Linux distributions. 530 531An example patch is at migrate_patch_. 532 533If you are using custom boot scripts for your board, consider creating your 534own bootmeth to hold the logic. There are various examples at 535`boot/bootmeth_...`. 536 537 538Theory of operation 539------------------- 540 541This describes how standard boot progresses through to booting an operating 542system. 543 544To start, all the necessary devices must be bound, including bootstd, which 545provides the top-level `struct bootstd_priv` containing optional configuration 546information. The bootstd device also holds the various lists used while 547scanning. This step is normally handled automatically by driver model, as 548described in `Automatic Devices`_. 549 550Bootdevs are also required, to provide access to the media to use. These are not 551useful by themselves: bootmeths are needed to provide the means of scanning 552those bootdevs. So, all up, we need a single bootstd device, one or more bootdev 553devices and one or more bootmeth devices. 554 555Once these are ready, typically a `bootflow scan` command is issued. This kicks 556off the iteration process, which involves hunting for bootdevs and looking 557through the bootdevs and their partitions one by one to find bootflows. 558 559Iteration is kicked off using `bootflow_scan_first()`. 560 561The iterator is set up with `bootflow_iter_init()`. This simply creates an 562empty one with the given flags. Flags are used to control whether each 563iteration is displayed, whether to return iterations even if they did not result 564in a valid bootflow, whether to iterate through just a single bootdev, etc. 565 566Then the iterator is set up to according to the parameters given: 567 568- When `dev` is provided, then a single bootdev is scanned. In this case, 569 `BOOTFLOWIF_SKIP_GLOBAL` and `BOOTFLOWIF_SINGLE_DEV` are set. No hunters are 570 used in this case 571 572- Otherwise, when `label` is provided, then a single label or named bootdev is 573 scanned. In this case `BOOTFLOWIF_SKIP_GLOBAL` is set and there are three 574 options (with an effect on the `iter_incr()` function described later): 575 576 - If `label` indicates a numeric bootdev number (e.g. "2") then 577 `BOOTFLOW_METHF_SINGLE_DEV` is set. In this case, moving to the next bootdev 578 simply stops, since there is only one. No hunters are used. 579 - If `label` indicates a particular media device (e.g. "mmc1") then 580 `BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev 581 processes just the children of the media device. Hunters are used, in this 582 example just the "mmc" hunter. 583 - If `label` indicates a particular partition in a particular media device 584 (e.g. "mmc1:3") then `BOOTFLOWIF_SINGLE_PARTITION` is set. In this case, 585 only a single partition within a bootdev is processed. Hunters are used, in 586 this example just the "mmc" hunter. 587 - If `label` indicates a media uclass (e.g. "mmc") then 588 `BOOTFLOWIF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass 589 are used. Hunters are used, in this example just the "mmc" hunter 590 591- Otherwise, none of the above flags is set and iteration is set up to work 592 through `boot_targets` environment variable (or `bootdev-order` device tree 593 property) in order, running the relevant hunter first. In this case 594 `cur_label` is used to indicate the label being processed. If there is no list 595 of labels, then all bootdevs are processed in order of priority, running the 596 hunters as it goes. 597 598With the above it is therefore possible to iterate in a variety of ways. 599 600No attempt is made to determine the ordering of bootdevs, since this cannot be 601known in advance if we are using the hunters. Any hunter might discover a new 602bootdev and disturb the original ordering. 603 604Next, the ordering of bootmeths is determined, by `bootmeth_setup_iter_order()`. 605By default the ordering is again by sequence number, i.e. the `/aliases` node, 606or failing that the order in the Device Tree. But the `bootmeth order` command 607or `bootmeths` environment variable can be used to set up an ordering. If that 608has been done, the ordering is in `struct bootstd_priv`, so that ordering is 609simply copied into the iterator. Either way, the `method_order` array it set up, 610along with `num_methods`. 611 612Note that global bootmeths are always put at the end of the ordering. If any are 613present, `cur_method` is set to the first one, so that global bootmeths are done 614first. Once all have been used, these bootmeths are dropped from the iteration. 615When there are no global bootmeths, `cur_method` is set to 0. 616 617At this point the iterator is ready to use, with the first bootmeth selected. 618Most of the other fields are 0. This means that the current partition 619is 0, which is taken to mean the whole device, since partition numbers start at 6201. It also means that `max_part` is 0, i.e. the maximum partition number we know 621about is 0, meaning that, as far as we know, there is no partition table on this 622bootdev. 623 624With the iterator ready, `bootflow_scan_first()` checks whether the current 625settings produce a valid bootflow. This is handled by `bootflow_check()`, which 626either returns 0 (if it got something) or an error if not (more on that later). 627If the `BOOTFLOWIF_ALL` iterator flag is set, even errors are returned as 628incomplete bootflows, but normally an error results in moving onto the next 629iteration. 630 631Note that `bootflow_check()` handles global bootmeths explicitly, by calling 632`bootmeth_get_bootflow()` on each one. The `doing_global` flag indicates when 633the iterator is in that state. 634 635The `bootflow_scan_next()` function handles moving onto the next iteration and 636checking it. In fact it sits in a loop doing that repeatedly until it finds 637something it wants to return. 638 639The actual 'moving on' part is implemented in `iter_incr()`. This is a fairly 640simple function. It increments the first counter. If that hits its maximum, it 641sets it to zero and increments the second counter. You can think of all the 642counters together as a number with three digits which increment in order, with 643the least-sigificant digit on the right, counting like this: 644 645 ======== ======= ======= 646 bootdev part method 647 ======== ======= ======= 648 0 0 0 649 0 0 1 650 0 0 2 651 0 1 0 652 0 1 1 653 0 1 2 654 1 0 0 655 1 0 1 656 ... 657 ======== ======= ======= 658 659The maximum value for `method` is `num_methods - 1` so when it exceeds that, it 660goes back to 0 and the next `part` is considered. The maximum value for that is 661`max_part`, which is initially zero for all bootdevs. If we find a partition 662table on that bootdev, `max_part` can be updated during the iteration to a 663higher value - see `bootdev_find_in_blk()` for that, described later. If that 664exceeds its maximum, then the next bootdev is used. In this way, iter_incr() 665works its way through all possibilities, moving forward one each time it is 666called. 667 668Note that global bootmeths introduce a subtlety into the above description. 669When `doing_global` is true, the iteration takes place only among the bootmeths, 670i.e. the last column above. The global bootmeths are at the end of the list. 671Assuming that they are entries 3 and 4 in the list, the iteration then looks 672like this: 673 674 ======== ======= ======= ======================================= 675 bootdev part method notes 676 ======== ======= ======= ======================================= 677 . . 3 doing_global = true, method_count = 5 678 . . 4 679 0 0 0 doing_global = false, method_count = 3 680 0 0 1 681 0 0 2 682 0 1 0 683 0 1 1 684 0 1 2 685 1 0 0 686 1 0 1 687 ... 688 ======== ======= ======= ======================================= 689 690The changeover of the value of `doing_global` from true to false is handled in 691`iter_incr()` as well. 692 693Note that the value in the `bootdev` column above is not actually stored - it is 694just for illustration. In practice, `iter_incr()` uses the flags to determine 695whether to move to the next bootdev in the uclass, the next child of the media 696device, the next label, or the next priority level, depending on the flag 697settings (see `BOOTFLOW_METHF_SINGLE_DEV`, etc. above). 698 699There is no expectation that iteration will actually finish. Quite often a 700valid bootflow is found early on. With `bootflow scan -b`, that causes the 701bootflow to be immediately booted. Assuming it is successful, the iteration never 702completes. 703 704Also note that the iterator holds the **current** combination being considered. 705So when `iter_incr()` is called, it increments to the next one and returns it, 706the new **current** combination. 707 708Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has 709thus no effect on `iter_inc()`. But if it is non-zero, signalling an error, 710it indicates to the iterator what it should do when called. It can force moving 711to the next partition, or bootdev, for example. The special values 712`BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees 713`BF_NO_MORE_PARTS` it knows that it should immediately move to the next bootdev. 714When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do 715so it should immediately return. The caller of `iter_incr()` is responsible for 716updating the `err` field, based on the return value it sees. 717 718The above describes the iteration process at a high level. It is basically a 719very simple increment function with a checker called `bootflow_check()` that 720checks the result of each iteration generated, to determine whether it can 721produce a bootflow. 722 723So what happens inside of `bootflow_check()`? It simply calls the uclass 724method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It 725passes the iterator to the bootdev method, so that function knows what we are 726talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`, 727with just the `method` and `dev` initialised. But the bootdev may fill in more, 728e.g. updating the state, depending on what it finds. For global bootmeths the 729`bootmeth_get_bootflow()` function is called instead of 730`bootdev_get_bootflow()`. 731 732Based on what the bootdev or bootmeth responds with, `bootflow_check()` either 733returns a valid bootflow, or a partial one with an error. A partial bootflow 734is one that has some fields set up, but did not reach the `BOOTFLOWST_READY` 735state. As noted before, if the `BOOTFLOWIF_ALL` iterator flag is set, then all 736bootflows are returned, even partial ones. This can help with debugging. 737 738So at this point you can see that total control over whether a bootflow can 739be generated from a particular iteration, or not, rests with the bootdev (or 740global bootmeth). Each one can adopt its own approach. 741 742Going down a level, what does the bootdev do in its `get_bootflow()` method? 743Let us consider the MMC bootdev. In that case the call to 744`bootdev_get_bootflow()` ends up in `default_get_bootflow()`. It locates the 745parent device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds 746the block device associated with it. It then calls the helper function 747`bootdev_find_in_blk()` to do all the work. This is common with just about any 748bootdev that is based on a media device. 749 750The `bootdev_find_in_blk()` helper is implemented in the bootdev uclass. It 751names the bootflow and copies the partition number in from the iterator. Then it 752calls the bootmeth device to check if it can support this device. This is 753important since some bootmeths only work with network devices, for example. If 754that check fails, it stops. 755 756Assuming the bootmeth is happy, or at least indicates that it is willing to try 757(by returning 0 from its `check()` method), the next step is to try the 758partition. If that works it tries to detect a file system. If that works then it 759calls the bootmeth device once more, this time to read the bootflow. 760 761Note: Normally a filesystem is needed for the bootmeth to be called on block 762devices, but bootmeths which don't need that can set the BOOTMETHF_ANY_PART 763flag to indicate that they can scan any partition. An example is the ChromiumOS 764bootmeth which can store a kernel in a raw partition. Note also that sandbox is 765a special case, since in that case the host filesystem can be accessed even 766though the block device is NULL. 767 768If we take the example of the `bootmeth_extlinux` driver, this call ends up at 769`extlinux_read_bootflow()`. It has the filesystem ready, so tries various 770filenames to try to find the `extlinux.conf` file, reading it if possible. If 771all goes well the bootflow ends up in the `BOOTFLOWST_READY` state. 772 773At this point, we fall back from the bootmeth driver, to 774`bootdev_find_in_blk()`, then back to `default_get_bootflow()`, then to 775`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller, 776either `bootflow_scan_first()` or `bootflow_scan_next()`. In either case, 777the bootflow is returned as the result of this iteration, assuming it made it to 778the `BOOTFLOWST_READY` state. 779 780That is the basic operation of scanning for bootflows. The process of booting a 781bootflow is handled by the bootmeth driver for that bootflow. In the case of 782extlinux boot, this parses and processes the `extlinux.conf` file that was read. 783See `extlinux_boot()` for how that works. The processing may involve reading 784additional files, which is handled by the `read_file()` method, which is 785`extlinux_read_file()` in this case. All bootmeths should support reading 786files, since the bootflow is typically only the basic instructions and does not 787include the operating system itself, ramdisk, device tree, etc. 788 789The vast majority of the bootstd code is concerned with iterating through 790partitions on bootdevs and using bootmeths to find bootflows. 791 792How about bootdevs which are not block devices? They are handled by the same 793methods as above, but with a different implementation. For example, the bootmeth 794for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`. 795But other than that it is very similar. 796 797 798Tests 799----- 800 801Tests are located in `test/boot` and cover the core functionality as well as 802the commands. All tests use sandbox so can be run on a standard Linux computer 803and in U-Boot's CI. 804 805For testing, a DOS-formatted disk image is used with a FAT partition on it and 806a second unused partition. This is created in `setup_bootflow_image()`, with a 807canned one from the source tree used if it cannot be created (e.g. in CI). 808 809 810Bootflow internals 811------------------ 812 813The bootstd device holds a linked list of scanned bootflows as well as the 814currently selected bootdev and bootflow (for use by commands). This is in 815`struct bootstd_priv`. 816 817Each bootdev device has its own `struct bootdev_uc_plat` which holds a 818list of scanned bootflows just for that device. 819 820The bootflow itself is documented in bootflow_h_. It includes various bits of 821information about the bootflow and a buffer to hold the file. 822 823 824Future 825------ 826 827Apart from the to-do items below, different types of bootflow files may be 828implemented in future, e.g. Chromium OS support which is currently only 829available as a script in chromebook_coral. 830 831 832To do 833----- 834 835Some things that need to be done to completely replace the distro-boot scripts: 836 837- implement extensions (devicetree overlays with add-on boards) 838- implement legacy (boot image v2) android boot flow 839 840Other ideas: 841 842- `bootflow prep` to load everything preparing for boot, so that `bootflow boot` 843 can just do the boot. 844- automatically load kernel, FDT, etc. to suitable addresses so the board does 845 not need to specify things like `pxefile_addr_r` 846 847 848.. _distro_bootcmd: https://github.com/u-boot/u-boot/blob/master/include/config_distro_bootcmd.h 849.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/ 850.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c 851.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h 852.. _migrate_patch: https://patchwork.ozlabs.org/project/uboot/patch/20230727215433.578830-2-sjg@chromium.org/