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