summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTom Rini <trini@konsulko.com>2026-08-14 10:31:51 -0600
committerTom Rini <trini@konsulko.com>2026-08-14 10:33:22 -0600
commitcf51beb755939728b119a8762b06b6c186f53429 (patch)
treefab7e9572c5d66475ca003f28460a5a77004a8f7
parentd3e8597e46b635ec556a057bc42f0b0859654bdf (diff)
parentdbe1b57e16caa3587c14a4abcf63559a6833742a (diff)
downloadu-boot-cf51beb755939728b119a8762b06b6c186f53429.tar.gz
u-boot-cf51beb755939728b119a8762b06b6c186f53429.zip
Merge patch series "mkimage: detect FIT image load address overlaps"
Aristo Chen <aristo.chen@canonical.com>m says: This series brings back the FIT load address overlap detection that was applied to next in September 2025 and reverted a day later in commit e482fdbbca93 ("Revert "Merge patch series "mkimage: Detect FIT image load address overlaps and fix related test/DTS issues"""). The v2 revert had two causes. On TI AM62x family boards the tispl FIT image references the mutually exclusive tifsstub variants at a single shared load address, and v2 tried to satisfy the checker by moving the variants 64 KiB apart. Neha had warned in the v1 review that this address is fixed by the platform and that moving the images would break tifsstub selection, and that feedback was regrettably still unaddressed when the series was applied. Nishanth then hit exactly this class of failure in the K3 upstream boot build with real firmware binaries, where am62px_evm, a board v2 had not even touched, failed the new check on tifsstub-hs and tifsstub-fs sharing 0x9ca00000. Separately, E Shattow reported an overlap on the StarFive VisionFive 2, which we later narrowed down to OpenSBI fw_payload.bin having been passed to the build instead of the documented fw_dynamic.bin. With fw_dynamic.bin the board has no overlap, as confirmed on the list in January 2026. Since then the structural fix for the tifsstub case has landed. The series merged as commit 4e7a9bb0885e ("Merge patch series "arm: k3: replace tifsstub runtime filter with per-state FIT configurations"") gives each K3 security state its own FIT configuration referencing only the matching tifsstub variant, so a per configuration overlap check sees no conflict while the variants keep their required common load address. That series was written precisely to unblock this one. The underlying semantics, that overlap is a property of a single configuration and that images referenced by different configurations never coexist in memory, were discussed with the FIT spec folks in flat-image-tree issue #32 [1]. The check itself is unchanged in spirit: for every configuration, collect the load regions of all referenced images that have both a load address and data, and fail the build if any two regions within that configuration intersect. Images referenced only by different configurations may freely share addresses. Verification done for this version: Running the new mkimage in reprocess mode over every FIT produced by current master builds of am62x_evm, verdin-am62 and phycore_am62x (A53 and R5 each) flags exactly one problem: the phycore u-boot FIT, where the four SPL devicetree overlays are loaded simultaneously from one configuration but are spaced only 4 KiB apart while each packaged image measures 5.9 to 6.1 KiB including its ti-secure certificate. That is a real overlap shipping today and patch 4 widens the spacing. All tispl FITs with the per-state tifsstub configurations pass. buildman with binman missing blob handling, matching CI, builds all of phycore_am62x, phycore_am62ax, phycore_am64x, am62x_evm, am62ax_evm, am62px_evm, am64x_evm, verdin-am62, verdin-am62p and am62x_beagleplay (A53 and R5 each) plus starfive_visionfive2 with the check active, since binman invokes the freshly built mkimage during these builds. starfive_visionfive2 was additionally built with a real OpenSBI 1.7 fw_dynamic.bin passed via OPENSBI and completes cleanly. The binman functional test suite shows no new failures compared to master in the same environment. The nine tests whose fixtures are touched by patches 1 to 3, including the OpenSSL engine and PKCS11 signing tests that only run when softhsm2 and opensc are available, all pass. The mkimage validation pytests, including the two new ones, pass against a sandbox build. [1] https://github.com/open-source-firmware/flat-image-tree/issues/32 Link: https://lore.kernel.org/r/20260731001347.35624-1-aristo.chen@canonical.com
-rw-r--r--arch/arm/dts/k3-am625-phycore-som-binman.dtsi6
-rw-r--r--arch/arm/dts/k3-am62a-phycore-som-binman.dtsi6
-rw-r--r--arch/arm/dts/k3-am642-phycore-som-binman.dtsi6
-rw-r--r--test/py/tests/test_fit_mkimage_validate.py136
-rw-r--r--tools/binman/etype/fit.py26
-rw-r--r--tools/binman/ftest.py4
-rw-r--r--tools/binman/test/Makefile8
l---------tools/binman/test/elf_sections_tee.c1
-rw-r--r--tools/binman/test/elf_sections_tee.lds35
-rw-r--r--tools/binman/test/fit/firmware_loadables.dts4
-rw-r--r--tools/binman/test/fit/key_name_hint_dir_signature.dts4
-rw-r--r--tools/binman/test/fit/signature.dts4
-rw-r--r--tools/binman/test/fit/signature_engine.dts4
-rw-r--r--tools/binman/test/fit/signature_engine_encrypt.dts4
-rw-r--r--tools/binman/test/fit/signature_engine_pkcs11.dts4
-rw-r--r--tools/binman/test/fit/signature_engine_pkcs11_object.dts4
-rw-r--r--tools/binman/test/fit/signature_multi_key.dts4
-rw-r--r--tools/binman/test/fit/signature_no_nodes.dts4
-rw-r--r--tools/fit_image.c99
-rw-r--r--tools/mkimage.c3
20 files changed, 334 insertions, 32 deletions
diff --git a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi
index 6d57a5d9ffa..d0eaa7dd992 100644
--- a/arch/arm/dts/k3-am625-phycore-som-binman.dtsi
+++ b/arch/arm/dts/k3-am625-phycore-som-binman.dtsi
@@ -368,7 +368,7 @@
description = "k3-am6xx-phycore-disable-spi-nor";
type = "flat_dt";
compression = "none";
- load = <0x8F001000>;
+ load = <0x8F004000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_spi_not_dtbo>;
@@ -383,7 +383,7 @@
description = "k3-am6xx-phycore-disable-eth-phy";
type = "flat_dt";
compression = "none";
- load = <0x8F002000>;
+ load = <0x8F008000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_eth_phy_dtbo>;
@@ -398,7 +398,7 @@
description = "k3-am6xx-phycore-qspi-nor";
type = "flat_dt";
compression = "none";
- load = <0x8F003000>;
+ load = <0x8F00C000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_qspi_nor_dtbo>;
diff --git a/arch/arm/dts/k3-am62a-phycore-som-binman.dtsi b/arch/arm/dts/k3-am62a-phycore-som-binman.dtsi
index cdc9a100a04..2c98e16b00b 100644
--- a/arch/arm/dts/k3-am62a-phycore-som-binman.dtsi
+++ b/arch/arm/dts/k3-am62a-phycore-som-binman.dtsi
@@ -295,7 +295,7 @@
description = "k3-am6xx-phycore-disable-spi-nor";
type = "flat_dt";
compression = "none";
- load = <0x8F001000>;
+ load = <0x8F004000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_spi_not_dtbo>;
@@ -310,7 +310,7 @@
description = "k3-am6xx-phycore-disable-eth-phy";
type = "flat_dt";
compression = "none";
- load = <0x8F002000>;
+ load = <0x8F008000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_eth_phy_dtbo>;
@@ -325,7 +325,7 @@
description = "k3-am6xx-phycore-qspi-nor";
type = "flat_dt";
compression = "none";
- load = <0x8F003000>;
+ load = <0x8F00C000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_qspi_nor_dtbo>;
diff --git a/arch/arm/dts/k3-am642-phycore-som-binman.dtsi b/arch/arm/dts/k3-am642-phycore-som-binman.dtsi
index 07cb79fd04a..64679195e72 100644
--- a/arch/arm/dts/k3-am642-phycore-som-binman.dtsi
+++ b/arch/arm/dts/k3-am642-phycore-som-binman.dtsi
@@ -402,7 +402,7 @@
description = "k3-am6xx-phycore-disable-spi-nor";
type = "flat_dt";
compression = "none";
- load = <0x8F001000>;
+ load = <0x8F004000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_spi_not_dtbo>;
@@ -417,7 +417,7 @@
description = "k3-am6xx-phycore-disable-eth-phy";
type = "flat_dt";
compression = "none";
- load = <0x8F002000>;
+ load = <0x8F008000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_eth_phy_dtbo>;
@@ -432,7 +432,7 @@
description = "k3-am6xx-phycore-qspi-nor";
type = "flat_dt";
compression = "none";
- load = <0x8F003000>;
+ load = <0x8F00C000>;
arch = "arm";
ti-secure {
content = <&am6xx_phycore_disable_qspi_nor_dtbo>;
diff --git a/test/py/tests/test_fit_mkimage_validate.py b/test/py/tests/test_fit_mkimage_validate.py
index 5922f071dd8..7c9213b2796 100644
--- a/test/py/tests/test_fit_mkimage_validate.py
+++ b/test/py/tests/test_fit_mkimage_validate.py
@@ -160,3 +160,139 @@ def test_fit_auto_basename_dotted_directory(ubman, dtb_relpath, expected_desc):
assert desc == expected_desc, (
f"Expected /images/fdt-1 description {expected_desc!r}, got {desc!r}"
)
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.requiredtool('dtc')
+def test_fit_load_addr_overlap(ubman):
+ """Test that mkimage fails when images in one config overlap in memory"""
+
+ its_fname = fit_util.make_fname(ubman, "overlap.its")
+ itb_fname = fit_util.make_fname(ubman, "overlap.itb")
+ kernel = fit_util.make_kernel(ubman, 'kernel.bin', 'kernel')
+ fdt = fit_util.make_dtb(ubman, '''
+/dts-v1/;
+/ {
+ model = "Test FDT";
+ compatible = "test";
+};
+''', 'test')
+
+ # Write ITS with kernel and FDT sharing the same load address
+ its_text = '''
+/dts-v1/;
+
+/ {
+ images {
+ kernel@1 {
+ description = "Test Kernel";
+ data = /incbin/("kernel.bin");
+ type = "kernel";
+ arch = "sandbox";
+ os = "linux";
+ compression = "none";
+ load = <0x40000>;
+ entry = <0x40000>;
+ };
+ fdt@1 {
+ description = "Test FDT";
+ data = /incbin/("test.dtb");
+ type = "flat_dt";
+ arch = "sandbox";
+ os = "linux";
+ compression = "none";
+ load = <0x40000>;
+ entry = <0x40000>;
+ };
+ };
+
+ configurations {
+ default = "conf@1";
+ conf@1 {
+ kernel = "kernel@1";
+ fdt = "fdt@1";
+ };
+ };
+};
+'''
+
+ with open(its_fname, 'w') as f:
+ f.write(its_text)
+
+ mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage')
+ cmd = [mkimage, '-f', its_fname, itb_fname]
+
+ result = subprocess.run(cmd, capture_output=True, text=True)
+
+ assert result.returncode != 0, "mkimage should fail due to memory overlap"
+ assert "has overlapping load regions" in result.stderr
+ # Check that it identifies the configuration and the specific
+ # overlapping components
+ assert "conf@1" in result.stderr
+ assert "kernel@1" in result.stderr and "fdt@1" in result.stderr
+
+@pytest.mark.boardspec('sandbox')
+@pytest.mark.requiredtool('dtc')
+def test_fit_same_load_addr_different_configs(ubman):
+ """Test that images may share a load address across configurations
+
+ Only one configuration is selected at runtime, so images that are
+ referenced by different configurations never coexist in memory. This
+ mirrors the TI K3 tispl layout, where each security state has its own
+ configuration and all tifsstub variants use the same load address.
+ """
+
+ its_fname = fit_util.make_fname(ubman, "exclusive.its")
+ itb_fname = fit_util.make_fname(ubman, "exclusive.itb")
+ kernel = fit_util.make_kernel(ubman, 'kernel.bin', 'kernel')
+
+ its_text = '''
+/dts-v1/;
+
+/ {
+ images {
+ kernel@1 {
+ description = "Test Kernel HS";
+ data = /incbin/("kernel.bin");
+ type = "kernel";
+ arch = "sandbox";
+ os = "linux";
+ compression = "none";
+ load = <0x40000>;
+ entry = <0x40000>;
+ };
+ kernel@2 {
+ description = "Test Kernel GP";
+ data = /incbin/("kernel.bin");
+ type = "kernel";
+ arch = "sandbox";
+ os = "linux";
+ compression = "none";
+ load = <0x40000>;
+ entry = <0x40000>;
+ };
+ };
+
+ configurations {
+ default = "conf@1";
+ conf@1 {
+ kernel = "kernel@1";
+ };
+ conf@2 {
+ kernel = "kernel@2";
+ };
+ };
+};
+'''
+
+ with open(its_fname, 'w') as f:
+ f.write(its_text)
+
+ mkimage = os.path.join(ubman.config.build_dir, 'tools/mkimage')
+ cmd = [mkimage, '-f', its_fname, itb_fname]
+
+ result = subprocess.run(cmd, capture_output=True, text=True)
+
+ assert result.returncode == 0, (
+ f"mkimage should accept same load address in different configs:\n"
+ f"stderr:\n{result.stderr}"
+ )
diff --git a/tools/binman/etype/fit.py b/tools/binman/etype/fit.py
index 32caa03a7e1..4657ed1fd76 100644
--- a/tools/binman/etype/fit.py
+++ b/tools/binman/etype/fit.py
@@ -319,6 +319,32 @@ class Entry_fit(Entry_section):
Generates a `load = <...>` property with the load address of the
segment
+ Note: The load address comes from the ELF file's program headers.
+ To determine where an ELF file will be loaded, you can:
+
+ 1. Use readelf to examine the program headers:
+
+ ``readelf -l your_elf_file.elf``
+
+ Look for the LOAD segments and their VirtAddr (Virtual Address)
+
+ 2. Check the linker script (.lds file) used to build the ELF:
+ look for the `. = <address>;` statements which set the location
+ counter and determine load addresses for different sections
+
+ 3. Use objdump to see section addresses:
+
+ ``objdump -h your_elf_file.elf``
+
+ For example, in binman tests, elf_sections.lds sets the ATF load
+ address to 0x00000010, while elf_sections_tee.lds sets the TEE
+ load address to 0x00100010 to avoid memory overlap conflicts.
+
+ Note that the mkimage load address overlap check compares the
+ packaged data size of each image, so it assumes uncompressed
+ images: a compressed image occupies more memory after
+ decompression than the check accounts for.
+
fit,entry
Generates a `entry = <...>` property with the entry address of the
ELF. This is only produced for the first entry
diff --git a/tools/binman/ftest.py b/tools/binman/ftest.py
index 66695a83508..f79d2a05c58 100644
--- a/tools/binman/ftest.py
+++ b/tools/binman/ftest.py
@@ -253,7 +253,7 @@ class TestFunctional(unittest.TestCase):
TestFunctional._MakeInputFile('bl31.elf',
tools.read_file(cls.ElfTestFile('elf_sections')))
TestFunctional.tee_elf_path = TestFunctional._MakeInputFile('tee.elf',
- tools.read_file(cls.ElfTestFile('elf_sections')))
+ tools.read_file(cls.ElfTestFile('elf_sections_tee')))
# Newer OP_TEE file in v1 binary format
cls.make_tee_bin('tee.bin')
@@ -8514,7 +8514,7 @@ fdt fdtmap Extract the devicetree blob from the fdtmap
'Node \'/binman/fit\': multiple key paths found',
str(e.exception))
- def testFitSignNoSingatureNodes(self):
+ def testFitSignNoSignatureNodes(self):
"""Test that fit,sign doens't raise error if no signature nodes found"""
if not elf.ELF_TOOLS:
self.skipTest('Python elftools not available')
diff --git a/tools/binman/test/Makefile b/tools/binman/test/Makefile
index 6b42db6559f..783bb4f62cd 100644
--- a/tools/binman/test/Makefile
+++ b/tools/binman/test/Makefile
@@ -30,13 +30,14 @@ LDS_BINMAN_BAD := -T $(SRC)u_boot_binman_syms_bad.lds
LDS_BINMAN_X86 := -T $(SRC)u_boot_binman_syms_x86.lds
LDS_BINMAN_EMBED := -T $(SRC)u_boot_binman_embed.lds
LDS_EFL_SECTIONS := -T $(SRC)elf_sections.lds
+LDS_EFL_SECTIONS_TEE := -T $(SRC)elf_sections_tee.lds
LDS_BLOB := -T $(SRC)blob_syms.lds
TARGETS = u_boot_ucode_ptr u_boot_no_ucode_ptr bss_data bss_data_zero \
u_boot_binman_syms u_boot_binman_syms.bin u_boot_binman_syms_bad \
u_boot_binman_syms_size u_boot_binman_syms_x86 embed_data \
- u_boot_binman_embed u_boot_binman_embed_sm elf_sections blob_syms.bin \
- dummy-rsa-engine.so
+ u_boot_binman_embed u_boot_binman_embed_sm elf_sections \
+ elf_sections_tee blob_syms.bin dummy-rsa-engine.so
all: $(TARGETS)
@@ -85,6 +86,9 @@ blob_syms: blob_syms.c
elf_sections: CFLAGS += $(LDS_EFL_SECTIONS)
elf_sections: elf_sections.c
+elf_sections_tee: CFLAGS += $(LDS_EFL_SECTIONS_TEE)
+elf_sections_tee: elf_sections_tee.c
+
dummy-rsa-engine.so: $(SRC)fit/dummy-rsa-engine.c
$(CC) -fPIC -shared -lcrypto -lssl -o $@ $<
diff --git a/tools/binman/test/elf_sections_tee.c b/tools/binman/test/elf_sections_tee.c
new file mode 120000
index 00000000000..01b200a365e
--- /dev/null
+++ b/tools/binman/test/elf_sections_tee.c
@@ -0,0 +1 @@
+elf_sections.c \ No newline at end of file
diff --git a/tools/binman/test/elf_sections_tee.lds b/tools/binman/test/elf_sections_tee.lds
new file mode 100644
index 00000000000..6074b45a1f9
--- /dev/null
+++ b/tools/binman/test/elf_sections_tee.lds
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Copyright (c) 2016 Google, Inc
+ * Copyright (c) 2026 Canonical Ltd.
+ *
+ * Mirrors elf_sections.lds with the addresses shifted up by 0x100000 so
+ * the TEE image does not overlap the ATF image; keep the two in sync.
+ */
+
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = 0x00100010;
+ _start = .;
+
+ . = ALIGN(4);
+ .text :
+ {
+ *(.text*)
+ }
+
+ . = 0x00101000;
+ .sram :
+ {
+ *(.sram*)
+ }
+
+ /DISCARD/ : {
+ *(.comment)
+ *(.dyn*)
+ }
+}
diff --git a/tools/binman/test/fit/firmware_loadables.dts b/tools/binman/test/fit/firmware_loadables.dts
index 2f79cdc9bb8..d344036a11a 100644
--- a/tools/binman/test/fit/firmware_loadables.dts
+++ b/tools/binman/test/fit/firmware_loadables.dts
@@ -19,8 +19,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/key_name_hint_dir_signature.dts b/tools/binman/test/fit/key_name_hint_dir_signature.dts
index 96e2126dadb..33b4ff8ea02 100644
--- a/tools/binman/test/fit/key_name_hint_dir_signature.dts
+++ b/tools/binman/test/fit/key_name_hint_dir_signature.dts
@@ -20,8 +20,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/signature.dts b/tools/binman/test/fit/signature.dts
index 9dce62e52de..1c25d52cba4 100644
--- a/tools/binman/test/fit/signature.dts
+++ b/tools/binman/test/fit/signature.dts
@@ -20,8 +20,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/signature_engine.dts b/tools/binman/test/fit/signature_engine.dts
index fd374e0edd2..ba4df53a0c0 100644
--- a/tools/binman/test/fit/signature_engine.dts
+++ b/tools/binman/test/fit/signature_engine.dts
@@ -21,8 +21,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/signature_engine_encrypt.dts b/tools/binman/test/fit/signature_engine_encrypt.dts
index fbcde342c65..40090431459 100644
--- a/tools/binman/test/fit/signature_engine_encrypt.dts
+++ b/tools/binman/test/fit/signature_engine_encrypt.dts
@@ -22,8 +22,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/signature_engine_pkcs11.dts b/tools/binman/test/fit/signature_engine_pkcs11.dts
index 60ba04c13d4..8d86c994afe 100644
--- a/tools/binman/test/fit/signature_engine_pkcs11.dts
+++ b/tools/binman/test/fit/signature_engine_pkcs11.dts
@@ -21,8 +21,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/signature_engine_pkcs11_object.dts b/tools/binman/test/fit/signature_engine_pkcs11_object.dts
index 5226ab4c6cf..48cd963476d 100644
--- a/tools/binman/test/fit/signature_engine_pkcs11_object.dts
+++ b/tools/binman/test/fit/signature_engine_pkcs11_object.dts
@@ -22,8 +22,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/signature_multi_key.dts b/tools/binman/test/fit/signature_multi_key.dts
index 77bec8df1e5..3b8da190b42 100644
--- a/tools/binman/test/fit/signature_multi_key.dts
+++ b/tools/binman/test/fit/signature_multi_key.dts
@@ -20,8 +20,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/binman/test/fit/signature_no_nodes.dts b/tools/binman/test/fit/signature_no_nodes.dts
index 267105d0f68..2ac600b1c70 100644
--- a/tools/binman/test/fit/signature_no_nodes.dts
+++ b/tools/binman/test/fit/signature_no_nodes.dts
@@ -20,8 +20,8 @@
arch = "arm64";
os = "u-boot";
compression = "none";
- load = <0x00000000>;
- entry = <0x00000000>;
+ load = <0x00002000>;
+ entry = <0x00002000>;
u-boot-nodtb {
};
diff --git a/tools/fit_image.c b/tools/fit_image.c
index 7e59bc43b77..f0fe68894d6 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -24,6 +24,18 @@
static struct legacy_img_hdr header;
+struct fit_region {
+ ulong load;
+ ulong size;
+ const char *name;
+};
+
+static bool fit_regions_overlap(const struct fit_region *a,
+ const struct fit_region *b)
+{
+ return a->load < b->load + b->size && b->load < a->load + a->size;
+}
+
static int fit_estimate_hash_sig_size(struct image_tool_params *params, const char *fname)
{
bool signing = IMAGE_ENABLE_SIGN &&
@@ -905,6 +917,8 @@ static int fit_import_data(struct image_tool_params *params, const char *fname)
int images;
int confs;
int node;
+ struct fit_region *regions = NULL;
+ unsigned int regions_alloc = 0;
fd = mmap_fdt(params->cmdname, fname, 0, &old_fdt, &sbuf, false, false);
if (fd < 0)
@@ -1009,6 +1023,7 @@ static int fit_import_data(struct image_tool_params *params, const char *fname)
fdt_for_each_subnode(node, fdt, confs) {
const char *conf_name = fdt_get_name(fdt, node, NULL);
+ unsigned int reg_count = 0;
for (int i = 0; i < ARRAY_SIZE(props); i++) {
int count = fdt_stringlist_count(fdt, node, props[i]);
@@ -1017,6 +1032,11 @@ static int fit_import_data(struct image_tool_params *params, const char *fname)
continue;
for (int j = 0; j < count; j++) {
+ const char *img_data;
+ ulong img_load;
+ int img_size;
+ unsigned int k;
+
const char *img_name =
fdt_stringlist_get(fdt, node, props[i], j, NULL);
if (!img_name || !*img_name)
@@ -1031,10 +1051,88 @@ static int fit_import_data(struct image_tool_params *params, const char *fname)
ret = FDT_ERR_NOTFOUND;
goto err_munmap;
}
+
+ /*
+ * Collect the memory region the image is
+ * loaded to. Images without a load address or
+ * without data are never copied anywhere, so
+ * they cannot conflict.
+ */
+ if (fit_image_get_load(fdt, img, &img_load))
+ continue;
+ img_data = fdt_getprop(fdt, img, FIT_DATA_PROP,
+ &img_size);
+ if (!img_data || img_size <= 0)
+ continue;
+
+ /*
+ * A configuration may reference one image
+ * through several properties, for example
+ * both "firmware" and "loadables". Count
+ * each image only once.
+ */
+ for (k = 0; k < reg_count; k++) {
+ if (!strcmp(regions[k].name, img_name))
+ break;
+ }
+ if (k < reg_count)
+ continue;
+
+ if (reg_count == regions_alloc) {
+ struct fit_region *tmp;
+
+ regions_alloc = regions_alloc ?
+ regions_alloc * 2 : 8;
+ tmp = realloc(regions, regions_alloc *
+ sizeof(*regions));
+ if (!tmp) {
+ fprintf(stderr,
+ "%s: Out of memory for %u load regions\n",
+ params->cmdname,
+ regions_alloc);
+ ret = -ENOMEM;
+ goto err_munmap;
+ }
+ regions = tmp;
+ }
+
+ regions[reg_count].load = img_load;
+ regions[reg_count].size = img_size;
+ regions[reg_count].name = img_name;
+ reg_count++;
+ }
+ }
+
+ /*
+ * All images referenced by one configuration are loaded
+ * together, so no two of them may claim overlapping memory
+ * regions. Images sharing a load address across different
+ * configurations are fine, since only one configuration is
+ * selected at runtime.
+ */
+ for (unsigned int i = 0; i < reg_count; i++) {
+ for (unsigned int j = i + 1; j < reg_count; j++) {
+ if (!fit_regions_overlap(&regions[i],
+ &regions[j]))
+ continue;
+ fprintf(stderr,
+ "Error: configuration '%s' has overlapping load regions:\n"
+ " - %s: [0x%lx - 0x%lx]\n"
+ " - %s: [0x%lx - 0x%lx]\n",
+ conf_name,
+ regions[i].name, regions[i].load,
+ regions[i].load + regions[i].size,
+ regions[j].name, regions[j].load,
+ regions[j].load + regions[j].size);
+ ret = FDT_ERR_BADSTRUCTURE;
+ goto err_munmap;
}
}
}
+ free(regions);
+ regions = NULL;
+
munmap(old_fdt, sbuf.st_size);
/* Close the old fd so we can re-use it. */
@@ -1067,6 +1165,7 @@ static int fit_import_data(struct image_tool_params *params, const char *fname)
err_munmap:
munmap(old_fdt, sbuf.st_size);
err:
+ free(regions);
free(fdt);
close(fd);
return ret;
diff --git a/tools/mkimage.c b/tools/mkimage.c
index 3c43962807d..6b3fd60adbf 100644
--- a/tools/mkimage.c
+++ b/tools/mkimage.c
@@ -550,7 +550,8 @@ int main(int argc, char **argv)
retval = tparams->fflag_handle(&params);
if (retval != EXIT_SUCCESS) {
- if (retval == FDT_ERR_NOTFOUND) {
+ if (retval == FDT_ERR_NOTFOUND ||
+ retval == FDT_ERR_BADSTRUCTURE) {
// Already printed error, exit cleanly
exit(EXIT_FAILURE);
}