[U-Boot] [PATCH v2 00/10] uboot overlays, FIT image & unittest

This patchset allows uboot to handle overlays in a manner that uses a base DT blob and an arbitrary number of DT overlays blobs.
While it is intended to be used with FIT images since handling a multitude of device tree blobs manually is a chore, manual fdt overlay application is supported and described.
The first 2 patches have already been accepted in DTC mainline. We can apply them now, or expect the updated drop from mainline.
The next patch contains the FIT FDT blob generation logic as well as documentation about how it works.
Path #4 spits out an informative message in case of an overlay failure that may be attribute to mis-compilation (which is a common problem).
Patches 5 & 6 are documentation entries.
Patch #7 makes sure unit tests using overlays can be used on non-sandbox boards.
Patch #8 adds overlay unit tests as part of sandbox's defconfig.
Patch #9 fixes a problem with unit tests using an already present symbol.
Finally, #10 adds a unit test using a stacked overlay.
The patchset is available at
https://github.com/pantoniou/u-boot/tree/uboot-overlays
and is against mainline u-boot as pulled today, 11/8/2017.
Franklin S Cooper Jr (1): doc: overlays: Tweak documentation regarding overlays
Pantelis Antoniou (9): Introduce fdt_setprop_placeholder() method fdt: Allow stacked overlays phandle references fit: Introduce methods for applying overlays on fit-load fdt-overlay: Spit out a descriptive failure warning doc: Document how to apply fdt overlays dtbo: make dtbos special config: sandbox: Add unit tests ut: fix fdt_getprop_u32() change test: overlay: Add unit test for stacked overlay
cmd/fdt.c | 8 + common/image-fdt.c | 7 +- common/image-fit.c | 226 ++++++++++++++++++++++++-- configs/sandbox_defconfig | 2 + doc/README.fdt-overlays | 114 ++++++++++++++ doc/uImage.FIT/command_syntax_extensions.txt | 12 +- doc/uImage.FIT/overlay-fdt-boot.txt | 225 ++++++++++++++++++++++++++ doc/uImage.FIT/source_file_format.txt | 6 +- include/image.h | 10 ++ lib/libfdt/fdt_overlay.c | 228 ++++++++++++++++++++++++--- lib/libfdt/fdt_rw.c | 20 ++- lib/libfdt/libfdt.h | 31 ++++ scripts/Makefile.lib | 17 ++ test/overlay/Makefile | 1 + test/overlay/cmd_ut_overlay.c | 50 ++++-- test/overlay/test-fdt-overlay-stacked.dts | 21 +++ 16 files changed, 926 insertions(+), 52 deletions(-) create mode 100644 doc/README.fdt-overlays create mode 100644 doc/uImage.FIT/overlay-fdt-boot.txt create mode 100644 test/overlay/test-fdt-overlay-stacked.dts

