Bjørn Mork <bj...@mork.no> writes:

> Robert Marko <robima...@gmail.com> writes:
>
>> What should be done is to expand mkimage with an option to align to an
>> 8-byte boundary.
>
> Definitely.
>
> However, this implies that mkimage must mangle the output of libfdt to
> align one specific property.  AFAICS, there are no such possibilities in
> device tree.

Well, you made me take a closer look.  And I found one possibility:

libfdt supports overwriting properties with FDT_NOP.  So we can add an
empty property in front of the image data and overwrite it with nops.
This result is 3 x 4 byte FDT_NOP values

What do you think about something like the attached hack?

Is it OK to make this unconditional?  My reasoning is that it's pretty
hard to know when the alignment is required, the failures are arbitrary
and hard to debug, and it doesn't seem to harm. This adds 12 bytes to
every unaligned fdt node and that's it.

I'll try to run it by u-boot too if you think it's acceptable.

I tested this briefly, with a kernel I knew would cause an unaligned fdt
from previous failures.  The result looks like this and it booted fine
on my Unifi 6 Lite:

$ fdtdump 
bin/r21167+1-1673b7dca384/targets/ramips/mt7621/openwrt-snapshot-ramips-mt7621-ubnt_unifi-6-lite-squashfs-sysupgrade.bin
  | sed -e 's/\(data = \[.. .. .. .. .. .. .. .. .. .. .. .. .. 
\).*\(.....\].*\)/\1 ... \2/' |less

**** fdtdump is a low-level debugging tool, not meant for general use.
**** If you want to decompile a dtb, you probably want
****     dtc -I dtb -O dts <filename>

/dts-v1/;
// magic:               0xd00dfeed
// totalsize:           0x2d4e50 (2969168)
// off_dt_struct:       0x38
// off_dt_strings:      0x2d4a70
// off_mem_rsvmap:      0x28
// version:             17
// last_comp_version:   16
// boot_cpuid_phys:     0x0
// size_dt_strings:     0x72
// size_dt_struct:      0x2d4a38

/ {
    timestamp = <0x6366d7d8>;
    description = "MIPS OpenWrt FIT (Flattened Image Tree)";
    #address-cells = <0x00000001>;
    images {
        kernel-1 {
            description = "MIPS OpenWrt Linux-5.15.76";
            data = [6d 00 00 80 00 20 cd 96 00 00 00 00 00  ... a5 3e];
            type = "kernel";
            arch = "mips";
            os = "linux";
            compression = "lzma";
            load = <0x80001000>;
            entry = <0x80001000>;
            hash@1 {
                value = <0xbd771d3e>;
                algo = "crc32";
            };
            hash@2 {
                value = <0x7c11c808 0x508aada9 0x2f14f1b1 0x6b6d7e89 
0x652dd798>;
                algo = "sha1";
            };
        };
        fdt-1 {
            // [NOP]
            // [NOP]
            // [NOP]
            description = "MIPS OpenWrt ubnt_unifi-6-lite device tree blob";
            data = [d0 0d fe ed 00 00 2c 7b 00 00 00 38 00  ... 65 00];
            type = "flat_dt";
            arch = "mips";
            compression = "none";
            hash@1 {
                value = <0x16bb5a14>;
                algo = "crc32";
            };
            hash@2 {
                value = <0x40f26bf2 0x8e33bbe6 0x61fec716 0x929f2003 
0x301f5e4d>;
                algo = "sha1";
            };
        };
    };
    configurations {
        default = "config@1";
        config@1 {
            description = "OpenWrt ubnt_unifi-6-lite";
            kernel = "kernel-1";
            fdt = "fdt-1";
        };
    };
};

$ binwalk 
bin/r21167+1-1673b7dca384/targets/ramips/mt7621/openwrt-snapshot-ramips-mt7621-ubnt_unifi-6-lite-squashfs-sysupgrade.bin
 

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
0             0x0             Flattened device tree, size: 2969168 bytes, 
version: 17
228           0xE4            LZMA compressed data, properties: 0x6D, 
dictionary size: 8388608 bytes, uncompressed size: 9882912 bytes
2956440       0x2D1C98        Flattened device tree, size: 11387 bytes, 
version: 17
2969168       0x2D4E50        Squashfs filesystem, little endian, version 4.0, 
compression:xz, size: 5224258 bytes, 1061 inodes, blocksize: 262144 bytes, 
created: 2022-11-05 21:38:32


Bjørn

>From 2a81e80aed1e0f8f4cd947f77ce45c9f4358e2fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Mork?= <bj...@mork.no>
Date: Sat, 5 Nov 2022 22:33:31 +0100
Subject: [PATCH] mkimage: Align fdt images in FIT to 8 bytes
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Bjørn Mork <bj...@mork.no>
---
 tools/fit_image.c | 48 +++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/tools/fit_image.c b/tools/fit_image.c
index 923a9755b709..f0ef3333aa7d 100644
--- a/tools/fit_image.c
+++ b/tools/fit_image.c
@@ -24,6 +24,50 @@
 
 static struct legacy_img_hdr header;
 
+#define FIT_NOP_PROP	"x-nop"
+
+/**
+ * fit_align_fdt_images() - Align all fdt images in the FIT to 8 bytes
+ *
+ * An fdt image must be 8 byte aligned to be used "in place".  Verify
+ * that all images are properly aligned, and insert 3 FDT_NOP tags in
+ * front of the imaga "data" property if necessary.
+ */
+static int fit_align_fdt_images(void *fit)
+{
+	int images_noffset;
+	int noffset;
+	uint8_t type;
+	size_t size;
+	const void *ptr;
+
+	images_noffset = fdt_path_offset(fit, FIT_IMAGES_PATH);
+	if (images_noffset < 0) {
+		printf("Can't find images parent node '%s' (%s)\n",
+		       FIT_IMAGES_PATH, fdt_strerror(images_noffset));
+		return images_noffset;
+	}
+
+	for (noffset = fdt_first_subnode(fit, images_noffset);
+	     noffset >= 0;
+	     noffset = fdt_next_subnode(fit, noffset)) {
+		fit_image_get_type(fit, noffset, &type);
+		if (type != IH_TYPE_FLATDT)
+			continue;
+
+		fit_image_get_data(fit, noffset, &ptr, &size);
+		debug("%s: Found fdt with size %zu at offset %zu\n", size, ptr - fit);
+		if ((ptr - fit) % 8 == 0)
+			continue;
+
+		/* Insert an empty dummy property and overwrite it with FDT_NOP */
+		debug("Aligning 8 byte boundary by adding 3 FDT_NOP tags\n");
+		fdt_setprop_empty(fit, noffset, FIT_NOP_PROP);
+		fdt_nop_property(fit, noffset, FIT_NOP_PROP);
+	}
+	return 0;
+}
+
 static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
 			     const char *tmpfile)
 {
@@ -81,6 +125,10 @@ static int fit_add_file_data(struct image_tool_params *params, size_t size_inc,
 						&params->summary);
 	}
 
+	if (!ret) {
+		ret = fit_align_fdt_images(ptr);
+	}
+
 	if (dest_blob) {
 		munmap(dest_blob, destfd_size);
 		close(destfd);
-- 
2.30.2

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to