mail archive of the barebox mailing list
 help / color / mirror / Atom feed
From: Ahmad Fatoum <a.fatoum@pengutronix.de>
To: barebox@lists.infradead.org
Cc: Ahmad Fatoum <a.fatoum@barebox.org>
Subject: [PATCH 2/2] test: py: add test for FIT images in global.of.overlay.path
Date: Thu, 15 Oct 2026 13:29:41 +0200	[thread overview]
Message-ID: <20261015112949.2983458-2-a.fatoum@pengutronix.de> (raw)
In-Reply-To: <20261015112949.2983458-1-a.fatoum@pengutronix.de>

From: Ahmad Fatoum <a.fatoum@barebox.org>

Applying overlays from a FIT image in global.of.overlay.path has no test
coverage so far.

Let's add a test that builds a FIT with three overlay configurations and
a kernel configuration and checks the fixed-up device tree: the kernel
configuration is skipped, the pattern and compatible filters are honoured
and an overlay with a bad hash is not applied.

Assisted-by: Claude:opus-5.5
Signed-off-by: Ahmad Fatoum <a.fatoum@barebox.org>
---
 test/py/test_of_overlay.py | 204 +++++++++++++++++++++++++++++++++++++
 1 file changed, 204 insertions(+)
 create mode 100644 test/py/test_of_overlay.py

