[U-Boot] [PATCH v5 3/3] fit: Support compat string property in configuration node

Julius Werner jwerner at chromium.org
Thu Jul 11 20:53:20 UTC 2019


This patch adds support for an optional optimization to compatible
string matching where the compatible string property from the root node
of the kernel FDT can be copied into the configuration node of the FIT
image. This is most useful when using compressed FDTs or when using FDT
overlays, where the traditional extraction of the compatible string from
the kernel FDT itself is not easily possible.

Signed-off-by: Julius Werner <jwerner at chromium.org>
---
 - No changes for v2
 - No changes for v3
 - Changes for v4:
   - Added documentation for compatible string in config node.
   - Added example .its file for compressed FDT with compat string in
     config node.
 - No changes for v5

 common/image-fit.c                        | 67 ++++++++++++---------
 doc/uImage.FIT/kernel_fdts_compressed.its | 73 +++++++++++++++++++++++
 doc/uImage.FIT/source_file_format.txt     |  7 +++
 3 files changed, 119 insertions(+), 28 deletions(-)
 create mode 100644 doc/uImage.FIT/kernel_fdts_compressed.its

diff --git a/common/image-fit.c b/common/image-fit.c
index c9ffc441aa..e346fed550 100644
--- a/common/image-fit.c
+++ b/common/image-fit.c
@@ -1522,6 +1522,10 @@ int fit_check_format(const void *fit)
  * compatible list, "foo,bar", matches a compatible string in the root of fdt1.
  * "bim,bam" in fdt2 matches the second string which isn't as good as fdt1.
  *
+ * As an optimization, the compatible property from the FDT's root node can be
+ * copied into the configuration node in the FIT image. This is required to
+ * match configurations with compressed FDTs.
+ *
  * returns:
  *     offset to the configuration to use if one was found
  *     -1 otherwise
