fit: Support compat string property in configuration node
authorJulius Werner <jwerner@chromium.org>
Thu, 25 Jul 2019 02:37:56 +0000 (19:37 -0700)
committerTom Rini <trini@konsulko.com>
Mon, 29 Jul 2019 13:32:08 +0000 (09:32 -0400)
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@chromium.org>
Reviewed-by: Simon Glass <sjg@chromium.org>
common/image-fit.c
doc/uImage.FIT/kernel_fdts_compressed.its [new file with mode: 0644]
doc/uImage.FIT/source_file_format.txt

index c9ffc441aa653bae7fbb756a691d4998a4fc597f..e346fed550e842538430eb6fcb0a6b192784eeaa 100644 (file)
@@ -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 (file)
index 0000000..8f81106
--- /dev/null
@@ -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@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@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@1";
+               conf@1 {
+                       description = "Boot Linux kernel with FDT blob 1";
+                       kernel = "kernel";
+                       fdt = "fdt@1";
+                       compatible = "myvendor,myboard-variant1";
+               };
+               conf@2 {
+                       description = "Boot Linux kernel with FDT blob 2";
+                       kernel = "kernel";
+                       fdt = "fdt@2";
+                       compatible = "myvendor,myboard-variant2";
+               };
+       };
+};
index d701b9bb760999af228658fd9d0b9a2fdc4fbe33..f8e27ed34e81a85a14a8444ea983d41eceb573ec 100644 (file)
@@ -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.