diff options
| author | Tom Rini <trini@konsulko.com> | 2026-08-14 10:31:51 -0600 |
|---|---|---|
| committer | Tom Rini <trini@konsulko.com> | 2026-08-14 10:33:22 -0600 |
| commit | cf51beb755939728b119a8762b06b6c186f53429 (patch) | |
| tree | fab7e9572c5d66475ca003f28460a5a77004a8f7 | |
| parent | d3e8597e46b635ec556a057bc42f0b0859654bdf (diff) | |
| parent | dbe1b57e16caa3587c14a4abcf63559a6833742a (diff) | |
| download | u-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
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(®ions[i], + ®ions[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(¶ms); 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); } |
