blob: a07a72581e7ad9a556a325555987c36c1c457d4e [file] [log] [blame]
Simon Glass83b9be62022-04-24 23:31:26 -06001.. SPDX-License-Identifier: GPL-2.0+:
2
3U-Boot Standard Boot
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
Paul Barker6c55d0d2022-07-29 14:31:58 +010024distro_bootcmd_ for details. This is done because U-Boot has no native support
Simon Glass83b9be62022-04-24 23:31:26 -060025for 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
Simon Glassc08a9922022-07-30 15:52:03 -060035Finally, standard boot supports the operation of :doc:`vbe`.
Simon Glass83b9be62022-04-24 23:31:26 -060036
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
Paul Barker6c55d0d2022-07-29 14:31:58 +010055which to load devicetree files. The details are described in distro_bootcmd_.
Simon Glass83b9be62022-04-24 23:31:26 -060056
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
Simon Glass736612e2023-01-17 10:48:19 -070074MMC device. It scans through these to find filesystems with the boot flag set,
75then provides a list of these for consideration.
Simon Glass83b9be62022-04-24 23:31:26 -060076
Simon Glass736612e2023-01-17 10:48:19 -070077Some 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
Simon Glass83b9be62022-04-24 23:31:26 -060083
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.
98
Simon Glassafaeb772022-07-30 15:52:35 -060099Note that some bootmeths are 'global', meaning that they select the bootdev
100themselves. Examples include VBE and EFI boot manager. In this case, they
101provide a `read_bootflow()` method which checks whatever bootdevs it likes, then
102returns the bootflow, if found. Some of these bootmeths may be very slow, if
103they scan a lot of devices.
104
Simon Glass83b9be62022-04-24 23:31:26 -0600105
106Boot process
107------------
108
109U-Boot tries to use the 'lazy init' approach whereever possible and distro boot
110is no exception. The algorithm is::
111
112 while (get next bootdev)
113 while (get next bootmeth)
114 while (get next bootflow)
115 try to boot it
116
117So U-Boot works its way through the bootdevs, trying each bootmeth in turn to
118obtain bootflows, until it either boots or exhausts the available options.
119
120Instead of 500 lines of #defines and a 4KB boot script, all that is needed is
121the following command::
122
123 bootflow scan -lb
124
125which scans for available bootflows, optionally listing each find it finds (-l)
126and trying to boot it (-b).
127
Simon Glassafaeb772022-07-30 15:52:35 -0600128When global bootmeths are available, these are typically checked before the
129above bootdev scanning.
130
Simon Glass83b9be62022-04-24 23:31:26 -0600131
132Controlling ordering
133--------------------
134
Simon Glass2f27e472023-08-19 16:49:35 -0600135By default, faster bootdevs (or those which are assumed to be faster) are used
136first, since they are more likely to be able to boot the device quickly.
137
Simon Glass83b9be62022-04-24 23:31:26 -0600138Several options are available to control the ordering of boot scanning:
139
140
141boot_targets
142~~~~~~~~~~~~
143
144This environment variable can be used to control the list of bootdevs searched
145and their ordering, for example::
146
147 setenv boot_targets "mmc0 mmc1 usb pxe"
148
149Entries may be removed or re-ordered in this list to affect the boot order. If
150the variable is empty, the default ordering is used, based on the priority of
151bootdevs and their sequence numbers.
152
153
154bootmeths
155~~~~~~~~~
156
Simon Glass2f27e472023-08-19 16:49:35 -0600157By default bootmeths are checked in name order. Use `bootmeth list` to see the
158ordering. Note that the `extlinux` and `script` bootmeth is first, to preserve the behaviour
159used by the old distro scripts.
160
Simon Glass83b9be62022-04-24 23:31:26 -0600161This environment variable can be used to control the list of bootmeths used and
162their ordering for example::
163
Simon Glassb71d7f72023-05-10 16:34:46 -0600164 setenv bootmeths "extlinux efi"
Simon Glass83b9be62022-04-24 23:31:26 -0600165
166Entries may be removed or re-ordered in this list to affect the order the
167bootmeths are tried on each bootdev. If the variable is empty, the default
168ordering is used, based on the bootmeth sequence numbers, which can be
169controlled by aliases.
170
171The :ref:`usage/cmd/bootmeth:bootmeth command` (`bootmeth order`) operates in
172the same way as setting this variable.
173
Simon Glass83b9be62022-04-24 23:31:26 -0600174Bootdev uclass
175--------------
176
177The bootdev uclass provides an simple API call to obtain a bootflows from a
178device::
179
180 int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
181 struct bootflow *bflow);
182
183This takes a iterator which indicates the bootdev, partition and bootmeth to
184use. It returns a bootflow. This is the core of the bootdev implementation. The
185bootdev drivers that implement this differ depending on the media they are
186reading from, but each is responsible for returning a valid bootflow if
187available.
188
189A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this
Simon Glass736612e2023-01-17 10:48:19 -0700190function for each media device uclass, in a few lines of code. For many types
191ot bootdevs, the `get_bootflow` member can be NULL, indicating that the default
192handler is used. This is called `default_get_bootflow()` and it only works with
193block devices.
Simon Glass83b9be62022-04-24 23:31:26 -0600194
195
196Bootdev drivers
197---------------
198
199A bootdev driver is typically fairly simple. Here is one for mmc::
200
Simon Glass83b9be62022-04-24 23:31:26 -0600201 static int mmc_bootdev_bind(struct udevice *dev)
202 {
203 struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
204
Simon Glass7e1f6a42023-01-17 10:48:08 -0700205 ucp->prio = BOOTDEVP_2_INTERNAL_FAST;
Simon Glass83b9be62022-04-24 23:31:26 -0600206
207 return 0;
208 }
209
210 struct bootdev_ops mmc_bootdev_ops = {
Simon Glass83b9be62022-04-24 23:31:26 -0600211 };
212
213 static const struct udevice_id mmc_bootdev_ids[] = {
214 { .compatible = "u-boot,bootdev-mmc" },
215 { }
216 };
217
218 U_BOOT_DRIVER(mmc_bootdev) = {
219 .name = "mmc_bootdev",
220 .id = UCLASS_BOOTDEV,
221 .ops = &mmc_bootdev_ops,
222 .bind = mmc_bootdev_bind,
223 .of_match = mmc_bootdev_ids,
224 };
225
Simon Glass736612e2023-01-17 10:48:19 -0700226You may notice that the `get_bootflow` memory is not provided, so is NULL. This
227means that `default_get_bootflow()` is used. This simply obtains the
228block device and calls a bootdev helper function to do the rest. The
Simon Glass83b9be62022-04-24 23:31:26 -0600229implementation of `bootdev_find_in_blk()` checks the partition table, and
230attempts to read a file from a filesystem on the partition number given by the
Simon Glass736612e2023-01-17 10:48:19 -0700231`@iter->part` parameter. If there are any bootable partitions in the table,
232then only bootable partitions are considered.
233
234Each bootdev has a priority, which indicates the order in which it is used,
235if `boot_targets` is not used. Faster bootdevs are used first, since they are
236more likely to be able to boot the device quickly.
237
238
239Environment Variables
240---------------------
241
242Various environment variables are used by standard boot. These allow the board
243to control where things are placed when booting the OS. You should ensure that
244your boards sets values for these.
245
246fdtfile
247 Name of the flattened device tree (FDT) file to load, e.g.
248 "rockchip/rk3399-rockpro64.dtb"
249
Heinrich Schuchardt75e86db2023-11-16 10:09:07 +0100250fdt_addr_r
Simon Glass736612e2023-01-17 10:48:19 -0700251 Address at which to load the FDT, e.g. 0x01f00000
252
253fdtoverlay_addr_r (needed if overlays are used)
254 Address at which to load the overlay for the FDT, e.g. 0x02000000
255
256kernel_addr_r
257 Address at which to load the kernel, e.g. 0x02080000
258
259kernel_comp_addr_r
260 Address to which to decompress the kernel, e.g. 0x08000000
261
262kernel_comp_size
263 Size of available space for decompressed kernel, e.g. 0x2000000
264
265pxefile_addr_r
266 Address at which to load the PXE file, e.g. 0x00600000
267
268ramdisk_addr_r
269 Address at which to load the ramdisk, e.g. 0x06000000
270
271scriptaddr
272 Address at which to load the U-Boot script, e.g. 0x00500000
Simon Glass83b9be62022-04-24 23:31:26 -0600273
Simon Glass736612e2023-01-17 10:48:19 -0700274script_offset_f
275 SPI flash offset from which to load the U-Boot script, e.g. 0xffe000
Simon Glass83b9be62022-04-24 23:31:26 -0600276
Simon Glass736612e2023-01-17 10:48:19 -0700277script_size_f
278 Size of the script to load, e.g. 0x2000
279
280Some variables are set by script bootmeth:
281
282devtype
283 Device type being used for boot, e.g. mmc
284
285devnum
286 Device number being used for boot, e.g. 1
287
288distro_bootpart
289 Partition being used for boot, e.g. 2
290
291prefix
292 Directory containing the script
293
294mmc_bootdev
295 Device number being used for boot (e.g. 1). This is only used by MMC on
296 sunxi boards.
297
Simon Glass83b9be62022-04-24 23:31:26 -0600298
299Device hierarchy
300----------------
301
302A bootdev device is a child of the media device. In this example, you can see
303that the bootdev is a sibling of the block device and both are children of
304media device::
305
306 mmc 0 [ + ] bcm2835-sdhost | |-- mmc@7e202000
307 blk 0 [ + ] mmc_blk | | |-- mmc@7e202000.blk
308 bootdev 0 [ ] mmc_bootdev | | `-- mmc@7e202000.bootdev
309 mmc 1 [ + ] sdhci-bcm2835 | |-- sdhci@7e300000
310 blk 1 [ ] mmc_blk | | |-- sdhci@7e300000.blk
311 bootdev 1 [ ] mmc_bootdev | | `-- sdhci@7e300000.bootdev
312
313The bootdev device is typically created automatically in the media uclass'
Simon Glass736612e2023-01-17 10:48:19 -0700314`post_bind()` method by calling `bootdev_setup_for_dev()` or
Simon Glassb1d581d2023-07-30 11:15:14 -0600315`bootdev_setup_for_sibling_blk()`. The code typically something like this::
Simon Glass83b9be62022-04-24 23:31:26 -0600316
Simon Glass736612e2023-01-17 10:48:19 -0700317 /* dev is the Ethernet device */
Simon Glass83b9be62022-04-24 23:31:26 -0600318 ret = bootdev_setup_for_dev(dev, "eth_bootdev");
319 if (ret)
320 return log_msg_ret("bootdev", ret);
321
Simon Glass736612e2023-01-17 10:48:19 -0700322or::
323
324 /* blk is the block device (child of MMC device)
Simon Glassb1d581d2023-07-30 11:15:14 -0600325 ret = bootdev_setup_for_sibling_blk(blk, "mmc_bootdev");
Simon Glass736612e2023-01-17 10:48:19 -0700326 if (ret)
327 return log_msg_ret("bootdev", ret);
328
329
Simon Glass83b9be62022-04-24 23:31:26 -0600330Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev`
331is the ethernet device. This function is safe to call even if standard boot is
332not enabled, since it does nothing in that case. It can be added to all uclasses
333which implement suitable media.
334
335
336The bootstd device
337------------------
338
339Standard boot requires a single instance of the bootstd device to make things
340work. This includes global information about the state of standard boot. See
341`struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`.
342
Simon Glassafaeb772022-07-30 15:52:35 -0600343Within the devicetree, if you add bootmeth devices, they should be children of
344the bootstd device. See `arch/sandbox/dts/test.dts` for an example of this.
Simon Glass83b9be62022-04-24 23:31:26 -0600345
Simon Glass83b9be62022-04-24 23:31:26 -0600346
347.. _`Automatic Devices`:
348
349Automatic devices
350-----------------
351
352It is possible to define all the required devices in the devicetree manually,
353but it is not necessary. The bootstd uclass includes a `dm_scan_other()`
354function which creates the bootstd device if not found. If no bootmeth devices
Simon Glassafaeb772022-07-30 15:52:35 -0600355are found at all, it creates one for each available bootmeth driver.
Simon Glass83b9be62022-04-24 23:31:26 -0600356
357If your devicetree has any bootmeth device it must have all of them that you
Simon Glassafaeb772022-07-30 15:52:35 -0600358want to use, since no bootmeth devices will be created automatically in that
359case.
Simon Glass83b9be62022-04-24 23:31:26 -0600360
361
362Using devicetree
363----------------
364
365If a bootdev is complicated or needs configuration information, it can be
366added to the devicetree as a child of the media device. For example, imagine a
367bootdev which reads a bootflow from SPI flash. The devicetree fragment might
368look like this::
369
370 spi@0 {
371 flash@0 {
372 reg = <0>;
373 compatible = "spansion,m25p16", "jedec,spi-nor";
374 spi-max-frequency = <40000000>;
375
376 bootdev {
377 compatible = "u-boot,sf-bootdev";
378 offset = <0x2000>;
379 size = <0x1000>;
380 };
381 };
382 };
383
384The `sf-bootdev` driver can implement a way to read from the SPI flash, using
385the offset and size provided, and return that bootflow file back to the caller.
Dario Binacchi3c9c6d72022-08-26 15:15:41 +0200386When distro boot wants to read the kernel it calls distro_getfile() which must
Simon Glass83b9be62022-04-24 23:31:26 -0600387provide a way to read from the SPI flash. See `distro_boot()` at distro_boot_
388for more details.
389
390Of course this is all internal to U-Boot. All the distro sees is another way
391to boot.
392
393
394Configuration
395-------------
396
397Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG
Simon Glassb71d7f72023-05-10 16:34:46 -0600398option also. For example, `CONFIG_BOOTMETH_EXTLINUX` enables support for
399booting from a disk using an `extlinux.conf` file.
Simon Glass83b9be62022-04-24 23:31:26 -0600400
Simon Glass736612e2023-01-17 10:48:19 -0700401To enable all feature sof standard boot, use `CONFIG_BOOTSTD_FULL`. This
402includes the full set of commands, more error messages when things go wrong and
403bootmeth ordering with the bootmeths environment variable.
404
Simon Glass2e5161eb2023-01-28 15:00:21 -0700405You should probably also enable `CONFIG_BOOTSTD_DEFAULTS`, which provides
406several filesystem and network features (if `CONFIG_NET` is enabled) so that
407a good selection of boot options is available.
408
Simon Glass83b9be62022-04-24 23:31:26 -0600409
410Available bootmeth drivers
411--------------------------
412
413Bootmeth drivers are provided for:
414
Simon Glassb71d7f72023-05-10 16:34:46 -0600415 - extlinux / syslinux boot from a disk
416 - extlinux boot from a network (PXE)
Simon Glass736612e2023-01-17 10:48:19 -0700417 - U-Boot scripts from disk, network or SPI flash
418 - EFI boot using bootefi from disk
Simon Glassafaeb772022-07-30 15:52:35 -0600419 - VBE
Simon Glass83b9be62022-04-24 23:31:26 -0600420 - EFI boot using boot manager
421
422
423Command interface
424-----------------
425
426Three commands are available:
427
428`bootdev`
429 Allows listing of available bootdevs, selecting a particular one and
430 getting information about it. See :doc:`../usage/cmd/bootdev`
431
432`bootflow`
433 Allows scanning one or more bootdevs for bootflows, listing available
434 bootflows, selecting one, obtaining information about it and booting it.
435 See :doc:`../usage/cmd/bootflow`
436
437`bootmeth`
438 Allow listing of available bootmethds and setting the order in which they
439 are tried. See :doc:`../usage/cmd/bootmeth`
440
441.. _BootflowStates:
442
443Bootflow states
444---------------
445
446Here is a list of states that a bootflow can be in:
447
448======= =======================================================================
449State Meaning
450======= =======================================================================
451base Starting-out state, indicates that no media/partition was found. For an
452 SD card socket it may indicate that the card is not inserted.
453media Media was found (e.g. SD card is inserted) but no partition information
454 was found. It might lack a partition table or have a read error.
455part Partition was found but a filesystem could not be read. This could be
456 because the partition does not hold a filesystem or the filesystem is
457 very corrupted.
458fs Filesystem was found but the file could not be read. It could be
459 missing or in the wrong subdirectory.
460file File was found and its size detected, but it could not be read. This
461 could indicate filesystem corruption.
462ready File was loaded and is ready for use. In this state the bootflow is
463 ready to be booted.
464======= =======================================================================
465
466
Simon Glasse27d7df2023-09-14 10:55:55 -0600467Migrating from distro_boot
468--------------------------
469
470To migrate from distro_boot:
471
472#. Update your board header files to remove the BOOTENV and BOOT_TARGET_xxx
473 defines. Standard boot finds available boot devices automatically.
474
475#. Remove the "boot_targets" variable unless you need it. Standard boot uses a
476 default order from fastest to slowest, which generally matches the order used
477 by boards.
478
479#. Make sure that CONFIG_BOOTSTD_DEFAULTS is enabled by your board, so it can
480 boot common Linux distributions.
481
482An example patch is at migrate_patch_.
483
484If you are using custom boot scripts for your board, consider creating your
485own bootmeth to hold the logic. There are various examples at
486`boot/bootmeth_...`.
487
488
Simon Glass83b9be62022-04-24 23:31:26 -0600489Theory of operation
490-------------------
491
492This describes how standard boot progresses through to booting an operating
493system.
494
495To start. all the necessary devices must be bound, including bootstd, which
496provides the top-level `struct bootstd_priv` containing optional configuration
497information. The bootstd device is also holds the various lists used while
498scanning. This step is normally handled automatically by driver model, as
499described in `Automatic Devices`_.
500
501Bootdevs are also required, to provide access to the media to use. These are not
502useful by themselves: bootmeths are needed to provide the means of scanning
503those bootdevs. So, all up, we need a single bootstd device, one or more bootdev
504devices and one or more bootmeth devices.
505
506Once these are ready, typically a `bootflow scan` command is issued. This kicks
Simon Glass736612e2023-01-17 10:48:19 -0700507of the iteration process, which involves hunting for bootdevs and looking
508through the bootdevs and their partitions one by one to find bootflows.
Simon Glass83b9be62022-04-24 23:31:26 -0600509
Simon Glass736612e2023-01-17 10:48:19 -0700510Iteration is kicked off using `bootflow_scan_first()`.
Simon Glass83b9be62022-04-24 23:31:26 -0600511
512The iterator is set up with `bootflow_iter_init()`. This simply creates an
513empty one with the given flags. Flags are used to control whether each
514iteration is displayed, whether to return iterations even if they did not result
515in a valid bootflow, whether to iterate through just a single bootdev, etc.
516
Simon Glass736612e2023-01-17 10:48:19 -0700517Then the iterator is set up to according to the parameters given:
518
519- When `dev` is provided, then a single bootdev is scanned. In this case,
Simon Glass99e68182023-02-22 12:17:03 -0700520 `BOOTFLOWIF_SKIP_GLOBAL` and `BOOTFLOWIF_SINGLE_DEV` are set. No hunters are
Simon Glass736612e2023-01-17 10:48:19 -0700521 used in this case
522
523- Otherwise, when `label` is provided, then a single label or named bootdev is
Simon Glass99e68182023-02-22 12:17:03 -0700524 scanned. In this case `BOOTFLOWIF_SKIP_GLOBAL` is set and there are three
Simon Glass736612e2023-01-17 10:48:19 -0700525 options (with an effect on the `iter_incr()` function described later):
526
527 - If `label` indicates a numeric bootdev number (e.g. "2") then
528 `BOOTFLOW_METHF_SINGLE_DEV` is set. In this case, moving to the next bootdev
529 simple stops, since there is only one. No hunters are used.
530 - If `label` indicates a particular media device (e.g. "mmc1") then
Simon Glass99e68182023-02-22 12:17:03 -0700531 `BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev
Simon Glass736612e2023-01-17 10:48:19 -0700532 processes just the children of the media device. Hunters are used, in this
533 example just the "mmc" hunter.
Nam Caocb0d3fb2024-02-21 13:41:44 +0100534 - If `label` indicates a particular partition in a particular media device
535 (e.g. "mmc1:3") then `BOOTFLOWIF_SINGLE_PARTITION` is set. In this case,
536 only a single partition within a bootdev is processed. Hunters are used, in
537 this example just the "mmc" hunter.
Simon Glass736612e2023-01-17 10:48:19 -0700538 - If `label` indicates a media uclass (e.g. "mmc") then
Simon Glass99e68182023-02-22 12:17:03 -0700539 `BOOTFLOWIF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass
Simon Glass736612e2023-01-17 10:48:19 -0700540 are used. Hunters are used, in this example just the "mmc" hunter
541
542- Otherwise, none of the above flags is set and iteration is set up to work
543 through `boot_targets` environment variable (or `bootdev-order` device tree
544 property) in order, running the relevant hunter first. In this case
545 `cur_label` is used to indicate the label being processed. If there is no list
546 of labels, then all bootdevs are processed in order of priority, running the
547 hunters as it goes.
548
549With the above it is therefore possible to iterate in a variety of ways.
550
551No attempt is made to determine the ordering of bootdevs, since this cannot be
552known in advance if we are using the hunters. Any hunter might discover a new
553bootdev and disturb the original ordering.
Simon Glass83b9be62022-04-24 23:31:26 -0600554
Simon Glassafaeb772022-07-30 15:52:35 -0600555Next, the ordering of bootmeths is determined, by `bootmeth_setup_iter_order()`.
Simon Glass83b9be62022-04-24 23:31:26 -0600556By default the ordering is again by sequence number, i.e. the `/aliases` node,
557or failing that the order in the devicetree. But the `bootmeth order` command
558or `bootmeths` environment variable can be used to set up an ordering. If that
559has been done, the ordering is in `struct bootstd_priv`, so that ordering is
560simply copied into the iterator. Either way, the `method_order` array it set up,
Simon Glassafaeb772022-07-30 15:52:35 -0600561along with `num_methods`.
562
563Note that global bootmeths are always put at the end of the ordering. If any are
564present, `cur_method` is set to the first one, so that global bootmeths are done
565first. Once all have been used, these bootmeths are dropped from the iteration.
566When there are no global bootmeths, `cur_method` is set to 0.
Simon Glass83b9be62022-04-24 23:31:26 -0600567
Simon Glass736612e2023-01-17 10:48:19 -0700568At this point the iterator is ready to use, with the first bootmeth selected.
569Most of the other fields are 0. This means that the current partition
Simon Glassafaeb772022-07-30 15:52:35 -0600570is 0, which is taken to mean the whole device, since partition numbers start at
5711. It also means that `max_part` is 0, i.e. the maximum partition number we know
Simon Glass83b9be62022-04-24 23:31:26 -0600572about is 0, meaning that, as far as we know, there is no partition table on this
573bootdev.
574
Simon Glass736612e2023-01-17 10:48:19 -0700575With the iterator ready, `bootflow_scan_first()` checks whether the current
Simon Glass83b9be62022-04-24 23:31:26 -0600576settings produce a valid bootflow. This is handled by `bootflow_check()`, which
577either returns 0 (if it got something) or an error if not (more on that later).
Simon Glass99e68182023-02-22 12:17:03 -0700578If the `BOOTFLOWIF_ALL` iterator flag is set, even errors are returned as
Simon Glass83b9be62022-04-24 23:31:26 -0600579incomplete bootflows, but normally an error results in moving onto the next
580iteration.
581
Simon Glass736612e2023-01-17 10:48:19 -0700582Note that `bootflow_check()` handles global bootmeths explicitly, by calling
Simon Glassafaeb772022-07-30 15:52:35 -0600583`bootmeth_get_bootflow()` on each one. The `doing_global` flag indicates when
584the iterator is in that state.
585
Simon Glass83b9be62022-04-24 23:31:26 -0600586The `bootflow_scan_next()` function handles moving onto the next iteration and
587checking it. In fact it sits in a loop doing that repeatedly until it finds
588something it wants to return.
589
Simon Glass736612e2023-01-17 10:48:19 -0700590The actual 'moving on' part is implemented in `iter_incr()`. This is a fairly
Simon Glass83b9be62022-04-24 23:31:26 -0600591simple function. It increments the first counter. If that hits its maximum, it
592sets it to zero and increments the second counter. You can think of all the
593counters together as a number with three digits which increment in order, with
594the least-sigificant digit on the right, counting like this:
595
596 ======== ======= =======
597 bootdev part method
598 ======== ======= =======
599 0 0 0
600 0 0 1
601 0 0 2
602 0 1 0
603 0 1 1
Simon Glassafaeb772022-07-30 15:52:35 -0600604 0 1 2
Simon Glass83b9be62022-04-24 23:31:26 -0600605 1 0 0
606 1 0 1
Simon Glassafaeb772022-07-30 15:52:35 -0600607 ...
Simon Glass83b9be62022-04-24 23:31:26 -0600608 ======== ======= =======
609
610The maximum value for `method` is `num_methods - 1` so when it exceeds that, it
611goes back to 0 and the next `part` is considered. The maximum value for that is
612`max_part`, which is initially zero for all bootdevs. If we find a partition
613table on that bootdev, `max_part` can be updated during the iteration to a
614higher value - see `bootdev_find_in_blk()` for that, described later. If that
615exceeds its maximum, then the next bootdev is used. In this way, iter_incr()
616works its way through all possibilities, moving forward one each time it is
617called.
618
Simon Glassafaeb772022-07-30 15:52:35 -0600619Note that global bootmeths introduce a subtlety into the above description.
620When `doing_global` is true, the iteration takes place only among the bootmeths,
621i.e. the last column above. The global bootmeths are at the end of the list.
622Assuming that they are entries 3 and 4 in the list, the iteration then looks
623like this:
624
625 ======== ======= ======= =======================================
626 bootdev part method notes
627 ======== ======= ======= =======================================
628 . . 3 doing_global = true, method_count = 5
629 . . 4
630 0 0 0 doing_global = false, method_count = 3
631 0 0 1
632 0 0 2
633 0 1 0
634 0 1 1
635 0 1 2
636 1 0 0
637 1 0 1
638 ...
639 ======== ======= ======= =======================================
640
641The changeover of the value of `doing_global` from true to false is handled in
642`iter_incr()` as well.
643
Simon Glass736612e2023-01-17 10:48:19 -0700644Note that the value in the `bootdev` column above is not actually stored - it is
645just for illustration. In practice, `iter_incr()` uses the flags to determine
646whether to move to the next bootdev in the uclass, the next child of the media
647device, the next label, or the next priority level, depending on the flag
648settings (see `BOOTFLOW_METHF_SINGLE_DEV`, etc. above).
649
Simon Glass83b9be62022-04-24 23:31:26 -0600650There is no expectation that iteration will actually finish. Quite often a
651valid bootflow is found early on. With `bootflow scan -b`, that causes the
652bootflow to be immediately booted. Assuming it is successful, the iteration never
653completes.
654
655Also note that the iterator hold the **current** combination being considered.
656So when `iter_incr()` is called, it increments to the next one and returns it,
657the new **current** combination.
658
659Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has
660thus has no effect on `iter_inc()`. But if it is non-zero, signalling an error,
661it indicates to the iterator what it should do when called. It can force moving
662to the next partition, or bootdev, for example. The special values
663`BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees
664`BF_NO_MORE_PARTS` it knows that it should immediately move to the next bootdev.
665When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do
666so it should immediately return. The caller of `iter_incr()` is responsible for
667updating the `err` field, based on the return value it sees.
668
669The above describes the iteration process at a high level. It is basically a
670very simple increment function with a checker called `bootflow_check()` that
671checks the result of each iteration generated, to determine whether it can
672produce a bootflow.
673
674So what happens inside of `bootflow_check()`? It simply calls the uclass
675method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It
676passes the iterator to the bootdev method, so that function knows what we are
677talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`,
678with just the `method` and `dev` intiialised. But the bootdev may fill in more,
Simon Glassafaeb772022-07-30 15:52:35 -0600679e.g. updating the state, depending on what it finds. For global bootmeths the
680`bootmeth_get_bootflow()` function is called instead of
681`bootdev_get_bootflow()`.
Simon Glass83b9be62022-04-24 23:31:26 -0600682
Simon Glassafaeb772022-07-30 15:52:35 -0600683Based on what the bootdev or bootmeth responds with, `bootflow_check()` either
Simon Glass83b9be62022-04-24 23:31:26 -0600684returns a valid bootflow, or a partial one with an error. A partial bootflow
685is one that has some fields set up, but did not reach the `BOOTFLOWST_READY`
Simon Glass99e68182023-02-22 12:17:03 -0700686state. As noted before, if the `BOOTFLOWIF_ALL` iterator flag is set, then all
Simon Glass83b9be62022-04-24 23:31:26 -0600687bootflows are returned, even partial ones. This can help with debugging.
688
689So at this point you can see that total control over whether a bootflow can
Simon Glassafaeb772022-07-30 15:52:35 -0600690be generated from a particular iteration, or not, rests with the bootdev (or
691global bootmeth). Each one can adopt its own approach.
Simon Glass83b9be62022-04-24 23:31:26 -0600692
693Going down a level, what does the bootdev do in its `get_bootflow()` method?
694Let us consider the MMC bootdev. In that case the call to
Simon Glass736612e2023-01-17 10:48:19 -0700695`bootdev_get_bootflow()` ends up in `default_get_bootflow()`. It locates the
696parent device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds
697the block device associated with it. It then calls the helper function
Simon Glass83b9be62022-04-24 23:31:26 -0600698`bootdev_find_in_blk()` to do all the work. This is common with just about any
699bootdev that is based on a media device.
700
701The `bootdev_find_in_blk()` helper is implemented in the bootdev uclass. It
702names the bootflow and copies the partition number in from the iterator. Then it
703calls the bootmeth device to check if it can support this device. This is
704important since some bootmeths only work with network devices, for example. If
705that check fails, it stops.
706
707Assuming the bootmeth is happy, or at least indicates that it is willing to try
708(by returning 0 from its `check()` method), the next step is to try the
709partition. If that works it tries to detect a file system. If that works then it
710calls the bootmeth device once more, this time to read the bootflow.
711
Simon Glass0fca7e82023-08-24 13:55:43 -0600712Note: Normally a filesystem is needed for the bootmeth to be called on block
713devices, but bootmeths which don't need that can set the BOOTMETHF_ANY_PART
714flag to indicate that they can scan any partition. An example is the ChromiumOS
715bootmeth which can store a kernel in a raw partition. Note also that sandbox is
716a special case, since in that case the host filesystem can be accessed even
717though the block device is NULL.
Simon Glass83b9be62022-04-24 23:31:26 -0600718
Simon Glassb71d7f72023-05-10 16:34:46 -0600719If we take the example of the `bootmeth_extlinux` driver, this call ends up at
720`extlinux_read_bootflow()`. It has the filesystem ready, so tries various
Simon Glass83b9be62022-04-24 23:31:26 -0600721filenames to try to find the `extlinux.conf` file, reading it if possible. If
722all goes well the bootflow ends up in the `BOOTFLOWST_READY` state.
723
724At this point, we fall back from the bootmeth driver, to
Simon Glass736612e2023-01-17 10:48:19 -0700725`bootdev_find_in_blk()`, then back to `default_get_bootflow()`, then to
Simon Glass83b9be62022-04-24 23:31:26 -0600726`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller,
Simon Glass736612e2023-01-17 10:48:19 -0700727either `bootflow_scan_first()` or `bootflow_scan_next()`. In either case,
Simon Glass83b9be62022-04-24 23:31:26 -0600728the bootflow is returned as the result of this iteration, assuming it made it to
729the `BOOTFLOWST_READY` state.
730
731That is the basic operation of scanning for bootflows. The process of booting a
732bootflow is handled by the bootmeth driver for that bootflow. In the case of
Simon Glassb71d7f72023-05-10 16:34:46 -0600733extlinux boot, this parses and processes the `extlinux.conf` file that was read.
734See `extlinux_boot()` for how that works. The processing may involve reading
Simon Glass83b9be62022-04-24 23:31:26 -0600735additional files, which is handled by the `read_file()` method, which is
Simon Glassb71d7f72023-05-10 16:34:46 -0600736`extlinux_read_file()` in this case. All bootmethds should support reading
737files, since the bootflow is typically only the basic instructions and does not
738include the operating system itself, ramdisk, device tree, etc.
Simon Glass83b9be62022-04-24 23:31:26 -0600739
740The vast majority of the bootstd code is concerned with iterating through
741partitions on bootdevs and using bootmethds to find bootflows.
742
743How about bootdevs which are not block devices? They are handled by the same
744methods as above, but with a different implementation. For example, the bootmeth
745for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`.
746But other than that it is very similar.
747
748
749Tests
750-----
751
752Tests are located in `test/boot` and cover the core functionality as well as
753the commands. All tests use sandbox so can be run on a standard Linux computer
754and in U-Boot's CI.
755
Simon Glass736612e2023-01-17 10:48:19 -0700756For testing, a DOS-formatted disk image is used with a FAT partition on it and
757a second unused partition. This is created in `setup_bootflow_image()`, with a
758canned one from the source tree used if it cannot be created (e.g. in CI).
Simon Glass83b9be62022-04-24 23:31:26 -0600759
760
761Bootflow internals
762------------------
763
764The bootstd device holds a linked list of scanned bootflows as well as the
765currently selected bootdev and bootflow (for use by commands). This is in
766`struct bootstd_priv`.
767
768Each bootdev device has its own `struct bootdev_uc_plat` which holds a
769list of scanned bootflows just for that device.
770
771The bootflow itself is documented in bootflow_h_. It includes various bits of
772information about the bootflow and a buffer to hold the file.
773
774
775Future
776------
777
778Apart from the to-do items below, different types of bootflow files may be
779implemented in future, e.g. Chromium OS support which is currently only
780available as a script in chromebook_coral.
781
782
783To do
784-----
785
786Some things that need to be done to completely replace the distro-boot scripts:
787
Simon Glass5fd48162023-08-24 19:39:24 -0600788- implement extensions (devicetree overlays with add-on boards)
Simon Glass83b9be62022-04-24 23:31:26 -0600789
790Other ideas:
791
792- `bootflow prep` to load everything preparing for boot, so that `bootflow boot`
793 can just do the boot.
794- automatically load kernel, FDT, etc. to suitable addresses so the board does
795 not need to specify things like `pxefile_addr_r`
796
797
Paul Barker6c55d0d2022-07-29 14:31:58 +0100798.. _distro_bootcmd: https://github.com/u-boot/u-boot/blob/master/include/config_distro_bootcmd.h
Simon Glass83b9be62022-04-24 23:31:26 -0600799.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
800.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c
801.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h
Simon Glasse27d7df2023-09-14 10:55:55 -0600802.. _migrate_patch: https://patchwork.ozlabs.org/project/uboot/patch/20230727215433.578830-2-sjg@chromium.org/