From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CC887C433EF for ; Sat, 23 Oct 2021 23:33:57 +0000 (UTC) Received: from phobos.denx.de (phobos.denx.de [85.214.62.61]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 26DB060EB2 for ; Sat, 23 Oct 2021 23:33:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.1 mail.kernel.org 26DB060EB2 Authentication-Results: mail.kernel.org; dmarc=fail (p=none dis=none) header.from=chromium.org Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=lists.denx.de Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 05387835A1; Sun, 24 Oct 2021 01:32:00 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.b="MN5QSEjh"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 0D5A783521; Sun, 24 Oct 2021 01:28:52 +0200 (CEST) Received: from mail-ot1-x335.google.com (mail-ot1-x335.google.com [IPv6:2607:f8b0:4864:20::335]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id 395B883564 for ; Sun, 24 Oct 2021 01:27:32 +0200 (CEST) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=chromium.org Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=sjg@chromium.org Received: by mail-ot1-x335.google.com with SMTP id d21-20020a9d4f15000000b0054e677e0ac5so9263160otl.11 for ; Sat, 23 Oct 2021 16:27:32 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=chromium.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=SsXZrOnRMARjD2NDBpnvvaFgNL49E+ypASk9agz9UHE=; b=MN5QSEjh79Qq2EupitYwX9cGzQWFNVMHYUZ05wEah1FWXHbBiS9TfJG2CmLaZKJsBY gPUJxAlafemUpoBc4A1FDwlhS5ycT3z3IaE0Ip2zgVLLtSquzVLFxbzpProSxDdRkoWo EMwoi9LZbyPWYEdIvzicZ4W9in3HB+rAFlr4k= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=SsXZrOnRMARjD2NDBpnvvaFgNL49E+ypASk9agz9UHE=; b=49SovQjV5dwhy0OhFUIcIN3jkpC6cpV+IRRTxuTrDrUgzqnEef/5zwUZEQkprY7x34 GGxZWr1G5PbDoFUNQphr1ZZ2RqMZyl+IYicY373c9iRjaTQdbRgX0YkpoIttLGi1nfny c8YRb5a4XkuhkzDYjw71/FcLd46rgLpdQATG6v03Y/s6rThRUB2Y6k9q9kfM2pcqsZS5 mn1d8c8tjgPgQIurCwXhGFuXINEm/3Jg8L0J+LbXsaybmwbnXGpz5CXH8IZPOYWNQgDE SwH+1Vx63xIPs5JsODaCW2qiSCKaS/G/Nm787/wmMpNny+628RS9U0nszsdI+MvbWmd+ dGNg== X-Gm-Message-State: AOAM530t+n7zDFHdixpr9OefzKzl7xCap4J/PBHoBFqzDV4gPyQiQYmf rvnDRMJPurZFd25eEX9ZXG0wcSNFzvxH+g== X-Google-Smtp-Source: ABdhPJxNW2qNX3Lhh71fCzMYu9cpEV7mBTHxydJaU8+ok6PdeQuggt9TDQk4d0Hcp8t+udXc4MAX0Q== X-Received: by 2002:a9d:7253:: with SMTP id a19mr6827903otk.315.1635031649429; Sat, 23 Oct 2021 16:27:29 -0700 (PDT) Received: from kiwi.bld.corp.google.com (c-67-190-101-114.hsd1.co.comcast.net. [67.190.101.114]) by smtp.gmail.com with ESMTPSA id l24sm2253885oop.4.2021.10.23.16.27.28 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 23 Oct 2021 16:27:29 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Michal Simek , Heinrich Schuchardt , Tom Rini , Ilias Apalodimas , Daniel Schwierzeck , Steffen Jaeckel , =?UTF-8?q?Marek=20Beh=C3=BAn?= , Lukas Auer , Dennis Gilmore , Simon Glass Subject: [PATCH v2 40/41] bootstd: doc: Add documentation Date: Sat, 23 Oct 2021 17:26:34 -0600 Message-Id: <20211023172618.v2.40.Iba98b6212bfe50abe5af3b81f3bbcf833923928c@changeid> X-Mailer: git-send-email 2.33.0.1079.g6e70778dc9-goog In-Reply-To: <20211023232635.9195-1-sjg@chromium.org> References: <20211023232635.9195-1-sjg@chromium.org> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.34 Precedence: list List-Id: U-Boot discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: u-boot-bounces@lists.denx.de Sender: "U-Boot" X-Virus-Scanned: clamav-milter 0.103.2 at phobos.denx.de X-Virus-Status: Clean Add documentation for this feature, including the commands and full devicetree bindings. Signed-off-by: Simon Glass --- (no changes since v1) MAINTAINERS | 4 + doc/develop/bootstd.rst | 600 ++++++++++++++++++++++++++ doc/develop/distro.rst | 3 + doc/develop/index.rst | 1 + doc/device-tree-bindings/bootdev.txt | 18 + doc/device-tree-bindings/bootmeth.txt | 31 ++ doc/device-tree-bindings/bootstd.txt | 8 + doc/usage/bootdev.rst | 135 ++++++ doc/usage/bootflow.rst | 427 ++++++++++++++++++ doc/usage/bootmeth.rst | 106 +++++ doc/usage/index.rst | 3 + 11 files changed, 1336 insertions(+) create mode 100644 doc/develop/bootstd.rst create mode 100644 doc/device-tree-bindings/bootmeth.txt create mode 100644 doc/usage/bootdev.rst create mode 100644 doc/usage/bootflow.rst create mode 100644 doc/usage/bootmeth.rst diff --git a/MAINTAINERS b/MAINTAINERS index 886802c81a4..f2964ec2eb0 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -642,6 +642,10 @@ F: boot/bootmeth*.c F: boot/bootstd.c F: cmd/bootdev.c F: cmd/bootflow.c +F: doc/develop/bootstd.rst +F: doc/usage/bootdev.rst +F: doc/usage/bootflow.rst +F: doc/usage/bootmeth.rst F: drivers/mmc/mmc_bootdev.c F: include/bootdev.h F: include/bootflow.h diff --git a/doc/develop/bootstd.rst b/doc/develop/bootstd.rst new file mode 100644 index 00000000000..8b27549601a --- /dev/null +++ b/doc/develop/bootstd.rst @@ -0,0 +1,600 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +U-Boot Standard Boot +==================== + +Introduction +------------ + +Standard boot provides a built-in way for U-Boot to automatically boot +an Operating System without custom scripting and other customisation. It +introduces the following concepts: + + - bootdev - a device which can hold or access a distro (e.g. MMC, Ethernet) + - bootmeth - a method to scan a bootdev to find bootflows (e.g. distro boot) + - bootflow - a description of how to boot (provided by the distro) + +For Linux, the distro (Linux distribution, e.g. Debian, Fedora) is responsible +for creating a bootflow for each kernel combination that it wants to offer. +These bootflows are stored on media so they can be discovered by U-Boot. This +feature is typically called `distro boot` (see :doc:`distro`) because it is +a way for distributions to boot on any hardware. + +Traditionally U-Boot has relied on scripts to implement this feature. See +disto_boodcmd_ for details. This is done because U-Boot has no native support +for scanning devices. While the scripts work remarkably well, they can be hard +to understand and extend, and the feature does not include tests. They are also +making it difficult to move away from ad-hoc CONFIGs, since they are implemented +using the environment and a lot of #defines. + +Standard boot is a generalisation of distro boot. It provides a more built-in +way to boot with U-Boot. The feature is extensible to different Operating +Systems (such as Chromium OS) and devices (beyond just block and network +devices). It supports EFI boot and EFI bootmgr too. + + +Bootflow +-------- + +A bootflow is a file that describes how to boot a distro. Conceptually there can +be different formats for that file but at present U-Boot only supports the +BootLoaderSpec_ format. which looks something like this:: + + menu autoboot Welcome to Fedora-Workstation-armhfp-31-1.9. Automatic boot in # second{,s}. Press a key for options. + menu title Fedora-Workstation-armhfp-31-1.9 Boot Options. + menu hidden + + label Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + kernel /vmlinuz-5.3.7-301.fc31.armv7hl + append ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + fdtdir /dtb-5.3.7-301.fc31.armv7hl/ + initrd /initramfs-5.3.7-301.fc31.armv7hl.img + +As you can see it specifies a kernel, a ramdisk (initrd) and a directory from +which to load devicetree files. The details are described in disto_boodcmd_. + +The bootflow is provided by the distro. It is not part of U-Boot. U-Boot's job +is simply to interpret the file and carry out the instructions. This allows +distros to boot on essentially any device supported by U-Boot. + +Typically the first available bootflow is selected and booted. If that fails, +then the next one is tried. + + +Bootdev +------- + +Where does U-Boot find the media that holds the operating systems? That is the +job of bootdev. A bootdev is simply a layer on top of a media device (such as +MMC, NVMe). The bootdev accesses the device, including partitions and +filesystems that might contain things related to an operating system. + +For example, an MMC bootdev provides access to the individual partitions on the +MMC device. It scans through these to find filesystems, then provides a list of +these for consideration. + + +Bootmeth +-------- + +Once the list of filesystems is provided, how does U-Boot find the bootflow +files in these filesystems. That is the job of bootmeth. Each boot method has +its own way of doing this. + +For example, the distro bootmeth simply looks through the provided filesystem +for a file called `extlinux/extlinux.conf`. This files constitutes a bootflow. +If the distro bootmeth is used on multiple partitions it may produce multiple +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. + + +Boot process +------------ + +U-Boot tries to use the 'lazy init' approach whereever possible and distro boot +is no exception. The algorithm is:: + + while (get next bootdev) + while (get next bootmeth) + while (get next bootflow) + try to boot it + +So U-Boot works its way through the bootdevs, trying each bootmeth in turn to +obtain bootflows, until it either boots or exhausts the available options. + +Instead of 500 lines of #defines and a 4KB boot script, all that is needed is +the following command:: + + bootflow scan -lb + +which scans for available bootflows, optionally listing each find it finds (-l) +and trying to boot it (-b). + + +Bootdev uclass +-------------- + +The bootdev uclass provides an simple API call to obtain a bootflows from a +device:: + + int bootdev_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow); + +This takes a iterator which indicates the bootdev, partition and bootmeth to +use. It returns a bootflow. This is the core of the bootdev implementation. The +bootdev drivers that implement this differ depending on the media they are +reading from, but each is responsible for returning a valid bootflow if +available. + +A helper called `bootdev_find_in_blk()` makes it fairly easy to implement this +function for each media device uclass, in a few lines of code. + + +Bootdev drivers +--------------- + +A bootdev driver is typically fairly simple. Here is one for mmc:: + + static int mmc_get_bootflow(struct udevice *dev, struct bootflow_iter *iter, + struct bootflow *bflow) + { + struct udevice *mmc_dev = dev_get_parent(dev); + struct udevice *blk; + int ret; + + ret = mmc_get_blk(mmc_dev, &blk); + /* + * If there is no media, indicate that no more partitions should be + * checked + */ + if (ret == -EOPNOTSUPP) + ret = -ESHUTDOWN; + if (ret) + return log_msg_ret("blk", ret); + assert(blk); + ret = bootdev_find_in_blk(dev, blk, iter, bflow); + if (ret) + return log_msg_ret("find", ret); + + return 0; + } + + static int mmc_bootdev_bind(struct udevice *dev) + { + struct bootdev_uc_plat *ucp = dev_get_uclass_plat(dev); + + ucp->prio = BOOTDEVP_0_INTERNAL_FAST; + + return 0; + } + + struct bootdev_ops mmc_bootdev_ops = { + .get_bootflow = mmc_get_bootflow, + }; + + static const struct udevice_id mmc_bootdev_ids[] = { + { .compatible = "u-boot,bootdev-mmc" }, + { } + }; + + U_BOOT_DRIVER(mmc_bootdev) = { + .name = "mmc_bootdev", + .id = UCLASS_BOOTDEV, + .ops = &mmc_bootdev_ops, + .bind = mmc_bootdev_bind, + .of_match = mmc_bootdev_ids, + }; + +The implementation of the `get_bootflow()` method is simply to obtain the +block device and call a bootdev helper function to do the rest. The +implementation of `bootdev_find_in_blk()` checks the partition table, and +attempts to read a file from a filesystem on the partition number given by the +`@iter->part` parameter. + +Each bootdev has a priority, which indicates the order in which it is used. +Faster bootdevs are used first, since they are more likely to be able to boot +the device quickly. + + +Device hierarchy +---------------- + +A bootdev device is a child of the media device. In this example, you can see +that the bootdev is a sibling of the block device and both are children of +media device:: + + mmc 0 [ + ] bcm2835-sdhost | |-- mmc@7e202000 + blk 0 [ + ] mmc_blk | | |-- mmc@7e202000.blk + bootdev 0 [ ] mmc_bootdev | | `-- mmc@7e202000.bootdev + mmc 1 [ + ] sdhci-bcm2835 | |-- sdhci@7e300000 + blk 1 [ ] mmc_blk | | |-- sdhci@7e300000.blk + bootdev 1 [ ] mmc_bootdev | | `-- sdhci@7e300000.bootdev + +The bootdev device is typically created automatically in the media uclass' +`post_bind()` method by calling `bootdev_setup_for_dev()`. The code typically +something like this:: + + ret = bootdev_setup_for_dev(dev, "eth_bootdev"); + if (ret) + return log_msg_ret("bootdev", ret); + +Here, `eth_bootdev` is the name of the Ethernet bootdev driver and `dev` +is the ethernet device. This function is safe to call even if standard boot is +not enabled, since it does nothing in that case. It can be added to all uclasses +which implement suitable media. + + +The bootstd device +------------------ + +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()`. + +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. + + +.. _`Automatic Devices`: + +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 +are found at all, it creates one for each available bootmeth driver as well as a +system bootdev. + +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. + + +Using devicetree +---------------- + +If a bootdev is complicated or needs configuration information, it can be +added to the devicetree as a child of the media device. For example, imagine a +bootdev which reads a bootflow from SPI flash. The devicetree fragment might +look like this:: + + spi@0 { + flash@0 { + reg = <0>; + compatible = "spansion,m25p16", "jedec,spi-nor"; + spi-max-frequency = <40000000>; + + bootdev { + compatible = "u-boot,sf-bootdev"; + offset = <0x2000>; + size = <0x1000>; + }; + }; + }; + +The `sf-bootdev` driver can implement a way to read from the SPI flash, using +the offset and size provided, and return that bootflow file back to the caller. +When distro boot wants to read the kernel it calls disto_getfile() which must +provide a way to read from the SPI flash. See `distro_boot()` at distro_boot_ +for more details. + +Of course this is all internal to U-Boot. All the distro sees is another way +to boot. + + +Configuration +------------- + +Standard boot is enabled with `CONFIG_BOOTSTD`. Each bootmeth has its own CONFIG +option also. For example, `CONFIG_BOOTMETH_DISTRO` enables support for distro +boot from a disk. + + +Available bootmeth drivers +-------------------------- + +Bootmeth drivers are provided for: + + - distro boot from a disk (syslinux) + - distro boot from a network (PXE) + - EFI boot using bootefi + - EFI boot using boot manager + + +Command interface +----------------- + +Three commands are available: + +`bootdev` + Allows listing of available bootdevs, selecting a particular one and + getting information about it. See :doc:`../usage/bootdev` + +`bootflow` + Allows scanning one or more bootdevs for bootflows, listing available + bootflows, selecting one, obtaining information about it and booting it. + See :doc:`../usage/bootflow` + +`bootmeth` + Allow listing of available bootmethds and setting the order in which they + are tried. See :doc:`../usage/bootmeth` + +.. _BootflowStates: + +Bootflow states +--------------- + +Here is a list of states that a bootflow can be in: + +======= ======================================================================= +State Meaning +======= ======================================================================= +base Starting-out state, indicates that no media/partition was found. For an + SD card socket it may indicate that the card is not inserted. +media Media was found (e.g. SD card is inserted) but no partition information + was found. It might lack a partition table or have a read error. +part Partition was found but a filesystem could not be read. This could be + because the partition does not hold a filesystem or the filesystem is + very corrupted. +fs Filesystem was found but the file could not be read. It could be + missing or in the wrong subdirectory. +file File was found and its size detected, but it could not be read. This + could indicate filesystem corruption. +ready File was loaded and is ready for use. In this state the bootflow is + ready to be booted. +======= ======================================================================= + + +Theory of operation +------------------- + +This describes how standard boot progresses through to booting an operating +system. + +To start. all the necessary devices must be bound, including bootstd, which +provides the top-level `struct bootstd_priv` containing optional configuration +information. The bootstd device is also holds the various lists used while +scanning. This step is normally handled automatically by driver model, as +described in `Automatic Devices`_. + +Bootdevs are also required, to provide access to the media to use. These are not +useful by themselves: bootmeths are needed to provide the means of scanning +those bootdevs. So, all up, we need a single bootstd device, one or more bootdev +devices and one or more bootmeth devices. + +Once these are ready, typically a `bootflow scan` command is issued. This kicks +of the iteration process, which involves looking through the bootdevs and their +partitions one by one to find bootflows. + +Iteration is kicked off using `bootflow_scan_first()`, which calls +`bootflow_scan_bootdev()`. + +The iterator is set up with `bootflow_iter_init()`. This simply creates an +empty one with the given flags. Flags are used to control whether each +iteration is displayed, whether to return iterations even if they did not result +in a valid bootflow, whether to iterate through just a single bootdev, etc. + +Then the ordering of bootdevs is determined, by `setup_bootdev_order()`. By +default, the bootdevs are used in their sequence order, as determined by the +`/aliases` node, or failing that their order in the devicetree. But if there is +a `bootdev-order` property in the bootstd node, then this is used instead. In +any 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. + +Next, the ordering of bootdevs is determined, by `setup_bootmeth_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 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. + +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 +about is 0, meaning that, as far as we know, there is no partition table on this +bootdev. + +With the iterator ready, `bootflow_scan_bootdev()` checks whether the current +settings produce a valid bootflow. This is handled by `bootflow_check()`, which +either returns 0 (if it got something) or an error if not (more on that later). +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. + +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 actual 'moving on' part is implemented in `iter_incr()`. This is a very +simple function. It increments the first counter. If that hits its maximum, it +sets it to zero and increments the second counter. You can think of all the +counters together as a number with three digits which increment in order, with +the least-sigificant digit on the right, counting like this: + + ======== ======= ======= + bootdev part method + ======== ======= ======= + 0 0 0 + 0 0 1 + 0 0 2 + 0 1 0 + 0 1 1 + 0 1 1 + 1 0 0 + 1 0 1 + ======== ======= ======= + +The maximum value for `method` is `num_methods - 1` so when it exceeds that, it +goes back to 0 and the next `part` is considered. The maximum value for that is +`max_part`, which is initially zero for all bootdevs. If we find a partition +table on that bootdev, `max_part` can be updated during the iteration to a +higher value - see `bootdev_find_in_blk()` for that, described later. If that +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. + +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 +completes. + +Also note that the iterator hold the **current** combination being considered. +So when `iter_incr()` is called, it increments to the next one and returns it, +the new **current** combination. + +Note also the `err` field in `struct bootflow_iter`. This is normally 0 and has +thus has no effect on `iter_inc()`. But if it is non-zero, signalling an error, +it indicates to the iterator what it should do when called. It can force moving +to the next partition, or bootdev, for example. The special values +`BF_NO_MORE_PARTS` and `BF_NO_MORE_DEVICES` handle this. When `iter_incr` sees +`BF_NO_MORE_PARTS` it knows that it should immediately move to the next bootdev. +When it sees `BF_NO_MORE_DEVICES` it knows that there is nothing more it can do +so it should immediately return. The caller of `iter_incr()` is responsible for +updating the `err` field, based on the return value it sees. + +The above describes the iteration process at a high level. It is basically a +very simple increment function with a checker called `bootflow_check()` that +checks the result of each iteration generated, to determine whether it can +produce a bootflow. + +So what happens inside of `bootflow_check()`? It simply calls the uclass +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, +e.g. updating the state, depending on what it finds. + +Based on what the bootdev 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 +be generated from a particular iteration, or not, rests with the bootdev. +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 +`bootdev_get_bootflow()` ends up in `mmc_get_bootflow()`. It locates the parent +device of the bootdev, i.e. the `UCLASS_MMC` device itself, then finds the block +device associated with it. It then calls the helper function +`bootdev_find_in_blk()` to do all the work. This is common with just about any +bootdev that is based on a media device. + +The `bootdev_find_in_blk()` helper is implemented in the bootdev uclass. It +names the bootflow and copies the partition number in from the iterator. Then it +calls the bootmeth device to check if it can support this device. This is +important since some bootmeths only work with network devices, for example. If +that check fails, it stops. + +Assuming the bootmeth is happy, or at least indicates that it is willing to try +(by returning 0 from its `check()` method), the next step is to try the +partition. If that works it tries to detect a file system. If that works then it +calls the bootmeth device once more, this time to read the bootflow. + +Note: At present a filesystem is needed for the bootmeth to be called on block +devices, simply because we don't have any examples where this is not the case. +This feature can be added as needed. + +If we take the example of the `bootmeth_distro` driver, this call ends up at +`distro_read_bootflow()`. It has the filesystem ready, so tries various +filenames to try to find the `extlinux.conf` file, reading it if possible. If +all goes well the bootflow ends up in the `BOOTFLOWST_READY` state. + +At this point, we fall back from the bootmeth driver, to +`bootdev_find_in_blk()`, then back to `mmc_get_bootflow()`, then to +`bootdev_get_bootflow()`, then to `bootflow_check()` and finally to its caller, +either `bootflow_scan_bootdev()` or `bootflow_scan_next()`. In either case, +the bootflow is returned as the result of this iteration, assuming it made it to +the `BOOTFLOWST_READY` state. + +That is the basic operation of scanning for bootflows. The process of booting a +bootflow is handled by the bootmeth driver for that bootflow. In the case of +distro boot, this parses and processes the `extlinux.conf` file that was read. +See `distro_boot()` for how that works. The processing may involve reading +additional files, which is handled by the `read_file()` method, which is +`distro_read_file()` in this case. All bootmethds should support reading files, +since the bootflow is typically only the basic instructions and does not include +the operating system itself, ramdisk, device tree, etc. + +The vast majority of the bootstd code is concerned with iterating through +partitions on bootdevs and using bootmethds to find bootflows. + +How about bootdevs which are not block devices? They are handled by the same +methods as above, but with a different implementation. For example, the bootmeth +for PXE boot (over a network) uses `tftp` to read files rather than `fs_read()`. +But other that that it is very similar. + + +Tests +----- + +Tests are located in `test/boot` and cover the core functionality as well as +the commands. All tests use sandbox so can be run on a standard Linux computer +and in U-Boot's CI. + +For testing, a DOS-formatted disk image is used with a single FAT partition on +it. This is created in `setup_bootflow_image()`, with a canned one from the +source tree used if it cannot be created (e.g. in CI). + + +Bootflow internals +------------------ + +The bootstd device holds a linked list of scanned bootflows as well as the +currently selected bootdev and bootflow (for use by commands). This is in +`struct bootstd_priv`. + +Each bootdev device has its own `struct bootdev_uc_plat` which holds a +list of scanned bootflows just for that device. + +The bootflow itself is documented in bootflow_h_. It includes various bits of +information about the bootflow and a buffer to hold the file. + + +Future +------ + +Apart from the to-do items below, different types of bootflow files may be +implemented in future, e.g. Chromium OS support which is currently only +available as a script in chromebook_coral. + + +To do +----- + +Some things that need to be done to completely replace the distro-boot scripts: + +- add bootdev drivers for dhcp, sata, scsi, ide, virtio +- PXE boot for EFI +- support for loading U-Boot scripts + +Other ideas: + +- `bootflow prep` to load everything preparing for boot, so that `bootflow boot` + can just do the boot. +- automatically load kernel, FDT, etc. to suitable addresses so the board does + not need to specify things like `pxefile_addr_r` + + +.. _disto_boodcmd: https://github.com/u-boot/u-boot/blob/master/include/config_distro_bootcmd.h +.. _BootLoaderSpec: http://www.freedesktop.org/wiki/Specifications/BootLoaderSpec/ +.. _distro_boot: https://github.com/u-boot/u-boot/blob/master/boot/distro.c +.. _bootflow_h: https://github.com/u-boot/u-boot/blob/master/include/bootflow.h diff --git a/doc/develop/distro.rst b/doc/develop/distro.rst index c522be69349..7ea84b5793c 100644 --- a/doc/develop/distro.rst +++ b/doc/develop/distro.rst @@ -157,6 +157,9 @@ a line with "CONFIG_DISTRO_DEFAULTS=y". If you want to enable this from Kconfig itself, for e.g. all boards using a specific SoC then add a "imply DISTRO_DEFAULTS" to your SoC CONFIG option. + +TO BE UPDATED: + In your board configuration file, include the following:: #ifndef CONFIG_SPL_BUILD diff --git a/doc/develop/index.rst b/doc/develop/index.rst index b3871b16f35..dbd66b68870 100644 --- a/doc/develop/index.rst +++ b/doc/develop/index.rst @@ -10,6 +10,7 @@ Implementation :maxdepth: 1 bloblist + bootstd ci_testing commands config_binding diff --git a/doc/device-tree-bindings/bootdev.txt b/doc/device-tree-bindings/bootdev.txt index 95b7fec8212..4bb2345a0b9 100644 --- a/doc/device-tree-bindings/bootdev.txt +++ b/doc/device-tree-bindings/bootdev.txt @@ -6,3 +6,21 @@ child of the media device (UCLASS_MMC, UCLASS_SPI_FLASH, etc.) The bootdev driver is provided by the media devices. The bindings for each are described in this file (to come). + +Required properties: + +compatible: + "u-boot,bootdev-eth" - Ethernet bootdev + "u-boot,bootdev-mmc" - MMC bootdev + "u-boot,bootdev-usb" - USB bootdev + + +Example: + + mmc1 { + compatible = "sandbox,mmc"; + + mmc-bootdev { + compatible = "u-boot,bootdev-eth"; + }; + }; diff --git a/doc/device-tree-bindings/bootmeth.txt b/doc/device-tree-bindings/bootmeth.txt new file mode 100644 index 00000000000..cba2dbe871c --- /dev/null +++ b/doc/device-tree-bindings/bootmeth.txt @@ -0,0 +1,31 @@ +U-Boot standard boot methods (bootmeth) +====================================== + +This provides methods (called bootmeths) for locating bootflows on a boot +device (bootdev). These are normally created as children of the bootstd device. + +Required properties: + +compatible: + "u-boot,distro-syslinux" - distro boot from a block device + "u-boot,distro-pxe" - distro boot from a network device + "u-boot,distro-efi" - EFI boot from a .efi file + "u-boot,efi-bootmgr" - EFI boot using boot manager (bootmgr) + + +Example: + + bootstd { + compatible = "u-boot,boot-std"; + + filename-prefixes = "/", "/boot/"; + bootdev-order = "mmc2", "mmc1"; + + syslinux { + compatible = "u-boot,distro-syslinux"; + }; + + efi { + compatible = "u-boot,distro-efi"; + }; + }; diff --git a/doc/device-tree-bindings/bootstd.txt b/doc/device-tree-bindings/bootstd.txt index f048b9dd327..8706c5f4993 100644 --- a/doc/device-tree-bindings/bootstd.txt +++ b/doc/device-tree-bindings/bootstd.txt @@ -25,4 +25,12 @@ Example: filename-prefixes = "/", "/boot/"; bootdev-order = "mmc2", "mmc1"; + + syslinux { + compatible = "u-boot,distro-syslinux"; + }; + + efi { + compatible = "u-boot,distro-efi"; + }; }; diff --git a/doc/usage/bootdev.rst b/doc/usage/bootdev.rst new file mode 100644 index 00000000000..ca5671e6f74 --- /dev/null +++ b/doc/usage/bootdev.rst @@ -0,0 +1,135 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +bootdev command +=============== + +Synopis +------- + +:: + + bootdev list [-p] - list all available bootdevs (-p to probe)\n" + bootdev select - select a bootdev by name\n" + bootdev info [-p] - show information about a bootdev"; + +Description +----------- + +The `bootdev` command is used to manage bootdevs. It can list available +bootdevs, select one and obtain information about it. + +See :doc:`../develop/bootstd` for more information about bootdevs in general. + + +bootdev list +~~~~~~~~~~~~ + +This lists available bootdevs + +Scanning with `-p` causes the bootdevs to be probed. This happens automatically +when they are used. + +The list looks something like this: + +=== ====== ====== ======== ========================= +Seq Probed Status Uclass Name +=== ====== ====== ======== ========================= + 0 [ + ] OK mmc mmc@7e202000.bootdev + 1 [ ] OK mmc sdhci@7e300000.bootdev + 2 [ ] OK ethernet smsc95xx_eth.bootdev +=== ====== ====== ======== ========================= + + +The fields are as follows: + +Seq: + Sequence number in the scan, used to reference the bootflow later + +Probed: + Shows a plus (+) if the device is probed, empty if not. + +Status: + Shows the status of the device. Typically this is `OK` meaning that there is + no error. If you use -p and an error occurs when probing, then this shows + the error number. You can look up Linux error codes to find the meaning of + the number. + +Uclass: + Name of the media device's Uclass. This indicates the type of the parent + device (e.g. MMC, Ethernet). + +Name: + Name of the bootdev. This is generated from the media device appended + with `.bootdev` + + +bootdev select +~~~~~~~~~~~~~~~~~ + +Use this to select a particular bootdev. You can select it by the sequence +number or name, as shown in `bootdev list`. + +Once a bootdev is selected, you can use `bootdev info` to look at it or +`bootflow scan` to scan it. + +If no bootdev name or number is provided, then any existing bootdev is +unselected. + + +bootdev info +~~~~~~~~~~~~~~~ + +This shows information on the current bootdev, with the format looking like +this: + +========= ======================= +Name mmc@7e202000.bootdev +Sequence 0 +Status Probed +Uclass mmc +Bootflows 1 (1 valid) +========= ======================= + +Most of the information is the same as `bootdev list` above. The new fields +are: + +Device + Name of the bootdev + +Status + Shows `Probed` if the device is probed, `OK` if not. If `-p` is used and the + device fails to probe, an error code is shown. + +Bootflows + Indicates the number of bootflows attached to the bootdev. This is 0 + unless you have used 'bootflow scan' on the bootflow, or on all bootflows. + + +Example +------- + +This example shows listing available bootdev and getting information about +one of them:: + + U-Boot> bootdev list + Seq Probed Status Uclass Name + --- ------ ------ -------- ------------------ + 0 [ + ] OK mmc mmc@7e202000.bootdev + 1 [ ] OK mmc sdhci@7e300000.bootdev + 2 [ ] OK ethernet smsc95xx_eth.bootdev + --- ------ ------ -------- ------------------ + (3 devices) + U-Boot> bootdev sel 0 + U-Boot> bootflow scan + U-Boot> bootdev info + Name: mmc@7e202000.bootdev + Sequence: 0 + Status: Probed + Uclass: mmc + Bootflows: 1 (1 valid) + + +Return value +------------ + +The return value $? is always 0 (true). diff --git a/doc/usage/bootflow.rst b/doc/usage/bootflow.rst new file mode 100644 index 00000000000..347cc181bc5 --- /dev/null +++ b/doc/usage/bootflow.rst @@ -0,0 +1,427 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +bootflow command +================ + +Synopis +------- + +:: + + bootflow scan [-abel] [bootdev] + bootflow list [-e] + bootflow select [] + bootflow info [-d] + bootflow boot + + +Description +----------- + +The `bootflow` command is used to manage bootflows. It can scan bootdevs to +locate bootflows, list them and boot them. + +See :doc:`../develop/bootstd` for more information. + + +bootflow scan +~~~~~~~~~~~~~ + +Scans for available bootflows, optionally booting the first valid one it finds. +This operates in two modes: + +- If no bootdev is selected (see `bootdev select`) it scans bootflows one + by one, extracting all the bootdevs from each +- If a bootdev is selected, it just scans that one bootflow + +Flags are: + +-a + Collect all bootflows, even those that cannot be loaded. Normally if a file + is not where it is expected, then the bootflow fails and so is dropped + during the scan. With this option you can see why each bootflow would be + dropped. + +-b + Boot each valid bootflow as it is scanned. Typically only the first bootflow + matters, since by then the system boots in the OS and U-Boot is no-longer + running. `bootflow scan -b` is a quick way to boot the first available OS. + A valid bootflow is one that made it all the way to the `loaded` state. + +-e + Used with -l to also show errors for each bootflow. The shows detailed error + information for each bootflow that failed to make it to the `loaded` state. + +-l + List bootflows while scanning. This is helpful when you want to see what + is happening during scanning. Use it with the `-b` flag to see which + bootdev and bootflows are being tried. + +The optional argument specifies a particular bootdev to scan. This can either be +the name of a bootdev or its sequence number (both shown with `bootdev list`). +Alternatively a convenience label can be used, like `mmc0`, which is the type of +device and an optional sequence number. Specifically, the label is the uclass of +the bootdev's parent followed by the sequence number of that parent. Sequence +numbers are typically set by aliases, so if you have 'mmc0' in your devicetree +alias section, then `mmc0` refers to the bootdev attached to that device. + + +bootflow list +~~~~~~~~~~~~~ + +Lists the previously scanned bootflows. You must use `bootflow scan` before this +to see anything. + +If you scanned with -a and have bootflows with errors, -e can be used to show +those errors. + +The list looks something like this: + +=== ====== ====== ======== ==== =============================== ================ +Seq Method State Uclass Part Name Filename +=== ====== ====== ======== ==== =============================== ================ + 0 distro ready mmc 2 mmc\@7e202000.bootdev.part_2 /boot/extlinux/extlinux.conf + 1 pxe ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf +=== ====== ====== ======== ==== =============================== ================ + +The fields are as follows: + +Seq: + Sequence number in the scan, used to reference the bootflow later + +Method: + The boot method (bootmeth) used to find the bootflow. Several methods are + included in U-Boot. + +State: + Current state of the bootflow, indicating how far the bootdev got in + obtaining a valid one. See :ref:`BootflowStates` for a list of states. + +Uclass: + Name of the media device's Uclass. This indicates the type of the parent + device (e.g. MMC, Ethernet). + +Part: + Partition number being accesseed, numbered from 1. Normally a device will + have a partition table with a small number of partitions. For devices + without partition tables (e.g. network) this field is 0. + +Name: + Name of the bootflow. This is generated from the bootdev appended with + the partition information + +Filename: + Name of the bootflow file. This indicates where the file is on the + filesystem or network device. + + +bootflow select +~~~~~~~~~~~~~~~ + +Use this to select a particular bootflow. You can select it by the sequence +number or name, as shown in `bootflow list`. + +Once a bootflow is selected, you can use `bootflow info` and `bootflow boot`. + +If no bootflow name or number is provided, then any existing bootflow is +unselected. + + +bootflow info +~~~~~~~~~~~~~ + +This shows information on the current bootflow, with the format looking like +this: + +========= =============================== +Name mmc\@7e202000.bootdev.part_2 +Device mmc\@7e202000.bootdev +Block dev mmc\@7e202000.blk +Type distro +Method: syslinux +State ready +Partition 2 +Subdir (none) +Filename /extlinux/extlinux.conf +Buffer 3db7ad48 +Size 232 (562 bytes) +Error 0 +========= =============================== + +Most of the information is the same as `bootflow list` above. The new fields +are: + +Device + Name of the bootdev + +Block dev + Name of the block device, if any. Network devices don't have a block device. + +Subdir + Subdirectory used for retrieving files. For network bootdevs this is the + directory of the 'bootfile' parameter passed from DHCP. All file retrievals + when booting are relative to this. + +Buffer + Buffer containing the bootflow file. You can use the :doc:`md` to look at + it, or dump it with `bootflow info -d`. + +Size + Size of the bootflow file + +Error + Error number returned from scanning for the bootflow. This is 0 if the + bootflow is in the 'loaded' state, or a negative error value on error. You + can look up Linux error codes to find the meaning of the number. + +Use the `-d` flag to dump out the contents of the bootfile file. + + +bootflow boot +~~~~~~~~~~~~~ + +This boots the current bootflow. + + +Example +------- + +Here is an example of scanning for bootflows, then listing them:: + + U-Boot> bootflow scan -l + Scanning for bootflows in all bootdevs + Seq Type State Uclass Part Name Filename + --- ----------- ------ -------- ---- ------------------------ ---------------- + Scanning bootdev 'mmc@7e202000.bootdev': + 0 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + Scanning bootdev 'sdhci@7e300000.bootdev': + Card did not respond to voltage select! : -110 + Scanning bootdev 'smsc95xx_eth.bootdev': + Waiting for Ethernet connection... done. + BOOTP broadcast 1 + DHCP client bound to address 192.168.4.30 (4 ms) + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/'. + Load address: 0x200000 + Loading: * + TFTP error: 'Is a directory' (0) + Starting again + + missing environment variable: pxeuuid + Retrieving file: rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1 + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1'. + Load address: 0x2500000 + Loading: ################################################## 566 Bytes + 45.9 KiB/s + done + Bytes transferred = 566 (236 hex) + 1 distro ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf + No more bootdevs + --- ----------- ------ -------- ---- ------------------------ ---------------- + (2 bootflows, 2 valid) + U-Boot> bootflow l + Showing all bootflows + Seq Type State Uclass Part Name Filename + --- ----------- ------ -------- ---- ------------------------ ---------------- + 0 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + 1 pxe ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf + --- ----------- ------ -------- ---- ------------------------ ---------------- + (2 bootflows, 2 valid) + + +The second one is then selected by name (we could instead use `bootflow sel 0`), +displayed and booted:: + + U-Boot> bootflow info + No bootflow selected + U-Boot> bootflow sel mmc@7e202000.bootdev.part_2 + U-Boot> bootflow info + Name: mmc@7e202000.bootdev.part_2 + Device: mmc@7e202000.bootdev + Block dev: mmc@7e202000.blk + Sequence: 1 + Method: distro + State: ready + Partition: 2 + Subdir: (none) + Filename: extlinux/extlinux.conf + Buffer: 3db7ae88 + Size: 232 (562 bytes) + Error: 0 + U-Boot> bootflow boot + ** Booting bootflow 'smsc95xx_eth.bootdev.0' + Ignoring unknown command: ui + Ignoring malformed menu command: autoboot + Ignoring malformed menu command: hidden + Ignoring unknown command: totaltimeout + 1: Fedora-Workstation-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + Retrieving file: rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img + get 2700000 rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/initramfs-5.3.7-301.fc31.armv7hl.img'. + Load address: 0x2700000 + Loading: ###################################T ############### 57.7 MiB + 1.9 MiB/s + done + Bytes transferred = 60498594 (39b22a2 hex) + Retrieving file: rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl + get 80000 rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe//vmlinuz-5.3.7-301.fc31.armv7hl'. + Load address: 0x80000 + Loading: ################################################## 7.2 MiB + 2.3 MiB/s + done + Bytes transferred = 7508480 (729200 hex) + append: ro root=UUID=9732b35b-4cd5-458b-9b91-80f7047e0b8a rhgb quiet LANG=en_US.UTF-8 cma=192MB cma=256MB + Retrieving file: rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + get 2600000 rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe//dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb'. + Load address: 0x2600000 + Loading: ################################################## 13.8 KiB + 764.6 KiB/s + done + Bytes transferred = 14102 (3716 hex) + Kernel image @ 0x080000 [ 0x000000 - 0x729200 ] + ## Flattened Device Tree blob at 02600000 + Booting using the fdt blob at 0x2600000 + Using Device Tree in place at 02600000, end 02606715 + + Starting kernel ... + + [ OK ] Started Show Plymouth Boot Screen. + [ OK ] Started Forward Password R…s to Plymouth Directory Watch. + [ OK ] Reached target Local Encrypted Volumes. + [ OK ] Reached target Paths. + .... + + +Here we scan for bootflows and boot the first one found:: + + U-Boot> bootflow scan -bl + Scanning for bootflows in all bootdevs + Seq Method State Uclass Part Name Filename + --- ----------- ------ -------- ---- ---------------------- ---------------- + Scanning bootdev 'mmc@7e202000.bootdev': + 0 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + ** Booting bootflow 'mmc@7e202000.bootdev.part_2' + Ignoring unknown command: ui + Ignoring malformed menu command: autoboot + Ignoring malformed menu command: hidden + Ignoring unknown command: totaltimeout + 1: Fedora-KDE-armhfp-31-1.9 (5.3.7-301.fc31.armv7hl) + Retrieving file: /initramfs-5.3.7-301.fc31.armv7hl.img + getfile 2700000 /initramfs-5.3.7-301.fc31.armv7hl.img + Retrieving file: /vmlinuz-5.3.7-301.fc31.armv7hl + getfile 80000 /vmlinuz-5.3.7-301.fc31.armv7hl + append: ro root=UUID=b8781f09-e2dd-4cb8-979b-7df5eeaaabea rhgb LANG=en_US.UTF-8 cma=192MB console=tty0 console=ttyS1,115200 + Retrieving file: /dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + getfile 2600000 /dtb-5.3.7-301.fc31.armv7hl/bcm2837-rpi-3-b.dtb + Kernel image @ 0x080000 [ 0x000000 - 0x729200 ] + ## Flattened Device Tree blob at 02600000 + Booting using the fdt blob at 0x2600000 + Using Device Tree in place at 02600000, end 02606715 + + Starting kernel ... + + [ 0.000000] Booting Linux on physical CPU 0x0 + + +Here is am example using the -e flag to see all errors:: + + U-Boot> bootflow scan -a + Card did not respond to voltage select! : -110 + Waiting for Ethernet connection... done. + BOOTP broadcast 1 + DHCP client bound to address 192.168.4.30 (4 ms) + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/'. + Load address: 0x200000 + Loading: * + TFTP error: 'Is a directory' (0) + Starting again + + missing environment variable: pxeuuid + Retrieving file: rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1 + Waiting for Ethernet connection... done. + Using smsc95xx_eth device + TFTP from server 192.168.4.1; our IP address is 192.168.4.30 + Filename 'rpi.pxe/pxelinux.cfg/01-b8-27-eb-a6-61-e1'. + Load address: 0x2500000 + Loading: ################################################## 566 Bytes + 49.8 KiB/s + done + Bytes transferred = 566 (236 hex) + U-Boot> bootflow l -e + Showing all bootflows + Seq Type State Uclass Part Name Filename + --- ----------- ------ -------- ---- --------------------- ---------------- + 0 distro fs mmc 1 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + ** File not found, err=-2 + 1 distro ready mmc 2 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + 2 distro fs mmc 3 mmc@7e202000.bootdev.p /extlinux/extlinux.conf + ** File not found, err=-1 + 3 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 4 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 5 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 6 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 7 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 8 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 9 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + a distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + b distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + c distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + d distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + e distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + f distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 10 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 11 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 12 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 13 distro media mmc 0 mmc@7e202000.bootdev.p + ** No partition found, err=-2 + 14 distro ready ethernet 0 smsc95xx_eth.bootdev.0 rpi.pxe/extlinux/extlinux.conf + --- ----------- ------ -------- ---- --------------------- ---------------- + (21 bootflows, 2 valid) + U-Boot> + + +Return value +------------ + +On success `bootflow boot` normally boots into the Operating System and does not +return to U-Boot. If something about the U-Boot processing fails, then the +return value $? is 1. If the boot succeeds but for some reason the Operating +System returns, then $? is 0, indicating success. + +For other subcommands, the return value $? is always 0 (true). + + +.. BootflowStates_: diff --git a/doc/usage/bootmeth.rst b/doc/usage/bootmeth.rst new file mode 100644 index 00000000000..2e6cc2a77e6 --- /dev/null +++ b/doc/usage/bootmeth.rst @@ -0,0 +1,106 @@ +.. SPDX-License-Identifier: GPL-2.0+: + +bootmeth command +================ + +Synopis +------- + +:: + + bootmeth list [-a] - list selected bootmeths (-a for all) + bootmeth order [...] - select the order of bootmeths\n" + + +Description +----------- + +The `bootmeth` command is used to manage bootmeths. It can list them and change +the order in which they are used. + +See :doc:`../develop/bootstd` for more information. + + +bootmeth order +~~~~~~~~~~~~~~ + +Selects which bootmeths to use and the order in which they are invoked. When +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. + +The arguments are a list of bootmeths to use, by name. + + +bootmeth list +~~~~~~~~~~~~~ + +This lists the selected bootmeths, or all of them, if the `-a` flag is used. +The format looks like this: + +===== === ================== ================================= +Order Seq Name Description +===== === ================== ================================= + 0 0 distro Syslinux boot from a block device + 1 1 efi EFI boot from a .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 +===== === ================== ================================= + +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. + +Seq: + The sequence number of the bootmeth, i.e. the normal ordering if none is set + +Name: + Name of the bootmeth + +Description: + A friendly description for the bootmeth + + +Example +------- + +This shows listing bootmeths. All are present and in the normal order:: + + => bootmeth list + Order Seq Name Description + ----- --- ------------------ ------------------ + 0 0 distro Syslinux boot from a block device + 1 1 efi EFI boot from a .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 + ----- --- ------------------ ------------------ + (5 bootmeths) + +Now the order is changed, to include only two of them:: + + => bootmeth order sandbox distro + => bootmeth list + Order Seq Name Description + ----- --- ------------------ ------------------ + 0 3 sandbox Sandbox boot for testing + 1 0 distro Syslinux boot from a block device + ----- --- ------------------ ------------------ + (2 bootmeths) + +The -a flag shows all bootmeths so you can clearly see which ones are used and +which are not:: + + => bootmeth list -a + Order Seq Name Description + ----- --- ------------------ ------------------ + 1 0 distro Syslinux boot from a block device + - 1 efi EFI boot from a .efi file + - 2 pxe PXE boot from a network device + 0 3 sandbox Sandbox boot for testing + - 4 efi_mgr EFI bootmgr flow + ----- --- ------------------ ------------------ + (5 bootmeths) diff --git a/doc/usage/index.rst b/doc/usage/index.rst index 356f2a56181..6e96504142c 100644 --- a/doc/usage/index.rst +++ b/doc/usage/index.rst @@ -20,9 +20,12 @@ Shell commands addrmap askenv base + bootdev bootefi + bootflow booti bootmenu + bootmeth button x86/cbsysinfo conitrace -- 2.33.0.1079.g6e70778dc9-goog