* [PATCH v3 0/4] bootstd: Support scripts in raw partitions
@ 2026-10-26 14:02 He Yong
2026-10-26 14:02 ` [PATCH v3 1/4] image: Bound FIT script checks by the image size He Yong
` (3 more replies)
0 siblings, 4 replies; 9+ messages in thread
From: He Yong @ 2026-10-26 14:02 UTC (permalink / raw)
To: u-boot; +Cc: Simon Glass, Tom Rini
This series adds a script_raw bootmeth for U-Boot script images stored
at the start of a named partition, without a filesystem or a board-specific
bootcmd. It supports legacy scripts and FIT scripts with embedded data.
Image reads are bounded by the partition size and a configurable limit.
The raw and filesystem script bootmeths share the execution handler and
script parser. For known-size FIT scripts, the parser passes the buffer
size to fit_check_format() and rejects external data before verification.
The existing FIT_FULL_CHECK configuration controls full structural checks.
Changes since v2:
- Split the series into shared FIT validation, execution-handler export,
the raw bootmeth, and sandbox tests.
- Drop the legacy parser bounds-check changes from this series.
- Move known-size FIT validation and external-data rejection into the
shared script parser, with tests for both verify settings and source.
- Bind script_raw inside its C test, following bootflow_rauc(), so existing
bootmeth lists and bootflow tests stay unchanged, including -G coverage.
- Label each expected C error with its corresponding Python case name.
- Reuse fs_helper.setup_image() with an sfdisk partition specification and
generate the disk from test_ut_dm_init_bootstd(), avoiding sgdisk and a
separate initialization test.
- Preserve the CONFIG_SANDBOX comment and clear verify on helper failure.
Validation on this revision:
- Sandbox build: make O=build-sandbox -j8
- Sandbox pytest: 3 passed (bootstd image initialization,
image_fit_script_bounds and bootflow_script_raw)
Previous version:
https://www.mail-archive.com/u-boot@lists.u-boot-project.org/msg09207.html
He Yong (4):
image: Bound FIT script checks by the image size
bootstd: Export the script bootflow execution handler
bootstd: Add a bootmeth for scripts in raw partitions
test: bootstd: Cover scripts in raw partitions on sandbox
MAINTAINERS | 1 +
arch/sandbox/dts/test.dts | 8 ++
boot/Kconfig | 26 +++++
boot/Makefile | 1 +
boot/bootmeth_script.c | 4 +-
boot/bootmeth_script_raw.c | 152 ++++++++++++++++++++++++++
boot/image-board.c | 19 +++-
configs/sandbox_defconfig | 1 +
doc/develop/bootstd/index.rst | 1 +
doc/develop/bootstd/script_raw.rst | 51 +++++++++
doc/device-tree-bindings/bootmeth.txt | 1 +
include/bootmeth.h | 12 ++
test/boot/bootflow.c | 81 ++++++++++++++
test/boot/image.c | 118 ++++++++++++++++++++
test/py/img/__init__.py | 2 +
test/py/img/script_raw.py | 98 +++++++++++++++++
test/py/tests/fs_helper.py | 19 ++--
test/py/tests/test_ut.py | 3 +
18 files changed, 588 insertions(+), 10 deletions(-)
create mode 100644 boot/bootmeth_script_raw.c
create mode 100644 doc/develop/bootstd/script_raw.rst
create mode 100644 test/py/img/__init__.py
create mode 100644 test/py/img/script_raw.py
base-commit: 0a55b098d6f5f6bafa84fc2f18b433dd167bf729
--
2.43.0
^ permalink raw reply [flat|nested] 9+ messages in thread
* [PATCH v3 1/4] image: Bound FIT script checks by the image size
2026-10-26 14:02 [PATCH v3 0/4] bootstd: Support scripts in raw partitions He Yong
@ 2026-10-26 14:02 ` He Yong
2026-10-26 16:14 ` Simon Glass
2026-10-26 14:02 ` [PATCH v3 2/4] bootstd: Export the script bootflow execution handler He Yong
` (2 subsequent siblings)
3 siblings, 1 reply; 9+ messages in thread
From: He Yong @ 2026-10-26 14:02 UTC (permalink / raw)
To: u-boot; +Cc: Simon Glass, Tom Rini
FIT verification can follow malformed metadata or external-data offsets
beyond a buffer whose size is known to the caller.
Pass the known buffer size to fit_check_format() so FIT_FULL_CHECK
validates the complete structure against the actual buffer. Reject
external data in all subimages of known-size FITs before verification,
even when verify is disabled. Keep these checks in the shared parser so
filesystem and raw-partition scripts receive the same protection. Leave
unknown-size FIT handling unchanged.
Add C regression coverage with verification enabled and disabled, plus
source coverage. Clear verify even when a test helper assertion fails.
Signed-off-by: He Yong <hyyoxhk@163.com>
---
Changes in v3:
- Replace the legacy parser changes with shared known-size FIT validation.
- Reject external data before verification and cover both verify settings.
boot/image-board.c | 19 +++++++-
test/boot/image.c | 118 +++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 136 insertions(+), 1 deletion(-)
diff --git a/boot/image-board.c b/boot/image-board.c
index 7602f5bfaaa..15a79aa513e 100644
--- a/boot/image-board.c
+++ b/boot/image-board.c
@@ -1043,11 +1043,28 @@ int image_locate_script(void *buf, int size, const char *fit_uname,
goto exit_image_format;
} else {
fit_hdr = buf;
- if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
+ if (fit_check_format(fit_hdr,
+ size ? size : IMAGE_SIZE_INVAL)) {
puts("Bad FIT image format\n");
return 1;
}
+ if (size) {
+ int images, node;
+
+ /* Reject external data before any verification reads. */
+ images = fdt_path_offset(fit_hdr, FIT_IMAGES_PATH);
+ fdt_for_each_subnode(node, fit_hdr, images) {
+ if (fdt_getprop(fit_hdr, node,
+ FIT_DATA_OFFSET_PROP, NULL) ||
+ fdt_getprop(fit_hdr, node,
+ FIT_DATA_POSITION_PROP, NULL)) {
+ puts("External FIT script data is not supported\n");
+ return 1;
+ }
+ }
+ }
+
if (!fit_uname) {
/* If confname is empty, use the default */
if (confname && *confname)
diff --git a/test/boot/image.c b/test/boot/image.c
index 2c6d9dcbc22..17b1a4055da 100644
--- a/test/boot/image.c
+++ b/test/boot/image.c
@@ -6,7 +6,11 @@
* Written by Simon Glass <sjg@chromium.org>
*/
+#include <command.h>
+#include <env.h>
#include <image.h>
+#include <mapmem.h>
+#include <u-boot/crc.h>
#include <test/ut.h>
#include <linux/libfdt.h>
#include "bootstd_common.h"
@@ -100,3 +104,117 @@ static int test_image_phase(struct unit_test_state *uts)
return 0;
}
BOOTSTD_TEST(test_image_phase, 0);
+
+/* Known-size FITs must be structurally valid and contain all their data. */
+static int check_fit_script_bounds(struct unit_test_state *uts)
+{
+ static const char script[] = "true";
+ static const char * const external_props[] = {
+ FIT_DATA_OFFSET_PROP, FIT_DATA_POSITION_PROP,
+ };
+ char fit[1024] __aligned(8), bad[1024] __aligned(8);
+ const void *expected;
+ char *data;
+ uint len;
+ int images, node, confs, conf, hash, size, i;
+
+ ut_assertok(fdt_create_empty_tree(fit, sizeof(fit)));
+ ut_assertok(fdt_setprop_string(fit, 0, FIT_DESC_PROP, "Script test"));
+ ut_assertok(fdt_setprop_u32(fit, 0, FIT_TIMESTAMP_PROP, 0));
+ images = fdt_add_subnode(fit, 0, "images");
+ ut_assert(images >= 0);
+ ut_assertok(fdt_setprop_string(fit, images, FIT_DEFAULT_PROP, "script"));
+ node = fdt_add_subnode(fit, images, "script");
+ ut_assert(node >= 0);
+ ut_assertok(fdt_setprop_string(fit, node, FIT_TYPE_PROP, "script"));
+ ut_assertok(fdt_setprop(fit, node, FIT_DATA_PROP, script, sizeof(script)));
+ hash = fdt_add_subnode(fit, node, "hash");
+ ut_assert(hash >= 0);
+ ut_assertok(fdt_setprop_string(fit, hash, FIT_ALGO_PROP, "crc32"));
+ ut_assertok(fdt_setprop_u32(fit, hash, FIT_VALUE_PROP,
+ crc32(0, (const u8 *)script, sizeof(script))));
+ confs = fdt_add_subnode(fit, 0, "configurations");
+ ut_assert(confs >= 0);
+ ut_assertok(fdt_setprop_string(fit, confs, FIT_DEFAULT_PROP, "conf"));
+ conf = fdt_add_subnode(fit, confs, "conf");
+ ut_assert(conf >= 0);
+ ut_assertok(fdt_setprop_string(fit, conf, FIT_SCRIPT_PROP, "script"));
+ ut_assertok(fdt_pack(fit));
+ size = fdt_totalsize(fit);
+ node = fdt_path_offset(fit, "/images/script");
+ ut_assert(node >= 0);
+ expected = fdt_getprop(fit, node, FIT_DATA_PROP, NULL);
+ ut_assertnonnull(expected);
+
+ /* Exercise configuration lookup, direct image lookup and source. */
+ ut_assertok(image_locate_script(fit, size, NULL, NULL, &data, &len));
+ ut_asserteq(sizeof(script), len);
+ ut_asserteq_ptr(expected, data);
+ ut_assertok(image_locate_script(fit, size, "script", NULL, &data, &len));
+ ut_assertok(cmd_source_script(map_to_sysmem(fit), NULL, NULL));
+
+ /* Structural validation follows fit_check_format() configuration. */
+ if (CONFIG_IS_ENABLED(FIT_FULL_CHECK)) {
+ ut_asserteq(1, image_locate_script(fit, sizeof(struct fdt_header) - 1,
+ NULL, NULL, &data, &len));
+ ut_asserteq(1, image_locate_script(fit, sizeof(struct fdt_header),
+ NULL, NULL, &data, &len));
+ ut_asserteq(1, image_locate_script(fit, size - 1, NULL, NULL,
+ &data, &len));
+
+ memcpy(bad, fit, size);
+ fdt_set_totalsize(bad, sizeof(bad) + 1);
+ ut_asserteq(1, image_locate_script(bad, sizeof(bad), NULL, NULL,
+ &data, &len));
+
+ /* A valid header does not imply a valid structure block. */
+ memcpy(bad, fit, size);
+ *(fdt32_t *)(bad + fdt_off_dt_struct(bad)) = cpu_to_fdt32(0xffffffff);
+ ut_assertok(fdt_check_header(bad));
+ ut_asserteq(1, image_locate_script(bad, size, NULL, NULL, &data, &len));
+ }
+
+ for (i = 0; i < ARRAY_SIZE(external_props); i++) {
+ ut_assertok(fdt_open_into(fit, bad, sizeof(bad)));
+ node = fdt_path_offset(bad, "/images/script");
+ ut_assert(node >= 0);
+ ut_assertok(fdt_delprop(bad, node, FIT_DATA_PROP));
+ ut_assertok(fdt_setprop_u32(bad, node, external_props[i],
+ 0xfffffffc));
+ ut_assertok(fdt_setprop_u32(bad, node, FIT_DATA_SIZE_PROP,
+ sizeof(script)));
+ ut_asserteq(1, image_locate_script(bad, sizeof(bad), NULL,
+ NULL, &data, &len));
+
+ /* Reject external data even in an unselected image. */
+ ut_assertok(fdt_open_into(fit, bad, sizeof(bad)));
+ images = fdt_path_offset(bad, FIT_IMAGES_PATH);
+ ut_assert(images >= 0);
+ node = fdt_add_subnode(bad, images, "external");
+ ut_assert(node >= 0);
+ ut_assertok(fdt_setprop_u32(bad, node, external_props[i],
+ 0xfffffffc));
+ ut_asserteq(1, image_locate_script(bad, sizeof(bad), NULL,
+ NULL, &data, &len));
+ }
+
+ return 0;
+}
+
+static int image_fit_script_bounds(struct unit_test_state *uts)
+{
+ int ret, verify;
+
+ if (!IS_ENABLED(CONFIG_FIT))
+ return -EAGAIN;
+
+ for (verify = 0; verify < 2; verify++) {
+ ut_assertok(env_set("verify", verify ? "yes" : "no"));
+ ret = check_fit_script_bounds(uts);
+ ut_assertok(env_set("verify", NULL));
+ ut_assertok(ret);
+ }
+
+ return 0;
+}
+BOOTSTD_TEST(image_fit_script_bounds, 0);
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 2/4] bootstd: Export the script bootflow execution handler
2026-10-26 14:02 [PATCH v3 0/4] bootstd: Support scripts in raw partitions He Yong
2026-10-26 14:02 ` [PATCH v3 1/4] image: Bound FIT script checks by the image size He Yong
@ 2026-10-26 14:02 ` He Yong
2026-10-26 16:14 ` Simon Glass
2026-10-26 14:02 ` [PATCH v3 3/4] bootstd: Add a bootmeth for scripts in raw partitions He Yong
2026-10-26 14:02 ` [PATCH v3 4/4] test: bootstd: Cover scripts in raw partitions on sandbox He Yong
3 siblings, 1 reply; 9+ messages in thread
From: He Yong @ 2026-10-26 14:02 UTC (permalink / raw)
To: u-boot; +Cc: Simon Glass, Tom Rini
Make script_boot() available as bootmeth_script_boot() so another
bootmeth can reuse the device environment setup and script execution
without duplicating the filesystem script bootmeth's handler.
Signed-off-by: He Yong <hyyoxhk@163.com>
---
Changes in v3:
- Split the shared script execution-handler export into its own patch.
boot/bootmeth_script.c | 4 ++--
include/bootmeth.h | 12 ++++++++++++
2 files changed, 14 insertions(+), 2 deletions(-)
diff --git a/boot/bootmeth_script.c b/boot/bootmeth_script.c
index cd50977cc40..9e95cc51e58 100644
--- a/boot/bootmeth_script.c
+++ b/boot/bootmeth_script.c
@@ -188,7 +188,7 @@ static int script_set_bootflow(struct udevice *dev, struct bootflow *bflow,
return 0;
}
-static int script_boot(struct udevice *dev, struct bootflow *bflow)
+int bootmeth_script_boot(struct udevice *dev, struct bootflow *bflow)
{
struct blk_desc *desc;
ulong addr;
@@ -258,7 +258,7 @@ static struct bootmeth_ops script_bootmeth_ops = {
.read_bootflow = script_read_bootflow,
.set_bootflow = script_set_bootflow,
.read_file = bootmeth_common_read_file,
- .boot = script_boot,
+ .boot = bootmeth_script_boot,
};
static const struct udevice_id script_bootmeth_ids[] = {
diff --git a/include/bootmeth.h b/include/bootmeth.h
index 2a492dfd73a..2d855632a50 100644
--- a/include/bootmeth.h
+++ b/include/bootmeth.h
@@ -425,4 +425,16 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
*/
int bootmeth_get_bootflow(struct udevice *dev, struct bootflow *bflow);
+/**
+ * bootmeth_script_boot() - Execute a script bootflow
+ *
+ * Set the device and partition environment variables and execute the script
+ * stored in the bootflow buffer.
+ *
+ * @dev: Bootmeth device
+ * @bflow: Bootflow containing the script image
+ * @return 0 on success, or a error code
+ */
+int bootmeth_script_boot(struct udevice *dev, struct bootflow *bflow);
+
#endif
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 3/4] bootstd: Add a bootmeth for scripts in raw partitions
2026-10-26 14:02 [PATCH v3 0/4] bootstd: Support scripts in raw partitions He Yong
2026-10-26 14:02 ` [PATCH v3 1/4] image: Bound FIT script checks by the image size He Yong
2026-10-26 14:02 ` [PATCH v3 2/4] bootstd: Export the script bootflow execution handler He Yong
@ 2026-10-26 14:02 ` He Yong
2026-10-26 16:14 ` Simon Glass
2026-10-26 14:02 ` [PATCH v3 4/4] test: bootstd: Cover scripts in raw partitions on sandbox He Yong
3 siblings, 1 reply; 9+ messages in thread
From: He Yong @ 2026-10-26 14:02 UTC (permalink / raw)
To: u-boot; +Cc: Simon Glass, Tom Rini
Some disk layouts store a U-Boot script image directly in a named
partition, without a filesystem. Add a script_raw bootmeth to find these
images without a board-specific bootcmd.
Read the image size from the first block and bound it by the partition
size and configured limit. Support legacy scripts and FIT scripts with
embedded data, using the shared script parser for validation and the
shared execution handler for booting.
Keep raw-partition scanning independently selectable from filesystem
script lookup. Document the configuration and self-contained FIT policy.
Signed-off-by: He Yong <hyyoxhk@163.com>
---
Changes in v3:
- Move shared FIT checks, handler export and sandbox tests to separate patches.
MAINTAINERS | 1 +
boot/Kconfig | 26 +++++
boot/Makefile | 1 +
boot/bootmeth_script_raw.c | 152 ++++++++++++++++++++++++++
doc/develop/bootstd/index.rst | 1 +
doc/develop/bootstd/script_raw.rst | 51 +++++++++
doc/device-tree-bindings/bootmeth.txt | 1 +
7 files changed, 233 insertions(+)
create mode 100644 boot/bootmeth_script_raw.c
create mode 100644 doc/develop/bootstd/script_raw.rst
diff --git a/MAINTAINERS b/MAINTAINERS
index d1f51d9197d..6870298ee0f 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -846,6 +846,7 @@ F: include/bootflow.h
F: include/bootmeth.h
F: include/bootstd.h
F: test/boot/
+F: test/py/img/script_raw.py
BOOTMETH_ANDROID
M: Mattijs Korpershoek <mkorpershoek@kernel.org>
diff --git a/boot/Kconfig b/boot/Kconfig
index 8fcdc36c931..990c8bc0110 100644
--- a/boot/Kconfig
+++ b/boot/Kconfig
@@ -1009,6 +1009,32 @@ config BOOTMETH_SCRIPT
This provides a way to try out standard boot on an existing boot flow.
It is not enabled by default to save space.
+config BOOTMETH_SCRIPT_RAW
+ bool "Boot from a script in a raw partition"
+ depends on BOOTMETH_SCRIPT && BLK && PARTITIONS
+ depends on LEGACY_IMAGE_FORMAT || FIT
+ help
+ Locate a named partition and read a U-Boot script image directly from
+ its first block, without a filesystem. This adds the script_raw boot
+ method. Legacy script images and FIT scripts with embedded data are
+ supported.
+
+config BOOTMETH_SCRIPT_RAW_PARTITION
+ string "Raw script partition name"
+ depends on BOOTMETH_SCRIPT_RAW
+ default "uboot_scr"
+ help
+ Partition label to match when scanning for a raw script image.
+
+config BOOTMETH_SCRIPT_RAW_MAX_SIZE
+ hex "Maximum raw script image size"
+ depends on BOOTMETH_SCRIPT_RAW
+ default 0x100000
+ range 0x200 0x1000000
+ help
+ Maximum script image size in bytes, including its image header.
+ The image must also fit within the selected partition.
+
config UPL
bool "upl - Universal Payload Specification"
imply CMD_UPL
diff --git a/boot/Makefile b/boot/Makefile
index f2cbda176a0..12649286601 100644
--- a/boot/Makefile
+++ b/boot/Makefile
@@ -38,6 +38,7 @@ obj-$(CONFIG_$(PHASE_)BOOTMETH_QFW) += bootmeth_qfw.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_RAUC) += bootmeth_rauc.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_SANDBOX) += bootmeth_sandbox.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_SCRIPT) += bootmeth_script.o
+obj-$(CONFIG_$(PHASE_)BOOTMETH_SCRIPT_RAW) += bootmeth_script_raw.o
obj-$(CONFIG_$(PHASE_)CEDIT) += cedit.o
obj-$(CONFIG_$(PHASE_)BOOTMETH_EFI_BOOTMGR) += bootmeth_efi_mgr.o
diff --git a/boot/bootmeth_script_raw.c b/boot/bootmeth_script_raw.c
new file mode 100644
index 00000000000..53913f20e98
--- /dev/null
+++ b/boot/bootmeth_script_raw.c
@@ -0,0 +1,152 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Bootmethod for scripts stored in a raw partition
+ *
+ * Copyright 2026 He Yong <hyyoxhk@163.com>
+ */
+
+#define LOG_CATEGORY UCLASS_BOOTSTD
+
+#include <blk.h>
+#include <bootflow.h>
+#include <bootmeth.h>
+#include <dm.h>
+#include <image.h>
+#include <malloc.h>
+#include <mapmem.h>
+#include <part.h>
+#include <asm/cache.h>
+
+static int script_raw_check(struct udevice *dev, struct bootflow_iter *iter)
+{
+ return bootflow_iter_check_blk(iter);
+}
+
+static int script_raw_read_bootflow(struct udevice *dev, struct bootflow *bflow)
+{
+ struct legacy_img_hdr *hdr;
+ struct disk_partition info;
+ struct blk_desc *desc;
+ lbaint_t count;
+ uint size, len;
+ char *data;
+ void *buf;
+ int ret;
+
+ if (!bflow->blk || !bflow->part)
+ return log_msg_ret("part", -ENOENT);
+ desc = dev_get_uclass_plat(bflow->blk);
+ ret = part_get_info(desc, bflow->part, &info);
+ if (ret)
+ return log_msg_ret("part", ret);
+ if (strcmp(info.name, CONFIG_BOOTMETH_SCRIPT_RAW_PARTITION))
+ return log_msg_ret("name", -ENOENT);
+ bflow->state = BOOTFLOWST_PART;
+
+ if (!info.size || desc->blksz < sizeof(*hdr) ||
+ desc->blksz > CONFIG_BOOTMETH_SCRIPT_RAW_MAX_SIZE)
+ return log_msg_ret("block", -EINVAL);
+ buf = memalign(ARCH_DMA_MINALIGN, desc->blksz);
+ if (!buf)
+ return log_msg_ret("buf", -ENOMEM);
+ if (blk_dread(desc, info.start, 1, buf) != 1) {
+ ret = log_msg_ret("header-read", -EIO);
+ goto out;
+ }
+
+ hdr = buf;
+ if (IS_ENABLED(CONFIG_LEGACY_IMAGE_FORMAT) &&
+ genimg_get_format(buf) == IMAGE_FORMAT_LEGACY) {
+ if (!image_check_hcrc(hdr)) {
+ ret = log_msg_ret("header", -EINVAL);
+ goto out;
+ }
+ size = image_get_data_size(hdr);
+ if (size > CONFIG_BOOTMETH_SCRIPT_RAW_MAX_SIZE - sizeof(*hdr)) {
+ ret = log_msg_ret("legacy-size", -E2BIG);
+ goto out;
+ }
+ size += sizeof(*hdr);
+ } else if (IS_ENABLED(CONFIG_FIT) && !fdt_check_header(buf)) {
+ size = fdt_totalsize(buf);
+ if (size < sizeof(struct fdt_header)) {
+ ret = log_msg_ret("fit-size", -EINVAL);
+ goto out;
+ }
+ } else {
+ ret = log_msg_ret("format", -ENOEXEC);
+ goto out;
+ }
+ if (size > CONFIG_BOOTMETH_SCRIPT_RAW_MAX_SIZE) {
+ ret = log_msg_ret("size", -E2BIG);
+ goto out;
+ }
+ count = DIV_ROUND_UP(size, desc->blksz);
+ if (count > info.size) {
+ ret = log_msg_ret("partition-size", -E2BIG);
+ goto out;
+ }
+ free(buf);
+ buf = memalign(ARCH_DMA_MINALIGN, count * desc->blksz + 1);
+ if (!buf)
+ return log_msg_ret("buf", -ENOMEM);
+ if (blk_dread(desc, info.start, count, buf) != count) {
+ ret = log_msg_ret("image-read", -EIO);
+ goto out;
+ }
+ ((char *)buf)[size] = '\0';
+ ret = image_locate_script(buf, size, NULL, NULL, &data, &len);
+ if (ret) {
+ ret = log_msg_ret("script", -EINVAL);
+ goto out;
+ }
+
+ bflow->fname = strdup(CONFIG_BOOTMETH_SCRIPT_RAW_PARTITION);
+ bflow->subdir = strdup("");
+ if (!bflow->fname || !bflow->subdir) {
+ ret = log_msg_ret("name-alloc", -ENOMEM);
+ goto out;
+ }
+ if (!bootflow_img_add(bflow, bflow->fname, (enum bootflow_img_t)IH_TYPE_SCRIPT,
+ map_to_sysmem(buf), size)) {
+ ret = log_msg_ret("image-alloc", -ENOMEM);
+ goto out;
+ }
+ bflow->buf = buf;
+ bflow->size = size;
+ bflow->state = BOOTFLOWST_READY;
+
+ return 0;
+out:
+ free(buf);
+ return ret;
+}
+
+static int script_raw_bootmeth_bind(struct udevice *dev)
+{
+ struct bootmeth_uc_plat *plat = dev_get_uclass_plat(dev);
+
+ plat->desc = "Script boot from a raw partition";
+ plat->flags = BOOTMETHF_ANY_PART;
+
+ return 0;
+}
+
+static struct bootmeth_ops script_raw_bootmeth_ops = {
+ .check = script_raw_check,
+ .read_bootflow = script_raw_read_bootflow,
+ .boot = bootmeth_script_boot,
+};
+
+static const struct udevice_id script_raw_bootmeth_ids[] = {
+ { .compatible = "u-boot,script-raw" },
+ { }
+};
+
+U_BOOT_DRIVER(bootmeth_2script_raw) = {
+ .name = "bootmeth_script_raw",
+ .id = UCLASS_BOOTMETH,
+ .of_match = script_raw_bootmeth_ids,
+ .ops = &script_raw_bootmeth_ops,
+ .bind = script_raw_bootmeth_bind,
+};
diff --git a/doc/develop/bootstd/index.rst b/doc/develop/bootstd/index.rst
index 9271b5eef14..0a2452a44c2 100644
--- a/doc/develop/bootstd/index.rst
+++ b/doc/develop/bootstd/index.rst
@@ -15,4 +15,5 @@ Standard Boot
cros
rauc
script
+ script_raw
sandbox
diff --git a/doc/develop/bootstd/script_raw.rst b/doc/develop/bootstd/script_raw.rst
new file mode 100644
index 00000000000..29a63c0ceb7
--- /dev/null
+++ b/doc/develop/bootstd/script_raw.rst
@@ -0,0 +1,51 @@
+.. SPDX-License-Identifier: GPL-2.0+
+
+Raw Script Bootmeth
+===================
+
+The ``script_raw`` bootmeth reads a script image from the start of a named
+partition on a block device, without a filesystem. Enable
+``CONFIG_BOOTMETH_SCRIPT`` and ``CONFIG_BOOTMETH_SCRIPT_RAW`` to build it.
+The partition name is selected by ``CONFIG_BOOTMETH_SCRIPT_RAW_PARTITION``
+and defaults to ``uboot_scr``. The partition need not be marked bootable.
+
+The method reads the first block to determine the image size, then reads the
+complete image. The image must fit within the partition and the limit set by
+``CONFIG_BOOTMETH_SCRIPT_RAW_MAX_SIZE`` (1 MiB by default). It supports legacy
+U-Boot script images and FIT scripts with embedded data. FIT external data is
+not supported: script FITs are small and must be self-contained so that all
+metadata and script data can be validated within the loaded partition image.
+
+Plain text scripts must first be wrapped with ``mkimage``, for example::
+
+ mkimage -A arm64 -T script -C none -n 'Boot script' -d boot.cmd boot.scr
+
+Write ``boot.scr`` directly at the start of the ``uboot_scr`` partition when
+creating the disk image. There is no filename lookup on the target partition.
+Image validation is performed before the bootflow is marked ready, using the
+same verification policy as ``source`` (including the ``verify`` environment
+variable).
+
+To scan only this bootmeth on MMC device 0::
+
+ bootmeth order script_raw
+ bootflow scan -lb mmc0
+
+To use the configured bootmeth order for normal automatic boot, set
+``CONFIG_BOOTCOMMAND="bootflow scan -lb"``. Existing saved environments may
+override this default; check ``printenv bootcmd bootmeths boot_targets``.
+Restore the default bootmeth order with ``bootmeth order`` if necessary.
+
+The script is executed from the bootflow's allocated buffer, so ``scriptaddr``
+is not required. Before execution, the method sets ``devtype``, ``devnum`` and
+``distro_bootpart`` as described in :doc:`script`, with an empty ``prefix``.
+The script itself is responsible for selecting and booting an A/B slot.
+
+A separate bootmeth keeps raw-partition scanning independent of the existing
+filesystem script lookup and allows either method to be selected in the bootmeth
+order. Both methods share the script execution handler and verification policy.
+
+The compatible string is ``u-boot,script-raw``. On boards which explicitly
+declare bootmeth devices in their device tree, add a child node with this
+compatible under the ``bootstd`` node. Otherwise standard boot automatically
+binds the enabled bootmeth drivers.
diff --git a/doc/device-tree-bindings/bootmeth.txt b/doc/device-tree-bindings/bootmeth.txt
index 127b09cd1b2..6886842b8f3 100644
--- a/doc/device-tree-bindings/bootmeth.txt
+++ b/doc/device-tree-bindings/bootmeth.txt
@@ -11,6 +11,7 @@ compatible:
"u-boot,extlinux-pxe" - distro boot from a network device
"u-boot,distro-efi" - EFI boot from an .efi file
"u-boot,efi-bootmgr" - EFI boot using boot manager (bootmgr)
+ "u-boot,script-raw" - script boot from a named raw partition
Example:
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* [PATCH v3 4/4] test: bootstd: Cover scripts in raw partitions on sandbox
2026-10-26 14:02 [PATCH v3 0/4] bootstd: Support scripts in raw partitions He Yong
` (2 preceding siblings ...)
2026-10-26 14:02 ` [PATCH v3 3/4] bootstd: Add a bootmeth for scripts in raw partitions He Yong
@ 2026-10-26 14:02 ` He Yong
2026-10-26 16:14 ` Simon Glass
3 siblings, 1 reply; 9+ messages in thread
From: He Yong @ 2026-10-26 14:02 UTC (permalink / raw)
To: u-boot; +Cc: Simon Glass, Tom Rini
Enable script_raw for sandbox and add a GPT disk with valid legacy and
FIT scripts, as well as malformed and unsupported images. Bind the
bootmeth inside the new C test so existing bootmeth lists and bootflow
tests, including bootflow scan -G coverage, remain unchanged.
Introduce test/py/img/ as a package for disk-image generators. Existing
C-test image setup lives in test/py/tests/test_ut.py; keep the raw-script
case definitions and image generation in the new module and call it
from the existing test_ut_dm_init_bootstd() initialization.
Allow fs_helper.setup_image() to accept an sfdisk partition specification
and reuse it for the named GPT partitions. This avoids a dependency on
sgdisk or a separate initialization test. Annotate each expected C error
with its Python case name to keep the two lists in sync.
Signed-off-by: He Yong <hyyoxhk@163.com>
---
Changes in v3:
- Split sandbox coverage into its own patch.
- Bind script_raw only inside its test and preserve existing scan -G coverage.
- Annotate expected errors with Python case names.
- Reuse fs_helper and sfdisk from the existing bootstd initialization test.
arch/sandbox/dts/test.dts | 8 ++++
configs/sandbox_defconfig | 1 +
test/boot/bootflow.c | 81 +++++++++++++++++++++++++++++++
test/py/img/__init__.py | 2 +
test/py/img/script_raw.py | 98 ++++++++++++++++++++++++++++++++++++++
test/py/tests/fs_helper.py | 19 +++++---
test/py/tests/test_ut.py | 3 ++
7 files changed, 205 insertions(+), 7 deletions(-)
create mode 100644 test/py/img/__init__.py
create mode 100644 test/py/img/script_raw.py
diff --git a/arch/sandbox/dts/test.dts b/arch/sandbox/dts/test.dts
index 25c99ef8147..3470e4368d3 100644
--- a/arch/sandbox/dts/test.dts
+++ b/arch/sandbox/dts/test.dts
@@ -50,6 +50,7 @@
mmc9 = "/mmc9";
mmc10 = "/mmc10";
mmc11 = "/mmc11";
+ mmc12 = "/mmc12";
pci0 = &pci0;
pci1 = &pci1;
pci2 = &pci2;
@@ -1398,6 +1399,13 @@
filename = "mmc11.img";
};
+ /* This is used for raw script bootflow tests */
+ mmc12 {
+ status = "disabled";
+ compatible = "sandbox,mmc";
+ filename = "mmc12.img";
+ };
+
pch {
compatible = "sandbox,pch";
};
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig
index a2708e6fb33..09b2980f79b 100644
--- a/configs/sandbox_defconfig
+++ b/configs/sandbox_defconfig
@@ -28,6 +28,7 @@ CONFIG_FIT_VERBOSE=y
CONFIG_BOOTMETH_ANDROID=y
CONFIG_BOOTMETH_BLS=y
CONFIG_BOOTMETH_RAUC=y
+CONFIG_BOOTMETH_SCRIPT_RAW=y
CONFIG_UPL=y
CONFIG_LEGACY_IMAGE_FORMAT=y
CONFIG_MEASURED_BOOT=y
diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
index c4b41668a62..d7e5a51f7b5 100644
--- a/test/boot/bootflow.c
+++ b/test/boot/bootflow.c
@@ -35,6 +35,7 @@ extern U_BOOT_DRIVER(bootmeth_android);
extern U_BOOT_DRIVER(bootmeth_cros);
extern U_BOOT_DRIVER(bootmeth_rauc);
extern U_BOOT_DRIVER(bootmeth_2script);
+extern U_BOOT_DRIVER(bootmeth_2script_raw);
/* Use this as the vendor for EFI to tell the app to exit boot services */
static u16 __efi_runtime_data test_vendor[] = u"U-Boot testing";
@@ -1908,4 +1909,84 @@ static int bootdev_hunt_fallthrough(struct unit_test_state *uts)
}
BOOTSTD_TEST(bootdev_hunt_fallthrough,
UTF_DM | UTF_SCAN_FDT | UTF_SF_BOOTDEV | UTF_CONSOLE);
+
+/* Exercise valid and rejected images without restarting U-Boot per case. */
+static int check_script_raw(struct unit_test_state *uts,
+ struct bootflow_iter *iter)
+{
+ static const int errors[] = {
+ /* Keep in sync with CASES in test/py/img/script_raw.py. */
+ 0, /* legacy */
+ 0, /* fit */
+ -EINVAL, /* external */
+ -EINVAL, /* bad_crc */
+ -E2BIG, /* too_large */
+ -ENOENT, /* wrong_name */
+ -ENOEXEC, /* empty */
+ -EINVAL, /* bad_header */
+ -E2BIG, /* partition_size */
+ -EINVAL, /* bad_fit */
+ };
+ struct bootflow bflow;
+ int ret, part;
+
+ ret = bootflow_scan_first(NULL, NULL, iter, BOOTFLOWIF_ALL, &bflow);
+ /* A raw script belongs to a partition, never to the whole disk. */
+ ut_asserteq(-ENOENT, ret);
+ ut_asserteq(0, bflow.part);
+ bootflow_free(&bflow);
+ for (part = 1; part <= ARRAY_SIZE(errors); part++) {
+ ret = bootflow_scan_next(iter, &bflow);
+ ut_asserteq(part, bflow.part);
+ ut_asserteq(errors[part - 1], ret);
+ if (!ret) {
+ ut_asserteq(BOOTFLOWST_READY, bflow.state);
+ ut_asserteq_str("uboot_scr", bflow.fname);
+ /* A script returning successfully did not boot an OS. */
+ ut_asserteq(-EFAULT, bootflow_run_boot(iter, &bflow));
+ ut_assert_skip_to_line("%sraw-script-ok mmc c %d",
+ part == 2 ? "sha256+ " : "", part);
+ ut_asserteq_str("mmc", env_get("devtype"));
+ } else {
+ ut_assert(bflow.state < BOOTFLOWST_READY);
+ ut_assertnull(bflow.buf);
+ }
+ bootflow_free(&bflow);
+ }
+
+ return 0;
+}
+
+static int bootflow_script_raw(struct unit_test_state *uts)
+{
+ static const char *order[] = {"mmc12", NULL};
+ struct bootflow_iter iter;
+ struct bootstd_priv *std;
+ struct udevice *bootstd;
+ const char **old_order;
+ int ret;
+
+ if (!IS_ENABLED(CONFIG_BOOTMETH_SCRIPT_RAW))
+ return -EAGAIN;
+
+ /* Bind only for this test, leaving the default bootmeth list intact. */
+ ut_assertok(uclass_first_device_err(UCLASS_BOOTSTD, &bootstd));
+ ut_assertok(device_bind(bootstd, DM_DRIVER_REF(bootmeth_2script_raw),
+ "script_raw", 0, ofnode_null(), NULL));
+
+ ut_assertok(prep_mmc_bootdev(uts, "mmc12", false, &old_order));
+ ut_assertok(bootstd_get_priv(&std));
+ std->bootdev_order = order;
+ ut_assertok(bootmeth_set_order("script_raw"));
+ ut_assertok(env_set("verify", "yes"));
+ ret = check_script_raw(uts, &iter);
+ bootflow_iter_uninit(&iter);
+ std->bootdev_order = old_order;
+ /* Restore verify even if a scan or boot assertion failed. */
+ ut_assertok(env_set("verify", NULL));
+ ut_assertok(ret);
+
+ return 0;
+}
+BOOTSTD_TEST(bootflow_script_raw, UTF_DM | UTF_SCAN_FDT | UTF_CONSOLE);
#endif /* CONFIG_SANDBOX */
diff --git a/test/py/img/__init__.py b/test/py/img/__init__.py
new file mode 100644
index 00000000000..526c5dda958
--- /dev/null
+++ b/test/py/img/__init__.py
@@ -0,0 +1,2 @@
+# SPDX-License-Identifier: GPL-2.0+
+"""Disk-image generators for U-Boot C tests."""
diff --git a/test/py/img/script_raw.py b/test/py/img/script_raw.py
new file mode 100644
index 00000000000..671c5917d6d
--- /dev/null
+++ b/test/py/img/script_raw.py
@@ -0,0 +1,98 @@
+# SPDX-License-Identifier: GPL-2.0+
+# Copyright 2026 He Yong <hyyoxhk@163.com>
+
+"""Create a GPT disk containing valid and malformed raw script images."""
+
+import os
+import struct
+import zlib
+
+import utils
+from tests import fs_helper
+
+
+CASES = ('legacy', 'fit', 'external', 'bad_crc',
+ 'too_large', 'wrong_name', 'empty', 'bad_header', 'partition_size',
+ 'bad_fit')
+
+
+def script_image(ubman, case):
+ """Build one script image, optionally corrupting its header or data."""
+ workdir = ubman.config.build_dir
+ script = os.path.join(workdir, 'raw-script.cmd')
+ image = os.path.join(workdir, 'raw-script.scr')
+ mkimage = os.path.join(ubman.config.build_dir, 'tools', 'mkimage')
+ with open(script, 'w', encoding='utf-8') as outf:
+ outf.write('echo raw-script-ok ${devtype} ${devnum} '
+ '${distro_bootpart}\n')
+ if case in ('fit', 'external', 'bad_fit'):
+ its = os.path.join(workdir, 'raw-script.its')
+ with open(its, 'w', encoding='utf-8') as outf:
+ outf.write('''/dts-v1/;
+/ {
+ description = "Raw script test";
+ #address-cells = <1>;
+ images {
+ script {
+ description = "Boot script";
+ data = /incbin/("raw-script.cmd");
+ type = "script";
+ arch = "sandbox";
+ compression = "none";
+ hash { algo = "sha256"; };
+ };
+ };
+ configurations {
+ default = "conf";
+ conf {
+ script = "script";
+ };
+ };
+};
+''')
+ args = [mkimage, '-f', its]
+ if case == 'external':
+ args.append('-E')
+ utils.run_and_log(ubman, args + [image])
+ else:
+ utils.run_and_log(ubman, [mkimage, '-A', 'sandbox', '-T', 'script',
+ '-C', 'none', '-d', script, image])
+ with open(image, 'rb') as inf:
+ data = bytearray(inf.read())
+ if case == 'bad_crc':
+ data[-1] ^= 1
+ elif case == 'too_large':
+ struct.pack_into('>I', data, 12, 2 * 1024 * 1024)
+ elif case == 'empty':
+ data = bytearray(512)
+ if case == 'too_large':
+ struct.pack_into('>I', data, 4, 0)
+ struct.pack_into('>I', data, 4, zlib.crc32(data[:64]))
+ return data
+
+
+def setup_script_raw_image(ubman):
+ """Create one disk for all cases, with 512 KiB non-bootable partitions."""
+ spec = 'label: gpt\n'
+ for part, case in enumerate(CASES, 1):
+ start = part * 2048
+ label = 'other' if case == 'wrong_name' else 'uboot_scr'
+ spec += f'start={start}, size=1024, name="{label}"\n'
+ disk, _ = fs_helper.setup_image(ubman, 12, None, img_size=16,
+ part_spec=spec)
+ with open(disk, 'r+b') as outf:
+ for part, case in enumerate(CASES, 1):
+ data = script_image(ubman, case)
+ if case == 'bad_header':
+ data[4] ^= 1
+ elif case == 'partition_size':
+ struct.pack_into('>I', data, 12, 512 * 1024)
+ elif case == 'bad_fit':
+ # Keep the header valid but corrupt the structure block.
+ offset = struct.unpack_from('>I', data, 8)[0]
+ struct.pack_into('>I', data, offset, 0xffffffff)
+ if case == 'partition_size':
+ struct.pack_into('>I', data, 4, 0)
+ struct.pack_into('>I', data, 4, zlib.crc32(data[:64]))
+ outf.seek(part * 1024 * 1024)
+ outf.write(data)
diff --git a/test/py/tests/fs_helper.py b/test/py/tests/fs_helper.py
index e3824b2c1fd..7c9577e28b1 100644
--- a/test/py/tests/fs_helper.py
+++ b/test/py/tests/fs_helper.py
@@ -8,7 +8,7 @@
import re
import os
import shutil
-from subprocess import call, check_call, check_output, CalledProcessError
+from subprocess import call, check_call, check_output, CalledProcessError, run
from subprocess import DEVNULL
import tempfile
@@ -262,8 +262,8 @@ def mk_fs(config, fs_type, size, prefix, src_dir=None, fs_img=None, quiet=False)
raise
def setup_image(ubman, devnum, part_type, img_size=20, second_part=False,
- basename='mmc'):
- """Create a disk image with one or two partitions
+ basename='mmc', part_spec=None):
+ """Create a disk image with default or caller-specified partitions
Args:
ubman (ConsoleBase): Console to use
@@ -272,6 +272,8 @@ def setup_image(ubman, devnum, part_type, img_size=20, second_part=False,
img_size (int): Image size in MiB
second_part (bool): True to contain a small second partition
basename (str): Base name to use in the filename, e.g. 'mmc'
+ part_spec (str): Optional sfdisk partition specification, overriding
+ part_type and second_part
Returns:
tuple:
@@ -281,14 +283,17 @@ def setup_image(ubman, devnum, part_type, img_size=20, second_part=False,
fname = os.path.join(ubman.config.source_dir, f'{basename}{devnum}.img')
mnt = os.path.join(ubman.config.persistent_data_dir, 'scratch')
- spec = f'type={part_type:x}, size={img_size - 2}M, start=1M, bootable'
- if second_part:
- spec += '\ntype=c'
+ spec = part_spec
+ if spec is None:
+ spec = f'type={part_type:x}, size={img_size - 2}M, start=1M, bootable'
+ if second_part:
+ spec += '\ntype=c'
try:
check_call(f'mkdir -p {mnt}', shell=True)
check_call(f'qemu-img create {fname} {img_size}M', shell=True)
- check_call(f'printf "{spec}" | sfdisk {fname}', shell=True)
+ # Pass the specification directly, including quoted GPT names.
+ run(['sfdisk', fname], input=spec.encode(), check=True)
except CalledProcessError:
call(f'rm -f {fname}', shell=True)
raise
diff --git a/test/py/tests/test_ut.py b/test/py/tests/test_ut.py
index 2a5acc18c61..c52d7f46ac2 100644
--- a/test/py/tests/test_ut.py
+++ b/test/py/tests/test_ut.py
@@ -16,6 +16,7 @@ import re
import pytest
import utils
+from img.script_raw import setup_script_raw_image
# pylint: disable=E0611
from tests import fs_helper
from fs_helper import DiskHelper, FsHelper
@@ -755,6 +756,8 @@ def test_ut_dm_init_bootstd(ubman):
setup_efi_image(ubman)
setup_rauc_image(ubman)
setup_bls_prefix_image(ubman)
+ if ubman.config.buildconfig.get('config_bootmeth_script_raw') == 'y':
+ setup_script_raw_image(ubman)
# Restart so that the new mmc1.img is picked up
ubman.restart_uboot()
--
2.43.0
^ permalink raw reply related [flat|nested] 9+ messages in thread
* Re: [PATCH v3 1/4] image: Bound FIT script checks by the image size
2026-10-26 14:02 ` [PATCH v3 1/4] image: Bound FIT script checks by the image size He Yong
@ 2026-10-26 16:14 ` Simon Glass
0 siblings, 0 replies; 9+ messages in thread
From: Simon Glass @ 2026-10-26 16:14 UTC (permalink / raw)
To: hyyoxhk; +Cc: u-boot, Simon Glass, Tom Rini
Hi He,
On 2026-10-26T14:02:15, He Yong <hyyoxhk@163.com> wrote:
> image: Bound FIT script checks by the image size
>
> FIT verification can follow malformed metadata or external-data offsets
> beyond a buffer whose size is known to the caller.
>
> Pass the known buffer size to fit_check_format() so FIT_FULL_CHECK
> validates the complete structure against the actual buffer. Reject
> external data in all subimages of known-size FITs before verification,
> even when verify is disabled. Keep these checks in the shared parser so
> filesystem and raw-partition scripts receive the same protection. Leave
> unknown-size FIT handling unchanged.
>
> Add C regression coverage with verification enabled and disabled, plus
> source coverage. Clear verify even when a test helper assertion fails.
>
> Signed-off-by: He Yong <hyyoxhk@163.com>
>
> boot/image-board.c | 19 ++++++++-
> test/boot/image.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++++++++
> 2 files changed, 136 insertions(+), 1 deletion(-)
> diff --git a/boot/image-board.c b/boot/image-board.c
> @@ -1043,11 +1043,28 @@ int image_locate_script(void *buf, int size, const char *fit_uname,
> + if (size) {
> + int images, node;
> +
> + /* Reject external data before any verification reads. */
> + images = fdt_path_offset(fit_hdr, FIT_IMAGES_PATH);
> + fdt_for_each_subnode(node, fit_hdr, images) {
> + if (fdt_getprop(fit_hdr, node,
> + FIT_DATA_OFFSET_PROP, NULL) ||
> + fdt_getprop(fit_hdr, node,
> + FIT_DATA_POSITION_PROP, NULL)) {
> + puts("External FIT script data is not supported\n");
> + return 1;
> + }
> + }
> + }
One thing I'd like to check before this goes in.. bootmeth_script
already passes bflow->size, which is the size of the whole file it
read. A FIT script built with 'mkimage -E' has its external data
inside that file, so it works today and would be rejected after this
patch. It also rejects the FIT if any other subimage (e.g. a kernel)
uses external data, even if that subimage is never used.
Since 'size' is known, it would be better to check that each image's
data-offset/data-position plus data-size lies within it, rejecting
only images that go past the end. fit_image_get_data() already does
similar range checks, so a size-aware version of that might be the
natural place. The raw bootmeth would still be safe, since anything
past fdt_totalsize() would fail the check. What do you think?
If you prefer to keep the blanket rejection, you should describe it in
the commit message and doc as a behaviour change for filesystem
scripts too, not just raw partitions. I'm not sure if it would affect
anyone, but I'm a bit nervous about it.
> diff --git a/boot/image-board.c b/boot/image-board.c
> @@ -1043,11 +1043,28 @@ int image_locate_script(void *buf, int size, const char *fit_uname,
> - if (fit_check_format(fit_hdr, IMAGE_SIZE_INVAL)) {
> + if (fit_check_format(fit_hdr,
> + size ? size : IMAGE_SIZE_INVAL)) {
With FIT_FULL_CHECK disabled, 'size' is ignored, so nothing stops
fdt_totalsize() from exceeding the buffer. It would be worth adding a
plain 'fdt_totalsize(fit_hdr) > size' check when size is non-zero. It
costs nothing and makes the subject line true in all configurations.
Regards,
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 2/4] bootstd: Export the script bootflow execution handler
2026-10-26 14:02 ` [PATCH v3 2/4] bootstd: Export the script bootflow execution handler He Yong
@ 2026-10-26 16:14 ` Simon Glass
0 siblings, 0 replies; 9+ messages in thread
From: Simon Glass @ 2026-10-26 16:14 UTC (permalink / raw)
To: hyyoxhk; +Cc: u-boot, Simon Glass, Tom Rini
Hi He,
On 2026-10-26T14:02:15, He Yong <hyyoxhk@163.com> wrote:
> bootstd: Export the script bootflow execution handler
>
> Make script_boot() available as bootmeth_script_boot() so another
> bootmeth can reuse the device environment setup and script execution
> without duplicating the filesystem script bootmeth's handler.
>
> Signed-off-by: He Yong <hyyoxhk@163.com>
>
> boot/bootmeth_script.c | 4 ++--
> include/bootmeth.h | 12 ++++++++++++
> 2 files changed, 14 insertions(+), 2 deletions(-)
> diff --git a/include/bootmeth.h b/include/bootmeth.h
> @@ -425,4 +425,16 @@ int bootmeth_common_read_file(struct udevice *dev, struct bootflow *bflow,
> + * Set the device and partition environment variables and execute the script
> + * stored in the bootflow buffer.
> + *
> + * @dev: Bootmeth device
> + * @bflow: Bootflow containing the script image
> + * @return 0 on success, or a error code
Please can you use 'Return:' here (the kernel-doc form used by most of
this file) and change 'a error code' to '-ve on error'.
It would be worth listing the bootflow fields this uses, since a new
caller needs to know them: bflow->buf for the script, bflow->subdir
for the 'prefix' variable, and bflow->blk and bflow->part for
devtype/devnum/distro_bootpart. Patch 3 sets bflow->subdir to an empty
string just to satisfy this, so it is easy to miss.
Regards,
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 3/4] bootstd: Add a bootmeth for scripts in raw partitions
2026-10-26 14:02 ` [PATCH v3 3/4] bootstd: Add a bootmeth for scripts in raw partitions He Yong
@ 2026-10-26 16:14 ` Simon Glass
0 siblings, 0 replies; 9+ messages in thread
From: Simon Glass @ 2026-10-26 16:14 UTC (permalink / raw)
To: hyyoxhk; +Cc: u-boot, Simon Glass, Tom Rini
Hi He,
On 2026-10-26T14:02:15, He Yong <hyyoxhk@163.com> wrote:
> bootstd: Add a bootmeth for scripts in raw partitions
>
> Some disk layouts store a U-Boot script image directly in a named
> partition, without a filesystem. Add a script_raw bootmeth to find these
> images without a board-specific bootcmd.
>
> Read the image size from the first block and bound it by the partition
> size and configured limit. Support legacy scripts and FIT scripts with
> embedded data, using the shared script parser for validation and the
> shared execution handler for booting.
>
> Keep raw-partition scanning independently selectable from filesystem
> script lookup. Document the configuration and self-contained FIT policy.
>
> Signed-off-by: He Yong <hyyoxhk@163.com>
>
> MAINTAINERS | 1 +
> boot/Kconfig | 26 ++++++
> boot/Makefile | 1 +
> boot/bootmeth_script_raw.c | 152 ++++++++++++++++++++++++++++++++++
> doc/develop/bootstd/index.rst | 1 +
> doc/develop/bootstd/script_raw.rst | 51 ++++++++++++
> doc/device-tree-bindings/bootmeth.txt | 1 +
> 7 files changed, 233 insertions(+)
> diff --git a/MAINTAINERS b/MAINTAINERS
> @@ -847,6 +847,7 @@ F: include/bootflow.h
> F: include/bootmeth.h
> F: include/bootstd.h
> F: test/boot/
> +F: test/py/img/script_raw.py
This file is only added in the next patch, so ideally you could move
the MAINTAINERS change there.
Reviewed-by: Simon Glass <sjg@chromium.org>
Regards,
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
* Re: [PATCH v3 4/4] test: bootstd: Cover scripts in raw partitions on sandbox
2026-10-26 14:02 ` [PATCH v3 4/4] test: bootstd: Cover scripts in raw partitions on sandbox He Yong
@ 2026-10-26 16:14 ` Simon Glass
0 siblings, 0 replies; 9+ messages in thread
From: Simon Glass @ 2026-10-26 16:14 UTC (permalink / raw)
To: hyyoxhk; +Cc: u-boot, Simon Glass, Tom Rini
Hi He,
On 2026-10-26T14:02:15, He Yong <hyyoxhk@163.com> wrote:
> test: bootstd: Cover scripts in raw partitions on sandbox
>
> Enable script_raw for sandbox and add a GPT disk with valid legacy and
> FIT scripts, as well as malformed and unsupported images. Bind the
> bootmeth inside the new C test so existing bootmeth lists and bootflow
> tests, including bootflow scan -G coverage, remain unchanged.
>
> Introduce test/py/img/ as a package for disk-image generators. Existing
> C-test image setup lives in test/py/tests/test_ut.py; keep the raw-script
> case definitions and image generation in the new module and call it
> from the existing test_ut_dm_init_bootstd() initialization.
>
> Allow fs_helper.setup_image() to accept an sfdisk partition specification
> and reuse it for the named GPT partitions. This avoids a dependency on
> sgdisk or a separate initialization test. Annotate each expected C error
> with its Python case name to keep the two lists in sync.
The fs_helper change affects every caller of setup_image(), since it
switches from printf | sfdisk to run(). Please can you put it in its
own patch, before this one?
>
> Signed-off-by: He Yong <hyyoxhk@163.com>
>
> arch/sandbox/dts/test.dts | 8 ++++
> configs/sandbox_defconfig | 1 +
> test/boot/bootflow.c | 81 ++++++++++++++++++++++++++++++++++++++
> test/py/img/__init__.py | 2 +
> test/py/img/script_raw.py | 98 ++++++++++++++++++++++++++++++++++++++++++++++
> test/py/tests/fs_helper.py | 19 +++++----
> test/py/tests/test_ut.py | 3 ++
> 7 files changed, 205 insertions(+), 7 deletions(-)
> diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
> @@ -1948,4 +1949,84 @@ static int bootdev_hunt_fallthrough(struct unit_test_state *uts)
> + 0, /* legacy */
> + 0, /* fit */
> + -EINVAL, /* external */
> + -EINVAL, /* bad_crc */
> + -E2BIG, /* too_large */
> + -ENOENT, /* wrong_name */
> + -ENOEXEC, /* empty */
> + -EINVAL, /* bad_header */
> + -E2BIG, /* partition_size */
> + -EINVAL, /* bad_fit */
The raw bootmeth turns every image_locate_script() failure into
-EINVAL, so the external, bad_crc and bad_fit cases cannot tell which
check rejected the image. For example, if the external-data check in
patch 1 were dropped, the external case would still get -EINVAL from
somewhere else. Since the test already uses UTF_CONSOLE, it would be
worth checking the message for each case too, e.g. 'External FIT
script data is not supported' and 'Bad FIT image format'.
> diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
> @@ -1948,4 +1949,84 @@ static int bootdev_hunt_fallthrough(struct unit_test_state *uts)
> + bootflow_free(&bflow);
> + }
> +
> + return 0;
Please can you check that the scan ends after the last partition (i.e.
bootflow_scan_next() returns -ENODEV)? Otherwise an unexpected extra
bootflow would go unnoticed.
> diff --git a/test/boot/bootflow.c b/test/boot/bootflow.c
> @@ -1948,4 +1949,84 @@ static int bootdev_hunt_fallthrough(struct unit_test_state *uts)
> + ut_assertok(prep_mmc_bootdev(uts, "mmc12", false, &old_order));
> + ut_assertok(bootstd_get_priv(&std));
> + std->bootdev_order = order;
prep_mmc_bootdev() also binds the script bootmeth and sets its own
order {'mmc2', 'mmc1', 'mmc12'}, and you then override both straight
away. It would be clearer to bind mmc12 directly with lists_bind_fdt()
and set the order once, as bootflow_bls_prefix() and bootflow_rauc()
do.
> diff --git a/test/py/img/script_raw.py b/test/py/img/script_raw.py
> @@ -0,0 +1,98 @@
> + if case == 'bad_crc':
> + data[-1] ^= 1
> + elif case == 'too_large':
> + struct.pack_into('>I', data, 12, 2 * 1024 * 1024)
> + elif case == 'empty':
> + data = bytearray(512)
> + if case == 'too_large':
> + struct.pack_into('>I', data, 4, 0)
> + struct.pack_into('>I', data, 4, zlib.crc32(data[:64]))
> + return data
The corruption is split between script_image() and
setup_script_raw_image() for no obvious reason, and the header-CRC
fix-up is repeated in both. Please can you put all the per-case
changes in one place, with the CRC fix-up in a small helper? For
'empty' it would also be simpler to return early, before running
mkimage.
Regards,
Simon
^ permalink raw reply [flat|nested] 9+ messages in thread
end of thread, other threads:[~2026-10-26 16:14 UTC | newest]
Thread overview: 9+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-26 14:02 [PATCH v3 0/4] bootstd: Support scripts in raw partitions He Yong
2026-10-26 14:02 ` [PATCH v3 1/4] image: Bound FIT script checks by the image size He Yong
2026-10-26 16:14 ` Simon Glass
2026-10-26 14:02 ` [PATCH v3 2/4] bootstd: Export the script bootflow execution handler He Yong
2026-10-26 16:14 ` Simon Glass
2026-10-26 14:02 ` [PATCH v3 3/4] bootstd: Add a bootmeth for scripts in raw partitions He Yong
2026-10-26 16:14 ` Simon Glass
2026-10-26 14:02 ` [PATCH v3 4/4] test: bootstd: Cover scripts in raw partitions on sandbox He Yong
2026-10-26 16:14 ` Simon Glass
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.