On 1/28/26 5:48 PM, Sean Anderson wrote:
Hi Beleswar,

On 1/28/26 09:18, Beleswar Padhi wrote:
From: Marek Vasut <[email protected]>

When CONFIG_SPL_MULTI_DTB_FIT is enabled, multiple device trees are
packed inside the multidtb.fit FIT image. While the individual DTBs
and the FIT image start address are 8-byte aligned, the DTBs embedded
within the FIT image are not guaranteed to maintain 8-byte alignment.

This misalignment causes -FDT_ERR_ALIGNMENT failure in
setup_multi_dtb_fit() when locating the next available DTB within the
FIT blob and setting gd->fdt_blob, because of the recent libfdt
hardening since commit 0535e46d55d7 ("scripts/dtc: Update to upstream
version v1.7.2-35-g52f07dcca47c")

To fix this, check the image type when extracting FIT image data and
set the alignment size to 8 bytes (if not already) only for flat_dt
images. This ensures correct alignment for device tree blobs as per the
DT spec, while also allowing different alignment sizes for other image
types within the FIT.

Reported-by: Anshul Dalal <[email protected]>
Closes: https://lore.kernel.org/u-boot/[email protected]
Fixes: 0535e46d55d7 ("scripts/dtc: Update to upstream version v1.7.2-35-g52f07dcca47c")
Signed-off-by: Marek Vasut <[email protected]>
Signed-off-by: Beleswar Padhi <[email protected]>
---
Testing Done:
1. Boot tested on all TI K3 platforms.

v4: Changelog:
1. Align only the DTBs to 8-bytes, other images in a FIT can have their
    independent alignment. [Marek]

Link to v3:
https://lore.kernel.org/all/[email protected]/

v3: Changelog:
1. Default to 8-byte alignment for DTBs in mkimage instead of
    passing -B 0x8 in build command [Marek]
2. Remove previous R/Bs.

Link to v2:
https://lore.kernel.org/all/[email protected]/

v2: Changelog:
1. Carry R/B, Reported-by, Closes and Fixes tag.

Link to v1:
https://lore.kernel.org/all/[email protected]/

  tools/fit_image.c | 10 +++++++++-
  1 file changed, 9 insertions(+), 1 deletion(-)

Can you please update doc/mkimage.1 as well? There should be a note about
this under -E.

diff --git a/tools/fit_image.c b/tools/fit_image.c
index e865f65a400..f842c845771 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -682,9 +682,17 @@ static int fit_extract_data(struct image_tool_params *params, const char *fname)
      for (node = fdt_first_subnode(fdt, images);
           node >= 0;
           node = fdt_next_subnode(fdt, node)) {
-        const char *data;
+        const char *data, *type;
          int len;
+        /* Fallback to 8-byte alignment for DTBs if unaligned */
+        type = fdt_getprop(fdt, node, FIT_TYPE_PROP, &len);
+        if (type &&
+            len == sizeof("flat_dt") &&
+            !memcmp(type, "flat_dt", len) &&
+            align_size & 0x7)
+            align_size = 8;
+

Doesn't this increase the alignment for all images following the devicetree?

And actually, doesn't this happen too late? By the time we check whether the node is a devicetree, buf_ptr has already been updated. This check will only
affect the alignment of the *next* image in the FIT.
How about we turn this around this way, add up the alignments first to deal with allocation, and then fiddle with the buf_ptr based on the previous iteration to layout the images ?

diff --git a/tools/fit_image.c b/tools/fit_image.c
index e865f65a400..82ffd03c288 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -651,10 +651,9 @@ static int fit_extract_data(struct image_tool_params *params, const char *fname)
        int ret;
        int images;
        int node;
-       int image_number;
-       int align_size;
+       int align_size = 0;
+       int len = 0;

-       align_size = params->bl_len ? params->bl_len : 4;
        fd = mmap_fdt(params->cmdname, fname, 0, &fdt, &sbuf, false, false);
        if (fd < 0)
                return -EIO;
@@ -666,24 +665,54 @@ static int fit_extract_data(struct image_tool_params *params, const char *fname)
                ret = -EINVAL;
                goto err_munmap;
        }
-       image_number = fdtdec_get_child_count(fdt, images);
+
+       /* Add up all the alignments, we no longer need to count images. */
+       fdt_for_each_subnode(node, fdt, images) {
+               const char *type;
+               int len;
+
+               if (params->bl_len) {
+                       align_size += params->bl_len;
+                       continue;
+               }
+
+               type = fdt_getprop(fdt, node, FIT_TYPE_PROP, &len);
+               if (type && len == sizeof("flat_dt") && !memcmp(type, 
"flat_dt", len)) {
+                       align_size += 8; // or params->bl_len rounded up to 8 ?
+                       continue;
+               }
+
+               /* Default alignment to 4 Bytes */
+               align_size += 4;
+       }

        /*
         * Allocate space to hold the image data we will extract,
         * extral space allocate for image alignment to prevent overflow.
         */
-       buf = calloc(1, fit_size + (align_size * image_number));
+       buf = calloc(1, fit_size + align_size);
        if (!buf) {
                ret = -ENOMEM;
                goto err_munmap;
        }
        buf_ptr = 0;

-       for (node = fdt_first_subnode(fdt, images);
-            node >= 0;
-            node = fdt_next_subnode(fdt, node)) {
-               const char *data;
-               int len;
+       fdt_for_each_subnode(node, fdt, images) {
+               const char *data, *type;
+               int pl;
+
+               if (params->bl_len)
+                       align_size = 8;//params->bl_len;
+               else {
+                       type = fdt_getprop(fdt, node, FIT_TYPE_PROP, &pl);
+                       if (type && pl == sizeof("flat_dt") && !memcmp(type, 
"flat_dt", pl))
+                               align_size = 8; // or params->bl_len rounded up 
to 8 ?
+                       else    /* Default alignment to 4 Bytes */
+                               align_size = 8;
+               }
+
+               /* len is 0 in first round, else comes from previous round. */
+               buf_ptr += ALIGN(len, align_size);

                data = fdt_getprop(fdt, node, FIT_DATA_PROP, &len);
                if (!data)
@@ -716,10 +745,11 @@ static int fit_extract_data(struct image_tool_params *params, const char *fname)
                        ret = -EINVAL;
                        goto err_munmap;
                }
-
-               buf_ptr += ALIGN(len, align_size);
        }

+       /* comes from previous round. */
+       buf_ptr += ALIGN(len, align_size);
+
        /* Pack the FDT and place the data after it */
        fdt_pack(fdt);

--
From 7149d1052332b55242e5428ab762b6e20a60779e Mon Sep 17 00:00:00 2001
From: Marek Vasut <[email protected]>
Date: Wed, 28 Jan 2026 19:48:34 +0530
Subject: [PATCH] tools: fit_image: Fallback to 8-byte alignment for flat_dt
 images

When CONFIG_SPL_MULTI_DTB_FIT is enabled, multiple device trees are
packed inside the multidtb.fit FIT image. While the individual DTBs
and the FIT image start address are 8-byte aligned, the DTBs embedded
within the FIT image are not guaranteed to maintain 8-byte alignment.

This misalignment causes -FDT_ERR_ALIGNMENT failure in
setup_multi_dtb_fit() when locating the next available DTB within the
FIT blob and setting gd->fdt_blob, because of the recent libfdt
hardening since commit 0535e46d55d7 ("scripts/dtc: Update to upstream
version v1.7.2-35-g52f07dcca47c")

To fix this, check the image type when extracting FIT image data and
set the alignment size to 8 bytes (if not already) only for flat_dt
images. This ensures correct alignment for device tree blobs as per the
DT spec, while also allowing different alignment sizes for other image
types within the FIT.

Reported-by: Anshul Dalal <[email protected]>
Closes: https://lore.kernel.org/u-boot/[email protected]
Fixes: 0535e46d55d7 ("scripts/dtc: Update to upstream version v1.7.2-35-g52f07dcca47c")
Signed-off-by: Marek Vasut <[email protected]>
Signed-off-by: Beleswar Padhi <[email protected]>
---
 tools/fit_image.c | 54 ++++++++++++++++++++++++++++++++++++-----------
 1 file changed, 42 insertions(+), 12 deletions(-)

diff --git a/tools/fit_image.c b/tools/fit_image.c
index e865f65a400..82ffd03c288 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -651,10 +651,9 @@ static int fit_extract_data(struct image_tool_params *params, const char *fname)
 	int ret;
 	int images;
 	int node;
-	int image_number;
-	int align_size;
+	int align_size = 0;
+	int len = 0;
 
-	align_size = params->bl_len ? params->bl_len : 4;
 	fd = mmap_fdt(params->cmdname, fname, 0, &fdt, &sbuf, false, false);
 	if (fd < 0)
 		return -EIO;
@@ -666,24 +665,54 @@ static int fit_extract_data(struct image_tool_params *params, const char *fname)
 		ret = -EINVAL;
 		goto err_munmap;
 	}
-	image_number = fdtdec_get_child_count(fdt, images);
+
+	/* Add up all the alignments, we no longer need to count images. */
+	fdt_for_each_subnode(node, fdt, images) {
+		const char *type;
+		int len;
+
+		if (params->bl_len) {
+			align_size += params->bl_len;
+			continue;
+		}
+
+		type = fdt_getprop(fdt, node, FIT_TYPE_PROP, &len);
+		if (type && len == sizeof("flat_dt") && !memcmp(type, "flat_dt", len)) {
+			align_size += 8; // or params->bl_len rounded up to 8 ?
+			continue;
+		}
+
+		/* Default alignment to 4 Bytes */
+		align_size += 4;
+	}
 
 	/*
 	 * Allocate space to hold the image data we will extract,
 	 * extral space allocate for image alignment to prevent overflow.
 	 */
-	buf = calloc(1, fit_size + (align_size * image_number));
+	buf = calloc(1, fit_size + align_size);
 	if (!buf) {
 		ret = -ENOMEM;
 		goto err_munmap;
 	}
 	buf_ptr = 0;
 
-	for (node = fdt_first_subnode(fdt, images);
-	     node >= 0;
-	     node = fdt_next_subnode(fdt, node)) {
-		const char *data;
-		int len;
+	fdt_for_each_subnode(node, fdt, images) {
+		const char *data, *type;
+		int pl;
+
+		if (params->bl_len)
+			align_size = 8;//params->bl_len;
+		else {
+			type = fdt_getprop(fdt, node, FIT_TYPE_PROP, &pl);
+			if (type && pl == sizeof("flat_dt") && !memcmp(type, "flat_dt", pl))
+				align_size = 8; // or params->bl_len rounded up to 8 ?
+			else	/* Default alignment to 4 Bytes */
+				align_size = 8;
+		}
+
+		/* len is 0 in first round, else comes from previous round. */
+		buf_ptr += ALIGN(len, align_size);
 
 		data = fdt_getprop(fdt, node, FIT_DATA_PROP, &len);
 		if (!data)
@@ -716,10 +745,11 @@ static int fit_extract_data(struct image_tool_params *params, const char *fname)
 			ret = -EINVAL;
 			goto err_munmap;
 		}
-
-		buf_ptr += ALIGN(len, align_size);
 	}
 
+	/* comes from previous round. */
+	buf_ptr += ALIGN(len, align_size);
+
 	/* Pack the FDT and place the data after it */
 	fdt_pack(fdt);
 
-- 
2.51.0

Reply via email to