@@ -1554,55 +1558,62 @@ int fit_conf_find_compat(const void *fit, const void *fdt)
 	for (noffset = fdt_next_node(fit, confs_noffset, &ndepth);
 			(noffset >= 0) && (ndepth > 0);
 			noffset = fdt_next_node(fit, noffset, &ndepth)) {
-		const void *kfdt;
+		const void *fdt;
 		const char *kfdt_name;
-		int kfdt_noffset;
+		int kfdt_noffset, compat_noffset;
 		const char *cur_fdt_compat;
 		int len;
-		size_t size;
+		size_t sz;
 		int i;
 
 		if (ndepth > 1)
 			continue;
 
-		kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
-		if (!kfdt_name) {
-			debug("No fdt property found.\n");
-			continue;
-		}
-		kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
-						  kfdt_name);
-		if (kfdt_noffset < 0) {
-			debug("No image node named \"%s\" found.\n",
-			      kfdt_name);
-			continue;
-		}
+		/* If there's a compat property in the config node, use that. */
+		if (fdt_getprop(fit, noffset, "compatible", NULL)) {
+			fdt = fit;		  /* search in FIT image */
+			compat_noffset = noffset; /* search under config node */
+		} else {	/* Otherwise extract it from the kernel FDT. */
+			kfdt_name = fdt_getprop(fit, noffset, "fdt", &len);
+			if (!kfdt_name) {
+				debug("No fdt property found.\n");
+				continue;
+			}
+			kfdt_noffset = fdt_subnode_offset(fit, images_noffset,
+							  kfdt_name);
+			if (kfdt_noffset < 0) {
+				debug("No image node named \"%s\" found.\n",
+				      kfdt_name);
+				continue;
+			}
 
-		if (!fit_image_check_comp(fit, kfdt_noffset, IH_COMP_NONE)) {
-			debug("Can't extract compat from \"%s\" (compressed)\n",
-			      kfdt_name);
-			continue;
-		}
+			if (!fit_image_check_comp(fit, kfdt_noffset,
+						  IH_COMP_NONE)) {
+				debug("Can't extract compat from \"%s\" "
+				      "(compressed)\n", kfdt_name);
+				continue;
+			}
 
-		/*
-		 * Get a pointer to this configuration's fdt.
-		 */
-		if (fit_image_get_data(fit, kfdt_noffset, &kfdt, &size)) {
-			debug("Failed to get fdt \"%s\".\n", kfdt_name);
-			continue;
+			/* search in this config's kernel FDT */
+			if (fit_image_get_data(fit, kfdt_noffset, &fdt, &sz)) {
+				debug("Failed to get fdt \"%s\".\n", kfdt_name);
+				continue;
+			}
+
+			compat_noffset = 0;  /* search kFDT under root node */
 		}
 
 		len = fdt_compat_len;
 		cur_fdt_compat = fdt_compat;
 		/*
 		 * Look for a match for each U-Boot compatibility string in
-		 * turn in this configuration's fdt.
+		 * turn in the compat string property.
 		 */
 		for (i = 0; len > 0 &&
 		     (!best_match_offset || best_match_pos > i); i++) {
 			int cur_len = strlen(cur_fdt_compat) + 1;
 
-			if (!fdt_node_check_compatible(kfdt, 0,
+			if (!fdt_node_check_compatible(fdt, compat_noffset,
 						       cur_fdt_compat)) {
 				best_match_offset = noffset;
 				best_match_pos = i;
diff --git a/doc/uImage.FIT/kernel_fdts_compressed.its b/doc/uImage.FIT/kernel_fdts_compressed.its
new file mode 100644
index 0000000000..8f81106efc
--- /dev/null
+++ b/doc/uImage.FIT/kernel_fdts_compressed.its
@@ -0,0 +1,73 @@
+/*
+ * U-Boot uImage source file with a kernel and multiple compressed FDT blobs.
+ * Since the FDTs are compressed, configurations must provide a compatible
+ * string to match directly.
+ */
+
+/dts-v1/;
+
+/ {
+	description = "Image with single Linux kernel and compressed FDT blobs";
+	#address-cells = <1>;
+
+	images {
+		kernel {
+			description = "Vanilla Linux kernel";
+			data = /incbin/("./vmlinux.bin.gz");
+			type = "kernel";
+			arch = "ppc";
+			os = "linux";
+			compression = "gzip";
+			load = <00000000>;
+			entry = <00000000>;
+			hash-1 {
+				algo = "crc32";
+			};
+			hash-2 {
+				algo = "sha1";
+			};
+		};
+		fdt at 1 {
+			description = "Flattened Device Tree blob 1";
+			data = /incbin/("./myboard-var1.dtb");
+			type = "flat_dt";
+			arch = "ppc";
+			compression = "gzip";
+			hash-1 {
+				algo = "crc32";
+			};
+			hash-2 {
+				algo = "sha1";
+			};
+		};
+		fdt at 2 {
+			description = "Flattened Device Tree blob 2";
+			data = /incbin/("./myboard-var2.dtb");
+			type = "flat_dt";
+			arch = "ppc";
+			compression = "lzma";
+			hash-1 {
+				algo = "crc32";
+			};
+			hash-2 {
+				algo = "sha1";
+			};
+		};
+	};
+
+	configurations {
+		default = "conf at 1";
+		conf at 1 {
+			description = "Boot Linux kernel with FDT blob 1";
+			kernel = "kernel";
+			fdt = "fdt at 1";
+			compatible = "myvendor,myboard-variant1";
+		};
+		conf at 2 {
+			description = "Boot Linux kernel with FDT blob 2";
+			kernel = "kernel";
+			fdt = "fdt at 2";
+			compatible = "myvendor,myboard-variant2";
+		};
+	};
+};
diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt
index d701b9bb76..f8e27ed34e 100644
--- a/doc/uImage.FIT/source_file_format.txt
+++ b/doc/uImage.FIT/source_file_format.txt
@@ -240,6 +240,7 @@ o config-1
   |- fdt = "fdt sub-node unit-name" [, "fdt overlay sub-node unit-name", ...]
   |- fpga = "fpga sub-node unit-name"
   |- loadables = "loadables sub-node unit-name"
+  |- compatible = "vendor,board-style device tree compatible string"
 
 
   Mandatory properties:
@@ -263,6 +264,12 @@ o config-1
     of strings. U-Boot will load each binary at its given start-address and
     may optionaly invoke additional post-processing steps on this binary based
     on its component image node type.
+  - compatible : The root compatible string of the U-Boot device tree that
+    this configuration shall automatically match when CONFIG_FIT_BEST_MATCH is
+    enabled. If this property is not provided, the compatible string will be
+    extracted from the fdt blob instead. This is only possible if the fdt is
+    not compressed, so images with compressed fdts that want to use compatible
+    string matching must always provide this property.
 
 The FDT blob is required to properly boot FDT based kernel, so the minimal
 configuration for 2.6 FDT kernel is (kernel, fdt) pair.
-- 
2.20.1



More information about the U-Boot mailing list