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 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 smtp.lore.kernel.org (Postfix) with ESMTPS id 4D726C433F5 for ; Wed, 19 Jan 2022 11:39:23 +0000 (UTC) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id CEA978303A; Wed, 19 Jan 2022 12:39:20 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=canonical.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=u-boot-bounces@lists.denx.de Authentication-Results: phobos.denx.de; dkim=pass (2048-bit key; unprotected) header.d=canonical.com header.i=@canonical.com header.b="Ib42UC4w"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 95496832CD; Wed, 19 Jan 2022 12:39:19 +0100 (CET) Received: from smtp-relay-internal-0.canonical.com (smtp-relay-internal-0.canonical.com [185.125.188.122]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits)) (No client certificate requested) by phobos.denx.de (Postfix) with ESMTPS id DF37F82EC6 for ; Wed, 19 Jan 2022 12:39:11 +0100 (CET) Authentication-Results: phobos.denx.de; dmarc=pass (p=none dis=none) header.from=canonical.com Authentication-Results: phobos.denx.de; spf=pass smtp.mailfrom=heinrich.schuchardt@canonical.com Received: from mail-wm1-f70.google.com (mail-wm1-f70.google.com [209.85.128.70]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by smtp-relay-internal-0.canonical.com (Postfix) with ESMTPS id 93FEA3F31F for ; Wed, 19 Jan 2022 11:39:09 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=canonical.com; s=20210705; t=1642592349; bh=z+LZmfvxhH73hhxVzarAe9FQElyGQ1Wa47EzR6TiT+U=; h=Message-ID:Date:MIME-Version:Subject:To:Cc:References:From: In-Reply-To:Content-Type; b=Ib42UC4wGU8T9Zboj90OiEVBGuYfezlYgoBOTirnMkAkE8NlzJ7oJr1j8uC5snui1 IbnD9nJX+pMCRsBNg26sPbcj2vJDOpEEMMiYC0OWDIVlF6vSYJDDMveyjDJstV2KdJ 7MrhvC2cEYQZbwO2Y5pLTkj4AcIX5qlKB7j/n2wuugUm0mD/OUIC3T54e4rPrLyesZ oQVczjamcDGI3FhswWuvR/gQJbz2FuwseeHD/kZRIzzHdMO3gI6mvflx84PdEKjebc 1ezV8ZcNpkkTihJEXqjiIfLM+ZnegAzBVGvP8aV7I19YQDE/ZPzBqDr+RVaXARLF02 3bnvChiyEwdVw== Received: by mail-wm1-f70.google.com with SMTP id l20-20020a05600c1d1400b0034c29cad547so4164607wms.2 for ; Wed, 19 Jan 2022 03:39:09 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20210112; h=x-gm-message-state:message-id:date:mime-version:user-agent:subject :content-language:to:cc:references:from:in-reply-to :content-transfer-encoding; bh=z+LZmfvxhH73hhxVzarAe9FQElyGQ1Wa47EzR6TiT+U=; b=gme4jJyb4cklz48AEULtt8bGLGFSoG8UXOUjspRbIdejiZDwvM8mpg+QLi8K4TermF eL0uWxYe2ryVwXdVmQXGKSh1+IL01FizwkealKWowz6Yf4wvndofaAGwlsnuB7GUJ3Ka Qe9J0oxPtnbfejJC15Z3zvpGqhXCRqHlC40nOszgG5nWv+PlAwq/mGVdSAvAw/0v7wyG DgoV3Racghjj9emjYyw4FH7h8DP1g5+M+qVTaQtx5IXWR9pEkdpgfnlZxoeoRliLW3Pz u7Bkpv5dIWl0J5PgZLhQhvY6QwYueP0wydyiLg0exbwS2kasmJ7ZiybVO34xkNruwn4t Bnyw== X-Gm-Message-State: AOAM530ViLrVf/ez9jTBDA3YOTZeunU+ra+opPPPrp2N1vX+Kyb4OHMu a00x4xgnXb3/WIVMO4oUuxX0Gnayts5qsLbtfTqrtb3GvADSutYJ8wV0jpqJgNutjfDPqPCMBYP oLxXMrHFDJDlZSzCgMi5FSCX7JEXfoeE= X-Received: by 2002:a7b:cbc1:: with SMTP id n1mr3139375wmi.188.1642592346860; Wed, 19 Jan 2022 03:39:06 -0800 (PST) X-Google-Smtp-Source: ABdhPJxcCiK0DovNmabuuvA/q1Pb2XSYh4zkSO9EtAYXXgtgrGA1m9qf4Pv29hjZD+Hb5NAo2bNMIg== X-Received: by 2002:a7b:cbc1:: with SMTP id n1mr3139264wmi.188.1642592345594; Wed, 19 Jan 2022 03:39:05 -0800 (PST) Received: from [192.168.123.94] (ip-088-152-144-107.um26.pools.vodafone-ip.de. [88.152.144.107]) by smtp.gmail.com with ESMTPSA id k12sm16554wrd.74.2022.01.19.03.39.04 (version=TLS1_3 cipher=TLS_AES_128_GCM_SHA256 bits=128/128); Wed, 19 Jan 2022 03:39:04 -0800 (PST) Message-ID: <28d88952-e1aa-46cd-fd60-ac52cd2ab43b@canonical.com> Date: Wed, 19 Jan 2022 12:39:03 +0100 MIME-Version: 1.0 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:91.0) Gecko/20100101 Thunderbird/91.5.0 Subject: Re: [PATCH v3 30/31] bootstd: doc: Add documentation Content-Language: en-US To: Simon Glass Cc: Ilias Apalodimas , Daniel Schwierzeck , Dennis Gilmore , Steffen Jaeckel , Lukas Auer , Michal Simek , Tom Rini , U-Boot Mailing List References: <20220119014315.1938157-1-sjg@chromium.org> <20220119014315.1938157-20-sjg@chromium.org> From: Heinrich Schuchardt In-Reply-To: <20220119014315.1938157-20-sjg@chromium.org> Content-Type: text/plain; charset=UTF-8; format=flowed Content-Transfer-Encoding: 8bit X-BeenThere: u-boot@lists.denx.de X-Mailman-Version: 2.1.39 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 On 1/19/22 02:43, Simon Glass wrote: > Add documentation for this feature, including the commands and full > devicetree bindings. > > Signed-off-by: Simon Glass > --- > > Changes in v3: > - Update docs for "bootmeths" and "boot_targets" env vars > > MAINTAINERS | 4 + > doc/develop/bootstd.rst | 638 ++++++++++++++++++++++++++ > 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 | 108 +++++ > doc/usage/index.rst | 3 + > 11 files changed, 1376 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 8ad70d3d968..c2af8ada3c9 100644 > --- a/MAINTAINERS > +++ b/MAINTAINERS > @@ -669,6 +669,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..1b65a806efb > --- /dev/null > +++ b/doc/develop/bootstd.rst > @@ -0,0 +1,638 @@ > +.. 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. This gets it completely wrong. There is one standardized boot flow: UEFI. All major distros support this. U-Boot has to offer UEFI booting out of the box. Only when using the legacy entry point of the Linux kernel - which is discouraged - you have to think about other boot flows. Best regards Heinrich > +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). > + > + > +Controlling ordering > +-------------------- > + > +Several options are available to control the ordering of boot scanning: > + > + > +boot_targets > +~~~~~~~~~~~~ > + > +This environment variable can be used to control the list of bootdevs searched > +and their ordering, for example:: > + > + setenv boot_targets "mmc0 mmc1 usb pxe" > + > +Entries may be removed or re-ordered in this list to affect the boot order. If > +the variable is empty, the default ordering is used, based on the priority of > +bootdevs and their sequence numbers. > + > + > +bootmeths > +~~~~~~~~~ > + > +This environment variable can be used to control the list of bootmeths used and > +their ordering for example:: > + > + setenv bootmeths "syslinux efi" > + > +Entries may be removed or re-ordered in this list to affect the order the > +bootmeths are tried on each bootdev. If the variable is empty, the default > +ordering is used, based on the bootmeth sequence numbers, which can be > +controlled by aliases. > + > +The :ref:`usage/bootmeth:bootmeth command` (`bootmeth order`) operates in the > +same way as setting this variable. > + > + > +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 `bootdev_setup_iter_order()`. By > +default, the bootdevs are used in the order specified by the `boot_targets` > +environment variable (e.g. "mmc2 mmc0 usb"). If that is missing then their > +sequence order is used, as determined by the `/aliases` node, or failing that > +their order in the devicetree. For BOOTSTD_FULL, if there is a `bootdev-order` > +property in the bootstd node, then this is used as a final fallback. 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 `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, > +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 9592d193fca..7c41589fb92 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..1bb2b9d5c09 > --- /dev/null > +++ b/doc/usage/bootmeth.rst > @@ -0,0 +1,108 @@ > +.. 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: > + > +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 argument is a quoted 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 33761af96af..3f6903ad76b 100644 > --- a/doc/usage/index.rst > +++ b/doc/usage/index.rst > @@ -21,9 +21,12 @@ Shell commands > addrmap > askenv > base > + bootdev > bootefi > + bootflow > booti > bootmenu > + bootmeth > button > x86/cbsysinfo > conitrace