This patch enables an overlay to refer to a previous overlay's
labels by performing a merge of symbol information at application
time.

In a nutshell it allows an overlay to refer to a symbol that a previous
overlay has defined. It requires both the base and all the overlays
to be compiled with the -@ command line switch so that symbol
information is included.

base.dts
--------

        /dts-v1/;
        / {
                foo: foonode {
                        foo-property;
                };
        };

        $ dtc -@ -I dts -O dtb -o base.dtb base.dts

bar.dts
-------

        /dts-v1/;
        /plugin/;
        / {
                fragment@1 {
                        target = <&foo>;
                        __overlay__ {
                                overlay-1-property;
                                bar: barnode {
                                        bar-property;
                                };
                        };
                };
        };

        $ dtc -@ -I dts -O dtb -o bar.dtb bar.dts

baz.dts
-------

        /dts-v1/;
        /plugin/;
        / {
                fragment@1 {
                        target = <&bar>;
                        __overlay__ {
                                overlay-2-property;
                                baz: baznode {
                                        baz-property;
                                };
                        };
                };
        };

        $ dtc -@ -I dts -O dtb -o baz.dtb baz.dts

Applying the overlays:

        $ fdtoverlay -i base.dtb -o target.dtb bar.dtb baz.dtb

Dumping:

        $ fdtdump target.dtb
        / {
            foonode {
                overlay-1-property;
                foo-property;
                linux,phandle = <0x00000001>;
                phandle = <0x00000001>;
                barnode {
                    overlay-2-property;
                    phandle = <0x00000002>;
                    linux,phandle = <0x00000002>;
                    bar-property;
                    baznode {
                        phandle = <0x00000003>;
                        linux,phandle = <0x00000003>;
                        baz-property;
                    };
                };
            };
            __symbols__ {
                baz = "/foonode/barnode/baznode";
                bar = "/foonode/barnode";
                foo = "/foonode";
            };
        };

Signed-off-by: Pantelis Antoniou <[email protected]>
---
 lib/libfdt/fdt_overlay.c | 148 ++++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 147 insertions(+), 1 deletion(-)

diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
index ceb9687..59fd7f3 100644
--- a/lib/libfdt/fdt_overlay.c
+++ b/lib/libfdt/fdt_overlay.c
@@ -590,7 +590,7 @@ static int overlay_apply_node(void *fdt, int target,
  *
  * overlay_merge() merges an overlay into its base device tree.
  *
- * This is the final step in the device tree overlay application
+ * This is the next to last step in the device tree overlay application
  * process, when all the phandles have been adjusted and resolved and
  * you just have to merge overlay into the base device tree.
  *
@@ -630,6 +630,148 @@ static int overlay_merge(void *fdt, void *fdto)
        return 0;
 }
 
+/**
+ * overlay_symbol_update - Update the symbols of base tree after a merge
+ * @fdt: Base Device Tree blob
+ * @fdto: Device tree overlay blob
+ *
+ * overlay_symbol_update() updates the symbols of the base tree with the
+ * symbols of the applied overlay
+ *
+ * This is the last step in the device tree overlay application
+ * process, allowing the reference of overlay symbols by subsequent
+ * overlay operations.
+ *
+ * returns:
+ *      0 on success
+ *      Negative error code on failure
+ */
+static int overlay_symbol_update(void *fdt, void *fdto)
+{
+       int root_sym, ov_sym, prop, path_len, fragment, target;
+       int len, frag_name_len, ret, rel_path_len;
+       const char *s;
+       const char *path;
+       const char *name;
+       const char *frag_name;
+       const char *rel_path;
+       char *buf = NULL;
+
+       root_sym = fdt_subnode_offset(fdt, 0, "__symbols__");
+       ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__");
+
+       /* if neither exist we can't update symbols, but that's OK */
+       if (root_sym < 0 || ov_sym < 0)
+               return 0;
+
+       buf = malloc(FDT_PATH_MAX);
+       if (!buf)
+               return -FDT_ERR_NOSPACE;
+
+       /* iterate over each overlay symbol */
+       fdt_for_each_property_offset(prop, fdto, ov_sym) {
+
+               path = fdt_getprop_by_offset(fdto, prop, &name, &path_len);
+               if (!path) {
+                       ret = path_len;
+                       goto out;
+               }
+
+               /* skip autogenerated properties */
+               if (!strcmp(name, "name"))
+                       continue;
+
+               /* format: /<fragment-name>/__overlay__/<relative-subnode-path> 
*/
+
+               if (*path != '/') {
+                       ret = -FDT_ERR_BADVALUE;
+                       goto out;
+               }
+
+               /* get frag name first */
+               s = strchr(path + 1, '/');
+               if (!s) {
+                       ret = -FDT_ERR_BADVALUE;
+                       goto out;
+               }
+               frag_name = path + 1;
+               frag_name_len = s - path - 1;
+
+               /* verify format */
+               len = strlen("/__overlay__/");
+               if (strncmp(s, "/__overlay__/", len)) {
+                       ret = -FDT_ERR_NOTFOUND;
+                       goto out;
+               }
+
+               rel_path = s + len;
+               rel_path_len = strlen(rel_path);
+
+               /* find the fragment index in which the symbol lies */
+               fdt_for_each_subnode(fragment, fdto, 0) {
+
+                       s = fdt_get_name(fdto, fragment, &len);
+                       if (!s)
+                               continue;
+
+                       /* name must match */
+                       if (len == frag_name_len && !memcmp(s, frag_name, len))
+                               break;
+               }
+
+               /* not found? */
+               if (fragment < 0) {
+                       ret = -FDT_ERR_NOTFOUND;
+                       goto out;
+               }
+
+               /* an __overlay__ subnode must exist */
+               ret = fdt_subnode_offset(fdto, fragment, "__overlay__");
+               if (ret < 0)
+                       goto out;
+
+               /* get the target of the fragment */
+               ret = overlay_get_target(fdt, fdto, fragment);
+               if (ret < 0)
+                       goto out;
+               target = ret;
+
+               /* get the path of the target */
+               ret = fdt_get_path(fdt, target, buf, FDT_PATH_MAX);
+               if (ret < 0)
+                       goto out;
+
+               len = strlen(buf);
+
+               /* if the target is root strip leading / */
+               if (len == 1 && buf[0] == '/')
+                       len = 0;
+
+               /* make sure we have enough space */
+               if (len + 1 + rel_path_len + 1 > FDT_PATH_MAX) {
+                       ret = -FDT_ERR_NOSPACE;
+                       goto out;
+               }
+
+               /* create new symbol path in place */
+               buf[len] = '/';
+               memcpy(buf + len + 1, rel_path, rel_path_len);
+               buf[len + 1 + rel_path_len] = '\0';
+
+               ret = fdt_setprop_string(fdt, root_sym, name, buf);
+               if (ret < 0)
+                       goto out;
+       }
+
+       ret = 0;
+
+out:
+       if (buf)
+               free(buf);
+
+       return ret;
+}
+
 int fdt_overlay_apply(void *fdt, void *fdto)
 {
        uint32_t delta = fdt_get_max_phandle(fdt);
@@ -654,6 +796,10 @@ int fdt_overlay_apply(void *fdt, void *fdto)
        if (ret)
                goto err;
 
+       ret = overlay_symbol_update(fdt, fdto);
+       if (ret)
+               goto err;
+
        /*
         * The overlay has been damaged, erase its magic.
         */
-- 
2.1.4

_______________________________________________
U-Boot mailing list
[email protected]
https://lists.denx.de/listinfo/u-boot

Reply via email to