From patchwork Mon Apr 25 05:31:06 2022 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 1621688 X-Patchwork-Delegate: trini@ti.com Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: bilbo.ozlabs.org; dkim=pass (1024-bit key; unprotected) header.d=chromium.org header.i=@chromium.org header.a=rsa-sha256 header.s=google header.b=Xo9bd9Ff; dkim-atps=neutral Authentication-Results: ozlabs.org; spf=pass (sender SPF authorized) smtp.mailfrom=lists.denx.de (client-ip=2a01:238:438b:c500:173d:9f52:ddab:ee01; helo=phobos.denx.de; envelope-from=u-boot-bounces@lists.denx.de; receiver=) Received: from phobos.denx.de (phobos.denx.de [IPv6:2a01:238:438b:c500:173d:9f52:ddab:ee01]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits)) (No client certificate requested) by bilbo.ozlabs.org (Postfix) with ESMTPS id 4KmtxP6wnvz9s0r for ; Mon, 25 Apr 2022 15:34:33 +1000 (AEST) Received: from h2850616.stratoserver.net (localhost [IPv6:::1]) by phobos.denx.de (Postfix) with ESMTP id 9C95E83E83; Mon, 25 Apr 2022 07:33:24 +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="Xo9bd9Ff"; dkim-atps=neutral Received: by phobos.denx.de (Postfix, from userid 109) id 1A7CD83E90; Mon, 25 Apr 2022 07:32:39 +0200 (CEST) X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on phobos.denx.de X-Spam-Level: X-Spam-Status: No, score=0.7 required=5.0 tests=BAYES_00,DKIMWL_WL_HIGH, DKIM_SIGNED,DKIM_VALID,DKIM_VALID_AU,DKIM_VALID_EF,RCVD_IN_SBL_CSS, SPF_HELO_NONE,SPF_PASS autolearn=no autolearn_force=no version=3.4.2 Received: from mail-ed1-x532.google.com (mail-ed1-x532.google.com [IPv6:2a00:1450:4864:20::532]) (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 EF28483E5D for ; Mon, 25 Apr 2022 07:32:19 +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-ed1-x532.google.com with SMTP id a1so11403181edt.3 for ; Sun, 24 Apr 2022 22:32:19 -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=OCOlLzBCqQS6xA6gOt5kiaL5hHyRvPzW0aY5Uf0hKXM=; b=Xo9bd9Ffj4CaM9gkgaBA+TxgDrD9NuBhup1/vj2l/wgIY0i/J3cglr8o54udDX13bW swDudge8/ASVgmUvKsRxE6n54Eo82Zp59tneA66ABVkchdvrdX9CHOz29dHDVHImE1kc o9KHMt1DgR8xVrDNRbsqGbgpstb7My5aflLjg= 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=OCOlLzBCqQS6xA6gOt5kiaL5hHyRvPzW0aY5Uf0hKXM=; b=IRCT8HE0PYtM0aOgknsuQoWJ24BeB2IGSuamRgvWcvsxOMNrTyEFVj3ZBj3FzczKI9 KYzj1S58SomWKESWfx5PC+bur6+B47rrAeJeTD3ECXYwwMtJjiisTgKa9ZLcdwUM4F5w J/hjOVnWJct3br/kMxC4wCd4OLSiloNuUj9cUa7rv7xbopZPs2Wk9iiqiZLLd7z3ze4l AqQ2b9rzde3Fpj1FPf+VG/rC3pC2r/ovEbffWdEc1d8haKthjvZZGobbnrBN5kRNyDY/ NTvUKAKbVMuT+/LApgf7XioMAvZus/Va6bCjjqSlnTEQBbsPov5/1eWWuOwHTsAceR72 rYiA== X-Gm-Message-State: AOAM5325XzvRcKD3sbjFdPTgC/2O10RGeJrzJbaJsjx+QD6XjZxJ65uk 8066P6bUCo8xPKh8ZUtoqh+BWfhxgUxJwilz X-Google-Smtp-Source: ABdhPJzmQUwMg0cXpxIENQuggyn6V8Enk/O046DjLPUSfyjfAfpf8IBfh92dW/jq2wrO6JMdzW7uAw== X-Received: by 2002:a05:6402:50cb:b0:423:d7a8:719e with SMTP id h11-20020a05640250cb00b00423d7a8719emr16892075edb.37.1650864739157; Sun, 24 Apr 2022 22:32:19 -0700 (PDT) Received: from sjg1.c.hospitality.swisscom.com (d54c768e3.static.telenet.be. [84.199.104.227]) by smtp.gmail.com with ESMTPSA id s12-20020a1709062ecc00b006e8558c9a5csm3230784eji.94.2022.04.24.22.32.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sun, 24 Apr 2022 22:32:18 -0700 (PDT) From: Simon Glass To: U-Boot Mailing List Cc: Dennis Gilmore , Lukas Auer , Daniel Schwierzeck , Tom Rini , Michal Simek , Ilias Apalodimas , Steffen Jaeckel , Simon Glass Subject: [PATCH v5 13/34] bootstd: Add the bootstd uclass and core implementation Date: Sun, 24 Apr 2022 23:31:06 -0600 Message-Id: <20220424233055.v5.13.I3b5bc09d034cd72b2a9c604a0907c10abc05956a@changeid> X-Mailer: git-send-email 2.36.0.rc2.479.g8af0fa9b8e-goog In-Reply-To: <20220425053127.19950-1-sjg@chromium.org> References: <20220425053127.19950-1-sjg@chromium.org> MIME-Version: 1.0 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.5 at phobos.denx.de X-Virus-Status: Clean The 'bootstd' device provides the central information about U-Boot standard boot. Add a uclass for bootstd and the various helpers needed to make it work. Also add a binding file. Signed-off-by: Simon Glass --- Changes in v5: - Disable bootstd for EFI app builds, since they use dm_scan_other() Changes in v4: - NULL-terminate the default prefix list - Use new Return style in function comments Changes in v3: - Add CONFIG_BOOTSTD_FULL to enable the full feature set - Support bootdev-order and filename-prefixes only with CONFIG_BOOTSTD_FULL MAINTAINERS | 2 + boot/Kconfig | 34 ++++++ boot/Makefile | 3 + boot/bootstd-uclass.c | 152 +++++++++++++++++++++++++++ configs/efi-x86_app32_defconfig | 1 + configs/efi-x86_app64_defconfig | 1 + doc/device-tree-bindings/bootstd.txt | 28 +++++ include/bootstd.h | 80 ++++++++++++++ include/dm/uclass-id.h | 1 + 9 files changed, 302 insertions(+) create mode 100644 boot/bootstd-uclass.c create mode 100644 doc/device-tree-bindings/bootstd.txt create mode 100644 include/bootstd.h diff --git a/MAINTAINERS b/MAINTAINERS index d6d45573fdc..dd099d6240f 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -696,6 +696,8 @@ F: tools/binman/ BOOTDEVICE M: Simon Glass S: Maintained +F: boot/bootstd.c +F: include/bootstd.h F: include/bootflow.h BTRFS diff --git a/boot/Kconfig b/boot/Kconfig index ec5b956490d..9faa55a5418 100644 --- a/boot/Kconfig +++ b/boot/Kconfig @@ -292,6 +292,40 @@ endif # SPL endif # FIT +config BOOTSTD + bool "Standard boot support" + default y + depends on DM && OF_CONTROL && BLK + help + U-Boot supports a standard way of locating something to boot, + typically an Operating System such as Linux, provided by a distro such + as Arch Linux or Debian. Enable this to support iterating through + available bootdevs and using bootmeths to find bootflows suitable for + booting. + + Standard boot is not a standard way of booting, just a framework + within U-Boot for supporting all the different ways that exist. + + Terminology: + + - bootdev - a device which can hold a distro (e.g. MMC) + - bootmeth - a method to scan a bootdev to find bootflows (owned by + U-Boot) + - bootflow - a description of how to boot (owned by the distro) + +config BOOTSTD_FULL + bool "Enhanced features for standard boot" + default y if SANDBOX + help + This enables various useful features for standard boot, which are not + essential for operation: + + - bootdev, bootmeth commands + - extra features in the bootflow command + - support for selecting the ordering of bootmeths ("bootmeth order") + - support for selecting the ordering of bootdevs using the devicetree + as well as the "boot_targets" environment variable + config LEGACY_IMAGE_FORMAT bool "Enable support for the legacy image format" default y if !FIT_SIGNATURE diff --git a/boot/Makefile b/boot/Makefile index 1b99e6ee33f..21dcf6a6056 100644 --- a/boot/Makefile +++ b/boot/Makefile @@ -18,6 +18,9 @@ endif obj-y += image.o image-board.o obj-$(CONFIG_ANDROID_AB) += android_ab.o obj-$(CONFIG_ANDROID_BOOT_IMAGE) += image-android.o image-android-dt.o + +obj-$(CONFIG_$(SPL_TPL_)BOOTSTD) += bootstd-uclass.o + obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += image-fdt.o obj-$(CONFIG_$(SPL_TPL_)FIT_SIGNATURE) += fdt_region.o obj-$(CONFIG_$(SPL_TPL_)FIT) += image-fit.o diff --git a/boot/bootstd-uclass.c b/boot/bootstd-uclass.c new file mode 100644 index 00000000000..615cd89bf0b --- /dev/null +++ b/boot/bootstd-uclass.c @@ -0,0 +1,152 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Uclass implementation for standard boot + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +DECLARE_GLOBAL_DATA_PTR; + +/* These are used if filename-prefixes is not present */ +const char *const default_prefixes[] = {"/", "/boot/", NULL}; + +static int bootstd_of_to_plat(struct udevice *dev) +{ + struct bootstd_priv *priv = dev_get_priv(dev); + int ret; + + if (IS_ENABLED(CONFIG_BOOTSTD_FULL)) { + /* Don't check errors since livetree and flattree are different */ + ret = dev_read_string_list(dev, "filename-prefixes", + &priv->prefixes); + dev_read_string_list(dev, "bootdev-order", + &priv->bootdev_order); + } + + return 0; +} + +static void bootstd_clear_glob_(struct bootstd_priv *priv) +{ + while (!list_empty(&priv->glob_head)) { + struct bootflow *bflow; + + bflow = list_first_entry(&priv->glob_head, struct bootflow, + glob_node); + /* add later bootflow_remove(bflow); */ + } +} + +void bootstd_clear_glob(void) +{ + struct bootstd_priv *std; + + if (bootstd_get_priv(&std)) + return; + + bootstd_clear_glob_(std); +} + +static int bootstd_remove(struct udevice *dev) +{ + struct bootstd_priv *priv = dev_get_priv(dev); + + free(priv->prefixes); + free(priv->bootdev_order); + bootstd_clear_glob_(priv); + + return 0; +} + +const char *const *const bootstd_get_bootdev_order(struct udevice *dev) +{ + struct bootstd_priv *std = dev_get_priv(dev); + + return std->bootdev_order; +} + +const char *const *const bootstd_get_prefixes(struct udevice *dev) +{ + struct bootstd_priv *std = dev_get_priv(dev); + + return std->prefixes ? std->prefixes : default_prefixes; +} + +int bootstd_get_priv(struct bootstd_priv **stdp) +{ + struct udevice *dev; + int ret; + + ret = uclass_first_device_err(UCLASS_BOOTSTD, &dev); + if (ret) + return ret; + *stdp = dev_get_priv(dev); + + return 0; +} + +static int bootstd_probe(struct udevice *dev) +{ + struct bootstd_priv *std = dev_get_priv(dev); + + INIT_LIST_HEAD(&std->glob_head); + + return 0; +} + +/* For now, bind the boormethod device if none are found in the devicetree */ +int dm_scan_other(bool pre_reloc_only) +{ + struct udevice *bootstd; + int ret; + + /* These are not needed before relocation */ + if (!(gd->flags & GD_FLG_RELOC)) + return 0; + + /* Create a bootstd device if needed */ + uclass_find_first_device(UCLASS_BOOTSTD, &bootstd); + if (!bootstd) { + ret = device_bind_driver(gd->dm_root, "bootstd_drv", "bootstd", + &bootstd); + if (ret) + return log_msg_ret("bootstd", ret); + } + + return 0; +} + +static const struct udevice_id bootstd_ids[] = { + { .compatible = "u-boot,boot-std" }, + { } +}; + +U_BOOT_DRIVER(bootstd_drv) = { + .id = UCLASS_BOOTSTD, + .name = "bootstd_drv", + .of_to_plat = bootstd_of_to_plat, + .probe = bootstd_probe, + .remove = bootstd_remove, + .of_match = bootstd_ids, + .priv_auto = sizeof(struct bootstd_priv), +}; + +UCLASS_DRIVER(bootstd) = { + .id = UCLASS_BOOTSTD, + .name = "bootstd", +#if CONFIG_IS_ENABLED(OF_REAL) + .post_bind = dm_scan_fdt_dev, +#endif +}; diff --git a/configs/efi-x86_app32_defconfig b/configs/efi-x86_app32_defconfig index 228643a1bd6..7a723c136c2 100644 --- a/configs/efi-x86_app32_defconfig +++ b/configs/efi-x86_app32_defconfig @@ -8,6 +8,7 @@ CONFIG_VENDOR_EFI=y CONFIG_TARGET_EFI_APP32=y CONFIG_DEBUG_UART=y CONFIG_FIT=y +# CONFIG_BOOTSTD is not set CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" diff --git a/configs/efi-x86_app64_defconfig b/configs/efi-x86_app64_defconfig index 1ed2f130509..98f91d81164 100644 --- a/configs/efi-x86_app64_defconfig +++ b/configs/efi-x86_app64_defconfig @@ -8,6 +8,7 @@ CONFIG_VENDOR_EFI=y CONFIG_TARGET_EFI_APP64=y CONFIG_DEBUG_UART=y CONFIG_FIT=y +# CONFIG_BOOTSTD is not set CONFIG_SHOW_BOOT_PROGRESS=y CONFIG_USE_BOOTARGS=y CONFIG_BOOTARGS="root=/dev/sdb3 init=/sbin/init rootwait ro" diff --git a/doc/device-tree-bindings/bootstd.txt b/doc/device-tree-bindings/bootstd.txt new file mode 100644 index 00000000000..f048b9dd327 --- /dev/null +++ b/doc/device-tree-bindings/bootstd.txt @@ -0,0 +1,28 @@ +U-Boot standard boot device (bootstd) +===================================== + +This is the controlling device for U-Boot standard boot, providing a way to +boot operating systems in a way that can be controlled by distros. + +Required properties: + +compatible: "u-boot,boot-std" + +Optional properties: + +filename-prefixes: + List of strings, each a directory to search for bootflow files + +bootdev-order: + List of bootdevs to check for bootflows, each a bootdev label (the media + uclass followed by the numeric sequence number of the media device) + + +Example: + + bootstd { + compatible = "u-boot,boot-std"; + + filename-prefixes = "/", "/boot/"; + bootdev-order = "mmc2", "mmc1"; + }; diff --git a/include/bootstd.h b/include/bootstd.h new file mode 100644 index 00000000000..b002365f4f0 --- /dev/null +++ b/include/bootstd.h @@ -0,0 +1,80 @@ +/* SPDX-License-Identifier: GPL-2.0+ */ +/* + * Standard U-Boot boot framework + * + * Copyright 2021 Google LLC + * Written by Simon Glass + */ + +#ifndef __bootstd_h +#define __bootstd_h + +struct udevice; + +/** + * struct bootstd_priv - priv data for the bootstd driver + * + * This is attached to the (only) bootstd device, so there is only one instance + * of this struct. It provides overall information about bootdevs and bootflows. + * + * @prefixes: NULL-terminated list of prefixes to use for bootflow filenames, + * e.g. "/", "/boot/"; NULL if none + * @bootdev_order: Order to use for bootdevs (or NULL if none), with each item + * being a bootdev label, e.g. "mmc2", "mmc1"; + * @cur_bootdev: Currently selected bootdev (for commands) + * @cur_bootflow: Currently selected bootflow (for commands) + * @glob_head: Head for the global list of all bootflows across all bootdevs + * @bootmeth_count: Number of bootmeth devices in @bootmeth_order + * @bootmeth_order: List of bootmeth devices to use, in order, NULL-terminated + */ +struct bootstd_priv { + const char **prefixes; + const char **bootdev_order; + struct udevice *cur_bootdev; + struct bootflow *cur_bootflow; + struct list_head glob_head; + int bootmeth_count; + struct udevice **bootmeth_order; +}; + +/** + * bootstd_get_bootdev_order() - Get the boot-order list + * + * This reads the boot order, e.g. {"mmc0", "mmc2", NULL} + * + * The list is alloced by the bootstd driver so should not be freed. That is the + * reason for all the const stuff in the function signature + * + * Return: list of string points, terminated by NULL; or NULL if no boot order + */ +const char *const *const bootstd_get_bootdev_order(struct udevice *dev); + +/** + * bootstd_get_prefixes() - Get the filename-prefixes list + * + * This reads the prefixes, e.g. {"/", "/bpot", NULL} + * + * The list is alloced by the bootstd driver so should not be freed. That is the + * reason for all the const stuff in the function signature + * + * Return: list of string points, terminated by NULL; or NULL if no boot order + */ +const char *const *const bootstd_get_prefixes(struct udevice *dev); + +/** + * bootstd_get_priv() - Get the (single) state for the bootstd system + * + * The state holds a global list of all bootflows that have been found. + * + * Return: 0 if OK, -ve if the uclass does not exist + */ +int bootstd_get_priv(struct bootstd_priv **stdp); + +/** + * bootstd_clear_glob() - Clear the global list of bootflows + * + * This removes all bootflows globally and across all bootdevs. + */ +void bootstd_clear_glob(void); + +#endif diff --git a/include/dm/uclass-id.h b/include/dm/uclass-id.h index 0e26e1d1382..cece0626a11 100644 --- a/include/dm/uclass-id.h +++ b/include/dm/uclass-id.h @@ -38,6 +38,7 @@ enum uclass_id { UCLASS_AXI, /* AXI bus */ UCLASS_BLK, /* Block device */ UCLASS_BOOTCOUNT, /* Bootcount backing store */ + UCLASS_BOOTSTD, /* Standard boot driver */ UCLASS_BUTTON, /* Button */ UCLASS_CACHE, /* Cache controller */ UCLASS_CLK, /* Clock source, e.g. used by peripherals */