bootstd: Update documentation
authorSimon Glass <sjg@chromium.org>
Sat, 30 Jul 2022 21:52:35 +0000 (15:52 -0600)
committerTom Rini <trini@konsulko.com>
Fri, 12 Aug 2022 12:17:11 +0000 (08:17 -0400)
Add some documentation updates, particularly about global bootmeths.

Signed-off-by: Simon Glass <sjg@chromium.org>
doc/develop/bootstd.rst
doc/usage/cmd/bootmeth.rst

index dadd347..b8773f8 100644 (file)
@@ -90,6 +90,12 @@ bootflows.
 Note: it is possible to have a bootmeth that uses a partition or a whole device
 directly, but it is more common to use a filesystem.
 
 Note: it is possible to have a bootmeth that uses a partition or a whole device
 directly, but it is more common to use a filesystem.
 
+Note that some bootmeths are 'global', meaning that they select the bootdev
+themselves. Examples include VBE and EFI boot manager. In this case, they
+provide a `read_bootflow()` method which checks whatever bootdevs it likes, then
+returns the bootflow, if found. Some of these bootmeths may be very slow, if
+they scan a lot of devices.
+
 
 Boot process
 ------------
 
 Boot process
 ------------
@@ -113,6 +119,9 @@ the following command::
 which scans for available bootflows, optionally listing each find it finds (-l)
 and trying to boot it (-b).
 
 which scans for available bootflows, optionally listing each find it finds (-l)
 and trying to boot it (-b).
 
+When global bootmeths are available, these are typically checked before the
+above bootdev scanning.
+
 
 Controlling ordering
 --------------------
 
 Controlling ordering
 --------------------
@@ -270,18 +279,8 @@ Standard boot requires a single instance of the bootstd device to make things
 work. This includes global information about the state of standard boot. See
 `struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`.
 
 work. This includes global information about the state of standard boot. See
 `struct bootstd_priv` for this structure, accessed with `bootstd_get_priv()`.
 
-Within the devicetree, if you add bootmeth devices or a system bootdev, they
-should be children of the bootstd device. See `arch/sandbox/dts/test.dts` for
-an example of this.
-
-
-The system bootdev
-------------------
-
-Some bootmeths don't operate on individual bootdevs, but on the whole system.
-For example, the EFI boot manager does its own device scanning and does not
-make use of the bootdev devices. Such bootmeths can make use of the system
-bootdev, typically considered last, after everything else has been tried.
+Within the devicetree, if you add bootmeth devices, they should be children of
+the bootstd device. See `arch/sandbox/dts/test.dts` for an example of this.
 
 
 .. _`Automatic Devices`:
 
 
 .. _`Automatic Devices`:
@@ -292,12 +291,11 @@ Automatic devices
 It is possible to define all the required devices in the devicetree manually,
 but it is not necessary. The bootstd uclass includes a `dm_scan_other()`
 function which creates the bootstd device if not found. If no bootmeth devices
 It is possible to define all the required devices in the devicetree manually,
 but it is not necessary. The bootstd uclass includes a `dm_scan_other()`
 function which creates the bootstd device if not found. If no bootmeth devices
-are found at all, it creates one for each available bootmeth driver as well as a
-system bootdev.
+are found at all, it creates one for each available bootmeth driver.
 
 If your devicetree has any bootmeth device it must have all of them that you
 
 If your devicetree has any bootmeth device it must have all of them that you
-want to use, as well as the system bootdev if needed, since no bootmeth devices
-will be created automatically in that case.
+want to use, since no bootmeth devices will be created automatically in that
+case.
 
 
 Using devicetree
 
 
 Using devicetree
@@ -348,6 +346,7 @@ Bootmeth drivers are provided for:
    - distro boot from a disk (syslinux)
    - distro boot from a network (PXE)
    - EFI boot using bootefi
    - distro boot from a disk (syslinux)
    - distro boot from a network (PXE)
    - EFI boot using bootefi
+   - VBE
    - EFI boot using boot manager
 
 
    - EFI boot using boot manager
 
 
@@ -434,18 +433,23 @@ case, the iterator ends up with a `dev_order` array containing the bootdevs that
 are going to be used, with `num_devs` set to the number of bootdevs and
 `cur_dev` starting at 0.
 
 are going to be used, with `num_devs` set to the number of bootdevs and
 `cur_dev` starting at 0.
 
