blob: 5e9c0d282bb0342573abd465a0d326194e59bd3e [file] [log] [blame]
Simon Glasse7b2ce12022-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
24disto_boodcmd_ 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
35
36Bootflow
37--------
38
39A bootflow is a file that describes how to boot a distro. Conceptually there can
40be different formats for that file but at present U-Boot only supports the
41BootLoaderSpec_ format. which looks something like this::
42
43 menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options.
44 menu title Fedora-Workstation-armhfp-31-1.9 Boot Options.
45 menu hidden
46
47 label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl)
48 kernel /vmlinuz-5.3.7-301.fc31.armv7hl
49 append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB
50 fdtdir /dtb-5.3.7-301.fc31.armv7hl/
51 initrd /initramfs-5.3.7-301.fc31.armv7hl.img
52
53As you can see it specifies a kernel, a ramdisk (initrd) and a directory from
54which to load devicetree files. The details are described in disto_boodcmd_.
55
56The bootflow is provided by the distro. It is not part of U-Boot. U-Boot's job
57is simply to interpret the file and carry out the instructions. This allows
58distros to boot on essentially any device supported by U-Boot.
59
60Typically the first available bootflow is selected and booted. If that fails,
61then the next one is tried.
62
63
64Bootdev
65-------
66
67Where does U-Boot find the media that holds the operating systems? That is the
68job of bootdev. A bootdev is simply a layer on top of a media device (such as
69MMC, NVMe). The bootdev accesses the device, including partitions and
70filesystems that might contain things related to an operating system.
71
72For example, an MMC bootdev provides access to the individual partitions on the
73MMC device. It scans through these to find filesystems, then provides a list of
74these for consideration.
75
76
77Bootmeth
78--------
79
80Once the list of filesystems is provided, how does U-Boot find the bootflow
81files in these filesystems. That is the job of bootmeth. Each boot method has
82its own way of doing this.
83
84For example, the distro bootmeth simply looks through the provided filesystem
85for a file called `extlinux/extlinux.conf`. This files constitutes a bootflow.
86If the distro bootmeth is used on multiple partitions it may produce multiple
87bootflows.
88
89Note: it is possible to have a bootmeth that uses a partition or a whole device
90directly, but it is more common to use a filesystem.
91
92
93Boot process
94------------
95
96U-Boot tries to use the 'lazy init' approach whereever possible and distro boot
97is no exception. The algorithm is::
98
99 while (get next bootdev)
100 while (get next bootmeth)
101 while (get next bootflow)
102 try to boot it
103
104So U-Boot works its way through the bootdevs, trying each bootmeth in turn to
105obtain bootflows, until it either boots or exhausts the available options.
106
107Instead of 500 lines of #defines and a 4KB boot script, all that is needed is
108the following command::
109
110 bootflow scan -lb
111
112which scans for available bootflows, optionally listing each find it finds (-l)
113and trying to boot it (-b).
114
115
116Controlling ordering
117--------------------
118
119Several options are available to control the ordering of boot scanning:
120
121
122boot_targets
123~~~~~~~~~~~~
124
125This environment variable can be used to control the list of bootdevs searched
126and their ordering, for example::
127
128 setenv boot_targets "mmc0 mmc1 usb pxe"
129
130Entries may be removed or re-ordered in this list to affect the boot order. If
131the variable is empty, the default ordering is used, based on the priority of
132bootdevs and their sequence numbers.
133
134
135bootmeths
136~~~~~~~~~
137
138This environment variable can be used to control the list of bootmeths used and
139their ordering for example::
140
141 setenv bootmeths "syslinux efi"
142
143Entries may be removed or re-ordered in this list to affect the order the
144bootmeths are tried on each bootdev. If the variable is empty, the default
145ordering is used, based on the bootmeth sequence numbers, which can be
146controlled by aliases.
147
148The :ref:`usage/cmd/bootmeth:bootmeth command` (`bootmeth order`) operates in
149the same way as setting this variable.
150
151
152Bootdev uclass
153--------------
154
155The bootdev uclass provides an simple API call to obtain a bootflows from a
156device::
157
158 int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
159 struct bootflow *bflow);
160
161This takes a iterator which indicates the bootdev, partition and bootmeth to
162use. It returns a bootflow. This is the core of the bootdev implementation. The
163bootdev drivers that implement this differ depending on the media they are
164reading from, but each is responsible for returning a valid bootflow if
165available.
166
167A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this
168function for each media device uclass, in a few lines of code.
169
170
171Bootdev drivers
172---------------
173
174A bootdev driver is typically fairly simple. Here is one for mmc::
175
176 static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
177 struct bootflow *bflow)
178 {
179 struct udevice *mmc_dev = dev_get_parent(dev);
180 struct udevice *blk;
181 int ret;
182
183 ret = mmc_get_blk(mmc_dev, &blk);
184 /*
185 * If there is no media, indicate that no more partitions should be
186 * checked
187 */
188 if (ret == -EOPNOTSUPP)
189 ret = -ESHUTDOWN;
190 if (ret)
191 return log_msg_ret("blk", ret);
192 assert(blk);
193 ret = bootdev_find_in_blk(dev, blk, iter, bflow);
194 if (ret)
195 return log_msg_ret("find", ret);
196
197 return 0;
198 }
199
200 static int mmc_bootdev_bind(struct udevice *dev)
201 {
202 struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
203
204 ucp->prio = BOOTDEVP_0_INTERNAL_FAST;
205
206 return 0;
207 }
208
209 struct bootdev_ops mmc_bootdev_ops = {
210 .get_bootflow = mmc_get_bootflow,
211 };
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
226The implementation of the `get_bootflow()` method is simply to obtain the
227block device and call a bootdev helper function to do the rest. The
228implementation of `bootdev_find_in_blk()` checks the partition table, and
229attempts to read a file from a filesystem on the partition number given by the
230`@iter->part` parameter.
231
232Each bootdev has a priority, which indicates the order in which it is used.
233Faster bootdevs are used first, since they are more likely to be able to boot
234the device quickly.
235
236
237Device hierarchy
238----------------
239
240A bootdev device is a child of the media device. In this example, you can see
241that the bootdev is a sibling of the block device and both are children of
242media device::
243
244 mmc 0 [ + ] bcm2835-sdhost | |-- mmc@7e202000
245 blk 0 [ + ] mmc_blk | | |-- mmc@7e202000.blk
246 bootdev 0 [ ] mmc_bootdev | | `-- mmc@7e202000.bootdev
247 mmc 1 [ + ] sdhci-bcm2835 | |-- sdhci@7e300000
248 blk 1 [ ] mmc_blk | | |-- sdhci@7e300000.blk
249 bootdev 1 [ ] mmc_bootdev | | `-- sdhci@7e300000.bootdev
250
251The bootdev device is typically created automatically in the media uclass'
252`post_bind()` method by calling `bootdev_setup_for_dev()`. The code typically
253something like this::
254
255 ret = bootdev_setup_for_dev(dev, "eth_bootdev");
256 if (ret)
257 return log_msg_ret("bootdev", ret);
258
259Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev`
260is the ethernet device. This function is safe to call even if standard boot is
261not enabled, since it does nothing in that case. It can be added to all uclasses
262which implement suitable media.
263
264
265The bootstd device
266------------------
267
268Standard boot requires a single instance of the bootstd device to make things
269work. This includes global information about the state of standard boot. See
270`struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`.
271
272Within the devicetree, if you add bootmeth devices or a system bootdev, they
273should be children of the bootstd device. See `arch/sandbox/dts/test.dts` for
274an example of this.
275
276
277The system bootdev
278------------------
279
280Some bootmeths don't operate on individual bootdevs, but on the whole system.
281For example, the EFI boot manager does its own device scanning and does not
282make use of the bootdev devices. Such bootmeths can make use of the system
283bootdev, typically considered last, after everything else has been tried.
284
285
286.. _`Automatic Devices`:
287
288Automatic devices
289-----------------
290
291It is possible to define all the required devices in the devicetree manually,
292but it is not necessary. The bootstd uclass includes a `dm_scan_other()`
293function which creates the bootstd device if not found. If no bootmeth devices
294are found at all, it creates one for each available bootmeth driver as well as a
295system bootdev.
296
297If your devicetree has any bootmeth device it must have all of them that you
298want to use, as well as the system bootdev if needed, since no bootmeth devices
299will be created automatically in that case.
300
301
302Using devicetree
303----------------
304
305If a bootdev is complicated or needs configuration information, it can be
306added to the devicetree as a child of the media device. For example, imagine a
307bootdev which reads a bootflow from SPI flash. The devicetree fragment might
308look like this::
309
310 spi@0 {
311 flash@0 {
312 reg = <0>;
313 compatible = "spansion,m25p16", "jedec,spi-nor";
314 spi-max-frequency = <40000000>;
315
316 bootdev {
317 compatible = "u-boot,sf-bootdev";
318 offset = <0x2000>;
319 size = <0x1000>;
320 };
321 };
322 };
323
324The `sf-bootdev` driver can implement a way to read from the SPI flash, using
325the offset and size provided, and return that bootflow file back to the caller.
326When distro boot wants to read the kernel it calls disto_getfile() which must
327provide a way to read from the SPI flash. See `distro_boot()` at distro_boot_
328for more details.
329
330Of course this is all internal to U-Boot. All the distro sees is another way
331to boot.
332
333
334Configuration
335-------------
336
337Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG
338option also. For example, `CONFIG_BOOTMETH_DISTRO` enables support for distro
339boot from a disk.
340
341
342Available bootmeth drivers
343--------------------------
344
345Bootmeth drivers are provided for:
346
347 - distro boot from a disk (syslinux)
348 - distro boot from a network (PXE)
349 - EFI boot using bootefi
350 - EFI boot using boot manager
351
352
353Command interface
354-----------------
355
356Three commands are available:
357
358`bootdev`
359 Allows listing of available bootdevs, selecting a particular one and
360 getting information about it. See :doc:`../usage/cmd/bootdev`
361
362`bootflow`
363 Allows scanning one or more bootdevs for bootflows, listing available
364 bootflows, selecting one, obtaining information about it and booting it.
365 See :doc:`../usage/cmd/bootflow`
366
367`bootmeth`
368 Allow listing of available bootmethds and setting the order in which they
369 are tried. See :doc:`../usage/cmd/bootmeth`
370
371.. _BootflowStates:
372
373Bootflow states
374---------------
375
376Here is a list of states that a bootflow can be in:
377
378======= =======================================================================
379State Meaning
380======= =======================================================================
381base Starting-out state, indicates that no media/partition was found. For an
382 SD card socket it may indicate that the card is not inserted.
383media Media was found (e.g. SD card is inserted) but no partition information
384 was found. It might lack a partition table or have a read error.
385part Partition was found but a filesystem could not be read. This could be
386 because the partition does not hold a filesystem or the filesystem is
387 very corrupted.
388fs Filesystem was found but the file could not be read. It could be
389 missing or in the wrong subdirectory.
390file File was found and its size detected, but it could not be read. This
391 could indicate filesystem corruption.
392ready File was loaded and is ready for use. In this state the bootflow is
393 ready to be booted.
394======= =======================================================================
395
396
397Theory of operation
398-------------------
399
400This describes how standard boot progresses through to booting an operating
401system.
402
403To start. all the necessary devices must be bound, including bootstd, which
404provides the top-level `struct bootstd_priv` containing optional configuration
405information. The bootstd device is also holds the various lists used while
406scanning. This step is normally handled automatically by driver model, as
407described in `Automatic Devices`_.
408
409Bootdevs are also required, to provide access to the media to use. These are not
410useful by themselves: bootmeths are needed to provide the means of scanning
411those bootdevs. So, all up, we need a single bootstd device, one or more bootdev
412devices and one or more bootmeth devices.
413
414Once these are ready, typically a `bootflow scan` command is issued. This kicks
415of the iteration process, which involves looking through the bootdevs and their
416partitions one by one to find bootflows.
417
418Iteration is kicked off using `bootflow_scan_first()`, which calls
419`bootflow_scan_bootdev()`.
420
421The iterator is set up with `bootflow_iter_init()`. This simply creates an
422empty one with the given flags. Flags are used to control whether each
423iteration is displayed, whether to return iterations even if they did not result
424in a valid bootflow, whether to iterate through just a single bootdev, etc.
425
426Then the ordering of bootdevs is determined, by `bootdev_setup_iter_order()`. By
427default, the bootdevs are used in the order specified by the `boot_targets`
428environment variable (e.g. "mmc2 mmc0 usb"). If that is missing then their
429sequence order is used, as determined by the `/aliases` node, or failing that
430their order in the devicetree. For BOOTSTD_FULL, if there is a `bootdev-order`
431property in the bootstd node, then this is used as a final fallback. In any
432case, the iterator ends up with a `dev_order` array containing the bootdevs that
433are going to be used, with `num_devs` set to the number of bootdevs and
434`cur_dev` starting at 0.
435
436Next, the ordering of bootdevs is determined, by `bootmeth_setup_iter_order()`.
437By default the ordering is again by sequence number, i.e. the `/aliases` node,
438or failing that the order in the devicetree. But the `bootmeth order` command
439or `bootmeths` environment variable can be used to set up an ordering. If that
440has been done, the ordering is in `struct bootstd_priv`, so that ordering is
441simply copied into the iterator. Either way, the `method_order` array it set up,
442along with `num_methods`. Then `cur_method` is set to 0.
443
444At this point the iterator is ready to use, with the first bootdev and bootmeth
445selected. All the other fields are 0. This means that the current partition is
4460, which is taken to mean the whole device, since partition numbers start at 1.
447It also means that `max_part` is 0, i.e. the maximum partition number we know
448about is 0, meaning that, as far as we know, there is no partition table on this
449bootdev.
450
451With the iterator ready, `bootflow_scan_bootdev()` checks whether the current
452settings produce a valid bootflow. This is handled by `bootflow_check()`, which
453either returns 0 (if it got something) or an error if not (more on that later).
454If the `BOOTFLOWF_ALL` iterator flag is set, even errors are returned as
455incomplete bootflows, but normally an error results in moving onto the next
456iteration.
457
458The `bootflow_scan_next()` function handles moving onto the next iteration and
459checking it. In fact it sits in a loop doing that repeatedly until it finds
460something it wants to return.
461
462The actual 'moving on' part is implemented in `iter_incr()`. This is a very
463simple function. It increments the first counter. If that hits its maximum, it
464sets it to zero and increments the second counter. You can think of all the
465counters together as a number with three digits which increment in order, with
466the least-sigificant digit on the right, counting like this:
467
468 ======== ======= =======
469 bootdev part method
470 ======== ======= =======
471 0 0 0
472 0 0 1
473 0 0 2
474 0 1 0
475 0 1 1
476 0 1 1
477 1 0 0
478 1 0 1
479 ======== ======= =======
480
481The maximum value for `method` is `num_methods - 1` so when it exceeds that, it
482goes back to 0 and the next `part` is considered. The maximum value for that is
483`max_part`, which is initially zero for all bootdevs. If we find a partition
484table on that bootdev, `max_part` can be updated during the iteration to a
485higher value - see `bootdev_find_in_blk()` for that, described later. If that
486exceeds its maximum, then the next bootdev is used. In this way, iter_incr()
487works its way through all possibilities, moving forward one each time it is
488called.
489
490There is no expectation that iteration will actually finish. Quite often a
491valid bootflow is found early on. With `bootflow scan -b`, that causes the
492bootflow to be immediately booted. Assuming it is successful, the iteration never
493completes.
494
495Also note that the iterator hold the **current** combination being considered.
496So when `iter_incr()` is called, it increments to the next one and returns it,
497the new **current** combination.
498
499Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has
500thus has no effect on `iter_inc()`. But if it is non-zero, signalling an error,
501it indicates to the iterator what it should do when called. It can force moving
502to the next partition, or bootdev, for example. The special values
503`BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees
504`BF_NO_MORE_PARTS` it knows that it should immediately move to the next bootdev.
505When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do
506so it should immediately return. The caller of `iter_incr()` is responsible for
507updating the `err` field, based on the return value it sees.
508
509The above describes the iteration process at a high level. It is basically a
510very simple increment function with a checker called `bootflow_check()` that
511checks the result of each iteration generated, to determine whether it can
512produce a bootflow.
513
514So what happens inside of `bootflow_check()`? It simply calls the uclass
515method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It
516passes the iterator to the bootdev method, so that function knows what we are
517talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`,
518with just the `method` and `dev` intiialised. But the bootdev may fill in more,
519e.g. updating the state, depending on what it finds.
520
521Based on what the bootdev responds with, `bootflow_check()` either
522returns a valid bootflow, or a partial one with an error. A partial bootflow
523is one that has some fields set up, but did not reach the `BOOTFLOWST_READY`
524state. As noted before, if the `BOOTFLOWF_ALL` iterator flag is set, then all
525bootflows are returned, even partial ones. This can help with debugging.
526
527So at this point you can see that total control over whether a bootflow can
528be generated from a particular iteration, or not, rests with the bootdev.
529Each one can adopt its own approach.
530
531Going down a level, what does the bootdev do in its `get_bootflow()` method?
532Let us consider the MMC bootdev. In that case the call to
533`bootdev_get_bootflow()` ends up in `mmc_get_bootflow()`. It locates the parent
534device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds the block
535device associated with it. It then calls the helper function
536`bootdev_find_in_blk()` to do all the work. This is common with just about any
537bootdev that is based on a media device.
538
539The `bootdev_find_in_blk()` helper is implemented in the bootdev uclass. It
540names the bootflow and copies the partition number in from the iterator. Then it
541calls the bootmeth device to check if it can support this device. This is
542important since some bootmeths only work with network devices, for example. If
543that check fails, it stops.
544
545Assuming the bootmeth is happy, or at least indicates that it is willing to try
546(by returning 0 from its `check()` method), the next step is to try the
547partition. If that works it tries to detect a file system. If that works then it
548calls the bootmeth device once more, this time to read the bootflow.
549
550Note: At present a filesystem is needed for the bootmeth to be called on block
551devices, simply because we don't have any examples where this is not the case.
552This feature can be added as needed.
553
554If we take the example of the `bootmeth_distro` driver, this call ends up at
555`distro_read_bootflow()`. It has the filesystem ready, so tries various
556filenames to try to find the `extlinux.conf` file, reading it if possible. If
557all goes well the bootflow ends up in the `BOOTFLOWST_READY` state.
558
559At this point, we fall back from the bootmeth driver, to
560`bootdev_find_in_blk()`, then back to `mmc_get_bootflow()`, then to
561`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller,
562either `bootflow_scan_bootdev()` or `bootflow_scan_next()`. In either case,
563the bootflow is returned as the result of this iteration, assuming it made it to
564the `BOOTFLOWST_READY` state.
565
566That is the basic operation of scanning for bootflows. The process of booting a
567bootflow is handled by the bootmeth driver for that bootflow. In the case of
568distro boot, this parses and processes the `extlinux.conf` file that was read.
569See `distro_boot()` for how that works. The processing may involve reading
570additional files, which is handled by the `read_file()` method, which is
571`distro_read_file()` in this case. All bootmethds should support reading files,
572since the bootflow is typically only the basic instructions and does not include
573the operating system itself, ramdisk, device tree, etc.
574
575The vast majority of the bootstd code is concerned with iterating through
576partitions on bootdevs and using bootmethds to find bootflows.
577
578How about bootdevs which are not block devices? They are handled by the same
579methods as above, but with a different implementation. For example, the bootmeth
580for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`.
581But other than that it is very similar.
582
583
584Tests
585-----
586
587Tests are located in `test/boot` and cover the core functionality as well as
588the commands. All tests use sandbox so can be run on a standard Linux computer
589and in U-Boot's CI.
590
591For testing, a DOS-formatted disk image is used with a single FAT partition on
592it. This is created in `setup_bootflow_image()`, with a canned one from the
593source tree used if it cannot be created (e.g. in CI).
594
595
596Bootflow internals
597------------------
598
599The bootstd device holds a linked list of scanned bootflows as well as the
600currently selected bootdev and bootflow (for use by commands). This is in
601`struct bootstd_priv`.
602
603Each bootdev device has its own `struct bootdev_uc_plat` which holds a
604list of scanned bootflows just for that device.
605
606The bootflow itself is documented in bootflow_h_. It includes various bits of
607information about the bootflow and a buffer to hold the file.
608
609
610Future
611------
612
613Apart from the to-do items below, different types of bootflow files may be
614implemented in future, e.g. Chromium OS support which is currently only
615available as a script in chromebook_coral.
616
617
618To do
619-----
620
621Some things that need to be done to completely replace the distro-boot scripts:
622
623- add bootdev drivers for dhcp, sata, scsi, ide, virtio
624- PXE boot for EFI
625- support for loading U-Boot scripts
626
627Other ideas:
628
629- `bootflow prep` to load everything preparing for boot, so that `bootflow boot`
630 can just do the boot.
631- automatically load kernel, FDT, etc. to suitable addresses so the board does
632 not need to specify things like `pxefile_addr_r`
633
634
635.. _disto_boodcmd: https://github.com/u-boot/u-boot/blob/master/include/config_distro_bootcmd.h
636.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
637.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c
638.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h