In some cases you need to add a property but the contents of it are not known at creation time, merely the extend of it.
This method allows you to create a property of a given size (filled with garbage) while a pointer to the property data will be provided.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com [dwg: Corrected commit message] Signed-off-by: David Gibson david@gibson.dropbear.id.au --- lib/libfdt/fdt_rw.c | 20 +++++++++++++++++--- lib/libfdt/libfdt.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-)
diff --git a/lib/libfdt/fdt_rw.c b/lib/libfdt/fdt_rw.c index 80a3212..3dc7752 100644 --- a/lib/libfdt/fdt_rw.c +++ b/lib/libfdt/fdt_rw.c @@ -228,8 +228,8 @@ int fdt_set_name(void *fdt, int nodeoffset, const char *name) return 0; }
-int fdt_setprop(void *fdt, int nodeoffset, const char *name, - const void *val, int len) +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data) { struct fdt_property *prop; int err; @@ -242,8 +242,22 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, if (err) return err;
+ *prop_data = prop->data; + return 0; +} + +int fdt_setprop(void *fdt, int nodeoffset, const char *name, + const void *val, int len) +{ + void *prop_data; + int err; + + err = fdt_setprop_placeholder(fdt, nodeoffset, name, len, &prop_data); + if (err) + return err; + if (len) - memcpy(prop->data, val, len); + memcpy(prop_data, val, len); return 0; }
diff --git a/lib/libfdt/libfdt.h b/lib/libfdt/libfdt.h index f3f9cad..6af94cb 100644 --- a/lib/libfdt/libfdt.h +++ b/lib/libfdt/libfdt.h @@ -1405,6 +1405,37 @@ int fdt_setprop(void *fdt, int nodeoffset, const char *name, const void *val, int len);
/** + * fdt_setprop _placeholder - allocate space for a property + * @fdt: pointer to the device tree blob + * @nodeoffset: offset of the node whose property to change + * @name: name of the property to change + * @len: length of the property value + * @prop_data: return pointer to property data + * + * fdt_setprop_placeholer() allocates the named property in the given node. + * If the property exists it is resized. In either case a pointer to the + * property data is returned. + * + * This function may insert or delete data from the blob, and will + * therefore change the offsets of some existing nodes. + * + * returns: + * 0, on success + * -FDT_ERR_NOSPACE, there is insufficient free space in the blob to + * contain the new property value + * -FDT_ERR_BADOFFSET, nodeoffset did not point to FDT_BEGIN_NODE tag + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_BADMAGIC, + * -FDT_ERR_BADVERSION, + * -FDT_ERR_BADSTATE, + * -FDT_ERR_BADSTRUCTURE, + * -FDT_ERR_BADLAYOUT, + * -FDT_ERR_TRUNCATED, standard meanings + */ +int fdt_setprop_placeholder(void *fdt, int nodeoffset, const char *name, + int len, void **prop_data); + +/** * fdt_setprop_u32 - set a property to a 32-bit integer * @fdt: pointer to the device tree blob * @nodeoffset: offset of the node whose property to change

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
In some cases you need to add a property but the contents of it are not known at creation time, merely the extend of it.
This method allows you to create a property of a given size (filled with garbage) while a pointer to the property data will be provided.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com [dwg: Corrected commit message] Signed-off-by: David Gibson david@gibson.dropbear.id.au
lib/libfdt/fdt_rw.c | 20 +++++++++++++++++--- lib/libfdt/libfdt.h | 31 +++++++++++++++++++++++++++++++ 2 files changed, 48 insertions(+), 3 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

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 pantelis.antoniou@konsulko.com Signed-off-by: David Gibson david@gibson.dropbear.id.au --- lib/libfdt/fdt_overlay.c | 228 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 206 insertions(+), 22 deletions(-)
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c index ceb9687..bd81241 100644 --- a/lib/libfdt/fdt_overlay.c +++ b/lib/libfdt/fdt_overlay.c @@ -39,6 +39,7 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) * @fdt: Base device tree blob * @fdto: Device tree overlay blob * @fragment: node offset of the fragment in the overlay + * @pathp: pointer which receives the path of the target (or NULL) * * overlay_get_target() retrieves the target offset in the base * device tree of a fragment, no matter how the actual targetting is @@ -49,37 +50,47 @@ static uint32_t overlay_get_target_phandle(const void *fdto, int fragment) * Negative error code on error */ static int overlay_get_target(const void *fdt, const void *fdto, - int fragment) + int fragment, char const **pathp) { uint32_t phandle; - const char *path; - int path_len; + const char *path = NULL; + int path_len = 0, ret;
/* Try first to do a phandle based lookup */ phandle = overlay_get_target_phandle(fdto, fragment); if (phandle == (uint32_t)-1) return -FDT_ERR_BADPHANDLE;
- if (phandle) - return fdt_node_offset_by_phandle(fdt, phandle); + /* no phandle, try path */ + if (!phandle) { + /* And then a path based lookup */ + path = fdt_getprop(fdto, fragment, "target-path", &path_len); + if (path) + ret = fdt_path_offset(fdt, path); + else + ret = path_len; + } else + ret = fdt_node_offset_by_phandle(fdt, phandle);
- /* And then a path based lookup */ - path = fdt_getprop(fdto, fragment, "target-path", &path_len); - if (!path) { - /* - * If we haven't found either a target or a - * target-path property in a node that contains a - * __overlay__ subnode (we wouldn't be called - * otherwise), consider it a improperly written - * overlay - */ - if (path_len == -FDT_ERR_NOTFOUND) - return -FDT_ERR_BADOVERLAY; + /* + * If we haven't found either a target or a + * target-path property in a node that contains a + * __overlay__ subnode (we wouldn't be called + * otherwise), consider it a improperly written + * overlay + */ + if (ret < 0 && path_len == -FDT_ERR_NOTFOUND) + ret = -FDT_ERR_BADOVERLAY; + + /* return on error */ + if (ret < 0) + return ret;
- return path_len; - } + /* return pointer to path (if available) */ + if (pathp) + *pathp = path ? path : NULL;
- return fdt_path_offset(fdt, path); + return ret; }
/** @@ -590,7 +601,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. * @@ -618,7 +629,7 @@ static int overlay_merge(void *fdt, void *fdto) if (overlay < 0) return overlay;
- target = overlay_get_target(fdt, fdto, fragment); + target = overlay_get_target(fdt, fdto, fragment, NULL); if (target < 0) return target;
@@ -630,6 +641,175 @@ static int overlay_merge(void *fdt, void *fdto) return 0; }
+static int get_path_len(const void *fdt, int nodeoffset) +{ + int len = 0, namelen; + const char *name; + + FDT_CHECK_HEADER(fdt); + + for (;;) { + name = fdt_get_name(fdt, nodeoffset, &namelen); + if (!name) + return namelen; + + /* root? we're done */ + if (namelen == 0) + break; + + nodeoffset = fdt_parent_offset(fdt, nodeoffset); + if (nodeoffset < 0) + return nodeoffset; + len += namelen + 1; + } + + /* in case of root pretend it's "/" */ + if (len == 0) + len++; + return len; +} + +/** + * 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, *e; + const char *path; + const char *name; + const char *frag_name; + const char *rel_path; + const char *target_path; + char *buf; + void *p; + + ov_sym = fdt_subnode_offset(fdto, 0, "__symbols__"); + + /* if no overlay symbols exist no problem */ + if (ov_sym < 0) + return 0; + + root_sym = fdt_subnode_offset(fdt, 0, "__symbols__"); + + /* it no root symbols exist we should create them */ + if (root_sym == -FDT_ERR_NOTFOUND) + root_sym = fdt_add_subnode(fdt, 0, "__symbols__"); + + /* any error is fatal now */ + if (root_sym < 0) + return root_sym; + + /* 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) + return path_len; + + /* verify it's a string property (terminated by a single \0) */ + if (path_len < 1 || memchr(path, '\0', path_len) != &path[path_len - 1]) + return -FDT_ERR_BADVALUE; + + /* keep end marker to avoid strlen() */ + e = path + path_len; + + /* format: /<fragment-name>/__overlay__/<relative-subnode-path> */ + + if (*path != '/') + return -FDT_ERR_BADVALUE; + + /* get fragment name first */ + s = strchr(path + 1, '/'); + if (!s) + return -FDT_ERR_BADOVERLAY; + + frag_name = path + 1; + frag_name_len = s - path - 1; + + /* verify format; safe since "s" lies in \0 terminated prop */ + len = sizeof("/__overlay__/") - 1; + if ((e - s) < len || memcmp(s, "/__overlay__/", len)) + return -FDT_ERR_BADOVERLAY; + + rel_path = s + len; + rel_path_len = e - rel_path; + + /* find the fragment index in which the symbol lies */ + ret = fdt_subnode_offset_namelen(fdto, 0, frag_name, + frag_name_len); + /* not found? */ + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + fragment = ret; + + /* an __overlay__ subnode must exist */ + ret = fdt_subnode_offset(fdto, fragment, "__overlay__"); + if (ret < 0) + return -FDT_ERR_BADOVERLAY; + + /* get the target of the fragment */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + + /* if we have a target path use */ + if (!target_path) { + ret = get_path_len(fdt, target); + if (ret < 0) + return ret; + len = ret; + } else { + len = strlen(target_path); + } + + ret = fdt_setprop_placeholder(fdt, root_sym, name, + len + (len > 1) + rel_path_len + 1, &p); + if (ret < 0) + return ret; + + if (!target_path) { + /* again in case setprop_placeholder changed it */ + ret = overlay_get_target(fdt, fdto, fragment, &target_path); + if (ret < 0) + return ret; + target = ret; + } + + buf = p; + if (len > 1) { /* target is not root */ + if (!target_path) { + ret = fdt_get_path(fdt, target, buf, len + 1); + if (ret < 0) + return ret; + } else + memcpy(buf, target_path, len + 1); + + } else + len--; + + buf[len] = '/'; + memcpy(buf + len + 1, rel_path, rel_path_len); + buf[len + 1 + rel_path_len] = '\0'; + } + + return 0; +} + int fdt_overlay_apply(void *fdt, void *fdto) { uint32_t delta = fdt_get_max_phandle(fdt); @@ -654,6 +834,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. */

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
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 pantelis.antoniou@konsulko.com Signed-off-by: David Gibson david@gibson.dropbear.id.au
lib/libfdt/fdt_overlay.c | 228 ++++++++++++++++++++++++++++++++++++++++++----- 1 file changed, 206 insertions(+), 22 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Introduce an overlay based method for constructing a base DT blob to pass to the kernel.
Both canned and runtime feature selection is supported.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com --- common/image-fdt.c | 7 +- common/image-fit.c | 216 ++++++++++++++++++++++++-- doc/uImage.FIT/command_syntax_extensions.txt | 12 +- doc/uImage.FIT/overlay-fdt-boot.txt | 221 +++++++++++++++++++++++++++ doc/uImage.FIT/source_file_format.txt | 6 +- include/image.h | 10 ++ 6 files changed, 454 insertions(+), 18 deletions(-) create mode 100644 doc/uImage.FIT/overlay-fdt-boot.txt
diff --git a/common/image-fdt.c b/common/image-fdt.c index c6e8832..a59134c 100644 --- a/common/image-fdt.c +++ b/common/image-fdt.c @@ -356,17 +356,16 @@ int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, if (fit_check_format(buf)) { ulong load, len;
- fdt_noffset = fit_image_load(images, + fdt_noffset = boot_get_fdt_fit(images, fdt_addr, &fit_uname_fdt, &fit_uname_config, - arch, IH_TYPE_FLATDT, - BOOTSTAGE_ID_FIT_FDT_START, - FIT_LOAD_OPTIONAL, &load, &len); + arch, &load, &len);
images->fit_hdr_fdt = map_sysmem(fdt_addr, 0); images->fit_uname_fdt = fit_uname_fdt; images->fit_noffset_fdt = fdt_noffset; fdt_addr = load; + break; } else #endif diff --git a/common/image-fit.c b/common/image-fit.c index 109ecfa..cb089ea 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -19,6 +19,7 @@ #include <errno.h> #include <mapmem.h> #include <asm/io.h> +#include <malloc.h> DECLARE_GLOBAL_DATA_PTR; #endif /* !USE_HOSTCC*/
@@ -434,6 +435,10 @@ void fit_image_print(const void *fit, int image_noffset, const char *p) printf("0x%08lx\n", load); }
+ /* optional load address for FDT */ + if (type == IH_TYPE_FLATDT && !fit_image_get_load(fit, image_noffset, &load)) + printf("%s Load Address: 0x%08lx\n", p, load); + if ((type == IH_TYPE_KERNEL) || (type == IH_TYPE_STANDALONE) || (type == IH_TYPE_RAMDISK)) { ret = fit_image_get_entry(fit, image_noffset, &entry); @@ -1454,6 +1459,8 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) { int noffset, confs_noffset; int len; + const char *s; + char *conf_uname_copy = NULL;
confs_noffset = fdt_path_offset(fit, FIT_CONFS_PATH); if (confs_noffset < 0) { @@ -1475,29 +1482,58 @@ int fit_conf_get_node(const void *fit, const char *conf_uname) debug("Found default configuration: '%s'\n", conf_uname); }
+ s = strchr(conf_uname, '#'); + if (s) { + len = s - conf_uname; + conf_uname_copy = malloc(len + 1); + if (!conf_uname_copy) { + debug("Can't allocate uname copy: '%s'\n", + conf_uname); + return -ENOMEM; + } + memcpy(conf_uname_copy, conf_uname, len); + conf_uname_copy[len] = '\0'; + conf_uname = conf_uname_copy; + } + noffset = fdt_subnode_offset(fit, confs_noffset, conf_uname); if (noffset < 0) { debug("Can't get node offset for configuration unit name: '%s' (%s)\n", conf_uname, fdt_strerror(noffset)); }
+ if (conf_uname_copy) + free(conf_uname_copy); + return noffset; }
-int fit_conf_get_prop_node(const void *fit, int noffset, +int fit_conf_get_prop_node_count(const void *fit, int noffset, const char *prop_name) { - char *uname; + return fdt_stringlist_count(fit, noffset, prop_name); +} + +int fit_conf_get_prop_node_index(const void *fit, int noffset, + const char *prop_name, int index) +{ + const char *uname; int len;
/* get kernel image unit name from configuration kernel property */ - uname = (char *)fdt_getprop(fit, noffset, prop_name, &len); + uname = fdt_stringlist_get(fit, noffset, prop_name, index, &len); if (uname == NULL) return len;
return fit_image_get_node(fit, uname); }
+int fit_conf_get_prop_node(const void *fit, int noffset, + const char *prop_name) +{ + return fit_conf_get_prop_node_index(fit, noffset, prop_name, 0); +} + /** * fit_conf_print - prints out the FIT configuration details * @fit: pointer to the FIT format image header @@ -1515,7 +1551,7 @@ void fit_conf_print(const void *fit, int noffset, const char *p) char *desc; const char *uname; int ret; - int loadables_index; + int fdt_index, loadables_index;
/* Mandatory properties */ ret = fit_get_desc(fit, noffset, &desc); @@ -1537,9 +1573,17 @@ void fit_conf_print(const void *fit, int noffset, const char *p) if (uname) printf("%s Init Ramdisk: %s\n", p, uname);
- uname = fdt_getprop(fit, noffset, FIT_FDT_PROP, NULL); - if (uname) - printf("%s FDT: %s\n", p, uname); + for (fdt_index = 0; + uname = fdt_stringlist_get(fit, noffset, FIT_FDT_PROP, + fdt_index, NULL), uname; + fdt_index++) { + + if (fdt_index == 0) + printf("%s FDT: ", p); + else + printf("%s ", p); + printf("%s\n", uname); + }
uname = fdt_getprop(fit, noffset, FIT_FPGA_PROP, NULL); if (uname) @@ -1575,8 +1619,8 @@ static int fit_image_select(const void *fit, int rd_noffset, int verify) return 0; }
-int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, - ulong addr) +int fit_get_node_from_config_index(bootm_headers_t *images, const char *prop_name, + ulong addr, int index) { int cfg_noffset; void *fit_hdr; @@ -1593,7 +1637,8 @@ int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, return -EINVAL; }
- noffset = fit_conf_get_prop_node(fit_hdr, cfg_noffset, prop_name); + noffset = fit_conf_get_prop_node_index(fit_hdr, cfg_noffset, prop_name, + index); if (noffset < 0) { debug("* %s: no '%s' in config\n", prop_name, prop_name); return -ENOENT; @@ -1602,6 +1647,12 @@ int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, return noffset; }
+int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, + ulong addr) +{ + return fit_get_node_from_config_index(images, prop_name, addr, 0); +} + /** * fit_get_image_type_property() - get property name for IH_TYPE_... * @@ -1689,7 +1740,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, BOOTSTAGE_SUB_NO_UNIT_NAME); return -ENOENT; } - fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); + if (!fit_uname_config) + fit_uname_config = fdt_get_name(fit, cfg_noffset, NULL); printf(" Using '%s' configuration\n", fit_uname_config); if (image_type == IH_TYPE_KERNEL) { /* Remember (and possibly verify) this config */ @@ -1841,6 +1893,7 @@ int fit_image_load(bootm_headers_t *images, ulong addr, dst = map_sysmem(load, len); memmove(dst, buf, len); data = load; + } bootstage_mark(bootstage_id + BOOTSTAGE_SUB_LOAD);
@@ -1873,3 +1926,144 @@ int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch,
return ret; } + +#ifndef USE_HOSTCC +int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, ulong *datap, ulong *lenp) +{ + int fdt_noffset, cfg_noffset, count; + const void *fit; + const char *fit_uname = NULL; + const char *fit_uname_config = NULL; + char *fit_uname_config_copy = NULL; + char *next_config = NULL; + ulong load, len; +#ifdef CONFIG_OF_LIBFDT_OVERLAY + ulong image_start, image_end; + ulong ovload, ovlen; + const char *uconfig; + const char *uname; + void *base, *ov; + int i, err, noffset, ov_noffset; +#endif + + fit_uname = fit_unamep ? *fit_unamep : NULL; + + if (fit_uname_configp && *fit_uname_configp) { + fit_uname_config_copy = strdup(*fit_uname_configp); + if (!fit_uname_config_copy) + return -ENOMEM; + + next_config = strchr(fit_uname_config_copy, '#'); + if (next_config) + *next_config++ = '\0'; + if (next_config - 1 > fit_uname_config_copy) + fit_uname_config = fit_uname_config_copy; + } + + fdt_noffset = fit_image_load(images, + addr, &fit_uname, &fit_uname_config, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_OPTIONAL, &load, &len); + + if (fdt_noffset < 0) + goto out; + + debug("fit_uname=%s, fit_uname_config=%s\n", + fit_uname ? fit_uname : "<NULL>", + fit_uname_config ? fit_uname_config : "<NULL>"); + + fit = map_sysmem(addr, 0); + + cfg_noffset = fit_conf_get_node(fit, fit_uname_config); + + /* single blob, or error just return as well */ + count = fit_conf_get_prop_node_count(fit, cfg_noffset, FIT_FDT_PROP); + if (count <= 1 && !next_config) + goto out; + + /* we need to apply overlays */ + +#ifdef CONFIG_OF_LIBFDT_OVERLAY + image_start = addr; + image_end = addr + fit_get_size(fit); + /* verify that relocation took place by load address not being in fit */ + if (load >= image_start && load < image_end) { + /* check is simplified; fit load checks for overlaps */ + printf("Overlayed FDT requires relocation\n"); + fdt_noffset = -EBADF; + goto out; + } + + base = map_sysmem(load, len); + + /* apply extra configs in FIT first, followed by args */ + for (i = 1; ; i++) { + if (i < count) { + noffset = fit_conf_get_prop_node_index(fit, cfg_noffset, + FIT_FDT_PROP, i); + uname = fit_get_name(fit, noffset, NULL); + uconfig = NULL; + } else { + if (!next_config) + break; + uconfig = next_config; + next_config = strchr(next_config, '#'); + if (next_config) + *next_config++ = '\0'; + uname = NULL; + } + + debug("%d: using uname=%s uconfig=%s\n", i, uname, uconfig); + + ov_noffset = fit_image_load(images, + addr, &uname, &uconfig, + arch, IH_TYPE_FLATDT, + BOOTSTAGE_ID_FIT_FDT_START, + FIT_LOAD_REQUIRED, &ovload, &ovlen); + if (ov_noffset < 0) { + printf("load of %s failed\n", uname); + continue; + } + debug("%s loaded at 0x%08lx len=0x%08lx\n", + uname, ovload, ovlen); + ov = map_sysmem(ovload, ovlen); + + base = map_sysmem(load, len + ovlen); + err = fdt_open_into(base, base, len + ovlen); + if (err < 0) { + printf("failed on fdt_open_into\n"); + fdt_noffset = err; + goto out; + } + err = fdt_overlay_apply(base, ov); + if (err < 0) { + printf("failed on fdt_overlay_apply\n"); + fdt_noffset = err; + goto out; + } + fdt_pack(base); + len = fdt_totalsize(base); + } +#else + printf("config with overlays but CONFIG_OF_LIBFDT_OVERLAY not set\n"); + fdt_noffset = -EBADF; +#endif + +out: + if (datap) + *datap = load; + if (lenp) + *lenp = len; + if (fit_unamep) + *fit_unamep = fit_uname; + if (fit_uname_configp) + *fit_uname_configp = fit_uname_config; + + if (fit_uname_config_copy) + free(fit_uname_config_copy); + return fdt_noffset; +} +#endif diff --git a/doc/uImage.FIT/command_syntax_extensions.txt b/doc/uImage.FIT/command_syntax_extensions.txt index 6c99b1c..676f992 100644 --- a/doc/uImage.FIT/command_syntax_extensions.txt +++ b/doc/uImage.FIT/command_syntax_extensions.txt @@ -36,7 +36,7 @@ Old uImage: New uImage: 8. bootm <addr1> 9. bootm [<addr1>]:<subimg1> -10. bootm [<addr1>]#<conf> +10. bootm [<addr1>]#<conf>[#<extra-conf[#...]] 11. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> 12. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> [<addr3>]:<subimg3> 13. bootm [<addr1>]:<subimg1> [<addr2>]:<subimg2> <addr3> @@ -129,6 +129,12 @@ following syntax: - new uImage configuration specification <addr>#<configuration unit_name>
+- new uImage configuration specification with extra configuration components +<addr>#<configuration unit_name>[#<extra configuration unit_name>[#..]] + +The extra configuration currently is supported only for additional device tree +overlays to apply on the base device tree supplied by the first configuration +unit.
Examples:
@@ -138,6 +144,10 @@ bootm 200000:kernel@1 - boot configuration "cfg@1" from a new uImage located at 200000: bootm 200000#cfg@1
+- boot configuration "cfg@1" with extra "cfg@2" from a new uImage located + at 200000: +bootm 200000#cfg@1#cfg@2 + - boot "kernel@1" from a new uImage at 200000 with initrd "ramdisk@2" found in some other new uImage stored at address 800000: bootm 200000:kernel@1 800000:ramdisk@2 diff --git a/doc/uImage.FIT/overlay-fdt-boot.txt b/doc/uImage.FIT/overlay-fdt-boot.txt new file mode 100644 index 0000000..dbdf2a1 --- /dev/null +++ b/doc/uImage.FIT/overlay-fdt-boot.txt @@ -0,0 +1,221 @@ +U-Boot FDT Overlay usage +======================== + +Introduction +------------ +In many cases it is desirable to have a single FIT image support a multitude +of similar boards and their expansion options. The same kernel on DT enabled +platforms can support this easily enough by providing a DT blob upon boot +that matches the desired configuration. + +Configuration without overlays +------------------------------ + +Take a hypothetical board named 'foo' where there are different supported +revisions, reva and revb. Assume that both board revisions can use add a bar +add-on board, while only the revb board can use a baz add-on board. + +Without using overlays the configuration would be as follows for every case. + + /dts-v1/; + / { + images { + kernel@1 { + data = /incbin/("./zImage"); + type = "kernel"; + arch = "arm"; + os = "linux"; + load = <0x82000000>; + entry = <0x82000000>; + }; + fdt@1 { + data = /incbin/("./foo-reva.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt@2 { + data = /incbin/("./foo-revb.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt@3 { + data = /incbin/("./foo-reva-bar.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt@4 { + data = /incbin/("./foo-revb-bar.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt@5 { + data = /incbin/("./foo-revb-baz.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + fdt@6 { + data = /incbin/("./foo-revb-bar-baz.dtb"); + type = "flat_dt"; + arch = "arm"; + }; + }; + + configurations { + default = "foo-reva.dtb; + foo-reva.dtb { + kernel = "kernel@1"; + fdt = "fdt@1"; + }; + foo-revb.dtb { + kernel = "kernel@1"; + fdt = "fdt@2"; + }; + foo-reva-bar.dtb { + kernel = "kernel@1"; + fdt = "fdt@3"; + }; + foo-revb-bar.dtb { + kernel = "kernel@1"; + fdt = "fdt@4"; + }; + foo-revb-baz.dtb { + kernel = "kernel@1"; + fdt = "fdt@5"; + }; + foo-revb-bar-baz.dtb { + kernel = "kernel@1"; + fdt = "fdt@6"; + }; + }; + }; + +Note the blob needs to be compiled for each case and the combinatorial explosion of +configurations. A typical device tree blob is in the low hunderds of kbytes so a +multitude of configuration grows the image quite a bit. + +Booting this image is done by using + + # bootm <addr>#<config> + +Where config is one of: + foo-reva.dtb, foo-revb.dtb, foo-reva-bar.dtb, foo-revb-bar.dtb, + foo-revb-baz.dtb, foo-revb-bar-baz.dtb + +This selects the DTB to use when booting. + +Configuration using overlays +---------------------------- + +Device tree overlays can be applied to a base DT and result in the same blob +being passed to the booting kernel. This saves on space and avoid the combinatorial +explosion problem. + + /dts-v1/; + / { + images { + kernel@1 { + data = /incbin/("./zImage"); + type = "kernel"; + arch = "arm"; + os = "linux"; + load = <0x82000000>; + entry = <0x82000000>; + }; + fdt@1 { + data = /incbin/("./foo.dtb"); + type = "flat_dt"; + arch = "arm"; + load = <0x87f00000>; + }; + fdt@2 { + data = /incbin/("./reva.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + fdt@3 { + data = /incbin/("./revb.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + fdt@4 { + data = /incbin/("./bar.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + fdt@5 { + data = /incbin/("./baz.dtbo"); + type = "flat_dt"; + arch = "arm"; + load = <0x87fc0000>; + }; + }; + + configurations { + default = "foo-reva.dtb; + foo-reva.dtb { + kernel = "kernel@1"; + fdt = "fdt@1", "fdt@2"; + }; + foo-revb.dtb { + kernel = "kernel@1"; + fdt = "fdt@1", "fdt@3"; + }; + foo-reva-bar.dtb { + kernel = "kernel@1"; + fdt = "fdt@1", "fdt@2", "fdt@4"; + }; + foo-revb-bar.dtb { + kernel = "kernel@1"; + fdt = "fdt@1", "fdt@3", "fdt@4"; + }; + foo-revb-baz.dtb { + kernel = "kernel@1"; + fdt = "fdt@1", "fdt@3", "fdt@5"; + }; + foo-revb-bar-baz.dtb { + kernel = "kernel@1"; + fdt = "fdt@1", "fdt@3", "fdt@4", "fdt@5"; + }; + bar { + fdt = "fdt@4"; + }; + baz { + fdt = "fdt@5"; + }; + }; + }; + +Booting this image is exactly the same as the non-overlay example. +u-boot will retrieve the base blob and apply the overlays in sequence as +they are declared in the configuration. + +Note the minimum amount of different DT blobs, as well as the requirement for +the DT blobs to have a load address; the overlay application requires the blobs +to be writeable. + +Configuration using overlays and feature selection +-------------------------------------------------- + +Although the configuration in the previous section works is a bit inflexible +since it requires all possible configuration options to be laid out before +hand in the FIT image. For the add-on boards the extra config selection method +might make sense. + +Note the two bar & baz configuration nodes. To boot a reva board with +the bar add-on board enabled simply use: + + # bootm <addr>#foo-reva.dtb#bar + +While booting a revb with bar and baz is as follows: + + # bootm <addr>#foo-revb.dtb#bar#baz + +The limitation for a feature selection configuration node is that a single +fdt option is currently supported. + +Pantelis Antoniou +pantelis.antoniou@konsulko.com +12/6/2017 diff --git a/doc/uImage.FIT/source_file_format.txt b/doc/uImage.FIT/source_file_format.txt index 136d3d7..ba8013a 100644 --- a/doc/uImage.FIT/source_file_format.txt +++ b/doc/uImage.FIT/source_file_format.txt @@ -235,7 +235,7 @@ o config@1 |- description = "configuration description" |- kernel = "kernel sub-node unit name" |- ramdisk = "ramdisk sub-node unit name" - |- fdt = "fdt sub-node unit-name" + |- fdt = "fdt sub-node unit-name" [, "fdt overlay sub-node unit-name", ...] |- fpga = "fpga sub-node unit-name" |- loadables = "loadables sub-node unit-name"
@@ -249,7 +249,9 @@ o config@1 - ramdisk : Unit name of the corresponding ramdisk image (component image node of a "ramdisk" type). - fdt : Unit name of the corresponding fdt blob (component image node of a - "fdt type"). + "fdt type"). Additional fdt overlay nodes can be supplied which signify + that the resulting device tree blob is generated by the first base fdt + blob with all subsequent overlays applied. - setup : Unit name of the corresponding setup binary (used for booting an x86 kernel). This contains the setup.bin file built by the kernel. - fpga : Unit name of the corresponding fpga bitstream blob diff --git a/include/image.h b/include/image.h index c6f1513..aef71f3 100644 --- a/include/image.h +++ b/include/image.h @@ -592,6 +592,10 @@ int boot_get_loadable(int argc, char * const argv[], bootm_headers_t *images, int boot_get_setup_fit(bootm_headers_t *images, uint8_t arch, ulong *setup_start, ulong *setup_len);
+int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, + const char **fit_unamep, const char **fit_uname_configp, + int arch, ulong *datap, ulong *lenp); + /** * fit_image_load() - load an image from a FIT * @@ -657,6 +661,8 @@ int fit_image_load(bootm_headers_t *images, ulong addr, */ int fit_get_node_from_config(bootm_headers_t *images, const char *prop_name, ulong addr); +int fit_get_node_from_config_index(bootm_headers_t *images, const char *prop_name, + ulong addr, int index);
int boot_get_fdt(int flag, int argc, char * const argv[], uint8_t arch, bootm_headers_t *images, @@ -986,6 +992,10 @@ int fit_check_format(const void *fit); int fit_conf_find_compat(const void *fit, const void *fdt); int fit_conf_get_node(const void *fit, const char *conf_uname);
+int fit_conf_get_prop_node_count(const void *fit, int noffset, + const char *prop_name); +int fit_conf_get_prop_node_index(const void *fit, int noffset, + const char *prop_name, int index); /** * fit_conf_get_prop_node() - Get node refered to by a configuration * @fit: FIT to check

Hi,
On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
Introduce an overlay based method for constructing a base DT blob to pass to the kernel.
Both canned and runtime feature selection is supported.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
common/image-fdt.c | 7 +- common/image-fit.c | 216 ++++++++++++++++++++++++-- doc/uImage.FIT/command_syntax_extensions.txt | 12 +- doc/uImage.FIT/overlay-fdt-boot.txt | 221 +++++++++++++++++++++++++++ doc/uImage.FIT/source_file_format.txt | 6 +- include/image.h | 10 ++ 6 files changed, 454 insertions(+), 18 deletions(-) create mode 100644 doc/uImage.FIT/overlay-fdt-boot.txt
Can you please split this patch a bit?
I see changes to the existing code and some stuff inside an #ifdef. Can you split out the refactoring from the new features?
Also please comment the functions you add to the header file.

The most common trouble with overlays appears to be miscompiled blobs without the -@ option.
In case of an error, spit out a descriptive error message.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com --- cmd/fdt.c | 8 ++++++++ common/image-fit.c | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/cmd/fdt.c b/cmd/fdt.c index 05e19f8..9f192be 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -654,6 +654,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long addr; struct fdt_header *blob; int ret; + bool has_symbols;
if (argc != 3) return CMD_RET_USAGE; @@ -666,9 +667,16 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!fdt_valid(&blob)) return CMD_RET_FAILURE;
+ ret = fdt_path_offset(working_fdt, "/__symbols__"); + has_symbols = ret >= 0; + ret = fdt_overlay_apply(working_fdt, blob); if (ret) { printf("fdt_overlay_apply(): %s\n", fdt_strerror(ret)); + if (!has_symbols) { + printf("working fdt does did not have a /__symbols__ node\n"); + printf("make sure you've compiled with -@\n"); + } return CMD_RET_FAILURE; } } diff --git a/common/image-fit.c b/common/image-fit.c index cb089ea..28140f1 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1946,6 +1946,7 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, const char *uname; void *base, *ov; int i, err, noffset, ov_noffset; + bool has_symbols; #endif
fit_uname = fit_unamep ? *fit_unamep : NULL; @@ -2038,9 +2039,18 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, fdt_noffset = err; goto out; } + + err = fdt_path_offset(base, "/__symbols__"); + has_symbols = err >= 0; + err = fdt_overlay_apply(base, ov); if (err < 0) { - printf("failed on fdt_overlay_apply\n"); + printf("failed on fdt_overlay_apply(): %s\n", + fdt_strerror(err)); + if (!has_symbols) { + printf("base fdt does did not have a /__symbols__ node\n"); + printf("make sure you've compiled with -@\n"); + } fdt_noffset = err; goto out; }

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
The most common trouble with overlays appears to be miscompiled blobs without the -@ option.
In case of an error, spit out a descriptive error message.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
cmd/fdt.c | 8 ++++++++ common/image-fit.c | 12 +++++++++++- 2 files changed, 19 insertions(+), 1 deletion(-)
diff --git a/cmd/fdt.c b/cmd/fdt.c index 05e19f8..9f192be 100644 --- a/cmd/fdt.c +++ b/cmd/fdt.c @@ -654,6 +654,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) unsigned long addr; struct fdt_header *blob; int ret;
bool has_symbols; if (argc != 3) return CMD_RET_USAGE;
@@ -666,9 +667,16 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!fdt_valid(&blob)) return CMD_RET_FAILURE;
ret = fdt_path_offset(working_fdt, "/__symbols__");
has_symbols = ret >= 0;
ret = fdt_overlay_apply(working_fdt, blob); if (ret) { printf("fdt_overlay_apply(): %s\n", fdt_strerror(ret));
if (!has_symbols) {
printf("working fdt does did not have a /__symbols__ node\n");
printf("make sure you've compiled with -@\n");
} return CMD_RET_FAILURE; } }
diff --git a/common/image-fit.c b/common/image-fit.c index cb089ea..28140f1 100644 --- a/common/image-fit.c +++ b/common/image-fit.c @@ -1946,6 +1946,7 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, const char *uname; void *base, *ov; int i, err, noffset, ov_noffset;
bool has_symbols;
#endif
fit_uname = fit_unamep ? *fit_unamep : NULL;
@@ -2038,9 +2039,18 @@ int boot_get_fdt_fit(bootm_headers_t *images, ulong addr, fdt_noffset = err; goto out; }
err = fdt_path_offset(base, "/__symbols__");
has_symbols = err >= 0;
err = fdt_overlay_apply(base, ov); if (err < 0) {
printf("failed on fdt_overlay_apply\n");
printf("failed on fdt_overlay_apply(): %s\n",
fdt_strerror(err));
if (!has_symbols) {
printf("base fdt does did not have a /__symbols__ node\n");
printf("make sure you've compiled with -@\n");
}
Can you put this code in a common function and call it from both places?
Regards, Simon

We have the capability to apply overlays on the command line but we didn't have a document explaining how.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com --- doc/README.fdt-overlays | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 doc/README.fdt-overlays
diff --git a/doc/README.fdt-overlays b/doc/README.fdt-overlays new file mode 100644 index 0000000..ee868ec --- /dev/null +++ b/doc/README.fdt-overlays @@ -0,0 +1,37 @@ +U-Boot FDT Overlay usage (without FIT images) +============================================= + +FDT overlays are now available for use even without FIT images. +It is not as automagic as with FIT images though and require a few +manual steps. + +1. Figure out where to place both the base device tree blob and the +overlay. Make sure you have enough space to grow the base tree without +overlapping anything. + +=> setenv fdtaddr 0x87f00000 +=> setenv fdtovaddr 0x87fc0000 + +2. Load the base blob and overlay blobs + +=> load ${devtype} ${bootpart} ${fdtaddr} ${bootdir}/base.dtb +=> load ${devtype} ${bootpart} ${fdtovaddr} ${bootdir}/overlay.dtb + +3. Set it as the working fdt tree. + +=> fdtaddr $fdtaddr + +4. Grow it enough so it can 'fit' all the applied overlays + +=> fdt resize 8192 + +5. You are now ready to apply the overlay. + +=> fdt apply $fdtovaddr + +Please note that in case of an error, both the base and overlays are going +to be invalidated, so keep copies to avoid reloading. + +Pantelis Antoniou +pantelis.antoniou@konsulko.com +11/7/2017

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
We have the capability to apply overlays on the command line but we didn't have a document explaining how.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
doc/README.fdt-overlays | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 doc/README.fdt-overlays
Reviewed-by: Simon Glass sjg@chromium.org

From: Franklin S Cooper Jr fcooper@ti.com
Pull some information regarding overlays from commit messages and put them directly within the documentation. Also add some information regarding required dtc version to properly use overlays.
Signed-off-by: Franklin S Cooper Jr fcooper@ti.com --- doc/README.fdt-overlays | 85 +++++++++++++++++++++++++++++++++++-- doc/uImage.FIT/overlay-fdt-boot.txt | 8 +++- 2 files changed, 87 insertions(+), 6 deletions(-)
diff --git a/doc/README.fdt-overlays b/doc/README.fdt-overlays index ee868ec..39139cb 100644 --- a/doc/README.fdt-overlays +++ b/doc/README.fdt-overlays @@ -1,9 +1,76 @@ -U-Boot FDT Overlay usage (without FIT images) +U-Boot FDT Overlay usage =============================================
-FDT overlays are now available for use even without FIT images. -It is not as automagic as with FIT images though and require a few -manual steps. +Overlays Syntax +--------------- + +Overlays require slightly different syntax compared to traditional overlays. +Please refer to dt-object-internal.txt in the dtc sources for information +regarding the internal format of overlays: +https://git.kernel.org/pub/scm/utils/dtc/dtc.git/tree/Documentation/dt-objec... + +Building Overlays +----------------- + +In a nutshell overlays provides a means to manipulate a symbol a previous dtb +or 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. + +Note support for -@ option can only be found in dtc version 1.4.4 or newer. +Only version 4.14 or higher of the Linux kernel includes a built in version +of dtc that meets this requirement. + +Building an overlay follows the same process as building a traditional dtb. + +For example: + +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 + +Ways to Utilize Overlays in U-boot +---------------------------------- + +There are two ways to apply overlays in U-boot. +1. Include and define overlays within a FIT image and have overlays + automatically applied. + +2. Manually load and apply overlays + +The remainder of this document will discuss using overlays via the manual +approach. For information on using overlays as part of a FIT image please see: +doc/uImage.FIT/overlay-fdt-boot.txt + +Manually Loading and Applying Overlays +--------------------------------------
1. Figure out where to place both the base device tree blob and the overlay. Make sure you have enough space to grow the base tree without @@ -29,6 +96,16 @@ overlapping anything.
=> fdt apply $fdtovaddr
+6. Boot system like you would do with a traditional dtb. + +For bootm: + +=> bootm ${kerneladdr} - ${fdtaddr} + +For bootz: + +=> bootz ${kerneladdr} - ${fdtaddr} + Please note that in case of an error, both the base and overlays are going to be invalidated, so keep copies to avoid reloading.
diff --git a/doc/uImage.FIT/overlay-fdt-boot.txt b/doc/uImage.FIT/overlay-fdt-boot.txt index dbdf2a1..63e47da 100644 --- a/doc/uImage.FIT/overlay-fdt-boot.txt +++ b/doc/uImage.FIT/overlay-fdt-boot.txt @@ -1,5 +1,5 @@ -U-Boot FDT Overlay usage -======================== +U-Boot FDT Overlay FIT usage +============================
Introduction ------------ @@ -8,6 +8,10 @@ of similar boards and their expansion options. The same kernel on DT enabled platforms can support this easily enough by providing a DT blob upon boot that matches the desired configuration.
+This document focuses on specifically using overlays as part of a FIT image. +General information regarding overlays including its syntax and building it +can be found in doc/README.fdt-overlays + Configuration without overlays ------------------------------

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
From: Franklin S Cooper Jr fcooper@ti.com
Pull some information regarding overlays from commit messages and put them directly within the documentation. Also add some information regarding required dtc version to properly use overlays.
Signed-off-by: Franklin S Cooper Jr fcooper@ti.com
doc/README.fdt-overlays | 85 +++++++++++++++++++++++++++++++++++-- doc/uImage.FIT/overlay-fdt-boot.txt | 8 +++- 2 files changed, 87 insertions(+), 6 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Special rule for dtbo generation
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com --- scripts/Makefile.lib | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib index 9ce47b4..2a7ed70 100644 --- a/scripts/Makefile.lib +++ b/scripts/Makefile.lib @@ -321,6 +321,23 @@ $(obj)/%.dtb: $(src)/%.dts FORCE
dtc-tmp = $(subst $(comma),_,$(dot-target).dts.tmp)
+# DTCO +# --------------------------------------------------------------------------- + +quiet_cmd_dtco = DTCO $@ +# Rule for objects only; does not put specific u-boot include at the end +# No generation of assembly file either +# Modified for U-Boot +cmd_dtco = mkdir -p $(dir ${dtc-tmp}) ; \ + $(CPP) $(dtc_cpp_flags) -x assembler-with-cpp -o $(dtc-tmp) - ; \ + $(DTC) -@ -O dtb -o $@ -b 0 \ + -i $(dir $<) $(DTC_FLAGS) \ + -d $(depfile).dtc.tmp $(dtc-tmp) ; \ + cat $(depfile).pre.tmp $(depfile).dtc.tmp > $(depfile) + +$(obj)/%.dtbo: $(src)/%.dts FORCE + $(call if_changed_dep,dtco) + # Fonts # ---------------------------------------------------------------------------

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
Special rule for dtbo generation
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
scripts/Makefile.lib | 17 +++++++++++++++++ 1 file changed, 17 insertions(+)
Reviewed-by: Simon Glass sjg@chromium.org

Add unit tests for sandbox default config.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com --- configs/sandbox_defconfig | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index fd0b952..df8659a 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -187,7 +187,9 @@ CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ERRNO_STR=y +CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_UT_ENV=y +CONFIG_UT_OVERLAY=y

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
Add unit tests for sandbox default config.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
configs/sandbox_defconfig | 2 ++ 1 file changed, 2 insertions(+)
I don't see any tests in this patch?
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index fd0b952..df8659a 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -187,7 +187,9 @@ CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ERRNO_STR=y +CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_UT_ENV=y
+CONFIG_UT_OVERLAY=y
2.1.4
Regards, Simon

Hi Simon,
On Sat, 2017-08-26 at 07:37 -0600, Simon Glass wrote:
On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
Add unit tests for sandbox default config.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
configs/sandbox_defconfig | 2 ++ 1 file changed, 2 insertions(+)
I don't see any tests in this patch?
Err, maybe the wording of the commit message needs to change. There are no new tests, merely enabling overlays for the sandbox config makes them available as unitests.
I will reword.
diff --git a/configs/sandbox_defconfig b/configs/sandbox_defconfig index fd0b952..df8659a 100644 --- a/configs/sandbox_defconfig +++ b/configs/sandbox_defconfig @@ -187,7 +187,9 @@ CONFIG_CMD_DHRYSTONE=y CONFIG_TPM=y CONFIG_LZ4=y CONFIG_ERRNO_STR=y +CONFIG_OF_LIBFDT_OVERLAY=y CONFIG_UNIT_TEST=y CONFIG_UT_TIME=y CONFIG_UT_DM=y CONFIG_UT_ENV=y
+CONFIG_UT_OVERLAY=y
2.1.4
Regards, Simon

fdt_getprop_u32 is not exported and it's different than what the unit test uses. Rename u32 prop access methods to something that's unit test specific.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com --- test/overlay/cmd_ut_overlay.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c index cbef720..7106f42 100644 --- a/test/overlay/cmd_ut_overlay.c +++ b/test/overlay/cmd_ut_overlay.c @@ -21,7 +21,7 @@ extern u32 __dtb_test_fdt_base_begin; extern u32 __dtb_test_fdt_overlay_begin;
-static int fdt_getprop_u32_by_index(void *fdt, const char *path, +static int ut_fdt_getprop_u32_by_index(void *fdt, const char *path, const char *name, int index, u32 *out) { @@ -42,10 +42,10 @@ static int fdt_getprop_u32_by_index(void *fdt, const char *path, return 0; }
-static int fdt_getprop_u32(void *fdt, const char *path, const char *name, +static int ut_fdt_getprop_u32(void *fdt, const char *path, const char *name, u32 *out) { - return fdt_getprop_u32_by_index(fdt, path, name, 0, out); + return ut_fdt_getprop_u32_by_index(fdt, path, name, 0, out); }
static int fdt_getprop_str(void *fdt, const char *path, const char *name, @@ -68,7 +68,7 @@ static int fdt_overlay_change_int_property(struct unit_test_state *uts) void *fdt = uts->priv; u32 val = 0;
- ut_assertok(fdt_getprop_u32(fdt, "/test-node", "test-int-property", + ut_assertok(ut_fdt_getprop_u32(fdt, "/test-node", "test-int-property", &val)); ut_asserteq(43, val);
@@ -158,11 +158,11 @@ static int fdt_overlay_local_phandle(struct unit_test_state *uts) local_phandle = fdt_get_phandle(fdt, off); ut_assert(local_phandle);
- ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle", + ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle", 0, &val)); ut_asserteq(local_phandle, val);
- ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle", + ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-several-phandle", 1, &val)); ut_asserteq(local_phandle, val);
@@ -189,11 +189,11 @@ static int fdt_overlay_local_phandles(struct unit_test_state *uts) test_phandle = fdt_get_phandle(fdt, off); ut_assert(test_phandle);
- ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 0, + ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 0, &val)); ut_asserteq(test_phandle, val);
- ut_assertok(fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 1, + ut_assertok(ut_fdt_getprop_u32_by_index(fdt, "/", "test-phandle", 1, &val)); ut_asserteq(local_phandle, val);

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
fdt_getprop_u32 is not exported and it's different than what the unit test uses. Rename u32 prop access methods to something that's unit test specific.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
test/overlay/cmd_ut_overlay.c | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-)
Reviewed-by: Simon Glass sjg@chromium.org

Verify that stacked overlays work.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com --- test/overlay/Makefile | 1 + test/overlay/cmd_ut_overlay.c | 34 ++++++++++++++++++++++++++++++- test/overlay/test-fdt-overlay-stacked.dts | 21 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 test/overlay/test-fdt-overlay-stacked.dts
diff --git a/test/overlay/Makefile b/test/overlay/Makefile index 907f085..416645c 100644 --- a/test/overlay/Makefile +++ b/test/overlay/Makefile @@ -13,3 +13,4 @@ DTC_FLAGS += -@ # DT overlays obj-y += test-fdt-base.dtb.o obj-y += test-fdt-overlay.dtb.o +obj-y += test-fdt-overlay-stacked.dtb.o diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c index 7106f42..24891ee 100644 --- a/test/overlay/cmd_ut_overlay.c +++ b/test/overlay/cmd_ut_overlay.c @@ -20,6 +20,7 @@
extern u32 __dtb_test_fdt_base_begin; extern u32 __dtb_test_fdt_overlay_begin; +extern u32 __dtb_test_fdt_overlay_stacked_begin;
static int ut_fdt_getprop_u32_by_index(void *fdt, const char *path, const char *name, int index, @@ -201,6 +202,19 @@ static int fdt_overlay_local_phandles(struct unit_test_state *uts) } OVERLAY_TEST(fdt_overlay_local_phandles, 0);
+static int fdt_overlay_stacked(struct unit_test_state *uts) +{ + void *fdt = uts->priv; + u32 val = 0; + + ut_assertok(ut_fdt_getprop_u32(fdt, "/new-local-node", + "stacked-test-int-property", &val)); + ut_asserteq(43, val); + + return CMD_RET_SUCCESS; +} +OVERLAY_TEST(fdt_overlay_stacked, 0); + int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) { struct unit_test *tests = ll_entry_start(struct unit_test, @@ -210,7 +224,8 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) struct unit_test *test; void *fdt_base = &__dtb_test_fdt_base_begin; void *fdt_overlay = &__dtb_test_fdt_overlay_begin; - void *fdt_base_copy, *fdt_overlay_copy; + void *fdt_overlay_stacked = &__dtb_test_fdt_overlay_stacked_begin; + void *fdt_base_copy, *fdt_overlay_copy, *fdt_overlay_stacked_copy;
uts = calloc(1, sizeof(*uts)); if (!uts) @@ -228,6 +243,10 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) if (!fdt_overlay_copy) return -ENOMEM;
+ fdt_overlay_stacked_copy = malloc(FDT_COPY_SIZE); + if (!fdt_overlay_stacked_copy) + return -ENOMEM; + /* * Resize the FDT to 4k so that we have room to operate on * @@ -245,9 +264,21 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]) ut_assertok(fdt_open_into(fdt_overlay, fdt_overlay_copy, FDT_COPY_SIZE));
+ /* + * Resize the stacked overlay to 4k so that we have room to operate on + * + * (and relocate it since the memory might be mapped + * read-only) + */ + ut_assertok(fdt_open_into(fdt_overlay_stacked, fdt_overlay_stacked_copy, + FDT_COPY_SIZE)); + /* Apply the overlay */ ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
+ /* Apply the stacked overlay */ + ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_stacked_copy)); + if (argc == 1) printf("Running %d environment tests\n", n_ents);
@@ -263,6 +294,7 @@ int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
printf("Failures: %d\n", uts->fail_count);
+ free(fdt_overlay_stacked_copy); free(fdt_overlay_copy); free(fdt_base_copy); free(uts); diff --git a/test/overlay/test-fdt-overlay-stacked.dts b/test/overlay/test-fdt-overlay-stacked.dts new file mode 100644 index 0000000..9fb7c7b --- /dev/null +++ b/test/overlay/test-fdt-overlay-stacked.dts @@ -0,0 +1,21 @@ +/* + * Copyright (c) 2016 NextThing Co + * Copyright (c) 2016 Free Electrons + * Copyright (c) 2018 Konsulko Group + * + * SPDX-License-Identifier: GPL-2.0+ + */ + +/dts-v1/; +/plugin/; + +/ { + /* Test that we can reference an overlay symbol */ + fragment@0 { + target = <&local>; + + __overlay__ { + stacked-test-int-property = <43>; + }; + }; +};

On 11 August 2017 at 02:52, Pantelis Antoniou pantelis.antoniou@konsulko.com wrote:
Verify that stacked overlays work.
Signed-off-by: Pantelis Antoniou pantelis.antoniou@konsulko.com
test/overlay/Makefile | 1 + test/overlay/cmd_ut_overlay.c | 34 ++++++++++++++++++++++++++++++- test/overlay/test-fdt-overlay-stacked.dts | 21 +++++++++++++++++++ 3 files changed, 55 insertions(+), 1 deletion(-) create mode 100644 test/overlay/test-fdt-overlay-stacked.dts
Reviewed-by: Simon Glass sjg@chromium.org
participants (2)
-
Pantelis Antoniou
-
Simon Glass