-Next, the ordering of bootdevs is determined, by `bootmeth_setup_iter_order()`.
+Next, the ordering of bootmeths is determined, by `bootmeth_setup_iter_order()`.
 By default the ordering is again by sequence number, i.e. the `/aliases` node,
 or failing that the order in the devicetree. But the `bootmeth order` command
 or `bootmeths` environment variable can be used to set up an ordering. If that
 has been done, the ordering is in `struct bootstd_priv`, so that ordering is
 simply copied into the iterator. Either way, the `method_order` array it set up,
 By default the ordering is again by sequence number, i.e. the `/aliases` node,
 or failing that the order in the devicetree. But the `bootmeth order` command
 or `bootmeths` environment variable can be used to set up an ordering. If that
 has been done, the ordering is in `struct bootstd_priv`, so that ordering is
 simply copied into the iterator. Either way, the `method_order` array it set up,
-along with `num_methods`. Then `cur_method` is set to 0.
+along with `num_methods`.
+
+Note that global bootmeths are always put at the end of the ordering. If any are
+present, `cur_method` is set to the first one, so that global bootmeths are done
+first. Once all have been used, these bootmeths are dropped from the iteration.
+When there are no global bootmeths, `cur_method` is set to 0.
 
 At this point the iterator is ready to use, with the first bootdev and bootmeth
 
 At this point the iterator is ready to use, with the first bootdev and bootmeth
-selected. All the other fields are 0. This means that the current partition is
-0, which is taken to mean the whole device, since partition numbers start at 1.
-It also means that `max_part` is 0, i.e. the maximum partition number we know
+selected. Most of the other fields are 0. This means that the current partition
+is 0, which is taken to mean the whole device, since partition numbers start at
+1. It also means that `max_part` is 0, i.e. the maximum partition number we know
 about is 0, meaning that, as far as we know, there is no partition table on this
 bootdev.
 
 about is 0, meaning that, as far as we know, there is no partition table on this
 bootdev.
 
@@ -456,6 +460,10 @@ If the `BOOTFLOWF_ALL` iterator flag is set, even errors are returned as
 incomplete bootflows, but normally an error results in moving onto the next
 iteration.
 
 incomplete bootflows, but normally an error results in moving onto the next
 iteration.
 
+Note that `bootflow_check()` handles global bootmeths explicitly, but calling
+`bootmeth_get_bootflow()` on each one. The `doing_global` flag indicates when
+the iterator is in that state.
+
 The `bootflow_scan_next()` function handles moving onto the next iteration and
 checking it. In fact it sits in a loop doing that repeatedly until it finds
 something it wants to return.
 The `bootflow_scan_next()` function handles moving onto the next iteration and
 checking it. In fact it sits in a loop doing that repeatedly until it finds
 something it wants to return.
@@ -474,9 +482,10 @@ the least-sigificant digit on the right, counting like this:
    0           0          2
    0           1          0
    0           1          1
    0           0          2
    0           1          0
    0           1          1
-   0           1          1
+   0           1          2
    1           0          0
    1           0          1
    1           0          0
    1           0          1
+   ...
    ========    =======    =======
 
 The maximum value for `method` is `num_methods - 1` so when it exceeds that, it
    ========    =======    =======
 
 The maximum value for `method` is `num_methods - 1` so when it exceeds that, it
@@ -488,6 +497,31 @@ exceeds its maximum, then the next bootdev is used. In this way, iter_incr()
 works its way through all possibilities, moving forward one each time it is
 called.
 
 works its way through all possibilities, moving forward one each time it is
 called.
 
+Note that global bootmeths introduce a subtlety into the above description.
+When `doing_global` is true, the iteration takes place only among the bootmeths,
+i.e. the last column above. The global bootmeths are at the end of the list.
+Assuming that they are entries 3 and 4 in the list, the iteration then looks
+like this:
+
+   ========    =======    =======   =======================================
+   bootdev     part       method    notes
+   ========    =======    =======   =======================================
+   .           .          3         doing_global = true, method_count = 5
+   .           .          4
+   0           0          0         doing_global = false, method_count = 3
+   0           0          1
+   0           0          2
+   0           1          0
+   0           1          1
+   0           1          2
+   1           0          0
+   1           0          1
+   ...
+   ========    =======    =======   =======================================
+
+The changeover of the value of `doing_global` from true to false is handled in
+`iter_incr()` as well.
+
 There is no expectation that iteration will actually finish. Quite often a
 valid bootflow is found early on. With `bootflow scan -b`, that causes the
 bootflow to be immediately booted. Assuming it is successful, the iteration never
 There is no expectation that iteration will actually finish. Quite often a
 valid bootflow is found early on. With `bootflow scan -b`, that causes the
 bootflow to be immediately booted. Assuming it is successful, the iteration never
