From patchwork Thu May 7 22:14:47 2026 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Simon Glass X-Patchwork-Id: 2280 Return-Path: X-Original-To: u-boot-concept@u-boot.org Delivered-To: u-boot-concept@u-boot.org DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192125; bh=VNY6p1GeviKc/p8YlnArKb2ENCxeDY3E6pU2TGOAEvk=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=WnseetWIbvhVaJn3+8s8r8zpWoq9JxT5wXtapY76mfpvcxyZh+YYDcUKKdADUJpdJ qH432x6ZpijQ5OOYhVd+A1HmAH/YuX3fo/L7rGmD8VJ5m0FvrF5RPPIvg9PhRGZp6D hC7YwOf1OjfcWTq/QdDhpNHtUsggibwRhkM6GrYY= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 5177F6A9A5 for ; Thu, 7 May 2026 16:15:25 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10024) with ESMTP id eUXyA_jiuo1R for ; Thu, 7 May 2026 16:15:25 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192123; bh=VNY6p1GeviKc/p8YlnArKb2ENCxeDY3E6pU2TGOAEvk=; h=From:To:Date:In-Reply-To:References:CC:Subject:List-Id: List-Archive:List-Help:List-Owner:List-Post:List-Subscribe: List-Unsubscribe:From; b=YoRdfZkYOv4JOf1ETgEsuevUztwZZ+QGd5UOiAOahyM8CennIyrnpsFfIIGON3qP9 O6SXpUff3WxBwj6vdpfu0cPWrZXPygvw531WBM4rYKlwswRom0uM5cv1V3qQOVpzl4 Z9ZiMFuWnGumro/848LLC5ZgR3VhFDuH69/B55cs= Received: from mail.u-boot.org (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 8B1326A9AA for ; Thu, 7 May 2026 16:15:23 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192122; bh=RQbE6EWojgLQb2DdD1HyWxt2i1OZlgpRP2vWElT+Hf4=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=ACqHEjORRhvoyY7/BB87exsZYxVWRCBJffJPZRiEXjXoOG2V1QtQiMkbeWqvJ1Byx eyTlQNYx6bC1WP85N/mVRxnzPXzjriku0FMAn74V+A2L5p3oBl8gd6RfO1I8QHae5F ZS4bj+bM9Kp4J2AYUV9TAGS92O/muMbqEzWKvDew= Received: from localhost (localhost [127.0.0.1]) by mail.u-boot.org (Postfix) with ESMTP id 09B426A9A5; Thu, 7 May 2026 16:15:22 -0600 (MDT) X-Virus-Scanned: Debian amavis at Received: from mail.u-boot.org ([127.0.0.1]) by localhost (mail.u-boot.org [127.0.0.1]) (amavis, port 10026) with ESMTP id dDBrFrVvJQqC; Thu, 7 May 2026 16:15:21 -0600 (MDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=u-boot.org; s=default; t=1778192121; bh=VPJhncQYCl6LcTgulS/gFFdQebTmSdBxWzST91xH6gk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=F/TgXj3I5FNwVJzrmw4YOYwz08VoITFUYCPnobgZQ8cgwGNyVu6Wv2di0piA0JxuO hiyIHl1pZJsBLhmULA12MQc1hPj1kjRo0LY0a1z67krXpe4V0F7jWfZR84OS2PbhNG Xf//oGvoECXGSPEjceEffr4EPwEz1mFYm99f8k64= Received: from u-boot.org (unknown [174.51.25.52]) by mail.u-boot.org (Postfix) with ESMTPSA id 0CB506A959; Thu, 7 May 2026 16:15:20 -0600 (MDT) From: Simon Glass To: U-Boot Concept Date: Thu, 7 May 2026 16:14:47 -0600 Message-ID: <20260507221507.505998-3-sjg@u-boot.org> X-Mailer: git-send-email 2.43.0 In-Reply-To: <20260507221507.505998-1-sjg@u-boot.org> References: <20260507221507.505998-1-sjg@u-boot.org> MIME-Version: 1.0 Message-ID-Hash: ZLAAQQFKNF3R3SHQQWQJWCGTTXWLCU4W X-Message-ID-Hash: ZLAAQQFKNF3R3SHQQWQJWCGTTXWLCU4W X-MailFrom: sjg@u-boot.org X-Mailman-Rule-Misses: dmarc-mitigation; no-senders; approved; loop; banned-address; emergency; member-moderation; nonmember-moderation; administrivia; implicit-dest; max-recipients; max-size; news-moderation; no-subject; digests; suspicious-header CC: Simon Glass X-Mailman-Version: 3.3.10 Precedence: list Subject: [Concept] [PATCH 02/13] bootmeth: bls: Scan every partition for entries List-Id: Discussion and patches related to U-Boot Concept Archived-At: List-Archive: List-Help: List-Owner: List-Post: List-Subscribe: List-Unsubscribe: From: Simon Glass The Boot Loader Specification places loader/entries/*.conf on the ESP or XBOOTLDR partition, and bootmeth_bls relies on the iterator's BLS-target carve-out to reach those even when they are not marked bootable. In practice, however, kernel-install (the systemd helper that distros such as Ubuntu use for kernel package hooks) writes its entries to /boot/loader/entries on whichever partition holds /boot, which is typically the ext4 rootfs. Set BOOTMETHF_ANY_PART on the BLS bootmeth so the iterator hands it every partition on each bootdev rather than just bootable and BLS-target ones, matching bootmeth_android, bootmeth_rauc and bootmeth_cros. The default filename prefixes ('/' and '/boot/') already cover both ESP-relative and rootfs-relative entry paths, so the scan picks up entries on the ESP and on the rootfs. Visiting every partition means BLS now probes filesystems on raw data slots too (e.g. ChromeOS kernel partitions, which are a single LBA), and the ext4 superblock probe at sector 2 trips fs_devread()'s "Read outside partition" error on those. Filter out partitions below a small threshold up front so the FS probes only run on partitions that could plausibly hold one. Signed-off-by: Simon Glass --- boot/bootmeth_bls.c | 24 ++++++++++++++++- doc/develop/bootstd/bls.rst | 34 ++++++++++++++++------- doc/develop/bootstd/overview.rst | 11 +++++--- doc/usage/bls.rst | 46 ++++++++++++++++++++++++++------ 4 files changed, 93 insertions(+), 22 deletions(-) diff --git a/boot/bootmeth_bls.c b/boot/bootmeth_bls.c index 85d8dfa91df..6f6d03d286b 100644 --- a/boot/bootmeth_bls.c +++ b/boot/bootmeth_bls.c @@ -48,6 +48,13 @@ #define BLS_ENTRIES_DIR "loader/entries" #define BLS_ENTRY_FILE "loader/entry.conf" +/* + * Minimum partition size, in blocks, that is plausibly a filesystem. + * Partitions below this are skipped before FS probing to avoid + * out-of-bounds superblock reads on raw data slots + */ +#define BLS_MIN_PART_BLOCKS 64 + /** * struct bls_info - context information for BLS getfile callback * @@ -320,6 +327,21 @@ static int bls_read_bootflow(struct udevice *dev, struct bootflow *bflow) prefixes = bootstd_get_prefixes(bootstd); desc = bflow->blk ? dev_get_uclass_plat(bflow->blk) : NULL; + /* + * BOOTMETHF_ANY_PART makes the iterator visit every partition, + * including small non-filesystem ones (e.g. ChromeOS kernel slots). + * Skip partitions too small to hold any filesystem before probing, + * so probe-time reads do not trip the "Read outside partition" + * error path + */ + if (desc) { + struct disk_partition info; + + if (!part_get_info(desc, bflow->part, &info) && + info.size < BLS_MIN_PART_BLOCKS) + return -ENOENT; + } + /* Try each prefix: first scan entries/, then fall back to entry.conf */ i = 0; ret = -ENOENT; @@ -521,7 +543,7 @@ static int bls_bootmeth_bind(struct udevice *dev) plat->desc = IS_ENABLED(CONFIG_BOOTSTD_FULL) ? "Boot Loader Specification (BLS) Type #1" : "bls"; - plat->flags = BOOTMETHF_MULTI; + plat->flags = BOOTMETHF_MULTI | BOOTMETHF_ANY_PART; return 0; } diff --git a/doc/develop/bootstd/bls.rst b/doc/develop/bootstd/bls.rst index 327ab7c1c55..37eddd455f3 100644 --- a/doc/develop/bootstd/bls.rst +++ b/doc/develop/bootstd/bls.rst @@ -9,15 +9,31 @@ Fedora, RHEL and other distributions. .. _Boot Loader Specification: https://uapi-group.org/specifications/specs/boot_loader_specification/ -The entry file ``loader/entry.conf`` is searched for under each boot prefix -(``{"/", "/boot"}`` by default). These prefixes can be selected with the -`filename-prefixes` property in the bootstd device. - -The bootmeth sets ``BOOTMETHF_MULTI`` so that each ``.conf`` file in the -entries directory produces a separate bootflow. The ``bflow->entry`` field -selects which file to use during scanning. - -When invoked on a bootdev, the ``bls_read_bootflow()`` function searches for the +For each partition the bootmeth tries every boot prefix (``{"/", "/boot/"}`` +by default; selectable via the ``filename-prefixes`` property on the bootstd +device). Within each prefix it scans ``loader/entries/`` for ``.conf`` files +first, then falls back to the singular ``loader/entry.conf`` if the directory +is missing or empty. + +The bootmeth sets two flags at bind time: + +* ``BOOTMETHF_MULTI`` -- each ``.conf`` file in the entries directory produces + a separate bootflow, with ``bflow->entry`` indexing which one is returned. +* ``BOOTMETHF_ANY_PART`` -- the iterator visits every partition rather than + only bootable partitions and the ESP / XBOOTLDR / MBR-0xea targets carved out + by ``part_is_bls_target()``. Distros that drive their entries through + ``kernel-install`` typically place ``loader/entries/`` on whichever partition + holds ``/boot``, which on Debian/Ubuntu layouts is the ext4 rootfs rather + than the ESP, and ``BOOTMETHF_ANY_PART`` is what lets BLS reach those. + +Because ``BOOTMETHF_ANY_PART`` invites the bootmeth onto every partition, +``bls_read_bootflow()`` looks the partition up before mounting and returns +``-ENOENT`` for partitions below ``BLS_MIN_PART_BLOCKS`` blocks. This avoids +running the ext4 superblock probe (which reads sector 2) on raw single-LBA +slots like ChromeOS kernel partitions, where the probe would otherwise trip +``fs_devread()``'s "Read outside partition" error path. + +When invoked on a bootdev, the ``bls_read_bootflow()`` function searches for an entry file, reads it and passes it to ``bls_parse_entry()`` which processes the key-value pairs into a ``struct bls_entry``. The parser uses an enum-based token lookup to map field names, with most values pointing directly into the diff --git a/doc/develop/bootstd/overview.rst b/doc/develop/bootstd/overview.rst index b69156cb51d..89fd77cf695 100644 --- a/doc/develop/bootstd/overview.rst +++ b/doc/develop/bootstd/overview.rst @@ -815,10 +815,13 @@ calls the bootmeth device once more, this time to read the bootflow. Note: Normally a filesystem is needed for the bootmeth to be called on block devices, but bootmeths which don't need that can set the BOOTMETHF_ANY_PART -flag to indicate that they can scan any partition. An example is the ChromiumOS -bootmeth which can store a kernel in a raw partition. Note also that sandbox is -a special case, since in that case the host filesystem can be accessed even -though the block device is NULL. +flag to indicate that they can scan any partition. The ChromiumOS bootmeth +sets it because it stores a kernel in a raw partition; the BLS bootmeth sets +it so it can find ``loader/entries/`` on the rootfs partition that distros +mount at ``/boot`` (in addition to the ESP and XBOOTLDR partitions called out +by the BLS spec). Note also that sandbox is a special case, since in that +case the host filesystem can be accessed even though the block device is +NULL. If we take the example of the `bootmeth_extlinux` driver, this call ends up at `extlinux_read_bootflow()`. It has the filesystem ready, so tries various diff --git a/doc/usage/bls.rst b/doc/usage/bls.rst index 128092ae25b..8d8e7246243 100644 --- a/doc/usage/bls.rst +++ b/doc/usage/bls.rst @@ -13,11 +13,13 @@ Overview BLS provides a standardised way to describe boot entries. U-Boot's BLS support allows it to boot operating systems configured with BLS entries, which is used -by Fedora, RHEL, and other distributions. +by Fedora, RHEL, Ubuntu (via ``kernel-install``) and other distributions. -The current implementation supports a single BLS entry file at -``loader/entry.conf``. Future versions may support multiple entries in -``loader/entries/``. +U-Boot scans both the standard ``loader/entries/-.conf`` +layout used by ``kernel-install`` and a single ``loader/entry.conf`` fallback +under each boot prefix. When an entries directory is present, each ``.conf`` +file becomes a separate bootflow; ``loader/entry.conf`` is consulted only when +the directory is absent or empty. Configuration ------------- @@ -28,6 +30,30 @@ Enable BLS support with:: This automatically selects ``CONFIG_PXE_UTILS`` for booting. +Discovery +--------- + +The BLS bootmeth sets ``BOOTMETHF_ANY_PART``, so the bootflow iterator hands +it every partition on each bootdev rather than just the bootable partition or +those typed as ESP / XBOOTLDR / MBR-0xea. This matches the way ``kernel-install`` +places entries: distros that mount the ESP at ``/boot/efi`` keep +``loader/entries/`` on the ext4 rootfs at ``/boot/loader/entries/``, while +distros that mount the ESP at ``/boot`` keep them on the ESP at +``loader/entries/``. Both cases are reached without any board configuration. + +For each partition the bootmeth tries each filename prefix configured on the +bootstd device (``/`` and ``/boot/`` by default; see ``filename-prefixes`` in +:doc:`/develop/bootstd/overview`) and within each prefix tries the entries +directory first, then the singular ``entry.conf`` fallback:: + + loader/entries/*.conf + loader/entry.conf + +Partitions too small to hold any filesystem are filtered out before the +filesystem probe runs, so raw data partitions (for example ChromeOS kernel +slots, which are a single LBA) do not produce spurious "Read outside +partition" probe errors. + BLS Entry Format ---------------- @@ -128,23 +154,27 @@ BLS boot entries are discovered automatically by standard boot:: => bootflow select 0 => bootflow boot -The BLS entry at ``loader/entry.conf`` on any available media is recognised as -a bootflow. +Each ``.conf`` file in a discovered ``loader/entries/`` directory, or the +single ``loader/entry.conf`` fallback, becomes its own bootflow. Implementation Notes -------------------- -* Single BLS entry file support (``loader/entry.conf``) * Boot execution reuses U-Boot's PXE infrastructure for kernel loading * Unknown fields are ignored for forward compatibility * The bootmethod is ordered as ``bootmeth_2bls`` (after extlinux) * Zero-copy parsing: most fields point into bootflow buffer (except ``options`` which is allocated for concatenation) +* ``BOOTMETHF_MULTI`` is set, so each ``.conf`` file in the entries directory + produces a separate bootflow +* ``BOOTMETHF_ANY_PART`` is set, so the iterator visits every partition rather + than only those tagged as bootable or as BLS-target Current Limitations ------------------- -* Only single entry file, not multiple entries directory scanning +* Only the first ``.conf`` file in ``loader/entries/`` is loaded per call; + the iterator advances ``bflow->entry`` to retrieve subsequent ones * No devicetree-overlay support * No architecture/machine-id filtering * No version-based or sort-key sorting