blob: 7a2a69fdfcecc0a46c55fa7b718017f69d98f616 [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
Paul Barker7252f3c2022-07-29 14:31:58 +010024distro_bootcmd_ for details. This is done because U-Boot has no native support
Simon Glasse7b2ce12022-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 Glass915458e2022-07-30 15:52:03 -060035Finally, standard boot supports the operation of :doc:`vbe`.
Simon Glasse7b2ce12022-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 Barker7252f3c2022-07-29 14:31:58 +010055which to load devicetree files. The details are described in distro_bootcmd_.
Simon Glasse7b2ce12022-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 Glass1bdda5f2023-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.
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.
Simon Glasse7b2ce12022-04-24 23:31:26 -060082
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.
98
Simon Glass228fe572022-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 Glasse7b2ce12022-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 Glass228fe572022-07-30 15:52:35 -0600128When global bootmeths are available, these are typically checked before the
129above bootdev scanning.
130
Simon Glasse7b2ce12022-04-24 23:31:26 -0600131
132Controlling ordering
133--------------------
134
135Several options are available to control the ordering of boot scanning:
136
137
138boot_targets
139~~~~~~~~~~~~
140
141This environment variable can be used to control the list of bootdevs searched
142and their ordering, for example::
143
144 setenv boot_targets "mmc0 mmc1 usb pxe"
145
146Entries may be removed or re-ordered in this list to affect the boot order. If
147the variable is empty, the default ordering is used, based on the priority of
148bootdevs and their sequence numbers.
149
150
151bootmeths
152~~~~~~~~~
153
154This environment variable can be used to control the list of bootmeths used and
155their ordering for example::
156
Simon Glass79f66352023-05-10 16:34:46 -0600157 setenv bootmeths "extlinux efi"
Simon Glasse7b2ce12022-04-24 23:31:26 -0600158
159Entries may be removed or re-ordered in this list to affect the order the
160bootmeths are tried on each bootdev. If the variable is empty, the default
161ordering is used, based on the bootmeth sequence numbers, which can be
162controlled by aliases.
163
164The :ref:`usage/cmd/bootmeth:bootmeth command` (`bootmeth order`) operates in
165the same way as setting this variable.
166
167
168Bootdev uclass
169--------------
170
171The bootdev uclass provides an simple API call to obtain a bootflows from a
172device::
173
174 int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter,
175 struct bootflow *bflow);
176
177This takes a iterator which indicates the bootdev, partition and bootmeth to
178use. It returns a bootflow. This is the core of the bootdev implementation. The
179bootdev drivers that implement this differ depending on the media they are
180reading from, but each is responsible for returning a valid bootflow if
181available.
182
183A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this
Simon Glass1bdda5f2023-01-17 10:48:19 -0700184function for each media device uclass, in a few lines of code. For many types
185ot bootdevs, the `get_bootflow` member can be NULL, indicating that the default
186handler is used. This is called `default_get_bootflow()` and it only works with
187block devices.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600188
189
190Bootdev drivers
191---------------
192
193A bootdev driver is typically fairly simple. Here is one for mmc::
194
Simon Glasse7b2ce12022-04-24 23:31:26 -0600195 static int mmc_bootdev_bind(struct udevice *dev)
196 {
197 struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev);
198
Simon Glasseacc2612023-01-17 10:48:08 -0700199 ucp->prio = BOOTDEVP_2_INTERNAL_FAST;
Simon Glasse7b2ce12022-04-24 23:31:26 -0600200
201 return 0;
202 }
203
204 struct bootdev_ops mmc_bootdev_ops = {
Simon Glasse7b2ce12022-04-24 23:31:26 -0600205 };
206
207 static const struct udevice_id mmc_bootdev_ids[] = {
208 { .compatible = "u-boot,bootdev-mmc" },
209 { }
210 };
211
212 U_BOOT_DRIVER(mmc_bootdev) = {
213 .name = "mmc_bootdev",
214 .id = UCLASS_BOOTDEV,
215 .ops = &mmc_bootdev_ops,
216 .bind = mmc_bootdev_bind,
217 .of_match = mmc_bootdev_ids,
218 };
219
Simon Glass1bdda5f2023-01-17 10:48:19 -0700220You may notice that the `get_bootflow` memory is not provided, so is NULL. This
221means that `default_get_bootflow()` is used. This simply obtains the
222block device and calls a bootdev helper function to do the rest. The
Simon Glasse7b2ce12022-04-24 23:31:26 -0600223implementation of `bootdev_find_in_blk()` checks the partition table, and
224attempts to read a file from a filesystem on the partition number given by the
Simon Glass1bdda5f2023-01-17 10:48:19 -0700225`@iter->part` parameter. If there are any bootable partitions in the table,
226then only bootable partitions are considered.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600227
Simon Glass1bdda5f2023-01-17 10:48:19 -0700228Each bootdev has a priority, which indicates the order in which it is used,
229if `boot_targets` is not used. Faster bootdevs are used first, since they are
230more likely to be able to boot the device quickly.
231
232
233Environment Variables
234---------------------
235
236Various environment variables are used by standard boot. These allow the board
237to control where things are placed when booting the OS. You should ensure that
238your boards sets values for these.
239
240fdtfile
241 Name of the flattened device tree (FDT) file to load, e.g.
242 "rockchip/rk3399-rockpro64.dtb"
243
244fdtaddr_addr_r
245 Address at which to load the FDT, e.g. 0x01f00000
246
247fdtoverlay_addr_r (needed if overlays are used)
248 Address at which to load the overlay for the FDT, e.g. 0x02000000
249
250kernel_addr_r
251 Address at which to load the kernel, e.g. 0x02080000
252
253kernel_comp_addr_r
254 Address to which to decompress the kernel, e.g. 0x08000000
255
256kernel_comp_size
257 Size of available space for decompressed kernel, e.g. 0x2000000
258
259pxefile_addr_r
260 Address at which to load the PXE file, e.g. 0x00600000
261
262ramdisk_addr_r
263 Address at which to load the ramdisk, e.g. 0x06000000
264
265scriptaddr
266 Address at which to load the U-Boot script, e.g. 0x00500000
267
268script_offset_f
269 SPI flash offset from which to load the U-Boot script, e.g. 0xffe000
270
271script_size_f
272 Size of the script to load, e.g. 0x2000
273
274Some variables are set by script bootmeth:
275
276devtype
277 Device type being used for boot, e.g. mmc
278
279devnum
280 Device number being used for boot, e.g. 1
281
282distro_bootpart
283 Partition being used for boot, e.g. 2
284
285prefix
286 Directory containing the script
287
288mmc_bootdev
289 Device number being used for boot (e.g. 1). This is only used by MMC on
290 sunxi boards.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600291
292
293Device hierarchy
294----------------
295
296A bootdev device is a child of the media device. In this example, you can see
297that the bootdev is a sibling of the block device and both are children of
298media device::
299
300 mmc 0 [ + ] bcm2835-sdhost | |-- mmc@7e202000
301 blk 0 [ + ] mmc_blk | | |-- mmc@7e202000.blk
302 bootdev 0 [ ] mmc_bootdev | | `-- mmc@7e202000.bootdev
303 mmc 1 [ + ] sdhci-bcm2835 | |-- sdhci@7e300000
304 blk 1 [ ] mmc_blk | | |-- sdhci@7e300000.blk
305 bootdev 1 [ ] mmc_bootdev | | `-- sdhci@7e300000.bootdev
306
307The bootdev device is typically created automatically in the media uclass'
Simon Glass1bdda5f2023-01-17 10:48:19 -0700308`post_bind()` method by calling `bootdev_setup_for_dev()` or
309`bootdev_setup_sibling_blk()`. The code typically something like this::
Simon Glasse7b2ce12022-04-24 23:31:26 -0600310
Simon Glass1bdda5f2023-01-17 10:48:19 -0700311 /* dev is the Ethernet device */
Simon Glasse7b2ce12022-04-24 23:31:26 -0600312 ret = bootdev_setup_for_dev(dev, "eth_bootdev");
313 if (ret)
314 return log_msg_ret("bootdev", ret);
315
Simon Glass1bdda5f2023-01-17 10:48:19 -0700316or::
317
318 /* blk is the block device (child of MMC device)
319 ret = bootdev_setup_sibling_blk(blk, "mmc_bootdev");
320 if (ret)
321 return log_msg_ret("bootdev", ret);
322
323
Simon Glasse7b2ce12022-04-24 23:31:26 -0600324Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev`
325is the ethernet device. This function is safe to call even if standard boot is
326not enabled, since it does nothing in that case. It can be added to all uclasses
327which implement suitable media.
328
329
330The bootstd device
331------------------
332
333Standard boot requires a single instance of the bootstd device to make things
334work. This includes global information about the state of standard boot. See
335`struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`.
336
Simon Glass228fe572022-07-30 15:52:35 -0600337Within the devicetree, if you add bootmeth devices, they should be children of
338the bootstd device. See `arch/sandbox/dts/test.dts` for an example of this.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600339
340
341.. _`Automatic Devices`:
342
343Automatic devices
344-----------------
345
346It is possible to define all the required devices in the devicetree manually,
347but it is not necessary. The bootstd uclass includes a `dm_scan_other()`
348function which creates the bootstd device if not found. If no bootmeth devices
Simon Glass228fe572022-07-30 15:52:35 -0600349are found at all, it creates one for each available bootmeth driver.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600350
351If your devicetree has any bootmeth device it must have all of them that you
Simon Glass228fe572022-07-30 15:52:35 -0600352want to use, since no bootmeth devices will be created automatically in that
353case.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600354
355
356Using devicetree
357----------------
358
359If a bootdev is complicated or needs configuration information, it can be
360added to the devicetree as a child of the media device. For example, imagine a
361bootdev which reads a bootflow from SPI flash. The devicetree fragment might
362look like this::
363
364 spi@0 {
365 flash@0 {
366 reg = <0>;
367 compatible = "spansion,m25p16", "jedec,spi-nor";
368 spi-max-frequency = <40000000>;
369
370 bootdev {
371 compatible = "u-boot,sf-bootdev";
372 offset = <0x2000>;
373 size = <0x1000>;
374 };
375 };
376 };
377
378The `sf-bootdev` driver can implement a way to read from the SPI flash, using
379the offset and size provided, and return that bootflow file back to the caller.
Dario Binacchic2ee5ee2022-08-26 15:15:41 +0200380When distro boot wants to read the kernel it calls distro_getfile() which must
Simon Glasse7b2ce12022-04-24 23:31:26 -0600381provide a way to read from the SPI flash. See `distro_boot()` at distro_boot_
382for more details.
383
384Of course this is all internal to U-Boot. All the distro sees is another way
385to boot.
386
387
388Configuration
389-------------
390
391Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG
Simon Glass79f66352023-05-10 16:34:46 -0600392option also. For example, `CONFIG_BOOTMETH_EXTLINUX` enables support for
393booting from a disk using an `extlinux.conf` file.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600394
Simon Glass1bdda5f2023-01-17 10:48:19 -0700395To enable all feature sof standard boot, use `CONFIG_BOOTSTD_FULL`. This
396includes the full set of commands, more error messages when things go wrong and
397bootmeth ordering with the bootmeths environment variable.
398
Simon Glass22353fa2023-01-28 15:00:21 -0700399You should probably also enable `CONFIG_BOOTSTD_DEFAULTS`, which provides
400several filesystem and network features (if `CONFIG_NET` is enabled) so that
401a good selection of boot options is available.
402
Simon Glasse7b2ce12022-04-24 23:31:26 -0600403
404Available bootmeth drivers
405--------------------------
406
407Bootmeth drivers are provided for:
408
Simon Glass79f66352023-05-10 16:34:46 -0600409 - extlinux / syslinux boot from a disk
410 - extlinux boot from a network (PXE)
Simon Glass1bdda5f2023-01-17 10:48:19 -0700411 - U-Boot scripts from disk, network or SPI flash
412 - EFI boot using bootefi from disk
Simon Glass228fe572022-07-30 15:52:35 -0600413 - VBE
Simon Glasse7b2ce12022-04-24 23:31:26 -0600414 - EFI boot using boot manager
415
416
417Command interface
418-----------------
419
420Three commands are available:
421
422`bootdev`
423 Allows listing of available bootdevs, selecting a particular one and
424 getting information about it. See :doc:`../usage/cmd/bootdev`
425
426`bootflow`
427 Allows scanning one or more bootdevs for bootflows, listing available
428 bootflows, selecting one, obtaining information about it and booting it.
429 See :doc:`../usage/cmd/bootflow`
430
431`bootmeth`
432 Allow listing of available bootmethds and setting the order in which they
433 are tried. See :doc:`../usage/cmd/bootmeth`
434
435.. _BootflowStates:
436
437Bootflow states
438---------------
439
440Here is a list of states that a bootflow can be in:
441
442======= =======================================================================
443State Meaning
444======= =======================================================================
445base Starting-out state, indicates that no media/partition was found. For an
446 SD card socket it may indicate that the card is not inserted.
447media Media was found (e.g. SD card is inserted) but no partition information
448 was found. It might lack a partition table or have a read error.
449part Partition was found but a filesystem could not be read. This could be
450 because the partition does not hold a filesystem or the filesystem is
451 very corrupted.
452fs Filesystem was found but the file could not be read. It could be
453 missing or in the wrong subdirectory.
454file File was found and its size detected, but it could not be read. This
455 could indicate filesystem corruption.
456ready File was loaded and is ready for use. In this state the bootflow is
457 ready to be booted.
458======= =======================================================================
459
460
461Theory of operation
462-------------------
463
464This describes how standard boot progresses through to booting an operating
465system.
466
467To start. all the necessary devices must be bound, including bootstd, which
468provides the top-level `struct bootstd_priv` containing optional configuration
469information. The bootstd device is also holds the various lists used while
470scanning. This step is normally handled automatically by driver model, as
471described in `Automatic Devices`_.
472
473Bootdevs are also required, to provide access to the media to use. These are not
474useful by themselves: bootmeths are needed to provide the means of scanning
475those bootdevs. So, all up, we need a single bootstd device, one or more bootdev
476devices and one or more bootmeth devices.
477
478Once these are ready, typically a `bootflow scan` command is issued. This kicks
Simon Glass1bdda5f2023-01-17 10:48:19 -0700479of the iteration process, which involves hunting for bootdevs and looking
480through the bootdevs and their partitions one by one to find bootflows.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600481
Simon Glass1bdda5f2023-01-17 10:48:19 -0700482Iteration is kicked off using `bootflow_scan_first()`.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600483
484The iterator is set up with `bootflow_iter_init()`. This simply creates an
485empty one with the given flags. Flags are used to control whether each
486iteration is displayed, whether to return iterations even if they did not result
487in a valid bootflow, whether to iterate through just a single bootdev, etc.
488
Simon Glass1bdda5f2023-01-17 10:48:19 -0700489Then the iterator is set up to according to the parameters given:
490
491- When `dev` is provided, then a single bootdev is scanned. In this case,
Simon Glass4f806f32023-02-22 12:17:03 -0700492 `BOOTFLOWIF_SKIP_GLOBAL` and `BOOTFLOWIF_SINGLE_DEV` are set. No hunters are
Simon Glass1bdda5f2023-01-17 10:48:19 -0700493 used in this case
494
495- Otherwise, when `label` is provided, then a single label or named bootdev is
Simon Glass4f806f32023-02-22 12:17:03 -0700496 scanned. In this case `BOOTFLOWIF_SKIP_GLOBAL` is set and there are three
Simon Glass1bdda5f2023-01-17 10:48:19 -0700497 options (with an effect on the `iter_incr()` function described later):
498
499 - If `label` indicates a numeric bootdev number (e.g. "2") then
500 `BOOTFLOW_METHF_SINGLE_DEV` is set. In this case, moving to the next bootdev
501 simple stops, since there is only one. No hunters are used.
502 - If `label` indicates a particular media device (e.g. "mmc1") then
Simon Glass4f806f32023-02-22 12:17:03 -0700503 `BOOTFLOWIF_SINGLE_MEDIA` is set. In this case, moving to the next bootdev
Simon Glass1bdda5f2023-01-17 10:48:19 -0700504 processes just the children of the media device. Hunters are used, in this
505 example just the "mmc" hunter.
506 - If `label` indicates a media uclass (e.g. "mmc") then
Simon Glass4f806f32023-02-22 12:17:03 -0700507 `BOOTFLOWIF_SINGLE_UCLASS` is set. In this case, all bootdevs in that uclass
Simon Glass1bdda5f2023-01-17 10:48:19 -0700508 are used. Hunters are used, in this example just the "mmc" hunter
509
510- Otherwise, none of the above flags is set and iteration is set up to work
511 through `boot_targets` environment variable (or `bootdev-order` device tree
512 property) in order, running the relevant hunter first. In this case
513 `cur_label` is used to indicate the label being processed. If there is no list
514 of labels, then all bootdevs are processed in order of priority, running the
515 hunters as it goes.
516
517With the above it is therefore possible to iterate in a variety of ways.
518
519No attempt is made to determine the ordering of bootdevs, since this cannot be
520known in advance if we are using the hunters. Any hunter might discover a new
521bootdev and disturb the original ordering.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600522
Simon Glass228fe572022-07-30 15:52:35 -0600523Next, the ordering of bootmeths is determined, by `bootmeth_setup_iter_order()`.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600524By default the ordering is again by sequence number, i.e. the `/aliases` node,
525or failing that the order in the devicetree. But the `bootmeth order` command
526or `bootmeths` environment variable can be used to set up an ordering. If that
527has been done, the ordering is in `struct bootstd_priv`, so that ordering is
528simply copied into the iterator. Either way, the `method_order` array it set up,
Simon Glass228fe572022-07-30 15:52:35 -0600529along with `num_methods`.
530
531Note that global bootmeths are always put at the end of the ordering. If any are
532present, `cur_method` is set to the first one, so that global bootmeths are done
533first. Once all have been used, these bootmeths are dropped from the iteration.
534When there are no global bootmeths, `cur_method` is set to 0.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600535
Simon Glass1bdda5f2023-01-17 10:48:19 -0700536At this point the iterator is ready to use, with the first bootmeth selected.
537Most of the other fields are 0. This means that the current partition
Simon Glass228fe572022-07-30 15:52:35 -0600538is 0, which is taken to mean the whole device, since partition numbers start at
5391. It also means that `max_part` is 0, i.e. the maximum partition number we know
Simon Glasse7b2ce12022-04-24 23:31:26 -0600540about is 0, meaning that, as far as we know, there is no partition table on this
541bootdev.
542
Simon Glass1bdda5f2023-01-17 10:48:19 -0700543With the iterator ready, `bootflow_scan_first()` checks whether the current
Simon Glasse7b2ce12022-04-24 23:31:26 -0600544settings produce a valid bootflow. This is handled by `bootflow_check()`, which
545either returns 0 (if it got something) or an error if not (more on that later).
Simon Glass4f806f32023-02-22 12:17:03 -0700546If the `BOOTFLOWIF_ALL` iterator flag is set, even errors are returned as
Simon Glasse7b2ce12022-04-24 23:31:26 -0600547incomplete bootflows, but normally an error results in moving onto the next
548iteration.
549
Simon Glass1bdda5f2023-01-17 10:48:19 -0700550Note that `bootflow_check()` handles global bootmeths explicitly, by calling
Simon Glass228fe572022-07-30 15:52:35 -0600551`bootmeth_get_bootflow()` on each one. The `doing_global` flag indicates when
552the iterator is in that state.
553
Simon Glasse7b2ce12022-04-24 23:31:26 -0600554The `bootflow_scan_next()` function handles moving onto the next iteration and
555checking it. In fact it sits in a loop doing that repeatedly until it finds
556something it wants to return.
557
Simon Glass1bdda5f2023-01-17 10:48:19 -0700558The actual 'moving on' part is implemented in `iter_incr()`. This is a fairly
Simon Glasse7b2ce12022-04-24 23:31:26 -0600559simple function. It increments the first counter. If that hits its maximum, it
560sets it to zero and increments the second counter. You can think of all the
561counters together as a number with three digits which increment in order, with
562the least-sigificant digit on the right, counting like this:
563
564 ======== ======= =======
565 bootdev part method
566 ======== ======= =======
567 0 0 0
568 0 0 1
569 0 0 2
570 0 1 0
571 0 1 1
Simon Glass228fe572022-07-30 15:52:35 -0600572 0 1 2
Simon Glasse7b2ce12022-04-24 23:31:26 -0600573 1 0 0
574 1 0 1
Simon Glass228fe572022-07-30 15:52:35 -0600575 ...
Simon Glasse7b2ce12022-04-24 23:31:26 -0600576 ======== ======= =======
577
578The maximum value for `method` is `num_methods - 1` so when it exceeds that, it
579goes back to 0 and the next `part` is considered. The maximum value for that is
580`max_part`, which is initially zero for all bootdevs. If we find a partition
581table on that bootdev, `max_part` can be updated during the iteration to a
582higher value - see `bootdev_find_in_blk()` for that, described later. If that
583exceeds its maximum, then the next bootdev is used. In this way, iter_incr()
584works its way through all possibilities, moving forward one each time it is
585called.
586
Simon Glass228fe572022-07-30 15:52:35 -0600587Note that global bootmeths introduce a subtlety into the above description.
588When `doing_global` is true, the iteration takes place only among the bootmeths,
589i.e. the last column above. The global bootmeths are at the end of the list.
590Assuming that they are entries 3 and 4 in the list, the iteration then looks
591like this:
592
593 ======== ======= ======= =======================================
594 bootdev part method notes
595 ======== ======= ======= =======================================
596 . . 3 doing_global = true, method_count = 5
597 . . 4
598 0 0 0 doing_global = false, method_count = 3
599 0 0 1
600 0 0 2
601 0 1 0
602 0 1 1
603 0 1 2
604 1 0 0
605 1 0 1
606 ...
607 ======== ======= ======= =======================================
608
609The changeover of the value of `doing_global` from true to false is handled in
610`iter_incr()` as well.
611
Simon Glass1bdda5f2023-01-17 10:48:19 -0700612Note that the value in the `bootdev` column above is not actually stored - it is
613just for illustration. In practice, `iter_incr()` uses the flags to determine
614whether to move to the next bootdev in the uclass, the next child of the media
615device, the next label, or the next priority level, depending on the flag
616settings (see `BOOTFLOW_METHF_SINGLE_DEV`, etc. above).
617
Simon Glasse7b2ce12022-04-24 23:31:26 -0600618There is no expectation that iteration will actually finish. Quite often a
619valid bootflow is found early on. With `bootflow scan -b`, that causes the
620bootflow to be immediately booted. Assuming it is successful, the iteration never
621completes.
622
623Also note that the iterator hold the **current** combination being considered.
624So when `iter_incr()` is called, it increments to the next one and returns it,
625the new **current** combination.
626
627Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has
628thus has no effect on `iter_inc()`. But if it is non-zero, signalling an error,
629it indicates to the iterator what it should do when called. It can force moving
630to the next partition, or bootdev, for example. The special values
631`BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees
632`BF_NO_MORE_PARTS` it knows that it should immediately move to the next bootdev.
633When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do
634so it should immediately return. The caller of `iter_incr()` is responsible for
635updating the `err` field, based on the return value it sees.
636
637The above describes the iteration process at a high level. It is basically a
638very simple increment function with a checker called `bootflow_check()` that
639checks the result of each iteration generated, to determine whether it can
640produce a bootflow.
641
642So what happens inside of `bootflow_check()`? It simply calls the uclass
643method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It
644passes the iterator to the bootdev method, so that function knows what we are
645talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`,
646with just the `method` and `dev` intiialised. But the bootdev may fill in more,
Simon Glass228fe572022-07-30 15:52:35 -0600647e.g. updating the state, depending on what it finds. For global bootmeths the
648`bootmeth_get_bootflow()` function is called instead of
649`bootdev_get_bootflow()`.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600650
Simon Glass228fe572022-07-30 15:52:35 -0600651Based on what the bootdev or bootmeth responds with, `bootflow_check()` either
Simon Glasse7b2ce12022-04-24 23:31:26 -0600652returns a valid bootflow, or a partial one with an error. A partial bootflow
653is one that has some fields set up, but did not reach the `BOOTFLOWST_READY`
Simon Glass4f806f32023-02-22 12:17:03 -0700654state. As noted before, if the `BOOTFLOWIF_ALL` iterator flag is set, then all
Simon Glasse7b2ce12022-04-24 23:31:26 -0600655bootflows are returned, even partial ones. This can help with debugging.
656
657So at this point you can see that total control over whether a bootflow can
Simon Glass228fe572022-07-30 15:52:35 -0600658be generated from a particular iteration, or not, rests with the bootdev (or
659global bootmeth). Each one can adopt its own approach.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600660
661Going down a level, what does the bootdev do in its `get_bootflow()` method?
662Let us consider the MMC bootdev. In that case the call to
Simon Glass1bdda5f2023-01-17 10:48:19 -0700663`bootdev_get_bootflow()` ends up in `default_get_bootflow()`. It locates the
664parent device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds
665the block device associated with it. It then calls the helper function
Simon Glasse7b2ce12022-04-24 23:31:26 -0600666`bootdev_find_in_blk()` to do all the work. This is common with just about any
667bootdev that is based on a media device.
668
669The `bootdev_find_in_blk()` helper is implemented in the bootdev uclass. It
670names the bootflow and copies the partition number in from the iterator. Then it
671calls the bootmeth device to check if it can support this device. This is
672important since some bootmeths only work with network devices, for example. If
673that check fails, it stops.
674
675Assuming the bootmeth is happy, or at least indicates that it is willing to try
676(by returning 0 from its `check()` method), the next step is to try the
677partition. If that works it tries to detect a file system. If that works then it
678calls the bootmeth device once more, this time to read the bootflow.
679
680Note: At present a filesystem is needed for the bootmeth to be called on block
681devices, simply because we don't have any examples where this is not the case.
Simon Glass1bdda5f2023-01-17 10:48:19 -0700682This feature can be added as needed. Note that sandbox is a special case, since
683in that case the host filesystem can be accessed even though the block device
684is NULL.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600685
Simon Glass79f66352023-05-10 16:34:46 -0600686If we take the example of the `bootmeth_extlinux` driver, this call ends up at
687`extlinux_read_bootflow()`. It has the filesystem ready, so tries various
Simon Glasse7b2ce12022-04-24 23:31:26 -0600688filenames to try to find the `extlinux.conf` file, reading it if possible. If
689all goes well the bootflow ends up in the `BOOTFLOWST_READY` state.
690
691At this point, we fall back from the bootmeth driver, to
Simon Glass1bdda5f2023-01-17 10:48:19 -0700692`bootdev_find_in_blk()`, then back to `default_get_bootflow()`, then to
Simon Glasse7b2ce12022-04-24 23:31:26 -0600693`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller,
Simon Glass1bdda5f2023-01-17 10:48:19 -0700694either `bootflow_scan_first()` or `bootflow_scan_next()`. In either case,
Simon Glasse7b2ce12022-04-24 23:31:26 -0600695the bootflow is returned as the result of this iteration, assuming it made it to
696the `BOOTFLOWST_READY` state.
697
698That is the basic operation of scanning for bootflows. The process of booting a
699bootflow is handled by the bootmeth driver for that bootflow. In the case of
Simon Glass79f66352023-05-10 16:34:46 -0600700extlinux boot, this parses and processes the `extlinux.conf` file that was read.
701See `extlinux_boot()` for how that works. The processing may involve reading
Simon Glasse7b2ce12022-04-24 23:31:26 -0600702additional files, which is handled by the `read_file()` method, which is
Simon Glass79f66352023-05-10 16:34:46 -0600703`extlinux_read_file()` in this case. All bootmethds should support reading
704files, since the bootflow is typically only the basic instructions and does not
705include the operating system itself, ramdisk, device tree, etc.
Simon Glasse7b2ce12022-04-24 23:31:26 -0600706
707The vast majority of the bootstd code is concerned with iterating through
708partitions on bootdevs and using bootmethds to find bootflows.
709
710How about bootdevs which are not block devices? They are handled by the same
711methods as above, but with a different implementation. For example, the bootmeth
712for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`.
713But other than that it is very similar.
714
715
716Tests
717-----
718
719Tests are located in `test/boot` and cover the core functionality as well as
720the commands. All tests use sandbox so can be run on a standard Linux computer
721and in U-Boot's CI.
722
Simon Glass1bdda5f2023-01-17 10:48:19 -0700723For testing, a DOS-formatted disk image is used with a FAT partition on it and
724a second unused partition. This is created in `setup_bootflow_image()`, with a
725canned one from the source tree used if it cannot be created (e.g. in CI).
Simon Glasse7b2ce12022-04-24 23:31:26 -0600726
727
728Bootflow internals
729------------------
730
731The bootstd device holds a linked list of scanned bootflows as well as the
732currently selected bootdev and bootflow (for use by commands). This is in
733`struct bootstd_priv`.
734
735Each bootdev device has its own `struct bootdev_uc_plat` which holds a
736list of scanned bootflows just for that device.
737
738The bootflow itself is documented in bootflow_h_. It includes various bits of
739information about the bootflow and a buffer to hold the file.
740
741
742Future
743------
744
745Apart from the to-do items below, different types of bootflow files may be
746implemented in future, e.g. Chromium OS support which is currently only
747available as a script in chromebook_coral.
748
749
750To do
751-----
752
753Some things that need to be done to completely replace the distro-boot scripts:
754
755- add bootdev drivers for dhcp, sata, scsi, ide, virtio
756- PXE boot for EFI
757- support for loading U-Boot scripts
758
759Other ideas:
760
761- `bootflow prep` to load everything preparing for boot, so that `bootflow boot`
762 can just do the boot.
763- automatically load kernel, FDT, etc. to suitable addresses so the board does
764 not need to specify things like `pxefile_addr_r`
765
766
Paul Barker7252f3c2022-07-29 14:31:58 +0100767.. _distro_bootcmd: https://github.com/u-boot/u-boot/blob/master/include/config_distro_bootcmd.h
Simon Glasse7b2ce12022-04-24 23:31:26 -0600768.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/
769.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c
770.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h