@@ -517,17 +551,19 @@ method `bootdev_get_bootflow()` to ask the bootdev to return a bootflow. It
 passes the iterator to the bootdev method, so that function knows what we are
 talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`,
 with just the `method` and `dev` intiialised. But the bootdev may fill in more,
 passes the iterator to the bootdev method, so that function knows what we are
 talking about. At first, the bootflow is set up in the state `BOOTFLOWST_BASE`,
 with just the `method` and `dev` intiialised. But the bootdev may fill in more,
-e.g. updating the state, depending on what it finds.
+e.g. updating the state, depending on what it finds. For global bootmeths the
+`bootmeth_get_bootflow()` function is called instead of
+`bootdev_get_bootflow()`.
 
 
-Based on what the bootdev responds with, `bootflow_check()` either
+Based on what the bootdev or bootmeth responds with, `bootflow_check()` either
 returns a valid bootflow, or a partial one with an error. A partial bootflow
 is one that has some fields set up, but did not reach the `BOOTFLOWST_READY`
 state. As noted before, if the `BOOTFLOWF_ALL` iterator flag is set, then all
 bootflows are returned, even partial ones. This can help with debugging.
 
 So at this point you can see that total control over whether a bootflow can
 returns a valid bootflow, or a partial one with an error. A partial bootflow
 is one that has some fields set up, but did not reach the `BOOTFLOWST_READY`
 state. As noted before, if the `BOOTFLOWF_ALL` iterator flag is set, then all
 bootflows are returned, even partial ones. This can help with debugging.
 
 So at this point you can see that total control over whether a bootflow can
-be generated from a particular iteration, or not, rests with the bootdev.
-Each one can adopt its own approach.
+be generated from a particular iteration, or not, rests with the bootdev (or
+global bootmeth). Each one can adopt its own approach.
 
 Going down a level, what does the bootdev do in its `get_bootflow()` method?
 Let us consider the MMC bootdev. In that case the call to
 
 Going down a level, what does the bootdev do in its `get_bootflow()` method?
 Let us consider the MMC bootdev. In that case the call to
index 9fc7ebf..29d8215 100644 (file)
@@ -31,7 +31,9 @@ scanning bootdevs, each bootmeth is tried in turn to see if it can find a valid
 bootflow. You can use this command to adjust the order or even to omit some
 boomeths.
 
 bootflow. You can use this command to adjust the order or even to omit some
 boomeths.
 
-The argument is a quoted list of bootmeths to use, by name.
+The argument is a quoted list of bootmeths to use, by name. If global bootmeths
+are included, they must be at the end, otherwise the scanning mechanism will not
+work correctly.
 
 
 bootmeth list
 
 
 bootmeth list
@@ -47,14 +49,15 @@ Order  Seq  Name                Description
     1    1  efi                 EFI boot from an .efi file
     2    2  pxe                 PXE boot from a network device
     3    3  sandbox             Sandbox boot for testing
     1    1  efi                 EFI boot from an .efi file
     2    2  pxe                 PXE boot from a network device
     3    3  sandbox             Sandbox boot for testing
   4    4  efi_mgr             EFI bootmgr flow
glob    4  efi_mgr             EFI bootmgr flow
 =====  ===  ==================  =================================
 
 The fields are as follows:
 
 Order:
     The order in which these bootmeths are invoked for each bootdev. If this
 =====  ===  ==================  =================================
 
 The fields are as follows:
 
 Order:
     The order in which these bootmeths are invoked for each bootdev. If this
-    shows as a hyphen, then the bootmeth is not in the current ordering.
+    shows as a hyphen, then the bootmeth is not in the current ordering. If it
+    shows as 'glob', then this is a global bootmeth and should be at the end.
 
 Seq:
     The sequence number of the bootmeth, i.e. the normal ordering if none is set
 
 Seq:
     The sequence number of the bootmeth, i.e. the normal ordering if none is set