diff --git a/test/py/test_of_overlay.py b/test/py/test_of_overlay.py
new file mode 100644
index 000000000000..8eb2e5e30aa7
--- /dev/null
+++ b/test/py/test_of_overlay.py
@@ -0,0 +1,204 @@
+# SPDX-License-Identifier: GPL-2.0-or-later
+
+import os
+import shutil
+import subprocess
+import pytest
+from .helper import skip_disabled, filter_errors
+
+TESTNODE = "/barebox-fit-overlay-test"
+
+# name: (compatible, value of the order property)
+OVERLAYS = {
+    "a": (None, "a"),
+    "b": ("barebox,fit-overlay-test-b", "b"),
+    "c": ("barebox,fit-overlay-test-c", "c"),
+    "kernel": (None, "kernel"),
+}
+
+ITS = """/dts-v1/;
+
+/ {
+	description = "global.of.overlay.path test";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			data = /incbin/("kernel.bin");
+			type = "kernel";
+			arch = "arm64";
+			os = "linux";
+			compression = "none";
+			hash-1 {
+				algo = "sha256";
+			};
+		};
+%s	};
+
+	configurations {
+		/* has a kernel, so it is not an overlay configuration */
+		conf-kernel {
+			kernel = "kernel";
+			fdt = "overlay-kernel";
+		};
+%s	};
+};
+"""
+
+ITS_OVERLAY = """		overlay-%s {
+			data = /incbin/("%s.dtbo");
+			type = "flat_dt";
+			arch = "arm64";
+			compression = "none";
+			hash-1 {
+				algo = "sha256";
+			};
+		};
+"""
+
+ITS_CONFIG = """		conf-%s {
+			fdt = "overlay-%s";
+		};
+"""
+
+
+def mkdtso(name, compatible, order):
+    compat = f'\tcompatible = "{compatible}";\n' if compatible else ""
+
+    return f"""/dts-v1/;
+/plugin/;
+
+/ {{
+{compat}	fragment@0 {{
+		target-path = "/";
+		__overlay__ {{
+			{TESTNODE[1:]} {{
+				applied-{name};
+				order = "{order}";
+			}};
+		}};
+	}};
+}};
+"""
+
+
+def run(cmd, **kwargs):
+    subprocess.run(cmd, check=True, **kwargs)
+
+
+@pytest.fixture(scope="module")
+def overlay_fit(testfs):
+    path = os.path.join(testfs, "of-overlay")
+    os.makedirs(path, exist_ok=True)
+
+    images = configs = ""
+    for name, (compatible, order) in OVERLAYS.items():
+        with open(os.path.join(path, f"{name}.dtso"), "w") as f:
+            f.write(mkdtso(name, compatible, order))
+
+        if name != "kernel":
+            images += ITS_OVERLAY % (name, name)
+            configs += ITS_CONFIG % (name, name)
+
+    images += ITS_OVERLAY % ("kernel", "kernel")
+
+    with open(os.path.join(path, "overlays.its"), "w") as f:
+        f.write(ITS % (images, configs))
+    with open(os.path.join(path, "kernel.bin"), "wb") as f:
+        f.write(b"not a kernel")
+
+    try:
+        for name in OVERLAYS:
+            run(["dtc", "-I", "dts", "-O", "dtb", "-o", f"{name}.dtbo",
+                 f"{name}.dtso"], cwd=path)
+        run(["mkimage", "-f", "overlays.its", "overlays.fit"], cwd=path,
+            stdout=subprocess.DEVNULL)
+    except FileNotFoundError as e:
+        shutil.rmtree(path)
+        pytest.skip(f"missing dependency: {e}")
+
+    # Change a property name in overlay-b, so its hash no longer matches
+    with open(os.path.join(path, "overlays.fit"), "rb") as f:
+        fit = f.read()
+    assert fit.count(b"applied-b") == 1
+    with open(os.path.join(path, "tampered.fit"), "wb") as f:
+        f.write(fit.replace(b"applied-b", b"applied-x"))
+
+    yield "/mnt/9p/testfs/of-overlay"
+
+    shutil.rmtree(path)
+
+
+@pytest.fixture(scope="function")
+def overlay_vars(barebox, barebox_config):
+    skip_disabled(barebox_config, "CONFIG_FITIMAGE", "CONFIG_OF_OVERLAY",
+                  "CONFIG_CMD_OF_DUMP")
+
+    yield
+
+    barebox.run_check('global.of.overlay.path=""')
+    barebox.run_check('global.of.overlay.pattern="*"')
+    barebox.run_check('global.of.overlay.compatible=""')
+
+
+def fixed_testnode(barebox):
+    """Return the applied overlays and the order property of the test node
+    in the device tree a kernel would be started with"""
+    stdout, _, returncode = barebox.run(f"of_dump -F -p {TESTNODE}")
+    if returncode != 0:
+        return set(), None, stdout
+
+    applied = {line[len("applied-"):-1] for line in stdout
+               if line.startswith("applied-")}
+    order = next((line.split('"')[1] for line in stdout
+                  if line.startswith("order = ")), None)
+
+    return applied, order, stdout
+
+
+def test_of_overlay_fit(barebox, overlay_vars, overlay_fit):
+    barebox.run_check(f"global.of.overlay.path={overlay_fit}/overlays.fit")
+
+    applied, order, stdout = fixed_testnode(barebox)
+
+    assert filter_errors(stdout) == [], stdout
+    # conf-kernel is skipped, the others are applied in FIT order
+    assert applied == {"a", "b", "c"}, stdout
+    assert order == "c", stdout
+
+    # Only the device tree passed to the kernel is changed
+    _, _, returncode = barebox.run(f"of_dump {TESTNODE}")
+    assert returncode != 0
+
+
+def test_of_overlay_fit_pattern(barebox, overlay_vars, overlay_fit):
+    barebox.run_check(f"global.of.overlay.path={overlay_fit}/overlays.fit")
+
+    # The pattern matches on the configuration name
+    barebox.run_check('global.of.overlay.pattern="conf-a overlay-b *-c"')
+    applied, order, stdout = fixed_testnode(barebox)
+    assert applied == {"a", "c"}, stdout
+    assert order == "c", stdout
+
+    barebox.run_check('global.of.overlay.pattern="conf-kernel"')
+    applied, _, stdout = fixed_testnode(barebox)
+    assert applied == set(), stdout
+
+
+def test_of_overlay_fit_compatible(barebox, overlay_vars, overlay_fit):
+    barebox.run_check(f"global.of.overlay.path={overlay_fit}/overlays.fit")
+
+    # Overlays without a compatible are always applied
+    barebox.run_check("global.of.overlay.compatible=barebox,fit-overlay-test-b")
+    applied, order, stdout = fixed_testnode(barebox)
+    assert applied == {"a", "b"}, stdout
+    assert order == "b", stdout
+
+
+def test_of_overlay_fit_bad_hash(barebox, overlay_vars, overlay_fit):
+    barebox.run_check(f"global.of.overlay.path={overlay_fit}/tampered.fit")
+
+    # overlay-b sets applied-x instead of applied-b in tampered.fit
+    applied, _, stdout = fixed_testnode(barebox)
+    assert "x" not in applied, stdout
+    assert any("hash BAD" in line for line in stdout), stdout
-- 
2.47.3




  reply	other threads:[~2026-10-15 11:31 UTC|newest]

Thread overview: 3+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-15 11:29 [PATCH 1/2] Documentation: devicetree: document overlays in a FIT image Ahmad Fatoum
2026-10-15 11:29 ` Ahmad Fatoum [this message]
2026-10-15 12:49 ` Sascha Hauer

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261015112949.2983458-2-a.fatoum@pengutronix.de \
    --to=a.fatoum@pengutronix.de \
    --cc=a.fatoum@barebox.org \
    --cc=barebox@lists.infradead.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox