All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
@ 2016-06-24 14:27 ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

Hi,

The device tree overlays are a great solution to the issue raised by
the bunch expandable boards we find everywhere these days, like the
Beaglebone, Raspberry Pi or CHIP.

However, most of the time, the overlays are applied through a
mechanism involving the firmware request interface in Linux, that is
only fully functional once the userspace has been mounted and is
running.

Some expansion boards might need to be enabled before that, because
they simply need to patch the DT early on, or need to be initialized
early in order to be fully functional, or because they provide access
to the root filesystem.

In these cases, having the bootloader applying the overlay before
Linux starts seems like the easiest solution.

This implementation doesn't provide all the Linux fancyness though,
there's no transactional application, which means that if the overlay
cannot be applied for a reason while you're still halfway through the
application, you're probably screwed. It also cannot remove an
overlay, but I don't think that it is currently a use-case.

There's still a bunch of work to extend the libfdt unit tests to test
the new functions introduced, but these patches will be submitted
in a near future.

Let me know what you think,
Maxime

Changes from v2:
  - Add Kconfig option for the libfdt overlay support
  - Reworked the code to deal with Pantelis and David numerous
    comments, among which:
    * Remove the need for malloc in the overlay code, and added some
      libfdt functions to do that
    * Remove the DT magic in case of an error to not be able to use it
      anymore
    * Removed the fdt_ and _ function prefix for the static functions
    * Plus the usual bunch of rework, error checking and optimizations.

  - Added new tests to deal with bugs reported by David (the overlay
    was not applying when you add a subnode declared that was already
    in the base device tree, and using a local phandle was only
    working if the property storing it only had a length of 4).

Changes from v1:
  - Moved the overlay code to libfdt
  - Added unit tests
  - Refactored the code to reduce the amount of memory allocation
  - No longer modify the overlay itself, but create a copy to operate
    on instead.
  - Removed the limitations on the fixups path, names and properties
    length
  - Fixed a few things here and there according to comments		    

Maxime Ripard (12):
  cmd: fdt: Narrow the check for fdt addr
  scripts: Makefile.lib: Sanitize DTB names
  vsprintf: Include stdarg for va_list
  libfdt: Add new headers and defines
  libfdt: Add iterator over properties
  libfdt: Add max phandle retrieval function
  libfdt: Add fdt_setprop_inplace_by_index
  libfdt: Add fdt_path_offset_namelen
  libfdt: Add fdt_getprop_namelen_w
  libfdt: Add overlay application function
  cmd: fdt: add fdt overlay application subcommand
  tests: Introduce DT overlay tests

 Makefile                          |   1 +
 cmd/fdt.c                         |  26 ++-
 include/libfdt.h                  | 124 ++++++++++++-
 include/libfdt_env.h              |   6 +
 include/test/overlay.h            |  16 ++
 include/test/suites.h             |   1 +
 include/vsprintf.h                |   2 +
 lib/Kconfig                       |   5 +
 lib/libfdt/Makefile               |   2 +
 lib/libfdt/fdt_overlay.c          | 381 ++++++++++++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c               |  44 ++++-
 lib/libfdt/fdt_wip.c              |  13 +-
 scripts/Makefile.lib              |   8 +-
 test/Kconfig                      |   1 +
 test/cmd_ut.c                     |   6 +
 test/overlay/Kconfig              |  11 ++
 test/overlay/Makefile             |  15 ++
 test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++
 test/overlay/test-fdt-base.dts    |  21 +++
 test/overlay/test-fdt-overlay.dts |  88 +++++++++
 20 files changed, 992 insertions(+), 22 deletions(-)
 create mode 100644 include/test/overlay.h
 create mode 100644 lib/libfdt/fdt_overlay.c
 create mode 100644 test/overlay/Kconfig
 create mode 100644 test/overlay/Makefile
 create mode 100644 test/overlay/cmd_ut_overlay.c
 create mode 100644 test/overlay/test-fdt-base.dts
 create mode 100644 test/overlay/test-fdt-overlay.dts

-- 
2.9.0

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
@ 2016-06-24 14:27 ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

Hi,

The device tree overlays are a great solution to the issue raised by
the bunch expandable boards we find everywhere these days, like the
Beaglebone, Raspberry Pi or CHIP.

However, most of the time, the overlays are applied through a
mechanism involving the firmware request interface in Linux, that is
only fully functional once the userspace has been mounted and is
running.

Some expansion boards might need to be enabled before that, because
they simply need to patch the DT early on, or need to be initialized
early in order to be fully functional, or because they provide access
to the root filesystem.

In these cases, having the bootloader applying the overlay before
Linux starts seems like the easiest solution.

This implementation doesn't provide all the Linux fancyness though,
there's no transactional application, which means that if the overlay
cannot be applied for a reason while you're still halfway through the
application, you're probably screwed. It also cannot remove an
overlay, but I don't think that it is currently a use-case.

There's still a bunch of work to extend the libfdt unit tests to test
the new functions introduced, but these patches will be submitted
in a near future.

Let me know what you think,
Maxime

Changes from v2:
  - Add Kconfig option for the libfdt overlay support
  - Reworked the code to deal with Pantelis and David numerous
    comments, among which:
    * Remove the need for malloc in the overlay code, and added some
      libfdt functions to do that
    * Remove the DT magic in case of an error to not be able to use it
      anymore
    * Removed the fdt_ and _ function prefix for the static functions
    * Plus the usual bunch of rework, error checking and optimizations.

  - Added new tests to deal with bugs reported by David (the overlay
    was not applying when you add a subnode declared that was already
    in the base device tree, and using a local phandle was only
    working if the property storing it only had a length of 4).

Changes from v1:
  - Moved the overlay code to libfdt
  - Added unit tests
  - Refactored the code to reduce the amount of memory allocation
  - No longer modify the overlay itself, but create a copy to operate
    on instead.
  - Removed the limitations on the fixups path, names and properties
    length
  - Fixed a few things here and there according to comments		    

Maxime Ripard (12):
  cmd: fdt: Narrow the check for fdt addr
  scripts: Makefile.lib: Sanitize DTB names
  vsprintf: Include stdarg for va_list
  libfdt: Add new headers and defines
  libfdt: Add iterator over properties
  libfdt: Add max phandle retrieval function
  libfdt: Add fdt_setprop_inplace_by_index
  libfdt: Add fdt_path_offset_namelen
  libfdt: Add fdt_getprop_namelen_w
  libfdt: Add overlay application function
  cmd: fdt: add fdt overlay application subcommand
  tests: Introduce DT overlay tests

 Makefile                          |   1 +
 cmd/fdt.c                         |  26 ++-
 include/libfdt.h                  | 124 ++++++++++++-
 include/libfdt_env.h              |   6 +
 include/test/overlay.h            |  16 ++
 include/test/suites.h             |   1 +
 include/vsprintf.h                |   2 +
 lib/Kconfig                       |   5 +
 lib/libfdt/Makefile               |   2 +
 lib/libfdt/fdt_overlay.c          | 381 ++++++++++++++++++++++++++++++++++++++
 lib/libfdt/fdt_ro.c               |  44 ++++-
 lib/libfdt/fdt_wip.c              |  13 +-
 scripts/Makefile.lib              |   8 +-
 test/Kconfig                      |   1 +
 test/cmd_ut.c                     |   6 +
 test/overlay/Kconfig              |  11 ++
 test/overlay/Makefile             |  15 ++
 test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++
 test/overlay/test-fdt-base.dts    |  21 +++
 test/overlay/test-fdt-overlay.dts |  88 +++++++++
 20 files changed, 992 insertions(+), 22 deletions(-)
 create mode 100644 include/test/overlay.h
 create mode 100644 lib/libfdt/fdt_overlay.c
 create mode 100644 test/overlay/Kconfig
 create mode 100644 test/overlay/Makefile
 create mode 100644 test/overlay/cmd_ut_overlay.c
 create mode 100644 test/overlay/test-fdt-base.dts
 create mode 100644 test/overlay/test-fdt-overlay.dts

-- 
2.9.0

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 01/12] cmd: fdt: Narrow the check for fdt addr
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

The current code only checks if the fdt subcommand is fdt addr by checking
whether it starts with 'a'.

Since this is a pretty widely used letter, narrow down that check a bit.

Acked-by: Simon Glass <sjg@chromium.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 cmd/fdt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmd/fdt.c b/cmd/fdt.c
index 898217ffe5f8..0f5923e75a41 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -87,7 +87,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	/*
 	 * Set the address of the fdt
 	 */
-	if (argv[1][0] == 'a') {
+	if (strncmp(argv[1], "ad", 2) == 0) {
 		unsigned long addr;
 		int control = 0;
 		struct fdt_header *blob;
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 01/12] cmd: fdt: Narrow the check for fdt addr
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

The current code only checks if the fdt subcommand is fdt addr by checking
whether it starts with 'a'.

Since this is a pretty widely used letter, narrow down that check a bit.

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 cmd/fdt.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/cmd/fdt.c b/cmd/fdt.c
index 898217ffe5f8..0f5923e75a41 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -87,7 +87,7 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 	/*
 	 * Set the address of the fdt
 	 */
-	if (argv[1][0] == 'a') {
+	if (strncmp(argv[1], "ad", 2) == 0) {
 		unsigned long addr;
 		int control = 0;
 		struct fdt_header *blob;
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 02/12] scripts: Makefile.lib: Sanitize DTB names
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

Having dashes as a separator in the DTB name is a quite common practice.

However, the current code to generate objects from DTBs assumes the
separator is an underscore, leading to a compilation error when building a
device tree with dashes.

Replace all the dashes in the DTB name to generate the symbols name, which
should solve this issue.

Acked-by: Simon Glass <sjg@chromium.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 scripts/Makefile.lib | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index e720562623c9..45a0e1d486c0 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -275,11 +275,11 @@ cmd_dt_S_dtb=						\
 (							\
 	echo '.section .dtb.init.rodata,"a"';		\
 	echo '.balign 16';				\
-	echo '.global __dtb_$(*F)_begin';		\
-	echo '__dtb_$(*F)_begin:';			\
+	echo '.global __dtb_$(subst -,_,$(*F))_begin';	\
+	echo '__dtb_$(subst -,_,$(*F))_begin:';		\
 	echo '.incbin "$<" ';				\
-	echo '__dtb_$(*F)_end:';			\
-	echo '.global __dtb_$(*F)_end';			\
+	echo '__dtb_$(subst -,_,$(*F))_end:';		\
+	echo '.global __dtb_$(subst -,_,$(*F))_end';	\
 	echo '.balign 16';				\
 ) > $@
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 02/12] scripts: Makefile.lib: Sanitize DTB names
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

Having dashes as a separator in the DTB name is a quite common practice.

However, the current code to generate objects from DTBs assumes the
separator is an underscore, leading to a compilation error when building a
device tree with dashes.

Replace all the dashes in the DTB name to generate the symbols name, which
should solve this issue.

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 scripts/Makefile.lib | 8 ++++----
 1 file changed, 4 insertions(+), 4 deletions(-)

diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
index e720562623c9..45a0e1d486c0 100644
--- a/scripts/Makefile.lib
+++ b/scripts/Makefile.lib
@@ -275,11 +275,11 @@ cmd_dt_S_dtb=						\
 (							\
 	echo '.section .dtb.init.rodata,"a"';		\
 	echo '.balign 16';				\
-	echo '.global __dtb_$(*F)_begin';		\
-	echo '__dtb_$(*F)_begin:';			\
+	echo '.global __dtb_$(subst -,_,$(*F))_begin';	\
+	echo '__dtb_$(subst -,_,$(*F))_begin:';		\
 	echo '.incbin "$<" ';				\
-	echo '__dtb_$(*F)_end:';			\
-	echo '.global __dtb_$(*F)_end';			\
+	echo '__dtb_$(subst -,_,$(*F))_end:';		\
+	echo '.global __dtb_$(subst -,_,$(*F))_end';	\
 	echo '.balign 16';				\
 ) > $@
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 03/12] vsprintf: Include stdarg for va_list
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

vsprintf.h doesn't include the stdarg.h file, which means that it relies on
the files that include vsprintf.h to include stdarg.h as well.

Add an explicit include to avoid build errors when simply including that
file.

Acked-by: Simon Glass <sjg@chromium.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/vsprintf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index 376f5dd32499..60e91d119eee 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -8,6 +8,8 @@
 #ifndef __VSPRINTF_H
 #define __VSPRINTF_H
 
+#include <stdarg.h>
+
 ulong simple_strtoul(const char *cp, char **endp, unsigned int base);
 
 /**
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 03/12] vsprintf: Include stdarg for va_list
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

vsprintf.h doesn't include the stdarg.h file, which means that it relies on
the files that include vsprintf.h to include stdarg.h as well.

Add an explicit include to avoid build errors when simply including that
file.

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 include/vsprintf.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/vsprintf.h b/include/vsprintf.h
index 376f5dd32499..60e91d119eee 100644
--- a/include/vsprintf.h
+++ b/include/vsprintf.h
@@ -8,6 +8,8 @@
 #ifndef __VSPRINTF_H
 #define __VSPRINTF_H
 
+#include <stdarg.h>
+
 ulong simple_strtoul(const char *cp, char **endp, unsigned int base);
 
 /**
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

The libfdt overlay support introduces a bunch of new includes and
functions.

Make sure we are able to build it by adding the needed glue.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/libfdt_env.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/libfdt_env.h b/include/libfdt_env.h
index 273b5d30f867..6c6845f76cf7 100644
--- a/include/libfdt_env.h
+++ b/include/libfdt_env.h
@@ -23,6 +23,12 @@ typedef __be64 fdt64_t;
 #define fdt64_to_cpu(x)		be64_to_cpu(x)
 #define cpu_to_fdt64(x)		cpu_to_be64(x)
 
+#ifdef __UBOOT__
+#include <vsprintf.h>
+
+#define strtoul(cp, endp, base)	simple_strtoul(cp, endp, base)
+#endif
+
 /* adding a ramdisk needs 0x44 bytes in version 2008.10 */
 #define FDT_RAMDISK_OVERHEAD	0x80
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

The libfdt overlay support introduces a bunch of new includes and
functions.

Make sure we are able to build it by adding the needed glue.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 include/libfdt_env.h | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/include/libfdt_env.h b/include/libfdt_env.h
index 273b5d30f867..6c6845f76cf7 100644
--- a/include/libfdt_env.h
+++ b/include/libfdt_env.h
@@ -23,6 +23,12 @@ typedef __be64 fdt64_t;
 #define fdt64_to_cpu(x)		be64_to_cpu(x)
 #define cpu_to_fdt64(x)		cpu_to_be64(x)
 
+#ifdef __UBOOT__
+#include <vsprintf.h>
+
+#define strtoul(cp, endp, base)	simple_strtoul(cp, endp, base)
+#endif
+
 /* adding a ramdisk needs 0x44 bytes in version 2008.10 */
 #define FDT_RAMDISK_OVERHEAD	0x80
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 05/12] libfdt: Add iterator over properties
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

Implement a macro based on fdt_first_property_offset and
fdt_next_property_offset that provides a convenience to iterate over all
the properties of a given node.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/libfdt.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index 74b1d149c2dd..fbbe58ceb3f1 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -440,6 +440,30 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
  */
 int fdt_next_property_offset(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_property - iterate over all properties of a node
+ * @property_offset:	property offset (int)
+ * @fdt:		FDT blob (const void *)
+ * @node:		node offset (int)
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *	fdt_for_each_property(fdt, node, property) {
+ *		...
+ *		use property
+ *		...
+ *	}
+ *
+ * Note that this is implemented as a macro and property is used as
+ * iterator in the loop. It should therefore be a locally allocated
+ * variable. The node variable on the other hand is never modified, so
+ * it can be constant or even a literal.
+ */
+#define fdt_for_each_property_offset(property, fdt, node)	\
+	for (property = fdt_first_property_offset(fdt, node);	\
+	     property >= 0;					\
+	     property = fdt_next_property_offset(fdt, property))
+
 /**
  * fdt_get_property_by_offset - retrieve the property at a given offset
  * @fdt: pointer to the device tree blob
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 05/12] libfdt: Add iterator over properties
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

Implement a macro based on fdt_first_property_offset and
fdt_next_property_offset that provides a convenience to iterate over all
the properties of a given node.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 include/libfdt.h | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index 74b1d149c2dd..fbbe58ceb3f1 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -440,6 +440,30 @@ int fdt_first_property_offset(const void *fdt, int nodeoffset);
  */
 int fdt_next_property_offset(const void *fdt, int offset);
 
+/**
+ * fdt_for_each_property - iterate over all properties of a node
+ * @property_offset:	property offset (int)
+ * @fdt:		FDT blob (const void *)
+ * @node:		node offset (int)
+ *
+ * This is actually a wrapper around a for loop and would be used like so:
+ *
+ *	fdt_for_each_property(fdt, node, property) {
+ *		...
+ *		use property
+ *		...
+ *	}
+ *
+ * Note that this is implemented as a macro and property is used as
+ * iterator in the loop. It should therefore be a locally allocated
+ * variable. The node variable on the other hand is never modified, so
+ * it can be constant or even a literal.
+ */
+#define fdt_for_each_property_offset(property, fdt, node)	\
+	for (property = fdt_first_property_offset(fdt, node);	\
+	     property >= 0;					\
+	     property = fdt_next_property_offset(fdt, property))
+
 /**
  * fdt_get_property_by_offset - retrieve the property at a given offset
  * @fdt: pointer to the device tree blob
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 06/12] libfdt: Add max phandle retrieval function
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

Add a function to retrieve the highest phandle in a given device tree.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
Reviewed-by: Stefan Agner <stefan@agner.ch>
---
 include/libfdt.h    | 13 +++++++++++++
 lib/libfdt/fdt_ro.c | 26 ++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index fbbe58ceb3f1..4643be5adf39 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -283,6 +283,19 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
+/**
+ * fdt_get_max_phandle - retrieves the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ *
+ * fdt_get_max_phandle retrieves the highest phandle in the given
+ * device tree
+ *
+ * returns:
+ *      the highest phandle on success
+ *      0, if an error occurred
+ */
+uint32_t fdt_get_max_phandle(const void *fdt);
+
 /**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
  * @fdt: pointer to the device tree blob
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 12214c2dc2b5..503150ef1dc5 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -47,6 +47,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
 	return (strnlen(p, len + 1) == len) && (memcmp(p, s, len) == 0);
 }
 
+uint32_t fdt_get_max_phandle(const void *fdt)
+{
+	uint32_t max_phandle = 0;
+	int offset;
+
+	for (offset = fdt_next_node(fdt, -1, NULL);;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		uint32_t phandle;
+
+		if (offset == -FDT_ERR_NOTFOUND)
+			return max_phandle;
+
+		if (offset < 0)
+			return 0;
+
+		phandle = fdt_get_phandle(fdt, offset);
+		if (phandle == (uint32_t)-1)
+			return 0;
+
+		if (phandle > max_phandle)
+			max_phandle = phandle;
+	}
+
+	return 0;
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
 	FDT_CHECK_HEADER(fdt);
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 06/12] libfdt: Add max phandle retrieval function
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

Add a function to retrieve the highest phandle in a given device tree.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
Reviewed-by: Stefan Agner <stefan-XLVq0VzYD2Y@public.gmane.org>
---
 include/libfdt.h    | 13 +++++++++++++
 lib/libfdt/fdt_ro.c | 26 ++++++++++++++++++++++++++
 2 files changed, 39 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index fbbe58ceb3f1..4643be5adf39 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -283,6 +283,19 @@ int fdt_move(const void *fdt, void *buf, int bufsize);
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
+/**
+ * fdt_get_max_phandle - retrieves the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ *
+ * fdt_get_max_phandle retrieves the highest phandle in the given
+ * device tree
+ *
+ * returns:
+ *      the highest phandle on success
+ *      0, if an error occurred
+ */
+uint32_t fdt_get_max_phandle(const void *fdt);
+
 /**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
  * @fdt: pointer to the device tree blob
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 12214c2dc2b5..503150ef1dc5 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -47,6 +47,32 @@ static int _fdt_string_eq(const void *fdt, int stroffset,
 	return (strnlen(p, len + 1) == len) && (memcmp(p, s, len) == 0);
 }
 
+uint32_t fdt_get_max_phandle(const void *fdt)
+{
+	uint32_t max_phandle = 0;
+	int offset;
+
+	for (offset = fdt_next_node(fdt, -1, NULL);;
+	     offset = fdt_next_node(fdt, offset, NULL)) {
+		uint32_t phandle;
+
+		if (offset == -FDT_ERR_NOTFOUND)
+			return max_phandle;
+
+		if (offset < 0)
+			return 0;
+
+		phandle = fdt_get_phandle(fdt, offset);
+		if (phandle == (uint32_t)-1)
+			return 0;
+
+		if (phandle > max_phandle)
+			max_phandle = phandle;
+	}
+
+	return 0;
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
 	FDT_CHECK_HEADER(fdt);
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

Add a function to modify inplace a property starting from a given index.

This is especially useful when the property is an array of values, and you
want to update one of them without changing the DT size.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
 lib/libfdt/fdt_wip.c | 13 ++++++++-----
 2 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/include/libfdt.h b/include/libfdt.h
index 4643be5adf39..2c8a42bcb667 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
 /* Write-in-place functions                                           */
 /**********************************************************************/
 
+/**
+ * fdt_setprop_inplace_namelen_by_index - change a property's value,
+ *                                        but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @namelen: number of characters of name to consider
+ * @index: index of the property to change in the array
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * Identical to fdt_setprop_inplace(), but modifies the given property
+ * starting from the given index, and using only the first characters
+ * of the name. It is useful when you want to manipulate only one value of
+ * an array and you have a string that doesn't end with \0.
+ */
+int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
+					 const char *name, int namelen,
+					 uint32_t index, const void *val,
+					 int len);
+
 /**
  * fdt_setprop_inplace - change a property's value, but not its size
  * @fdt: pointer to the device tree blob
@@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
-int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
-			const void *val, int len);
+static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
+				      const char *name, const void *val,
+				      int len)
+{
+	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
+						    strlen(name), 0, val, len);
+}
 
 /**
  * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
@@ -1095,7 +1121,9 @@ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
 					  const char *name, uint32_t val)
 {
 	fdt32_t tmp = cpu_to_fdt32(val);
-	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset,
+						    name, strlen(name),
+						    0, &tmp, sizeof(tmp));
 }
 
 /**
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 9fe988655fe3..737769fa59e2 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -14,20 +14,23 @@
 
 #include "libfdt_internal.h"
 
-int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
-			const void *val, int len)
+int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
+					 const char *name, int namelen,
+					 uint32_t index, const void *val,
+					 int len)
 {
 	void *propval;
 	int proplen;
 
-	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+	propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
+					&proplen);
 	if (!propval)
 		return proplen;
 
-	if (proplen != len)
+	if (proplen < (len + index))
 		return -FDT_ERR_NOSPACE;
 
-	memcpy(propval, val, len);
+	memcpy(propval + index, val, len);
 	return 0;
 }
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

Add a function to modify inplace a property starting from a given index.

This is especially useful when the property is an array of values, and you
want to update one of them without changing the DT size.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
 lib/libfdt/fdt_wip.c | 13 ++++++++-----
 2 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/include/libfdt.h b/include/libfdt.h
index 4643be5adf39..2c8a42bcb667 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
 /* Write-in-place functions                                           */
 /**********************************************************************/
 
+/**
+ * fdt_setprop_inplace_namelen_by_index - change a property's value,
+ *                                        but not its size
+ * @fdt: pointer to the device tree blob
+ * @nodeoffset: offset of the node whose property to change
+ * @name: name of the property to change
+ * @namelen: number of characters of name to consider
+ * @index: index of the property to change in the array
+ * @val: pointer to data to replace the property value with
+ * @len: length of the property value
+ *
+ * Identical to fdt_setprop_inplace(), but modifies the given property
+ * starting from the given index, and using only the first characters
+ * of the name. It is useful when you want to manipulate only one value of
+ * an array and you have a string that doesn't end with \0.
+ */
+int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
+					 const char *name, int namelen,
+					 uint32_t index, const void *val,
+					 int len);
+
 /**
  * fdt_setprop_inplace - change a property's value, but not its size
  * @fdt: pointer to the device tree blob
@@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings
  */
-int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
-			const void *val, int len);
+static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
+				      const char *name, const void *val,
+				      int len)
+{
+	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
+						    strlen(name), 0, val, len);
+}
 
 /**
  * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
@@ -1095,7 +1121,9 @@ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
 					  const char *name, uint32_t val)
 {
 	fdt32_t tmp = cpu_to_fdt32(val);
-	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
+	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset,
+						    name, strlen(name),
+						    0, &tmp, sizeof(tmp));
 }
 
 /**
diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
index 9fe988655fe3..737769fa59e2 100644
--- a/lib/libfdt/fdt_wip.c
+++ b/lib/libfdt/fdt_wip.c
@@ -14,20 +14,23 @@
 
 #include "libfdt_internal.h"
 
-int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
-			const void *val, int len)
+int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
+					 const char *name, int namelen,
+					 uint32_t index, const void *val,
+					 int len)
 {
 	void *propval;
 	int proplen;
 
-	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
+	propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
+					&proplen);
 	if (!propval)
 		return proplen;
 
-	if (proplen != len)
+	if (proplen < (len + index))
 		return -FDT_ERR_NOSPACE;
 
-	memcpy(propval, val, len);
+	memcpy(propval + index, val, len);
 	return 0;
 }
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

Add a namelen variant of fdt_path_offset to retrieve the node offset using
only a fixed number of characters.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/libfdt.h    | 16 +++++++++++++++-
 lib/libfdt/fdt_ro.c | 18 ++++++++++--------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/include/libfdt.h b/include/libfdt.h
index 2c8a42bcb667..dbe8a0efca87 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -365,6 +365,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
  */
 int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
 
+/**
+ * fdt_path_offset_namelen - find a tree node based on substring
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_path_offset(), but only examine the first
+ * namelen characters of path for matching the node path.
+ */
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
+
 /**
  * fdt_path_offset - find a tree node by its full path
  * @fdt: pointer to the device tree blob
@@ -387,7 +398,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings.
  */
-int fdt_path_offset(const void *fdt, const char *path);
+static inline int fdt_path_offset(const void *fdt, const char *path)
+{
+	return fdt_path_offset_namelen(fdt, path, strlen(path));
+}
 
 /**
  * fdt_get_name - retrieve the name of a given node
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 503150ef1dc5..05344d3eebfe 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -145,10 +145,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
  * "foo/bar:option" and "bar:option/otheroption", both of which happen, so
  * first searching for either ':' or '/' does not work.
  */
-static const char *fdt_path_next_seperator(const char *path)
+static const char *fdt_path_next_seperator(const void *path, int len)
 {
-	const char *sep1 = strchr(path, '/');
-	const char *sep2 = strchr(path, ':');
+	const void *sep1 = memchr(path, '/', len);
+	const void *sep2 = memchr(path, ':', len);
 
 	if (sep1 && sep2)
 		return (sep1 < sep2) ? sep1 : sep2;
@@ -158,9 +158,9 @@ static const char *fdt_path_next_seperator(const char *path)
 		return sep2;
 }
 
-int fdt_path_offset(const void *fdt, const char *path)
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
 {
-	const char *end = path + strlen(path);
+	const char *end = path + namelen;
 	const char *p = path;
 	int offset = 0;
 
@@ -168,7 +168,7 @@ int fdt_path_offset(const void *fdt, const char *path)
 
 	/* see if we have an alias */
 	if (*path != '/') {
-		const char *q = fdt_path_next_seperator(path);
+		const char *q = fdt_path_next_seperator(path, namelen);
 
 		if (!q)
 			q = end;
@@ -181,14 +181,16 @@ int fdt_path_offset(const void *fdt, const char *path)
 		p = q;
 	}
 
-	while (*p) {
+	while (*p && (p < end)) {
 		const char *q;
 
 		while (*p == '/')
 			p++;
+
 		if (*p == '\0' || *p == ':')
 			return offset;
-		q = fdt_path_next_seperator(p);
+
+		q = fdt_path_next_seperator(p, end - p);
 		if (!q)
 			q = end;
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

Add a namelen variant of fdt_path_offset to retrieve the node offset using
only a fixed number of characters.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 include/libfdt.h    | 16 +++++++++++++++-
 lib/libfdt/fdt_ro.c | 18 ++++++++++--------
 2 files changed, 25 insertions(+), 9 deletions(-)

diff --git a/include/libfdt.h b/include/libfdt.h
index 2c8a42bcb667..dbe8a0efca87 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -365,6 +365,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
  */
 int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
 
+/**
+ * fdt_path_offset_namelen - find a tree node based on substring
+ * @fdt: pointer to the device tree blob
+ * @path: full path of the node to locate
+ * @namelen: number of characters of name to consider
+ *
+ * Identical to fdt_path_offset(), but only examine the first
+ * namelen characters of path for matching the node path.
+ */
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
+
 /**
  * fdt_path_offset - find a tree node by its full path
  * @fdt: pointer to the device tree blob
@@ -387,7 +398,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
  *	-FDT_ERR_BADSTRUCTURE,
  *	-FDT_ERR_TRUNCATED, standard meanings.
  */
-int fdt_path_offset(const void *fdt, const char *path);
+static inline int fdt_path_offset(const void *fdt, const char *path)
+{
+	return fdt_path_offset_namelen(fdt, path, strlen(path));
+}
 
 /**
  * fdt_get_name - retrieve the name of a given node
diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
index 503150ef1dc5..05344d3eebfe 100644
--- a/lib/libfdt/fdt_ro.c
+++ b/lib/libfdt/fdt_ro.c
@@ -145,10 +145,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
  * "foo/bar:option" and "bar:option/otheroption", both of which happen, so
  * first searching for either ':' or '/' does not work.
  */
-static const char *fdt_path_next_seperator(const char *path)
+static const char *fdt_path_next_seperator(const void *path, int len)
 {
-	const char *sep1 = strchr(path, '/');
-	const char *sep2 = strchr(path, ':');
+	const void *sep1 = memchr(path, '/', len);
+	const void *sep2 = memchr(path, ':', len);
 
 	if (sep1 && sep2)
 		return (sep1 < sep2) ? sep1 : sep2;
@@ -158,9 +158,9 @@ static const char *fdt_path_next_seperator(const char *path)
 		return sep2;
 }
 
-int fdt_path_offset(const void *fdt, const char *path)
+int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
 {
-	const char *end = path + strlen(path);
+	const char *end = path + namelen;
 	const char *p = path;
 	int offset = 0;
 
@@ -168,7 +168,7 @@ int fdt_path_offset(const void *fdt, const char *path)
 
 	/* see if we have an alias */
 	if (*path != '/') {
-		const char *q = fdt_path_next_seperator(path);
+		const char *q = fdt_path_next_seperator(path, namelen);
 
 		if (!q)
 			q = end;
@@ -181,14 +181,16 @@ int fdt_path_offset(const void *fdt, const char *path)
 		p = q;
 	}
 
-	while (*p) {
+	while (*p && (p < end)) {
 		const char *q;
 
 		while (*p == '/')
 			p++;
+
 		if (*p == '\0' || *p == ':')
 			return offset;
-		q = fdt_path_next_seperator(p);
+
+		q = fdt_path_next_seperator(p, end - p);
 		if (!q)
 			q = end;
 
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

Add a function to retrieve a writeable property only by the first
characters of its name.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/libfdt.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index dbe8a0efca87..b8758de3ae54 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
  */
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
 				const char *name, int namelen, int *lenp);
+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
+					  const char *name, int namelen,
+					  int *lenp)
+{
+	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
+						      namelen, lenp);
+}
 
 /**
  * fdt_getprop - retrieve the value of a given property
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

Add a function to retrieve a writeable property only by the first
characters of its name.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 include/libfdt.h | 7 +++++++
 1 file changed, 7 insertions(+)

diff --git a/include/libfdt.h b/include/libfdt.h
index dbe8a0efca87..b8758de3ae54 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
  */
 const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
 				const char *name, int namelen, int *lenp);
+static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
+					  const char *name, int namelen,
+					  int *lenp)
+{
+	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
+						      namelen, lenp);
+}
 
 /**
  * fdt_getprop - retrieve the value of a given property
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

The device tree overlays are a good way to deal with user-modifyable
boards or boards with some kind of an expansion mechanism where we can
easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).

Add a new function to merge overlays with a base device tree.

Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 include/libfdt.h         |  30 ++++
 lib/Kconfig              |   5 +
 lib/libfdt/Makefile      |   2 +
 lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 418 insertions(+)
 create mode 100644 lib/libfdt/fdt_overlay.c

diff --git a/include/libfdt.h b/include/libfdt.h
index b8758de3ae54..039ecb0c1ba7 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1747,6 +1747,36 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
  */
 int fdt_del_node(void *fdt, int nodeoffset);
 
+/**
+ * fdt_overlay_apply - Applies a DT overlay on a base DT
+ * @fdt: pointer to the base device tree blob
+ * @fdto: pointer to the device tree overlay blob
+ *
+ * fdt_overlay_apply() will apply the given device tree overlay on the
+ * given base device tree.
+ *
+ * Expect the base device tree to be modified, even if the function
+ * returns an error.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
+ *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
+ *		properties in the base DT
+ *	-FDT_ERR_BADPHANDLE, the phandles in the overlay do not have the right
+ *		magic
+ *	-FDT_ERR_INTERNAL,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADOFFSET,
+ *	-FDT_ERR_BADPATH,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_overlay_apply(void *fdt, void *fdto);
+
 /**********************************************************************/
 /* Debugging / informational functions                                */
 /**********************************************************************/
diff --git a/lib/Kconfig b/lib/Kconfig
index 02ca4058d37e..16ff01a2cd37 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -139,6 +139,11 @@ config OF_LIBFDT
 	  particular compatible nodes. The library operates on a flattened
 	  version of the device tree.
 
+config OF_LIBFDT_OVERLAY
+	bool "Enable the FDT library overlay support"
+	help
+	  This enables the FDT library (libfdt) overlay support.
+
 config SPL_OF_LIBFDT
 	bool "Enable the FDT library for SPL"
 	default y if SPL_OF_CONTROL
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index 8b86c15904cb..6ef8290f4e09 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -15,3 +15,5 @@ obj-y += \
 	fdt_empty_tree.o \
 	fdt_addresses.o \
 	fdt_region.o
+
+obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
new file mode 100644
index 000000000000..5835a90afafe
--- /dev/null
+++ b/lib/libfdt/fdt_overlay.c
@@ -0,0 +1,381 @@
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
+{
+	const uint32_t *val;
+	int len;
+
+	val = fdt_getprop(fdto, fragment, "target", &len);
+	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
+		return 0;
+
+	return fdt32_to_cpu(*val);
+}
+
+static int overlay_get_target(const void *fdt, const void *fdto,
+			      int fragment)
+{
+	uint32_t phandle;
+	const char *path;
+
+	/* Try first to do a phandle based lookup */
+	phandle = overlay_get_target_phandle(fdto, fragment);
+	if (phandle)
+		return fdt_node_offset_by_phandle(fdt, phandle);
+
+	/* And then a path based lookup */
+	path = fdt_getprop(fdto, fragment, "target-path", NULL);
+	if (!path)
+		return -FDT_ERR_NOTFOUND;
+
+	return fdt_path_offset(fdt, path);
+}
+
+static int overlay_phandle_add_offset(void *fdt, int node,
+				      const char *name, uint32_t delta)
+{
+	const uint32_t *val;
+	uint32_t adj_val;
+	int len;
+
+	val = fdt_getprop(fdt, node, name, &len);
+	if (!val)
+		return len;
+
+	if (len != sizeof(*val))
+		return -FDT_ERR_BADSTRUCTURE;
+
+	adj_val = fdt32_to_cpu(*val);
+	adj_val += delta;
+
+	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
+}
+
+static int overlay_adjust_node_phandles(void *fdto, int node,
+					uint32_t delta)
+{
+	bool found = false;
+	int child;
+	int ret;
+
+	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	if (!ret)
+		found = true;
+
+	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	/*
+	 * If neither phandle nor linux,phandle have been found return
+	 * an error.
+	 */
+	if (!found && !ret)
+		return ret;
+
+	fdt_for_each_subnode(fdto, child, node)
+		overlay_adjust_node_phandles(fdto, child, delta);
+
+	return 0;
+}
+
+static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
+{
+	/*
+	 * Start adjusting the phandles from the overlay root
+	 */
+	return overlay_adjust_node_phandles(fdto, 0, delta);
+}
+
+static int overlay_update_local_node_references(void *fdto,
+						int tree_node,
+						int fixup_node,
+						uint32_t delta)
+{
+	int fixup_prop;
+	int fixup_child;
+	int ret;
+
+	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
+		const uint32_t *val = NULL;
+		uint32_t adj_val, index;
+		const char *name;
+		int fixup_len;
+		int tree_len;
+
+		val = fdt_getprop_by_offset(fdto, fixup_prop,
+					    &name, &fixup_len);
+		if (!val)
+			return fixup_len;
+		index = fdt32_to_cpu(*val);
+
+		val = fdt_getprop(fdto, tree_node, name, &tree_len);
+		if (!val)
+			return tree_len;
+
+		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
+		adj_val += delta;
+		adj_val = cpu_to_fdt32(adj_val);
+
+		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
+							   name, strlen(name),
+							   index, &adj_val,
+							   sizeof(adj_val));
+		if (ret)
+			return ret;
+	}
+
+	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
+		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
+							    NULL);
+		int tree_child;
+
+		tree_child = fdt_subnode_offset(fdto, tree_node,
+						fixup_child_name);
+		if (tree_child < 0)
+			return tree_child;
+
+		ret = overlay_update_local_node_references(fdto,
+							   tree_child,
+							   fixup_child,
+							   delta);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int overlay_update_local_references(void *dto, uint32_t delta)
+{
+	int fixups;
+
+	fixups = fdt_path_offset(dto, "/__local_fixups__");
+	if (fixups < 0) {
+		/*
+		 * There's no local phandles to adjust, bail out
+		 */
+		if (fixups == -FDT_ERR_NOTFOUND)
+			return 0;
+
+		return fixups;
+	}
+
+	/*
+	 * Update our local references from the root of the tree
+	 */
+	return overlay_update_local_node_references(dto, 0, fixups,
+						    delta);
+}
+
+static int overlay_fixup_one_phandle(void *fdt, void *fdto,
+				     int symbols_off,
+				     const char *path, uint32_t path_len,
+				     const char *name, uint32_t name_len,
+				     int index, const char *label)
+{
+	const char *symbol_path;
+	uint32_t phandle;
+	int symbol_off, fixup_off;
+	int prop_len;
+
+	symbol_path = fdt_getprop(fdt, symbols_off, label,
+				  &prop_len);
+	if (!symbol_path)
+		return -FDT_ERR_NOTFOUND;
+
+	symbol_off = fdt_path_offset(fdt, symbol_path);
+	if (symbol_off < 0)
+		return symbol_off;
+
+	phandle = fdt_get_phandle(fdt, symbol_off);
+	if (!phandle)
+		return -FDT_ERR_NOTFOUND;
+
+	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
+	if (fixup_off < 0)
+		return fixup_off;
+
+	phandle = cpu_to_fdt32(phandle);
+	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
+						    name, name_len, index,
+						    &phandle, sizeof(phandle));
+};
+
+static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
+				 int property)
+{
+	const char *value;
+	const char *label;
+	int len;
+
+	value = fdt_getprop_by_offset(fdto, property,
+				      &label, &len);
+	if (!value)
+		return len;
+
+	do {
+		const char *prop_string = value;
+		const char *path, *name;
+		uint32_t path_len, name_len;
+		char *sep, *endptr;
+		int index;
+		int ret;
+
+		path = prop_string;
+		sep = strchr(prop_string, ':');
+		path_len = sep - path;
+
+		name = sep + 1;
+		sep = strchr(name, ':');
+		name_len = sep - name;
+
+		index = strtoul(sep + 1, &endptr, 10);
+		if (endptr <= (sep + 1))
+			return -FDT_ERR_BADSTRUCTURE;
+
+		index = strtoul(sep + 1, &endptr, 10);
+		if (endptr <= (sep + 1))
+			return -FDT_ERR_BADSTRUCTURE;
+
+		len -= strlen(prop_string) + 1;
+		value += strlen(prop_string) + 1;
+
+		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
+						path, path_len, name, name_len,
+						index, label);
+		if (ret)
+			return ret;
+	} while (len > 0);
+
+	return 0;
+}
+
+static int overlay_fixup_phandles(void *dt, void *dto)
+{
+	int fixups_off, symbols_off;
+	int property;
+
+	symbols_off = fdt_path_offset(dt, "/__symbols__");
+	fixups_off = fdt_path_offset(dto, "/__fixups__");
+
+	fdt_for_each_property_offset(property, dto, fixups_off)
+		overlay_fixup_phandle(dt, dto, symbols_off, property);
+
+	return 0;
+}
+
+static int apply_overlay_node(void *dt, int target,
+			      void *dto, int overlay)
+{
+	int property;
+	int node;
+
+	fdt_for_each_property_offset(property, dto, overlay) {
+		const char *name;
+		const void *prop;
+		int prop_len;
+		int ret;
+
+		prop = fdt_getprop_by_offset(dto, property, &name,
+					     &prop_len);
+		if (!prop)
+			return -FDT_ERR_INTERNAL;
+
+		ret = fdt_setprop(dt, target, name, prop, prop_len);
+		if (ret)
+			return ret;
+	}
+
+	fdt_for_each_subnode(dto, node, overlay) {
+		const char *name = fdt_get_name(dto, node, NULL);
+		int nnode;
+		int ret;
+
+		nnode = fdt_add_subnode(dt, target, name);
+		if (nnode == -FDT_ERR_EXISTS)
+			nnode = fdt_subnode_offset(dt, target, name);
+
+		if (nnode < 0)
+			return nnode;
+
+		ret = apply_overlay_node(dt, nnode, dto, node);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int overlay_merge(void *dt, void *dto)
+{
+	int fragment;
+
+	fdt_for_each_subnode(dto, fragment, 0) {
+		int overlay;
+		int target;
+		int ret;
+
+		target = overlay_get_target(dt, dto, fragment);
+		if (target < 0)
+			continue;
+
+		overlay = fdt_subnode_offset(dto, fragment, "__overlay__");
+		if (overlay < 0)
+			return overlay;
+
+		ret = apply_overlay_node(dt, target, dto, overlay);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int fdt_overlay_apply(void *fdt, void *fdto)
+{
+	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
+	int ret;
+
+	FDT_CHECK_HEADER(fdt);
+	FDT_CHECK_HEADER(fdto);
+
+	ret = overlay_adjust_local_phandles(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_update_local_references(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_fixup_phandles(fdt, fdto);
+	if (ret)
+		goto err;
+
+	ret = overlay_merge(fdt, fdto);
+	if (!ret)
+		goto out;
+
+err:
+	/*
+	 * The base device tree might have been damaged, erase its
+	 * magic.
+	 */
+	fdt_set_magic(fdt, ~0);
+
+out:
+	/*
+	 * The overlay has been damaged, erase its magic.
+	 */
+	fdt_set_magic(fdto, ~0);
+
+	return ret;
+}
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

The device tree overlays are a good way to deal with user-modifyable
boards or boards with some kind of an expansion mechanism where we can
easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).

Add a new function to merge overlays with a base device tree.

Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 include/libfdt.h         |  30 ++++
 lib/Kconfig              |   5 +
 lib/libfdt/Makefile      |   2 +
 lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 418 insertions(+)
 create mode 100644 lib/libfdt/fdt_overlay.c

diff --git a/include/libfdt.h b/include/libfdt.h
index b8758de3ae54..039ecb0c1ba7 100644
--- a/include/libfdt.h
+++ b/include/libfdt.h
@@ -1747,6 +1747,36 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
  */
 int fdt_del_node(void *fdt, int nodeoffset);
 
+/**
+ * fdt_overlay_apply - Applies a DT overlay on a base DT
+ * @fdt: pointer to the base device tree blob
+ * @fdto: pointer to the device tree overlay blob
+ *
+ * fdt_overlay_apply() will apply the given device tree overlay on the
+ * given base device tree.
+ *
+ * Expect the base device tree to be modified, even if the function
+ * returns an error.
+ *
+ * returns:
+ *	0, on success
+ *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
+ *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
+ *		properties in the base DT
+ *	-FDT_ERR_BADPHANDLE, the phandles in the overlay do not have the right
+ *		magic
+ *	-FDT_ERR_INTERNAL,
+ *	-FDT_ERR_BADLAYOUT,
+ *	-FDT_ERR_BADMAGIC,
+ *	-FDT_ERR_BADOFFSET,
+ *	-FDT_ERR_BADPATH,
+ *	-FDT_ERR_BADVERSION,
+ *	-FDT_ERR_BADSTRUCTURE,
+ *	-FDT_ERR_BADSTATE,
+ *	-FDT_ERR_TRUNCATED, standard meanings
+ */
+int fdt_overlay_apply(void *fdt, void *fdto);
+
 /**********************************************************************/
 /* Debugging / informational functions                                */
 /**********************************************************************/
diff --git a/lib/Kconfig b/lib/Kconfig
index 02ca4058d37e..16ff01a2cd37 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -139,6 +139,11 @@ config OF_LIBFDT
 	  particular compatible nodes. The library operates on a flattened
 	  version of the device tree.
 
+config OF_LIBFDT_OVERLAY
+	bool "Enable the FDT library overlay support"
+	help
+	  This enables the FDT library (libfdt) overlay support.
+
 config SPL_OF_LIBFDT
 	bool "Enable the FDT library for SPL"
 	default y if SPL_OF_CONTROL
diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
index 8b86c15904cb..6ef8290f4e09 100644
--- a/lib/libfdt/Makefile
+++ b/lib/libfdt/Makefile
@@ -15,3 +15,5 @@ obj-y += \
 	fdt_empty_tree.o \
 	fdt_addresses.o \
 	fdt_region.o
+
+obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
new file mode 100644
index 000000000000..5835a90afafe
--- /dev/null
+++ b/lib/libfdt/fdt_overlay.c
@@ -0,0 +1,381 @@
+#include "libfdt_env.h"
+
+#include <fdt.h>
+#include <libfdt.h>
+
+#include "libfdt_internal.h"
+
+static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
+{
+	const uint32_t *val;
+	int len;
+
+	val = fdt_getprop(fdto, fragment, "target", &len);
+	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
+		return 0;
+
+	return fdt32_to_cpu(*val);
+}
+
+static int overlay_get_target(const void *fdt, const void *fdto,
+			      int fragment)
+{
+	uint32_t phandle;
+	const char *path;
+
+	/* Try first to do a phandle based lookup */
+	phandle = overlay_get_target_phandle(fdto, fragment);
+	if (phandle)
+		return fdt_node_offset_by_phandle(fdt, phandle);
+
+	/* And then a path based lookup */
+	path = fdt_getprop(fdto, fragment, "target-path", NULL);
+	if (!path)
+		return -FDT_ERR_NOTFOUND;
+
+	return fdt_path_offset(fdt, path);
+}
+
+static int overlay_phandle_add_offset(void *fdt, int node,
+				      const char *name, uint32_t delta)
+{
+	const uint32_t *val;
+	uint32_t adj_val;
+	int len;
+
+	val = fdt_getprop(fdt, node, name, &len);
+	if (!val)
+		return len;
+
+	if (len != sizeof(*val))
+		return -FDT_ERR_BADSTRUCTURE;
+
+	adj_val = fdt32_to_cpu(*val);
+	adj_val += delta;
+
+	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
+}
+
+static int overlay_adjust_node_phandles(void *fdto, int node,
+					uint32_t delta)
+{
+	bool found = false;
+	int child;
+	int ret;
+
+	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	if (!ret)
+		found = true;
+
+	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
+	if (ret && ret != -FDT_ERR_NOTFOUND)
+		return ret;
+
+	/*
+	 * If neither phandle nor linux,phandle have been found return
+	 * an error.
+	 */
+	if (!found && !ret)
+		return ret;
+
+	fdt_for_each_subnode(fdto, child, node)
+		overlay_adjust_node_phandles(fdto, child, delta);
+
+	return 0;
+}
+
+static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
+{
+	/*
+	 * Start adjusting the phandles from the overlay root
+	 */
+	return overlay_adjust_node_phandles(fdto, 0, delta);
+}
+
+static int overlay_update_local_node_references(void *fdto,
+						int tree_node,
+						int fixup_node,
+						uint32_t delta)
+{
+	int fixup_prop;
+	int fixup_child;
+	int ret;
+
+	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
+		const uint32_t *val = NULL;
+		uint32_t adj_val, index;
+		const char *name;
+		int fixup_len;
+		int tree_len;
+
+		val = fdt_getprop_by_offset(fdto, fixup_prop,
+					    &name, &fixup_len);
+		if (!val)
+			return fixup_len;
+		index = fdt32_to_cpu(*val);
+
+		val = fdt_getprop(fdto, tree_node, name, &tree_len);
+		if (!val)
+			return tree_len;
+
+		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
+		adj_val += delta;
+		adj_val = cpu_to_fdt32(adj_val);
+
+		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
+							   name, strlen(name),
+							   index, &adj_val,
+							   sizeof(adj_val));
+		if (ret)
+			return ret;
+	}
+
+	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
+		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
+							    NULL);
+		int tree_child;
+
+		tree_child = fdt_subnode_offset(fdto, tree_node,
+						fixup_child_name);
+		if (tree_child < 0)
+			return tree_child;
+
+		ret = overlay_update_local_node_references(fdto,
+							   tree_child,
+							   fixup_child,
+							   delta);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int overlay_update_local_references(void *dto, uint32_t delta)
+{
+	int fixups;
+
+	fixups = fdt_path_offset(dto, "/__local_fixups__");
+	if (fixups < 0) {
+		/*
+		 * There's no local phandles to adjust, bail out
+		 */
+		if (fixups == -FDT_ERR_NOTFOUND)
+			return 0;
+
+		return fixups;
+	}
+
+	/*
+	 * Update our local references from the root of the tree
+	 */
+	return overlay_update_local_node_references(dto, 0, fixups,
+						    delta);
+}
+
+static int overlay_fixup_one_phandle(void *fdt, void *fdto,
+				     int symbols_off,
+				     const char *path, uint32_t path_len,
+				     const char *name, uint32_t name_len,
+				     int index, const char *label)
+{
+	const char *symbol_path;
+	uint32_t phandle;
+	int symbol_off, fixup_off;
+	int prop_len;
+
+	symbol_path = fdt_getprop(fdt, symbols_off, label,
+				  &prop_len);
+	if (!symbol_path)
+		return -FDT_ERR_NOTFOUND;
+
+	symbol_off = fdt_path_offset(fdt, symbol_path);
+	if (symbol_off < 0)
+		return symbol_off;
+
+	phandle = fdt_get_phandle(fdt, symbol_off);
+	if (!phandle)
+		return -FDT_ERR_NOTFOUND;
+
+	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
+	if (fixup_off < 0)
+		return fixup_off;
+
+	phandle = cpu_to_fdt32(phandle);
+	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
+						    name, name_len, index,
+						    &phandle, sizeof(phandle));
+};
+
+static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
+				 int property)
+{
+	const char *value;
+	const char *label;
+	int len;
+
+	value = fdt_getprop_by_offset(fdto, property,
+				      &label, &len);
+	if (!value)
+		return len;
+
+	do {
+		const char *prop_string = value;
+		const char *path, *name;
+		uint32_t path_len, name_len;
+		char *sep, *endptr;
+		int index;
+		int ret;
+
+		path = prop_string;
+		sep = strchr(prop_string, ':');
+		path_len = sep - path;
+
+		name = sep + 1;
+		sep = strchr(name, ':');
+		name_len = sep - name;
+
+		index = strtoul(sep + 1, &endptr, 10);
+		if (endptr <= (sep + 1))
+			return -FDT_ERR_BADSTRUCTURE;
+
+		index = strtoul(sep + 1, &endptr, 10);
+		if (endptr <= (sep + 1))
+			return -FDT_ERR_BADSTRUCTURE;
+
+		len -= strlen(prop_string) + 1;
+		value += strlen(prop_string) + 1;
+
+		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
+						path, path_len, name, name_len,
+						index, label);
+		if (ret)
+			return ret;
+	} while (len > 0);
+
+	return 0;
+}
+
+static int overlay_fixup_phandles(void *dt, void *dto)
+{
+	int fixups_off, symbols_off;
+	int property;
+
+	symbols_off = fdt_path_offset(dt, "/__symbols__");
+	fixups_off = fdt_path_offset(dto, "/__fixups__");
+
+	fdt_for_each_property_offset(property, dto, fixups_off)
+		overlay_fixup_phandle(dt, dto, symbols_off, property);
+
+	return 0;
+}
+
+static int apply_overlay_node(void *dt, int target,
+			      void *dto, int overlay)
+{
+	int property;
+	int node;
+
+	fdt_for_each_property_offset(property, dto, overlay) {
+		const char *name;
+		const void *prop;
+		int prop_len;
+		int ret;
+
+		prop = fdt_getprop_by_offset(dto, property, &name,
+					     &prop_len);
+		if (!prop)
+			return -FDT_ERR_INTERNAL;
+
+		ret = fdt_setprop(dt, target, name, prop, prop_len);
+		if (ret)
+			return ret;
+	}
+
+	fdt_for_each_subnode(dto, node, overlay) {
+		const char *name = fdt_get_name(dto, node, NULL);
+		int nnode;
+		int ret;
+
+		nnode = fdt_add_subnode(dt, target, name);
+		if (nnode == -FDT_ERR_EXISTS)
+			nnode = fdt_subnode_offset(dt, target, name);
+
+		if (nnode < 0)
+			return nnode;
+
+		ret = apply_overlay_node(dt, nnode, dto, node);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+static int overlay_merge(void *dt, void *dto)
+{
+	int fragment;
+
+	fdt_for_each_subnode(dto, fragment, 0) {
+		int overlay;
+		int target;
+		int ret;
+
+		target = overlay_get_target(dt, dto, fragment);
+		if (target < 0)
+			continue;
+
+		overlay = fdt_subnode_offset(dto, fragment, "__overlay__");
+		if (overlay < 0)
+			return overlay;
+
+		ret = apply_overlay_node(dt, target, dto, overlay);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+
+int fdt_overlay_apply(void *fdt, void *fdto)
+{
+	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
+	int ret;
+
+	FDT_CHECK_HEADER(fdt);
+	FDT_CHECK_HEADER(fdto);
+
+	ret = overlay_adjust_local_phandles(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_update_local_references(fdto, delta);
+	if (ret)
+		goto err;
+
+	ret = overlay_fixup_phandles(fdt, fdto);
+	if (ret)
+		goto err;
+
+	ret = overlay_merge(fdt, fdto);
+	if (!ret)
+		goto out;
+
+err:
+	/*
+	 * The base device tree might have been damaged, erase its
+	 * magic.
+	 */
+	fdt_set_magic(fdt, ~0);
+
+out:
+	/*
+	 * The overlay has been damaged, erase its magic.
+	 */
+	fdt_set_magic(fdto, ~0);
+
+	return ret;
+}
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 11/12] cmd: fdt: add fdt overlay application subcommand
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

The device tree overlays are a good way to deal with user-modifyable
boards or boards with some kind of an expansion mechanism where we can
easily plug new board in (like the BBB or the raspberry pi).

However, so far, the usual mechanism to deal with it was to have in Linux
some driver detecting the expansion boards plugged in and then request
these overlays using the firmware interface.

That works in most cases, but in some cases, you might want to have the
overlays applied before the userspace comes in. Either because the new
board requires some kind of an early initialization, or because your root
filesystem is accessed through that expansion board.

The easiest solution in such a case is to simply have the component before
Linux applying that overlay, removing all these drawbacks.

Reviewed-by: Stefan Agner <stefan@agner.ch>
Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Acked-by: Simon Glass <sjg@chromium.org>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 cmd/fdt.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/cmd/fdt.c b/cmd/fdt.c
index 0f5923e75a41..58af7727ba08 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -639,6 +639,27 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #endif
 
 	}
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+	/* apply an overlay */
+	else if (strncmp(argv[1], "ap", 2) == 0) {
+		unsigned long addr;
+		struct fdt_header *blob;
+
+		if (argc != 3)
+			return CMD_RET_USAGE;
+
+		if (!working_fdt)
+			return CMD_RET_FAILURE;
+
+		addr = simple_strtoul(argv[2], NULL, 16);
+		blob = map_sysmem(addr, 0);
+		if (!fdt_valid(&blob))
+			return CMD_RET_FAILURE;
+
+		if (fdt_overlay_apply(working_fdt, blob))
+			return CMD_RET_FAILURE;
+	}
+#endif
 	/* resize the fdt */
 	else if (strncmp(argv[1], "re", 2) == 0) {
 		fdt_shrink_to_minimum(working_fdt);
@@ -1025,6 +1046,9 @@ static int fdt_print(const char *pathp, char *prop, int depth)
 #ifdef CONFIG_SYS_LONGHELP
 static char fdt_help_text[] =
 	"addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>\n"
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+	"fdt apply <addr>                    - Apply overlay to the DT\n"
+#endif
 #ifdef CONFIG_OF_BOARD_SETUP
 	"fdt boardsetup                      - Do board-specific set up\n"
 #endif
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 11/12] cmd: fdt: add fdt overlay application subcommand
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

The device tree overlays are a good way to deal with user-modifyable
boards or boards with some kind of an expansion mechanism where we can
easily plug new board in (like the BBB or the raspberry pi).

However, so far, the usual mechanism to deal with it was to have in Linux
some driver detecting the expansion boards plugged in and then request
these overlays using the firmware interface.

That works in most cases, but in some cases, you might want to have the
overlays applied before the userspace comes in. Either because the new
board requires some kind of an early initialization, or because your root
filesystem is accessed through that expansion board.

The easiest solution in such a case is to simply have the component before
Linux applying that overlay, removing all these drawbacks.

Reviewed-by: Stefan Agner <stefan-XLVq0VzYD2Y@public.gmane.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 cmd/fdt.c | 24 ++++++++++++++++++++++++
 1 file changed, 24 insertions(+)

diff --git a/cmd/fdt.c b/cmd/fdt.c
index 0f5923e75a41..58af7727ba08 100644
--- a/cmd/fdt.c
+++ b/cmd/fdt.c
@@ -639,6 +639,27 @@ static int do_fdt(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
 #endif
 
 	}
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+	/* apply an overlay */
+	else if (strncmp(argv[1], "ap", 2) == 0) {
+		unsigned long addr;
+		struct fdt_header *blob;
+
+		if (argc != 3)
+			return CMD_RET_USAGE;
+
+		if (!working_fdt)
+			return CMD_RET_FAILURE;
+
+		addr = simple_strtoul(argv[2], NULL, 16);
+		blob = map_sysmem(addr, 0);
+		if (!fdt_valid(&blob))
+			return CMD_RET_FAILURE;
+
+		if (fdt_overlay_apply(working_fdt, blob))
+			return CMD_RET_FAILURE;
+	}
+#endif
 	/* resize the fdt */
 	else if (strncmp(argv[1], "re", 2) == 0) {
 		fdt_shrink_to_minimum(working_fdt);
@@ -1025,6 +1046,9 @@ static int fdt_print(const char *pathp, char *prop, int depth)
 #ifdef CONFIG_SYS_LONGHELP
 static char fdt_help_text[] =
 	"addr [-c]  <addr> [<length>]   - Set the [control] fdt location to <addr>\n"
+#ifdef CONFIG_OF_LIBFDT_OVERLAY
+	"fdt apply <addr>                    - Apply overlay to the DT\n"
+#endif
 #ifdef CONFIG_OF_BOARD_SETUP
 	"fdt boardsetup                      - Do board-specific set up\n"
 #endif
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 12/12] tests: Introduce DT overlay tests
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: u-boot

This adds a bunch of unit tests for the "fdt apply" command.

They've all been run successfully in the sandbox. However, as you still
require an out-of-tree dtc with overlay support, this is disabled by
default.

Acked-by: Simon Glass <sjg@chromium.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
---
 Makefile                          |   1 +
 include/test/overlay.h            |  16 +++
 include/test/suites.h             |   1 +
 test/Kconfig                      |   1 +
 test/cmd_ut.c                     |   6 +
 test/overlay/Kconfig              |  11 ++
 test/overlay/Makefile             |  15 +++
 test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++++++++++++++++
 test/overlay/test-fdt-base.dts    |  21 ++++
 test/overlay/test-fdt-overlay.dts |  88 ++++++++++++++
 10 files changed, 403 insertions(+)
 create mode 100644 include/test/overlay.h
 create mode 100644 test/overlay/Kconfig
 create mode 100644 test/overlay/Makefile
 create mode 100644 test/overlay/cmd_ut_overlay.c
 create mode 100644 test/overlay/test-fdt-base.dts
 create mode 100644 test/overlay/test-fdt-overlay.dts

diff --git a/Makefile b/Makefile
index d0e7a8a4ecc7..88353d091be8 100644
--- a/Makefile
+++ b/Makefile
@@ -665,6 +665,7 @@ libs-$(CONFIG_HAS_POST) += post/
 libs-y += test/
 libs-y += test/dm/
 libs-$(CONFIG_UT_ENV) += test/env/
+libs-$(CONFIG_UT_OVERLAY) += test/overlay/
 
 libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
 
diff --git a/include/test/overlay.h b/include/test/overlay.h
new file mode 100644
index 000000000000..392f28ff8405
--- /dev/null
+++ b/include/test/overlay.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __TEST_OVERLAY_H__
+#define __TEST_OVERLAY_H__
+
+#include <test/test.h>
+
+/* Declare a new environment test */
+#define OVERLAY_TEST(_name, _flags)	UNIT_TEST(_name, _flags, overlay_test)
+
+#endif /* __TEST_OVERLAY_H__ */
diff --git a/include/test/suites.h b/include/test/suites.h
index f5790333ff8e..0e94feb07a79 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -10,6 +10,7 @@
 
 int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 
 #endif /* __TEST_SUITES_H__ */
diff --git a/test/Kconfig b/test/Kconfig
index d71c332eee27..3643761bc6ef 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -17,3 +17,4 @@ config UT_TIME
 
 source "test/dm/Kconfig"
 source "test/env/Kconfig"
+source "test/overlay/Kconfig"
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index f6e1f413db7f..14333423a178 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -19,6 +19,9 @@ static cmd_tbl_t cmd_ut_sub[] = {
 #if defined(CONFIG_UT_ENV)
 	U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""),
 #endif
+#ifdef CONFIG_UT_OVERLAY
+	U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""),
+#endif
 #ifdef CONFIG_UT_TIME
 	U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
 #endif
@@ -68,6 +71,9 @@ static char ut_help_text[] =
 #ifdef CONFIG_UT_ENV
 	"ut env [test-name]\n"
 #endif
+#ifdef CONFIG_UT_OVERLAY
+	"ut overlay [test-name]\n"
+#endif
 #ifdef CONFIG_UT_TIME
 	"ut time - Very basic test of time functions\n"
 #endif
diff --git a/test/overlay/Kconfig b/test/overlay/Kconfig
new file mode 100644
index 000000000000..13c85428cbaa
--- /dev/null
+++ b/test/overlay/Kconfig
@@ -0,0 +1,11 @@
+config UT_OVERLAY
+	bool "Enable Device Tree Overlays Unit Tests"
+	depends on OF_LIBFDT_OVERLAY
+	depends on UNIT_TEST
+	help
+	  This enables the 'ut overlay' command which runs a series of unit
+	  tests on the fdt overlay code.
+	  If all is well then all tests pass although there will be a few
+	  messages printed along the way.
+	  Be warned that it requires an out-of-tree dtc compiler with patches
+	  to support the DT overlays, otherwise it will fail.
diff --git a/test/overlay/Makefile b/test/overlay/Makefile
new file mode 100644
index 000000000000..907f08544619
--- /dev/null
+++ b/test/overlay/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2016 NextThing Co
+# Copyright (c) 2016 Free Electrons
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+# Test files
+obj-y += cmd_ut_overlay.o
+
+DTC_FLAGS += -@
+
+# DT overlays
+obj-y += test-fdt-base.dtb.o
+obj-y += test-fdt-overlay.dtb.o
diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
new file mode 100644
index 000000000000..4a9b3398d119
--- /dev/null
+++ b/test/overlay/cmd_ut_overlay.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include <linux/sizes.h>
+
+#include <test/ut.h>
+#include <test/overlay.h>
+
+/* 4k ought to be enough for anybody */
+#define FDT_COPY_SIZE	(4 * SZ_1K)
+
+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,
+				    const char *name, int index,
+				    u32 *out)
+{
+	const fdt32_t *val;
+	int node_off;
+	int len;
+
+	node_off = fdt_path_offset(fdt, path);
+	if (node_off < 0)
+		return node_off;
+
+	val = fdt_getprop(fdt, node_off, name, &len);
+	if (!val || (len < (sizeof(uint32_t) * (index + 1))))
+		return -FDT_ERR_NOTFOUND;
+
+	*out = fdt32_to_cpu(*(val + index));
+
+	return 0;
+}
+
+static int fdt_getprop_u32(void *fdt, const char *path, const char *name,
+			   u32 *out)
+{
+	return fdt_getprop_u32_by_index(fdt, path, name, 0, out);
+}
+
+static int fdt_getprop_str(void *fdt, const char *path, const char *name,
+			   const char **out)
+{
+	int node_off;
+
+	node_off = fdt_path_offset(fdt, path);
+	if (node_off < 0)
+		return node_off;
+
+	return fdt_get_string(fdt, node_off, name, out);
+}
+
+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",
+				    &val));
+	ut_asserteq(43, val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_change_int_property, 0);
+
+static int fdt_overlay_change_str_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	const char *val = NULL;
+
+	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
+				    &val));
+	ut_asserteq_str("foobar", val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_change_str_property, 0);
+
+static int fdt_overlay_add_str_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	const char *val = NULL;
+
+	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
+				    &val));
+	ut_asserteq_str("foobar2", val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_str_property, 0);
+
+static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/test-node/new-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
+
+static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/new-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
+
+static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/test-node/sub-test-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
+
+static int fdt_overlay_local_phandle(struct unit_test_state *uts)
+{
+	uint32_t local_phandle, test_phandle;
+	void *fdt = uts->priv;
+	u32 val = 0;
+	int off;
+
+	off = fdt_path_offset(fdt, "/new-local-node");
+	ut_assert(off >= 0);
+
+	local_phandle = fdt_get_phandle(fdt, off);
+	ut_assert(local_phandle);
+
+	off = fdt_path_offset(fdt, "/test-node");
+	ut_assert(off >= 0);
+
+	test_phandle = fdt_get_phandle(fdt, off);
+	ut_assert(test_phandle);
+
+	ut_assertok(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,
+					     &val));
+	ut_asserteq(local_phandle, val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_local_phandle, 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,
+						 overlay_test);
+	const int n_ents = ll_entry_count(struct unit_test, overlay_test);
+	struct unit_test_state *uts;
+	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;
+
+	ut_assertok(fdt_check_header(fdt_base));
+	ut_assertok(fdt_check_header(fdt_overlay));
+
+	uts = calloc(1, sizeof(*uts));
+	if (!uts)
+		return -ENOMEM;
+
+	fdt_base_copy = malloc(FDT_COPY_SIZE);
+	if (!fdt_base_copy)
+		return -ENOMEM;
+	uts->priv = fdt_base_copy;
+
+	fdt_overlay_copy = malloc(FDT_COPY_SIZE);
+	if (!fdt_overlay_copy)
+		return -ENOMEM;
+
+	/*
+	 * Resize the FDT 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_base, fdt_base_copy, FDT_COPY_SIZE));
+
+	/*
+	 * Resize the 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, fdt_overlay_copy,
+				  FDT_COPY_SIZE));
+
+	/* Apply the overlay */
+	ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
+
+	if (argc == 1)
+		printf("Running %d environment tests\n", n_ents);
+
+	for (test = tests; test < tests + n_ents; test++) {
+		if (argc > 1 && strcmp(argv[1], test->name))
+			continue;
+		printf("Test: %s\n", test->name);
+
+		uts->start = mallinfo();
+
+		test->func(uts);
+	}
+
+	printf("Failures: %d\n", uts->fail_count);
+
+	free(fdt_overlay_copy);
+	free(fdt_base_copy);
+	free(uts);
+
+	return uts->fail_count ? CMD_RET_FAILURE : 0;
+}
diff --git a/test/overlay/test-fdt-base.dts b/test/overlay/test-fdt-base.dts
new file mode 100644
index 000000000000..2603adb6821e
--- /dev/null
+++ b/test/overlay/test-fdt-base.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+	test: test-node {
+		test-int-property = <42>;
+		test-str-property = "foo";
+
+		subtest: sub-test-node {
+			sub-test-property;
+		};
+	};
+};
+
+
diff --git a/test/overlay/test-fdt-overlay.dts b/test/overlay/test-fdt-overlay.dts
new file mode 100644
index 000000000000..199aa5797ef4
--- /dev/null
+++ b/test/overlay/test-fdt-overlay.dts
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/ {
+	/* Test that we can change an int by another */
+	fragment at 0 {
+		target = <&test>;
+
+		__overlay__ {
+			test-int-property = <43>;
+		};
+	};
+
+	/* Test that we can replace a string by a longer one */
+	fragment at 1 {
+		target = <&test>;
+
+		__overlay__ {
+			test-str-property = "foobar";
+		};
+	};
+
+	/* Test that we add a new property */
+	fragment at 2 {
+		target = <&test>;
+
+		__overlay__ {
+			test-str-property-2 = "foobar2";
+		};
+	};
+
+	/* Test that we add a new node (by phandle) */
+	fragment at 3 {
+		target = <&test>;
+
+		__overlay__ {
+			new-node {
+				new-property;
+			};
+		};
+	};
+
+	/* Test that we add a new node (by path) */
+	fragment at 4 {
+		target-path = "/";
+
+		__overlay__ {
+			new-node {
+				new-property;
+			};
+		};
+	};
+
+	fragment at 5 {
+		target-path = "/";
+
+		__overlay__ {
+			local: new-local-node {
+				new-property;
+			};
+		};
+	};
+
+	fragment at 6 {
+		target-path = "/";
+
+		__overlay__ {
+			test-phandle = <&test>, <&local>;
+		};
+	};
+
+	fragment at 7 {
+		target = <&test>;
+
+		__overlay__ {
+			sub-test-node {
+				new-sub-test-property;
+			};
+		};
+	};
+};
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [PATCH v3 12/12] tests: Introduce DT overlay tests
@ 2016-06-24 14:27   ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-24 14:27 UTC (permalink / raw)
  To: Pantelis Antoniou, Simon Glass
  Cc: Boris Brezillon, Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner, Maxime Ripard

This adds a bunch of unit tests for the "fdt apply" command.

They've all been run successfully in the sandbox. However, as you still
require an out-of-tree dtc with overlay support, this is disabled by
default.

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
---
 Makefile                          |   1 +
 include/test/overlay.h            |  16 +++
 include/test/suites.h             |   1 +
 test/Kconfig                      |   1 +
 test/cmd_ut.c                     |   6 +
 test/overlay/Kconfig              |  11 ++
 test/overlay/Makefile             |  15 +++
 test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++++++++++++++++
 test/overlay/test-fdt-base.dts    |  21 ++++
 test/overlay/test-fdt-overlay.dts |  88 ++++++++++++++
 10 files changed, 403 insertions(+)
 create mode 100644 include/test/overlay.h
 create mode 100644 test/overlay/Kconfig
 create mode 100644 test/overlay/Makefile
 create mode 100644 test/overlay/cmd_ut_overlay.c
 create mode 100644 test/overlay/test-fdt-base.dts
 create mode 100644 test/overlay/test-fdt-overlay.dts

diff --git a/Makefile b/Makefile
index d0e7a8a4ecc7..88353d091be8 100644
--- a/Makefile
+++ b/Makefile
@@ -665,6 +665,7 @@ libs-$(CONFIG_HAS_POST) += post/
 libs-y += test/
 libs-y += test/dm/
 libs-$(CONFIG_UT_ENV) += test/env/
+libs-$(CONFIG_UT_OVERLAY) += test/overlay/
 
 libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
 
diff --git a/include/test/overlay.h b/include/test/overlay.h
new file mode 100644
index 000000000000..392f28ff8405
--- /dev/null
+++ b/include/test/overlay.h
@@ -0,0 +1,16 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#ifndef __TEST_OVERLAY_H__
+#define __TEST_OVERLAY_H__
+
+#include <test/test.h>
+
+/* Declare a new environment test */
+#define OVERLAY_TEST(_name, _flags)	UNIT_TEST(_name, _flags, overlay_test)
+
+#endif /* __TEST_OVERLAY_H__ */
diff --git a/include/test/suites.h b/include/test/suites.h
index f5790333ff8e..0e94feb07a79 100644
--- a/include/test/suites.h
+++ b/include/test/suites.h
@@ -10,6 +10,7 @@
 
 int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
+int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
 
 #endif /* __TEST_SUITES_H__ */
diff --git a/test/Kconfig b/test/Kconfig
index d71c332eee27..3643761bc6ef 100644
--- a/test/Kconfig
+++ b/test/Kconfig
@@ -17,3 +17,4 @@ config UT_TIME
 
 source "test/dm/Kconfig"
 source "test/env/Kconfig"
+source "test/overlay/Kconfig"
diff --git a/test/cmd_ut.c b/test/cmd_ut.c
index f6e1f413db7f..14333423a178 100644
--- a/test/cmd_ut.c
+++ b/test/cmd_ut.c
@@ -19,6 +19,9 @@ static cmd_tbl_t cmd_ut_sub[] = {
 #if defined(CONFIG_UT_ENV)
 	U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""),
 #endif
+#ifdef CONFIG_UT_OVERLAY
+	U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""),
+#endif
 #ifdef CONFIG_UT_TIME
 	U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
 #endif
@@ -68,6 +71,9 @@ static char ut_help_text[] =
 #ifdef CONFIG_UT_ENV
 	"ut env [test-name]\n"
 #endif
+#ifdef CONFIG_UT_OVERLAY
+	"ut overlay [test-name]\n"
+#endif
 #ifdef CONFIG_UT_TIME
 	"ut time - Very basic test of time functions\n"
 #endif
diff --git a/test/overlay/Kconfig b/test/overlay/Kconfig
new file mode 100644
index 000000000000..13c85428cbaa
--- /dev/null
+++ b/test/overlay/Kconfig
@@ -0,0 +1,11 @@
+config UT_OVERLAY
+	bool "Enable Device Tree Overlays Unit Tests"
+	depends on OF_LIBFDT_OVERLAY
+	depends on UNIT_TEST
+	help
+	  This enables the 'ut overlay' command which runs a series of unit
+	  tests on the fdt overlay code.
+	  If all is well then all tests pass although there will be a few
+	  messages printed along the way.
+	  Be warned that it requires an out-of-tree dtc compiler with patches
+	  to support the DT overlays, otherwise it will fail.
diff --git a/test/overlay/Makefile b/test/overlay/Makefile
new file mode 100644
index 000000000000..907f08544619
--- /dev/null
+++ b/test/overlay/Makefile
@@ -0,0 +1,15 @@
+#
+# Copyright (c) 2016 NextThing Co
+# Copyright (c) 2016 Free Electrons
+#
+# SPDX-License-Identifier:	GPL-2.0+
+#
+
+# Test files
+obj-y += cmd_ut_overlay.o
+
+DTC_FLAGS += -@
+
+# DT overlays
+obj-y += test-fdt-base.dtb.o
+obj-y += test-fdt-overlay.dtb.o
diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
new file mode 100644
index 000000000000..4a9b3398d119
--- /dev/null
+++ b/test/overlay/cmd_ut_overlay.c
@@ -0,0 +1,243 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <command.h>
+#include <errno.h>
+#include <malloc.h>
+
+#include <linux/sizes.h>
+
+#include <test/ut.h>
+#include <test/overlay.h>
+
+/* 4k ought to be enough for anybody */
+#define FDT_COPY_SIZE	(4 * SZ_1K)
+
+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,
+				    const char *name, int index,
+				    u32 *out)
+{
+	const fdt32_t *val;
+	int node_off;
+	int len;
+
+	node_off = fdt_path_offset(fdt, path);
+	if (node_off < 0)
+		return node_off;
+
+	val = fdt_getprop(fdt, node_off, name, &len);
+	if (!val || (len < (sizeof(uint32_t) * (index + 1))))
+		return -FDT_ERR_NOTFOUND;
+
+	*out = fdt32_to_cpu(*(val + index));
+
+	return 0;
+}
+
+static int fdt_getprop_u32(void *fdt, const char *path, const char *name,
+			   u32 *out)
+{
+	return fdt_getprop_u32_by_index(fdt, path, name, 0, out);
+}
+
+static int fdt_getprop_str(void *fdt, const char *path, const char *name,
+			   const char **out)
+{
+	int node_off;
+
+	node_off = fdt_path_offset(fdt, path);
+	if (node_off < 0)
+		return node_off;
+
+	return fdt_get_string(fdt, node_off, name, out);
+}
+
+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",
+				    &val));
+	ut_asserteq(43, val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_change_int_property, 0);
+
+static int fdt_overlay_change_str_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	const char *val = NULL;
+
+	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
+				    &val));
+	ut_asserteq_str("foobar", val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_change_str_property, 0);
+
+static int fdt_overlay_add_str_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	const char *val = NULL;
+
+	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
+				    &val));
+	ut_asserteq_str("foobar2", val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_str_property, 0);
+
+static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/test-node/new-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
+
+static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/new-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
+
+static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
+{
+	void *fdt = uts->priv;
+	int off;
+
+	off = fdt_path_offset(fdt, "/test-node/sub-test-node");
+	ut_assert(off >= 0);
+
+	ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
+	ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
+
+static int fdt_overlay_local_phandle(struct unit_test_state *uts)
+{
+	uint32_t local_phandle, test_phandle;
+	void *fdt = uts->priv;
+	u32 val = 0;
+	int off;
+
+	off = fdt_path_offset(fdt, "/new-local-node");
+	ut_assert(off >= 0);
+
+	local_phandle = fdt_get_phandle(fdt, off);
+	ut_assert(local_phandle);
+
+	off = fdt_path_offset(fdt, "/test-node");
+	ut_assert(off >= 0);
+
+	test_phandle = fdt_get_phandle(fdt, off);
+	ut_assert(test_phandle);
+
+	ut_assertok(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,
+					     &val));
+	ut_asserteq(local_phandle, val);
+
+	return CMD_RET_SUCCESS;
+}
+OVERLAY_TEST(fdt_overlay_local_phandle, 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,
+						 overlay_test);
+	const int n_ents = ll_entry_count(struct unit_test, overlay_test);
+	struct unit_test_state *uts;
+	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;
+
+	ut_assertok(fdt_check_header(fdt_base));
+	ut_assertok(fdt_check_header(fdt_overlay));
+
+	uts = calloc(1, sizeof(*uts));
+	if (!uts)
+		return -ENOMEM;
+
+	fdt_base_copy = malloc(FDT_COPY_SIZE);
+	if (!fdt_base_copy)
+		return -ENOMEM;
+	uts->priv = fdt_base_copy;
+
+	fdt_overlay_copy = malloc(FDT_COPY_SIZE);
+	if (!fdt_overlay_copy)
+		return -ENOMEM;
+
+	/*
+	 * Resize the FDT 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_base, fdt_base_copy, FDT_COPY_SIZE));
+
+	/*
+	 * Resize the 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, fdt_overlay_copy,
+				  FDT_COPY_SIZE));
+
+	/* Apply the overlay */
+	ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
+
+	if (argc == 1)
+		printf("Running %d environment tests\n", n_ents);
+
+	for (test = tests; test < tests + n_ents; test++) {
+		if (argc > 1 && strcmp(argv[1], test->name))
+			continue;
+		printf("Test: %s\n", test->name);
+
+		uts->start = mallinfo();
+
+		test->func(uts);
+	}
+
+	printf("Failures: %d\n", uts->fail_count);
+
+	free(fdt_overlay_copy);
+	free(fdt_base_copy);
+	free(uts);
+
+	return uts->fail_count ? CMD_RET_FAILURE : 0;
+}
diff --git a/test/overlay/test-fdt-base.dts b/test/overlay/test-fdt-base.dts
new file mode 100644
index 000000000000..2603adb6821e
--- /dev/null
+++ b/test/overlay/test-fdt-base.dts
@@ -0,0 +1,21 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+
+/ {
+	test: test-node {
+		test-int-property = <42>;
+		test-str-property = "foo";
+
+		subtest: sub-test-node {
+			sub-test-property;
+		};
+	};
+};
+
+
diff --git a/test/overlay/test-fdt-overlay.dts b/test/overlay/test-fdt-overlay.dts
new file mode 100644
index 000000000000..199aa5797ef4
--- /dev/null
+++ b/test/overlay/test-fdt-overlay.dts
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2016 NextThing Co
+ * Copyright (c) 2016 Free Electrons
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+/dts-v1/;
+/plugin/;
+
+/ {
+	/* Test that we can change an int by another */
+	fragment@0 {
+		target = <&test>;
+
+		__overlay__ {
+			test-int-property = <43>;
+		};
+	};
+
+	/* Test that we can replace a string by a longer one */
+	fragment@1 {
+		target = <&test>;
+
+		__overlay__ {
+			test-str-property = "foobar";
+		};
+	};
+
+	/* Test that we add a new property */
+	fragment@2 {
+		target = <&test>;
+
+		__overlay__ {
+			test-str-property-2 = "foobar2";
+		};
+	};
+
+	/* Test that we add a new node (by phandle) */
+	fragment@3 {
+		target = <&test>;
+
+		__overlay__ {
+			new-node {
+				new-property;
+			};
+		};
+	};
+
+	/* Test that we add a new node (by path) */
+	fragment@4 {
+		target-path = "/";
+
+		__overlay__ {
+			new-node {
+				new-property;
+			};
+		};
+	};
+
+	fragment@5 {
+		target-path = "/";
+
+		__overlay__ {
+			local: new-local-node {
+				new-property;
+			};
+		};
+	};
+
+	fragment@6 {
+		target-path = "/";
+
+		__overlay__ {
+			test-phandle = <&test>, <&local>;
+		};
+	};
+
+	fragment@7 {
+		target = <&test>;
+
+		__overlay__ {
+			sub-test-node {
+				new-sub-test-property;
+			};
+		};
+	};
+};
-- 
2.9.0

^ permalink raw reply related	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: u-boot

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The libfdt overlay support introduces a bunch of new includes and
> functions.
>
> Make sure we are able to build it by adding the needed glue.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt_env.h | 6 ++++++
>  1 file changed, 6 insertions(+)

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The libfdt overlay support introduces a bunch of new includes and
> functions.
>
> Make sure we are able to build it by adding the needed glue.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt_env.h | 6 ++++++
>  1 file changed, 6 insertions(+)

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 05/12] libfdt: Add iterator over properties
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: u-boot

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Implement a macro based on fdt_first_property_offset and
> fdt_next_property_offset that provides a convenience to iterate over all
> the properties of a given node.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 05/12] libfdt: Add iterator over properties
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Implement a macro based on fdt_first_property_offset and
> fdt_next_property_offset that provides a convenience to iterate over all
> the properties of a given node.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt.h | 24 ++++++++++++++++++++++++
>  1 file changed, 24 insertions(+)

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 06/12] libfdt: Add max phandle retrieval function
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: u-boot

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add a function to retrieve the highest phandle in a given device tree.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> Reviewed-by: Stefan Agner <stefan@agner.ch>
> ---
>  include/libfdt.h    | 13 +++++++++++++
>  lib/libfdt/fdt_ro.c | 26 ++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+)

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 06/12] libfdt: Add max phandle retrieval function
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Add a function to retrieve the highest phandle in a given device tree.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> Reviewed-by: Stefan Agner <stefan-XLVq0VzYD2Y@public.gmane.org>
> ---
>  include/libfdt.h    | 13 +++++++++++++
>  lib/libfdt/fdt_ro.c | 26 ++++++++++++++++++++++++++
>  2 files changed, 39 insertions(+)

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: u-boot

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add a function to modify inplace a property starting from a given index.
>
> This is especially useful when the property is an array of values, and you
> want to update one of them without changing the DT size.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
>  lib/libfdt/fdt_wip.c | 13 ++++++++-----
>  2 files changed, 39 insertions(+), 8 deletions(-)

Acked-by: Simon Glass <sjg@chromium.org>

I need to get fdt_setprop_inplace() upstream.

- Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Add a function to modify inplace a property starting from a given index.
>
> This is especially useful when the property is an array of values, and you
> want to update one of them without changing the DT size.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
>  lib/libfdt/fdt_wip.c | 13 ++++++++-----
>  2 files changed, 39 insertions(+), 8 deletions(-)

Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

I need to get fdt_setprop_inplace() upstream.

- Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: u-boot

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add a namelen variant of fdt_path_offset to retrieve the node offset using
> only a fixed number of characters.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h    | 16 +++++++++++++++-
>  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
>  2 files changed, 25 insertions(+), 9 deletions(-)

fdt_setprop_inplace

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Add a namelen variant of fdt_path_offset to retrieve the node offset using
> only a fixed number of characters.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt.h    | 16 +++++++++++++++-
>  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
>  2 files changed, 25 insertions(+), 9 deletions(-)

fdt_setprop_inplace

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: u-boot

Hi Maxime,

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Add a function to retrieve a writeable property only by the first
> characters of its name.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/include/libfdt.h b/include/libfdt.h
> index dbe8a0efca87..b8758de3ae54 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
>   */
>  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>                                 const char *name, int namelen, int *lenp);
> +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> +                                         const char *name, int namelen,
> +                                         int *lenp)
> +{
> +       return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> +                                                     namelen, lenp);

What are the casts for?

> +}
>
>  /**
>   * fdt_getprop - retrieve the value of a given property
> --
> 2.9.0

Regards,
Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

Hi Maxime,

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Add a function to retrieve a writeable property only by the first
> characters of its name.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt.h | 7 +++++++
>  1 file changed, 7 insertions(+)
>
> diff --git a/include/libfdt.h b/include/libfdt.h
> index dbe8a0efca87..b8758de3ae54 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
>   */
>  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>                                 const char *name, int namelen, int *lenp);
> +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> +                                         const char *name, int namelen,
> +                                         int *lenp)
> +{
> +       return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> +                                                     namelen, lenp);

What are the casts for?

> +}
>
>  /**
>   * fdt_getprop - retrieve the value of a given property
> --
> 2.9.0

Regards,
Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: u-boot

Hi Maxime,

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> The device tree overlays are a good way to deal with user-modifyable
> boards or boards with some kind of an expansion mechanism where we can
> easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).
>
> Add a new function to merge overlays with a base device tree.
>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h         |  30 ++++
>  lib/Kconfig              |   5 +
>  lib/libfdt/Makefile      |   2 +
>  lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 418 insertions(+)
>  create mode 100644 lib/libfdt/fdt_overlay.c
>

Is there a change log?

> diff --git a/include/libfdt.h b/include/libfdt.h
> index b8758de3ae54..039ecb0c1ba7 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -1747,6 +1747,36 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
>   */
>  int fdt_del_node(void *fdt, int nodeoffset);
>
> +/**
> + * fdt_overlay_apply - Applies a DT overlay on a base DT
> + * @fdt: pointer to the base device tree blob
> + * @fdto: pointer to the device tree overlay blob
> + *
> + * fdt_overlay_apply() will apply the given device tree overlay on the
> + * given base device tree.
> + *
> + * Expect the base device tree to be modified, even if the function
> + * returns an error.
> + *
> + * returns:
> + *     0, on success
> + *     -FDT_ERR_NOSPACE, there's not enough space in the base device tree
> + *     -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
> + *             properties in the base DT
> + *     -FDT_ERR_BADPHANDLE, the phandles in the overlay do not have the right
> + *             magic
> + *     -FDT_ERR_INTERNAL,
> + *     -FDT_ERR_BADLAYOUT,
> + *     -FDT_ERR_BADMAGIC,
> + *     -FDT_ERR_BADOFFSET,
> + *     -FDT_ERR_BADPATH,
> + *     -FDT_ERR_BADVERSION,
> + *     -FDT_ERR_BADSTRUCTURE,
> + *     -FDT_ERR_BADSTATE,
> + *     -FDT_ERR_TRUNCATED, standard meanings
> + */
> +int fdt_overlay_apply(void *fdt, void *fdto);
> +
>  /**********************************************************************/
>  /* Debugging / informational functions                                */
>  /**********************************************************************/
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 02ca4058d37e..16ff01a2cd37 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -139,6 +139,11 @@ config OF_LIBFDT
>           particular compatible nodes. The library operates on a flattened
>           version of the device tree.
>
> +config OF_LIBFDT_OVERLAY
> +       bool "Enable the FDT library overlay support"
> +       help
> +         This enables the FDT library (libfdt) overlay support.
> +
>  config SPL_OF_LIBFDT
>         bool "Enable the FDT library for SPL"
>         default y if SPL_OF_CONTROL
> diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
> index 8b86c15904cb..6ef8290f4e09 100644
> --- a/lib/libfdt/Makefile
> +++ b/lib/libfdt/Makefile
> @@ -15,3 +15,5 @@ obj-y += \
>         fdt_empty_tree.o \
>         fdt_addresses.o \
>         fdt_region.o
> +
> +obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
> diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
> new file mode 100644
> index 000000000000..5835a90afafe
> --- /dev/null
> +++ b/lib/libfdt/fdt_overlay.c
> @@ -0,0 +1,381 @@
> +#include "libfdt_env.h"
> +
> +#include <fdt.h>
> +#include <libfdt.h>
> +
> +#include "libfdt_internal.h"
> +
> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> +{
> +       const uint32_t *val;
> +       int len;
> +
> +       val = fdt_getprop(fdto, fragment, "target", &len);
> +       if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> +               return 0;
> +
> +       return fdt32_to_cpu(*val);
> +}
> +
> +static int overlay_get_target(const void *fdt, const void *fdto,
> +                             int fragment)

function comment please.

> +{
> +       uint32_t phandle;
> +       const char *path;
> +
> +       /* Try first to do a phandle based lookup */
> +       phandle = overlay_get_target_phandle(fdto, fragment);
> +       if (phandle)
> +               return fdt_node_offset_by_phandle(fdt, phandle);
> +
> +       /* And then a path based lookup */
> +       path = fdt_getprop(fdto, fragment, "target-path", NULL);
> +       if (!path)
> +               return -FDT_ERR_NOTFOUND;
> +
> +       return fdt_path_offset(fdt, path);
> +}
> +
> +static int overlay_phandle_add_offset(void *fdt, int node,
> +                                     const char *name, uint32_t delta)

function comment please.

> +{
> +       const uint32_t *val;
> +       uint32_t adj_val;
> +       int len;
> +
> +       val = fdt_getprop(fdt, node, name, &len);
> +       if (!val)
> +               return len;
> +
> +       if (len != sizeof(*val))
> +               return -FDT_ERR_BADSTRUCTURE;
> +
> +       adj_val = fdt32_to_cpu(*val);
> +       adj_val += delta;
> +
> +       return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> +}
> +
> +static int overlay_adjust_node_phandles(void *fdto, int node,
> +                                       uint32_t delta)

function comment please.

> +{
> +       bool found = false;
> +       int child;
> +       int ret;
> +
> +       ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> +       if (ret && ret != -FDT_ERR_NOTFOUND)
> +               return ret;
> +
> +       if (!ret)
> +               found = true;
> +
> +       ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> +       if (ret && ret != -FDT_ERR_NOTFOUND)
> +               return ret;
> +
> +       /*
> +        * If neither phandle nor linux,phandle have been found return
> +        * an error.
> +        */
> +       if (!found && !ret)
> +               return ret;
> +
> +       fdt_for_each_subnode(fdto, child, node)
> +               overlay_adjust_node_phandles(fdto, child, delta);
> +
> +       return 0;
> +}
> +
> +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> +{
> +       /*
> +        * Start adjusting the phandles from the overlay root
> +        */
> +       return overlay_adjust_node_phandles(fdto, 0, delta);
> +}
> +
> +static int overlay_update_local_node_references(void *fdto,
> +                                               int tree_node,
> +                                               int fixup_node,
> +                                               uint32_t delta)
> +{

Please add function comments for all of these.


> +       int fixup_prop;
> +       int fixup_child;
> +       int ret;
> +
> +       fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> +               const uint32_t *val = NULL;
> +               uint32_t adj_val, index;
> +               const char *name;
> +               int fixup_len;
> +               int tree_len;
> +
> +               val = fdt_getprop_by_offset(fdto, fixup_prop,
> +                                           &name, &fixup_len);
> +               if (!val)
> +                       return fixup_len;
> +               index = fdt32_to_cpu(*val);
> +
> +               val = fdt_getprop(fdto, tree_node, name, &tree_len);
> +               if (!val)
> +                       return tree_len;
> +
> +               adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
> +               adj_val += delta;
> +               adj_val = cpu_to_fdt32(adj_val);
> +
> +               ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> +                                                          name, strlen(name),
> +                                                          index, &adj_val,
> +                                                          sizeof(adj_val));
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> +               const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> +                                                           NULL);
> +               int tree_child;
> +
> +               tree_child = fdt_subnode_offset(fdto, tree_node,
> +                                               fixup_child_name);
> +               if (tree_child < 0)
> +                       return tree_child;
> +
> +               ret = overlay_update_local_node_references(fdto,
> +                                                          tree_child,
> +                                                          fixup_child,
> +                                                          delta);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int overlay_update_local_references(void *dto, uint32_t delta)
> +{
> +       int fixups;
> +
> +       fixups = fdt_path_offset(dto, "/__local_fixups__");
> +       if (fixups < 0) {
> +               /*
> +                * There's no local phandles to adjust, bail out

On on line:

/* There's not local ... */

> +                */
> +               if (fixups == -FDT_ERR_NOTFOUND)
> +                       return 0;
> +
> +               return fixups;
> +       }
> +
> +       /*
> +        * Update our local references from the root of the tree
> +        */
> +       return overlay_update_local_node_references(dto, 0, fixups,
> +                                                   delta);
> +}
> +
> +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> +                                    int symbols_off,
> +                                    const char *path, uint32_t path_len,
> +                                    const char *name, uint32_t name_len,
> +                                    int index, const char *label)
> +{
> +       const char *symbol_path;
> +       uint32_t phandle;
> +       int symbol_off, fixup_off;
> +       int prop_len;
> +
> +       symbol_path = fdt_getprop(fdt, symbols_off, label,
> +                                 &prop_len);
> +       if (!symbol_path)
> +               return -FDT_ERR_NOTFOUND;
> +
> +       symbol_off = fdt_path_offset(fdt, symbol_path);
> +       if (symbol_off < 0)
> +               return symbol_off;
> +
> +       phandle = fdt_get_phandle(fdt, symbol_off);
> +       if (!phandle)
> +               return -FDT_ERR_NOTFOUND;
> +
> +       fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> +       if (fixup_off < 0)
> +               return fixup_off;
> +
> +       phandle = cpu_to_fdt32(phandle);
> +       return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> +                                                   name, name_len, index,
> +                                                   &phandle, sizeof(phandle));
> +};
> +
> +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> +                                int property)
> +{
> +       const char *value;
> +       const char *label;
> +       int len;
> +
> +       value = fdt_getprop_by_offset(fdto, property,
> +                                     &label, &len);
> +       if (!value)
> +               return len;
> +
> +       do {
> +               const char *prop_string = value;
> +               const char *path, *name;
> +               uint32_t path_len, name_len;
> +               char *sep, *endptr;
> +               int index;
> +               int ret;
> +
> +               path = prop_string;
> +               sep = strchr(prop_string, ':');
> +               path_len = sep - path;
> +
> +               name = sep + 1;
> +               sep = strchr(name, ':');
> +               name_len = sep - name;
> +
> +               index = strtoul(sep + 1, &endptr, 10);
> +               if (endptr <= (sep + 1))
> +                       return -FDT_ERR_BADSTRUCTURE;
> +
> +               index = strtoul(sep + 1, &endptr, 10);
> +               if (endptr <= (sep + 1))
> +                       return -FDT_ERR_BADSTRUCTURE;
> +
> +               len -= strlen(prop_string) + 1;
> +               value += strlen(prop_string) + 1;
> +
> +               ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> +                                               path, path_len, name, name_len,
> +                                               index, label);
> +               if (ret)
> +                       return ret;
> +       } while (len > 0);
> +
> +       return 0;
> +}
> +
> +static int overlay_fixup_phandles(void *dt, void *dto)
> +{
> +       int fixups_off, symbols_off;
> +       int property;
> +
> +       symbols_off = fdt_path_offset(dt, "/__symbols__");
> +       fixups_off = fdt_path_offset(dto, "/__fixups__");
> +
> +       fdt_for_each_property_offset(property, dto, fixups_off)
> +               overlay_fixup_phandle(dt, dto, symbols_off, property);
> +
> +       return 0;
> +}
> +
> +static int apply_overlay_node(void *dt, int target,
> +                             void *dto, int overlay)
> +{
> +       int property;
> +       int node;
> +
> +       fdt_for_each_property_offset(property, dto, overlay) {
> +               const char *name;
> +               const void *prop;
> +               int prop_len;
> +               int ret;
> +
> +               prop = fdt_getprop_by_offset(dto, property, &name,
> +                                            &prop_len);
> +               if (!prop)
> +                       return -FDT_ERR_INTERNAL;
> +
> +               ret = fdt_setprop(dt, target, name, prop, prop_len);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       fdt_for_each_subnode(dto, node, overlay) {
> +               const char *name = fdt_get_name(dto, node, NULL);
> +               int nnode;
> +               int ret;
> +
> +               nnode = fdt_add_subnode(dt, target, name);
> +               if (nnode == -FDT_ERR_EXISTS)
> +                       nnode = fdt_subnode_offset(dt, target, name);
> +
> +               if (nnode < 0)
> +                       return nnode;
> +
> +               ret = apply_overlay_node(dt, nnode, dto, node);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int overlay_merge(void *dt, void *dto)
> +{
> +       int fragment;
> +
> +       fdt_for_each_subnode(dto, fragment, 0) {
> +               int overlay;
> +               int target;
> +               int ret;
> +
> +               target = overlay_get_target(dt, dto, fragment);
> +               if (target < 0)
> +                       continue;
> +
> +               overlay = fdt_subnode_offset(dto, fragment, "__overlay__");
> +               if (overlay < 0)
> +                       return overlay;
> +
> +               ret = apply_overlay_node(dt, target, dto, overlay);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +int fdt_overlay_apply(void *fdt, void *fdto)
> +{
> +       uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> +       int ret;
> +
> +       FDT_CHECK_HEADER(fdt);
> +       FDT_CHECK_HEADER(fdto);
> +
> +       ret = overlay_adjust_local_phandles(fdto, delta);
> +       if (ret)
> +               goto err;
> +
> +       ret = overlay_update_local_references(fdto, delta);
> +       if (ret)
> +               goto err;
> +
> +       ret = overlay_fixup_phandles(fdt, fdto);
> +       if (ret)
> +               goto err;
> +
> +       ret = overlay_merge(fdt, fdto);
> +       if (!ret)
> +               goto out;
> +
> +err:
> +       /*
> +        * The base device tree might have been damaged, erase its
> +        * magic.
> +        */
> +       fdt_set_magic(fdt, ~0);
> +
> +out:
> +       /*
> +        * The overlay has been damaged, erase its magic.
> +        */
> +       fdt_set_magic(fdto, ~0);
> +
> +       return ret;
> +}
> --
> 2.9.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-26  2:53     ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-26  2:53 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

Hi Maxime,

On 24 June 2016 at 08:27, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> The device tree overlays are a good way to deal with user-modifyable
> boards or boards with some kind of an expansion mechanism where we can
> easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).
>
> Add a new function to merge overlays with a base device tree.
>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt.h         |  30 ++++
>  lib/Kconfig              |   5 +
>  lib/libfdt/Makefile      |   2 +
>  lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 418 insertions(+)
>  create mode 100644 lib/libfdt/fdt_overlay.c
>

Is there a change log?

> diff --git a/include/libfdt.h b/include/libfdt.h
> index b8758de3ae54..039ecb0c1ba7 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -1747,6 +1747,36 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
>   */
>  int fdt_del_node(void *fdt, int nodeoffset);
>
> +/**
> + * fdt_overlay_apply - Applies a DT overlay on a base DT
> + * @fdt: pointer to the base device tree blob
> + * @fdto: pointer to the device tree overlay blob
> + *
> + * fdt_overlay_apply() will apply the given device tree overlay on the
> + * given base device tree.
> + *
> + * Expect the base device tree to be modified, even if the function
> + * returns an error.
> + *
> + * returns:
> + *     0, on success
> + *     -FDT_ERR_NOSPACE, there's not enough space in the base device tree
> + *     -FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
> + *             properties in the base DT
> + *     -FDT_ERR_BADPHANDLE, the phandles in the overlay do not have the right
> + *             magic
> + *     -FDT_ERR_INTERNAL,
> + *     -FDT_ERR_BADLAYOUT,
> + *     -FDT_ERR_BADMAGIC,
> + *     -FDT_ERR_BADOFFSET,
> + *     -FDT_ERR_BADPATH,
> + *     -FDT_ERR_BADVERSION,
> + *     -FDT_ERR_BADSTRUCTURE,
> + *     -FDT_ERR_BADSTATE,
> + *     -FDT_ERR_TRUNCATED, standard meanings
> + */
> +int fdt_overlay_apply(void *fdt, void *fdto);
> +
>  /**********************************************************************/
>  /* Debugging / informational functions                                */
>  /**********************************************************************/
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 02ca4058d37e..16ff01a2cd37 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -139,6 +139,11 @@ config OF_LIBFDT
>           particular compatible nodes. The library operates on a flattened
>           version of the device tree.
>
> +config OF_LIBFDT_OVERLAY
> +       bool "Enable the FDT library overlay support"
> +       help
> +         This enables the FDT library (libfdt) overlay support.
> +
>  config SPL_OF_LIBFDT
>         bool "Enable the FDT library for SPL"
>         default y if SPL_OF_CONTROL
> diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
> index 8b86c15904cb..6ef8290f4e09 100644
> --- a/lib/libfdt/Makefile
> +++ b/lib/libfdt/Makefile
> @@ -15,3 +15,5 @@ obj-y += \
>         fdt_empty_tree.o \
>         fdt_addresses.o \
>         fdt_region.o
> +
> +obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
> diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
> new file mode 100644
> index 000000000000..5835a90afafe
> --- /dev/null
> +++ b/lib/libfdt/fdt_overlay.c
> @@ -0,0 +1,381 @@
> +#include "libfdt_env.h"
> +
> +#include <fdt.h>
> +#include <libfdt.h>
> +
> +#include "libfdt_internal.h"
> +
> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> +{
> +       const uint32_t *val;
> +       int len;
> +
> +       val = fdt_getprop(fdto, fragment, "target", &len);
> +       if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> +               return 0;
> +
> +       return fdt32_to_cpu(*val);
> +}
> +
> +static int overlay_get_target(const void *fdt, const void *fdto,
> +                             int fragment)

function comment please.

> +{
> +       uint32_t phandle;
> +       const char *path;
> +
> +       /* Try first to do a phandle based lookup */
> +       phandle = overlay_get_target_phandle(fdto, fragment);
> +       if (phandle)
> +               return fdt_node_offset_by_phandle(fdt, phandle);
> +
> +       /* And then a path based lookup */
> +       path = fdt_getprop(fdto, fragment, "target-path", NULL);
> +       if (!path)
> +               return -FDT_ERR_NOTFOUND;
> +
> +       return fdt_path_offset(fdt, path);
> +}
> +
> +static int overlay_phandle_add_offset(void *fdt, int node,
> +                                     const char *name, uint32_t delta)

function comment please.

> +{
> +       const uint32_t *val;
> +       uint32_t adj_val;
> +       int len;
> +
> +       val = fdt_getprop(fdt, node, name, &len);
> +       if (!val)
> +               return len;
> +
> +       if (len != sizeof(*val))
> +               return -FDT_ERR_BADSTRUCTURE;
> +
> +       adj_val = fdt32_to_cpu(*val);
> +       adj_val += delta;
> +
> +       return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> +}
> +
> +static int overlay_adjust_node_phandles(void *fdto, int node,
> +                                       uint32_t delta)

function comment please.

> +{
> +       bool found = false;
> +       int child;
> +       int ret;
> +
> +       ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> +       if (ret && ret != -FDT_ERR_NOTFOUND)
> +               return ret;
> +
> +       if (!ret)
> +               found = true;
> +
> +       ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> +       if (ret && ret != -FDT_ERR_NOTFOUND)
> +               return ret;
> +
> +       /*
> +        * If neither phandle nor linux,phandle have been found return
> +        * an error.
> +        */
> +       if (!found && !ret)
> +               return ret;
> +
> +       fdt_for_each_subnode(fdto, child, node)
> +               overlay_adjust_node_phandles(fdto, child, delta);
> +
> +       return 0;
> +}
> +
> +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> +{
> +       /*
> +        * Start adjusting the phandles from the overlay root
> +        */
> +       return overlay_adjust_node_phandles(fdto, 0, delta);
> +}
> +
> +static int overlay_update_local_node_references(void *fdto,
> +                                               int tree_node,
> +                                               int fixup_node,
> +                                               uint32_t delta)
> +{

Please add function comments for all of these.


> +       int fixup_prop;
> +       int fixup_child;
> +       int ret;
> +
> +       fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> +               const uint32_t *val = NULL;
> +               uint32_t adj_val, index;
> +               const char *name;
> +               int fixup_len;
> +               int tree_len;
> +
> +               val = fdt_getprop_by_offset(fdto, fixup_prop,
> +                                           &name, &fixup_len);
> +               if (!val)
> +                       return fixup_len;
> +               index = fdt32_to_cpu(*val);
> +
> +               val = fdt_getprop(fdto, tree_node, name, &tree_len);
> +               if (!val)
> +                       return tree_len;
> +
> +               adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
> +               adj_val += delta;
> +               adj_val = cpu_to_fdt32(adj_val);
> +
> +               ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> +                                                          name, strlen(name),
> +                                                          index, &adj_val,
> +                                                          sizeof(adj_val));
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> +               const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> +                                                           NULL);
> +               int tree_child;
> +
> +               tree_child = fdt_subnode_offset(fdto, tree_node,
> +                                               fixup_child_name);
> +               if (tree_child < 0)
> +                       return tree_child;
> +
> +               ret = overlay_update_local_node_references(fdto,
> +                                                          tree_child,
> +                                                          fixup_child,
> +                                                          delta);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int overlay_update_local_references(void *dto, uint32_t delta)
> +{
> +       int fixups;
> +
> +       fixups = fdt_path_offset(dto, "/__local_fixups__");
> +       if (fixups < 0) {
> +               /*
> +                * There's no local phandles to adjust, bail out

On on line:

/* There's not local ... */

> +                */
> +               if (fixups == -FDT_ERR_NOTFOUND)
> +                       return 0;
> +
> +               return fixups;
> +       }
> +
> +       /*
> +        * Update our local references from the root of the tree
> +        */
> +       return overlay_update_local_node_references(dto, 0, fixups,
> +                                                   delta);
> +}
> +
> +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> +                                    int symbols_off,
> +                                    const char *path, uint32_t path_len,
> +                                    const char *name, uint32_t name_len,
> +                                    int index, const char *label)
> +{
> +       const char *symbol_path;
> +       uint32_t phandle;
> +       int symbol_off, fixup_off;
> +       int prop_len;
> +
> +       symbol_path = fdt_getprop(fdt, symbols_off, label,
> +                                 &prop_len);
> +       if (!symbol_path)
> +               return -FDT_ERR_NOTFOUND;
> +
> +       symbol_off = fdt_path_offset(fdt, symbol_path);
> +       if (symbol_off < 0)
> +               return symbol_off;
> +
> +       phandle = fdt_get_phandle(fdt, symbol_off);
> +       if (!phandle)
> +               return -FDT_ERR_NOTFOUND;
> +
> +       fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> +       if (fixup_off < 0)
> +               return fixup_off;
> +
> +       phandle = cpu_to_fdt32(phandle);
> +       return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> +                                                   name, name_len, index,
> +                                                   &phandle, sizeof(phandle));
> +};
> +
> +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> +                                int property)
> +{
> +       const char *value;
> +       const char *label;
> +       int len;
> +
> +       value = fdt_getprop_by_offset(fdto, property,
> +                                     &label, &len);
> +       if (!value)
> +               return len;
> +
> +       do {
> +               const char *prop_string = value;
> +               const char *path, *name;
> +               uint32_t path_len, name_len;
> +               char *sep, *endptr;
> +               int index;
> +               int ret;
> +
> +               path = prop_string;
> +               sep = strchr(prop_string, ':');
> +               path_len = sep - path;
> +
> +               name = sep + 1;
> +               sep = strchr(name, ':');
> +               name_len = sep - name;
> +
> +               index = strtoul(sep + 1, &endptr, 10);
> +               if (endptr <= (sep + 1))
> +                       return -FDT_ERR_BADSTRUCTURE;
> +
> +               index = strtoul(sep + 1, &endptr, 10);
> +               if (endptr <= (sep + 1))
> +                       return -FDT_ERR_BADSTRUCTURE;
> +
> +               len -= strlen(prop_string) + 1;
> +               value += strlen(prop_string) + 1;
> +
> +               ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> +                                               path, path_len, name, name_len,
> +                                               index, label);
> +               if (ret)
> +                       return ret;
> +       } while (len > 0);
> +
> +       return 0;
> +}
> +
> +static int overlay_fixup_phandles(void *dt, void *dto)
> +{
> +       int fixups_off, symbols_off;
> +       int property;
> +
> +       symbols_off = fdt_path_offset(dt, "/__symbols__");
> +       fixups_off = fdt_path_offset(dto, "/__fixups__");
> +
> +       fdt_for_each_property_offset(property, dto, fixups_off)
> +               overlay_fixup_phandle(dt, dto, symbols_off, property);
> +
> +       return 0;
> +}
> +
> +static int apply_overlay_node(void *dt, int target,
> +                             void *dto, int overlay)
> +{
> +       int property;
> +       int node;
> +
> +       fdt_for_each_property_offset(property, dto, overlay) {
> +               const char *name;
> +               const void *prop;
> +               int prop_len;
> +               int ret;
> +
> +               prop = fdt_getprop_by_offset(dto, property, &name,
> +                                            &prop_len);
> +               if (!prop)
> +                       return -FDT_ERR_INTERNAL;
> +
> +               ret = fdt_setprop(dt, target, name, prop, prop_len);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       fdt_for_each_subnode(dto, node, overlay) {
> +               const char *name = fdt_get_name(dto, node, NULL);
> +               int nnode;
> +               int ret;
> +
> +               nnode = fdt_add_subnode(dt, target, name);
> +               if (nnode == -FDT_ERR_EXISTS)
> +                       nnode = fdt_subnode_offset(dt, target, name);
> +
> +               if (nnode < 0)
> +                       return nnode;
> +
> +               ret = apply_overlay_node(dt, nnode, dto, node);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +static int overlay_merge(void *dt, void *dto)
> +{
> +       int fragment;
> +
> +       fdt_for_each_subnode(dto, fragment, 0) {
> +               int overlay;
> +               int target;
> +               int ret;
> +
> +               target = overlay_get_target(dt, dto, fragment);
> +               if (target < 0)
> +                       continue;
> +
> +               overlay = fdt_subnode_offset(dto, fragment, "__overlay__");
> +               if (overlay < 0)
> +                       return overlay;
> +
> +               ret = apply_overlay_node(dt, target, dto, overlay);
> +               if (ret)
> +                       return ret;
> +       }
> +
> +       return 0;
> +}
> +
> +int fdt_overlay_apply(void *fdt, void *fdto)
> +{
> +       uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> +       int ret;
> +
> +       FDT_CHECK_HEADER(fdt);
> +       FDT_CHECK_HEADER(fdto);
> +
> +       ret = overlay_adjust_local_phandles(fdto, delta);
> +       if (ret)
> +               goto err;
> +
> +       ret = overlay_update_local_references(fdto, delta);
> +       if (ret)
> +               goto err;
> +
> +       ret = overlay_fixup_phandles(fdt, fdto);
> +       if (ret)
> +               goto err;
> +
> +       ret = overlay_merge(fdt, fdto);
> +       if (!ret)
> +               goto out;
> +
> +err:
> +       /*
> +        * The base device tree might have been damaged, erase its
> +        * magic.
> +        */
> +       fdt_set_magic(fdt, ~0);
> +
> +out:
> +       /*
> +        * The overlay has been damaged, erase its magic.
> +        */
> +       fdt_set_magic(fdto, ~0);
> +
> +       return ret;
> +}
> --
> 2.9.0
>

Regards,
Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-26  8:09       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-26  8:09 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sat, Jun 25, 2016 at 08:53:50PM -0600, Simon Glass wrote:
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Add a function to modify inplace a property starting from a given index.
> >
> > This is especially useful when the property is an array of values, and you
> > want to update one of them without changing the DT size.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
> >  lib/libfdt/fdt_wip.c | 13 ++++++++-----
> >  2 files changed, 39 insertions(+), 8 deletions(-)
> 
> Acked-by: Simon Glass <sjg@chromium.org>

Thanks for taking the time to review it.

> I need to get fdt_setprop_inplace() upstream.

It's already there (unless you mean another upstream than dtc?)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160626/770afc5e/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-26  8:09       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-26  8:09 UTC (permalink / raw)
  To: Simon Glass
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1062 bytes --]

Hi Simon,

On Sat, Jun 25, 2016 at 08:53:50PM -0600, Simon Glass wrote:
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> > Add a function to modify inplace a property starting from a given index.
> >
> > This is especially useful when the property is an array of values, and you
> > want to update one of them without changing the DT size.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > ---
> >  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
> >  lib/libfdt/fdt_wip.c | 13 ++++++++-----
> >  2 files changed, 39 insertions(+), 8 deletions(-)
> 
> Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

Thanks for taking the time to review it.

> I need to get fdt_setprop_inplace() upstream.

It's already there (unless you mean another upstream than dtc?)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
  2016-06-26  2:53     ` Simon Glass
@ 2016-06-26  8:10       ` Maxime Ripard
  -1 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-26  8:10 UTC (permalink / raw)
  To: u-boot

Hi,

On Sat, Jun 25, 2016 at 08:53:53PM -0600, Simon Glass wrote:
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Add a namelen variant of fdt_path_offset to retrieve the node offset using
> > only a fixed number of characters.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  include/libfdt.h    | 16 +++++++++++++++-
> >  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
> >  2 files changed, 25 insertions(+), 9 deletions(-)
> 
> fdt_setprop_inplace

What do you mean?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160626/58b33572/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-26  8:10       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-26  8:10 UTC (permalink / raw)
  To: Simon Glass
  Cc: Thomas Petazzoni, Tom Rini, U-Boot Mailing List,
	Pantelis Antoniou, Alexander Kaplan, Devicetree Compiler


[-- Attachment #1.1: Type: text/plain, Size: 685 bytes --]

Hi,

On Sat, Jun 25, 2016 at 08:53:53PM -0600, Simon Glass wrote:
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Add a namelen variant of fdt_path_offset to retrieve the node offset using
> > only a fixed number of characters.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  include/libfdt.h    | 16 +++++++++++++++-
> >  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
> >  2 files changed, 25 insertions(+), 9 deletions(-)
> 
> fdt_setprop_inplace

What do you mean?

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 134 bytes --]

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-26  8:11       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-26  8:11 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sat, Jun 25, 2016 at 08:53:55PM -0600, Simon Glass wrote:
> Hi Maxime,
> 
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > Add a function to retrieve a writeable property only by the first
> > characters of its name.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  include/libfdt.h | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index dbe8a0efca87..b8758de3ae54 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> >   */
> >  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> >                                 const char *name, int namelen, int *lenp);
> > +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> > +                                         const char *name, int namelen,
> > +                                         int *lenp)
> > +{
> > +       return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> > +                                                     namelen, lenp);
> 
> What are the casts for?

This is modelled after the already existing fdt_getprop_w.

The casts just remove the const qualifier in fdt_getprop return value
so that you can modify it.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160626/bfb69858/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-26  8:11       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-26  8:11 UTC (permalink / raw)
  To: Simon Glass
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1602 bytes --]

Hi Simon,

On Sat, Jun 25, 2016 at 08:53:55PM -0600, Simon Glass wrote:
> Hi Maxime,
> 
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> > Add a function to retrieve a writeable property only by the first
> > characters of its name.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > ---
> >  include/libfdt.h | 7 +++++++
> >  1 file changed, 7 insertions(+)
> >
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index dbe8a0efca87..b8758de3ae54 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> >   */
> >  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> >                                 const char *name, int namelen, int *lenp);
> > +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> > +                                         const char *name, int namelen,
> > +                                         int *lenp)
> > +{
> > +       return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> > +                                                     namelen, lenp);
> 
> What are the casts for?

This is modelled after the already existing fdt_getprop_w.

The casts just remove the const qualifier in fdt_getprop return value
so that you can modify it.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
@ 2016-06-26 15:37   ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:37 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 24, 2016 at 04:27:45PM +0200, Maxime Ripard wrote:
> Hi,
> 
> The device tree overlays are a great solution to the issue raised by
> the bunch expandable boards we find everywhere these days, like the
> Beaglebone, Raspberry Pi or CHIP.
> 
> However, most of the time, the overlays are applied through a
> mechanism involving the firmware request interface in Linux, that is
> only fully functional once the userspace has been mounted and is
> running.
> 
> Some expansion boards might need to be enabled before that, because
> they simply need to patch the DT early on, or need to be initialized
> early in order to be fully functional, or because they provide access
> to the root filesystem.
> 
> In these cases, having the bootloader applying the overlay before
> Linux starts seems like the easiest solution.
> 
> This implementation doesn't provide all the Linux fancyness though,
> there's no transactional application, which means that if the overlay
> cannot be applied for a reason while you're still halfway through the
> application, you're probably screwed. It also cannot remove an
> overlay, but I don't think that it is currently a use-case.
> 
> There's still a bunch of work to extend the libfdt unit tests to test
> the new functions introduced, but these patches will be submitted
> in a near future.

Are you planning to send a new version of (the relevant portions of)
these against upstream libfdt?

> 
> Let me know what you think,
> Maxime
> 
> Changes from v2:
>   - Add Kconfig option for the libfdt overlay support
>   - Reworked the code to deal with Pantelis and David numerous
>     comments, among which:
>     * Remove the need for malloc in the overlay code, and added some
>       libfdt functions to do that
>     * Remove the DT magic in case of an error to not be able to use it
>       anymore
>     * Removed the fdt_ and _ function prefix for the static functions
>     * Plus the usual bunch of rework, error checking and optimizations.
> 
>   - Added new tests to deal with bugs reported by David (the overlay
>     was not applying when you add a subnode declared that was already
>     in the base device tree, and using a local phandle was only
>     working if the property storing it only had a length of 4).
> 
> Changes from v1:
>   - Moved the overlay code to libfdt
>   - Added unit tests
>   - Refactored the code to reduce the amount of memory allocation
>   - No longer modify the overlay itself, but create a copy to operate
>     on instead.
>   - Removed the limitations on the fixups path, names and properties
>     length
>   - Fixed a few things here and there according to comments		    
> 
> Maxime Ripard (12):
>   cmd: fdt: Narrow the check for fdt addr
>   scripts: Makefile.lib: Sanitize DTB names
>   vsprintf: Include stdarg for va_list
>   libfdt: Add new headers and defines
>   libfdt: Add iterator over properties
>   libfdt: Add max phandle retrieval function
>   libfdt: Add fdt_setprop_inplace_by_index
>   libfdt: Add fdt_path_offset_namelen
>   libfdt: Add fdt_getprop_namelen_w
>   libfdt: Add overlay application function
>   cmd: fdt: add fdt overlay application subcommand
>   tests: Introduce DT overlay tests
> 
>  Makefile                          |   1 +
>  cmd/fdt.c                         |  26 ++-
>  include/libfdt.h                  | 124 ++++++++++++-
>  include/libfdt_env.h              |   6 +
>  include/test/overlay.h            |  16 ++
>  include/test/suites.h             |   1 +
>  include/vsprintf.h                |   2 +
>  lib/Kconfig                       |   5 +
>  lib/libfdt/Makefile               |   2 +
>  lib/libfdt/fdt_overlay.c          | 381 ++++++++++++++++++++++++++++++++++++++
>  lib/libfdt/fdt_ro.c               |  44 ++++-
>  lib/libfdt/fdt_wip.c              |  13 +-
>  scripts/Makefile.lib              |   8 +-
>  test/Kconfig                      |   1 +
>  test/cmd_ut.c                     |   6 +
>  test/overlay/Kconfig              |  11 ++
>  test/overlay/Makefile             |  15 ++
>  test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++
>  test/overlay/test-fdt-base.dts    |  21 +++
>  test/overlay/test-fdt-overlay.dts |  88 +++++++++
>  20 files changed, 992 insertions(+), 22 deletions(-)
>  create mode 100644 include/test/overlay.h
>  create mode 100644 lib/libfdt/fdt_overlay.c
>  create mode 100644 test/overlay/Kconfig
>  create mode 100644 test/overlay/Makefile
>  create mode 100644 test/overlay/cmd_ut_overlay.c
>  create mode 100644 test/overlay/test-fdt-base.dts
>  create mode 100644 test/overlay/test-fdt-overlay.dts
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/7ab7960b/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
@ 2016-06-26 15:37   ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:37 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 4903 bytes --]

On Fri, Jun 24, 2016 at 04:27:45PM +0200, Maxime Ripard wrote:
> Hi,
> 
> The device tree overlays are a great solution to the issue raised by
> the bunch expandable boards we find everywhere these days, like the
> Beaglebone, Raspberry Pi or CHIP.
> 
> However, most of the time, the overlays are applied through a
> mechanism involving the firmware request interface in Linux, that is
> only fully functional once the userspace has been mounted and is
> running.
> 
> Some expansion boards might need to be enabled before that, because
> they simply need to patch the DT early on, or need to be initialized
> early in order to be fully functional, or because they provide access
> to the root filesystem.
> 
> In these cases, having the bootloader applying the overlay before
> Linux starts seems like the easiest solution.
> 
> This implementation doesn't provide all the Linux fancyness though,
> there's no transactional application, which means that if the overlay
> cannot be applied for a reason while you're still halfway through the
> application, you're probably screwed. It also cannot remove an
> overlay, but I don't think that it is currently a use-case.
> 
> There's still a bunch of work to extend the libfdt unit tests to test
> the new functions introduced, but these patches will be submitted
> in a near future.

Are you planning to send a new version of (the relevant portions of)
these against upstream libfdt?

> 
> Let me know what you think,
> Maxime
> 
> Changes from v2:
>   - Add Kconfig option for the libfdt overlay support
>   - Reworked the code to deal with Pantelis and David numerous
>     comments, among which:
>     * Remove the need for malloc in the overlay code, and added some
>       libfdt functions to do that
>     * Remove the DT magic in case of an error to not be able to use it
>       anymore
>     * Removed the fdt_ and _ function prefix for the static functions
>     * Plus the usual bunch of rework, error checking and optimizations.
> 
>   - Added new tests to deal with bugs reported by David (the overlay
>     was not applying when you add a subnode declared that was already
>     in the base device tree, and using a local phandle was only
>     working if the property storing it only had a length of 4).
> 
> Changes from v1:
>   - Moved the overlay code to libfdt
>   - Added unit tests
>   - Refactored the code to reduce the amount of memory allocation
>   - No longer modify the overlay itself, but create a copy to operate
>     on instead.
>   - Removed the limitations on the fixups path, names and properties
>     length
>   - Fixed a few things here and there according to comments		    
> 
> Maxime Ripard (12):
>   cmd: fdt: Narrow the check for fdt addr
>   scripts: Makefile.lib: Sanitize DTB names
>   vsprintf: Include stdarg for va_list
>   libfdt: Add new headers and defines
>   libfdt: Add iterator over properties
>   libfdt: Add max phandle retrieval function
>   libfdt: Add fdt_setprop_inplace_by_index
>   libfdt: Add fdt_path_offset_namelen
>   libfdt: Add fdt_getprop_namelen_w
>   libfdt: Add overlay application function
>   cmd: fdt: add fdt overlay application subcommand
>   tests: Introduce DT overlay tests
> 
>  Makefile                          |   1 +
>  cmd/fdt.c                         |  26 ++-
>  include/libfdt.h                  | 124 ++++++++++++-
>  include/libfdt_env.h              |   6 +
>  include/test/overlay.h            |  16 ++
>  include/test/suites.h             |   1 +
>  include/vsprintf.h                |   2 +
>  lib/Kconfig                       |   5 +
>  lib/libfdt/Makefile               |   2 +
>  lib/libfdt/fdt_overlay.c          | 381 ++++++++++++++++++++++++++++++++++++++
>  lib/libfdt/fdt_ro.c               |  44 ++++-
>  lib/libfdt/fdt_wip.c              |  13 +-
>  scripts/Makefile.lib              |   8 +-
>  test/Kconfig                      |   1 +
>  test/cmd_ut.c                     |   6 +
>  test/overlay/Kconfig              |  11 ++
>  test/overlay/Makefile             |  15 ++
>  test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++
>  test/overlay/test-fdt-base.dts    |  21 +++
>  test/overlay/test-fdt-overlay.dts |  88 +++++++++
>  20 files changed, 992 insertions(+), 22 deletions(-)
>  create mode 100644 include/test/overlay.h
>  create mode 100644 lib/libfdt/fdt_overlay.c
>  create mode 100644 test/overlay/Kconfig
>  create mode 100644 test/overlay/Makefile
>  create mode 100644 test/overlay/cmd_ut_overlay.c
>  create mode 100644 test/overlay/test-fdt-base.dts
>  create mode 100644 test/overlay/test-fdt-overlay.dts
> 

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-26 15:39     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:39 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 24, 2016 at 04:27:49PM +0200, Maxime Ripard wrote:
> The libfdt overlay support introduces a bunch of new includes and
> functions.
> 
> Make sure we are able to build it by adding the needed glue.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Is this intended only for downstream u-boot only, or also for upstream
libfdt?

If it's u-boot only, you don't really need the #ifdef UBOOT.  If it's
for upstream, then it shouldn't have u-boot specific stuff.

In general the environment into which you're embedding libfdt (u-boot
in this case) should provide libfdt_env.h.  The one included in
upstream libfdt is essentially just an example version designed to
work with POSIX userspace.

> ---
>  include/libfdt_env.h | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/include/libfdt_env.h b/include/libfdt_env.h
> index 273b5d30f867..6c6845f76cf7 100644
> --- a/include/libfdt_env.h
> +++ b/include/libfdt_env.h
> @@ -23,6 +23,12 @@ typedef __be64 fdt64_t;
>  #define fdt64_to_cpu(x)		be64_to_cpu(x)
>  #define cpu_to_fdt64(x)		cpu_to_be64(x)
>  
> +#ifdef __UBOOT__
> +#include <vsprintf.h>
> +
> +#define strtoul(cp, endp, base)	simple_strtoul(cp, endp, base)
> +#endif
> +
>  /* adding a ramdisk needs 0x44 bytes in version 2008.10 */
>  #define FDT_RAMDISK_OVERHEAD	0x80
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/5c94196a/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-26 15:39     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:39 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1592 bytes --]

On Fri, Jun 24, 2016 at 04:27:49PM +0200, Maxime Ripard wrote:
> The libfdt overlay support introduces a bunch of new includes and
> functions.
> 
> Make sure we are able to build it by adding the needed glue.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Is this intended only for downstream u-boot only, or also for upstream
libfdt?

If it's u-boot only, you don't really need the #ifdef UBOOT.  If it's
for upstream, then it shouldn't have u-boot specific stuff.

In general the environment into which you're embedding libfdt (u-boot
in this case) should provide libfdt_env.h.  The one included in
upstream libfdt is essentially just an example version designed to
work with POSIX userspace.

> ---
>  include/libfdt_env.h | 6 ++++++
>  1 file changed, 6 insertions(+)
> 
> diff --git a/include/libfdt_env.h b/include/libfdt_env.h
> index 273b5d30f867..6c6845f76cf7 100644
> --- a/include/libfdt_env.h
> +++ b/include/libfdt_env.h
> @@ -23,6 +23,12 @@ typedef __be64 fdt64_t;
>  #define fdt64_to_cpu(x)		be64_to_cpu(x)
>  #define cpu_to_fdt64(x)		cpu_to_be64(x)
>  
> +#ifdef __UBOOT__
> +#include <vsprintf.h>
> +
> +#define strtoul(cp, endp, base)	simple_strtoul(cp, endp, base)
> +#endif
> +
>  /* adding a ramdisk needs 0x44 bytes in version 2008.10 */
>  #define FDT_RAMDISK_OVERHEAD	0x80
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-26 15:45     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:45 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 24, 2016 at 04:27:52PM +0200, Maxime Ripard wrote:
> Add a function to modify inplace a property starting from a given index.
> 
> This is especially useful when the property is an array of values, and you
> want to update one of them without changing the DT size.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
>  lib/libfdt/fdt_wip.c | 13 ++++++++-----
>  2 files changed, 39 insertions(+), 8 deletions(-)
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index 4643be5adf39..2c8a42bcb667 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
>  /* Write-in-place functions                                           */
>  /**********************************************************************/
>  
> +/**
> + * fdt_setprop_inplace_namelen_by_index - change a property's value,
> + *                                        but not its size
> + * @fdt: pointer to the device tree blob
> + * @nodeoffset: offset of the node whose property to change
> + * @name: name of the property to change
> + * @namelen: number of characters of name to consider
> + * @index: index of the property to change in the array
> + * @val: pointer to data to replace the property value with
> + * @len: length of the property value
> + *
> + * Identical to fdt_setprop_inplace(), but modifies the given property
> + * starting from the given index, and using only the first characters
> + * of the name. It is useful when you want to manipulate only one value of
> + * an array and you have a string that doesn't end with \0.
> + */
> +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> +					 const char *name, int namelen,
> +					 uint32_t index, const void *val,
> +					 int len);

This looks like a good addition to upstream, but I don't like the
name.  I'd suggest fdt_setprop_inplace_namelen_partial() because it
only overwrite part of the existing property value.

> +
>  /**
>   * fdt_setprop_inplace - change a property's value, but not its size
>   * @fdt: pointer to the device tree blob
> @@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
>   *	-FDT_ERR_BADSTRUCTURE,
>   *	-FDT_ERR_TRUNCATED, standard meanings
>   */
> -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> -			const void *val, int len);
> +static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
> +				      const char *name, const void *val,
> +				      int len)
> +{
> +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
> +						    strlen(name), 0, val, len);

This effectively removes the error if len is not equal to the existing
property length, so that needs to be put back.

> +}
>  
>  /**
>   * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
> @@ -1095,7 +1121,9 @@ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
>  					  const char *name, uint32_t val)
>  {
>  	fdt32_t tmp = cpu_to_fdt32(val);
> -	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
> +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset,
> +						    name, strlen(name),
> +						    0, &tmp, sizeof(tmp));
>  }
>  
>  /**
> diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
> index 9fe988655fe3..737769fa59e2 100644
> --- a/lib/libfdt/fdt_wip.c
> +++ b/lib/libfdt/fdt_wip.c
> @@ -14,20 +14,23 @@
>  
>  #include "libfdt_internal.h"
>  
> -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> -			const void *val, int len)
> +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> +					 const char *name, int namelen,
> +					 uint32_t index, const void *val,
> +					 int len)
>  {
>  	void *propval;
>  	int proplen;
>  
> -	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
> +	propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
> +					&proplen);
>  	if (!propval)
>  		return proplen;
>  
> -	if (proplen != len)
> +	if (proplen < (len + index))
>  		return -FDT_ERR_NOSPACE;
>  
> -	memcpy(propval, val, len);
> +	memcpy(propval + index, val, len);
>  	return 0;
>  }
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/d0e57923/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-26 15:45     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:45 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 4582 bytes --]

On Fri, Jun 24, 2016 at 04:27:52PM +0200, Maxime Ripard wrote:
> Add a function to modify inplace a property starting from a given index.
> 
> This is especially useful when the property is an array of values, and you
> want to update one of them without changing the DT size.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
>  lib/libfdt/fdt_wip.c | 13 ++++++++-----
>  2 files changed, 39 insertions(+), 8 deletions(-)
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index 4643be5adf39..2c8a42bcb667 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
>  /* Write-in-place functions                                           */
>  /**********************************************************************/
>  
> +/**
> + * fdt_setprop_inplace_namelen_by_index - change a property's value,
> + *                                        but not its size
> + * @fdt: pointer to the device tree blob
> + * @nodeoffset: offset of the node whose property to change
> + * @name: name of the property to change
> + * @namelen: number of characters of name to consider
> + * @index: index of the property to change in the array
> + * @val: pointer to data to replace the property value with
> + * @len: length of the property value
> + *
> + * Identical to fdt_setprop_inplace(), but modifies the given property
> + * starting from the given index, and using only the first characters
> + * of the name. It is useful when you want to manipulate only one value of
> + * an array and you have a string that doesn't end with \0.
> + */
> +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> +					 const char *name, int namelen,
> +					 uint32_t index, const void *val,
> +					 int len);

This looks like a good addition to upstream, but I don't like the
name.  I'd suggest fdt_setprop_inplace_namelen_partial() because it
only overwrite part of the existing property value.

> +
>  /**
>   * fdt_setprop_inplace - change a property's value, but not its size
>   * @fdt: pointer to the device tree blob
> @@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
>   *	-FDT_ERR_BADSTRUCTURE,
>   *	-FDT_ERR_TRUNCATED, standard meanings
>   */
> -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> -			const void *val, int len);
> +static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
> +				      const char *name, const void *val,
> +				      int len)
> +{
> +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
> +						    strlen(name), 0, val, len);

This effectively removes the error if len is not equal to the existing
property length, so that needs to be put back.

> +}
>  
>  /**
>   * fdt_setprop_inplace_u32 - change the value of a 32-bit integer property
> @@ -1095,7 +1121,9 @@ static inline int fdt_setprop_inplace_u32(void *fdt, int nodeoffset,
>  					  const char *name, uint32_t val)
>  {
>  	fdt32_t tmp = cpu_to_fdt32(val);
> -	return fdt_setprop_inplace(fdt, nodeoffset, name, &tmp, sizeof(tmp));
> +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset,
> +						    name, strlen(name),
> +						    0, &tmp, sizeof(tmp));
>  }
>  
>  /**
> diff --git a/lib/libfdt/fdt_wip.c b/lib/libfdt/fdt_wip.c
> index 9fe988655fe3..737769fa59e2 100644
> --- a/lib/libfdt/fdt_wip.c
> +++ b/lib/libfdt/fdt_wip.c
> @@ -14,20 +14,23 @@
>  
>  #include "libfdt_internal.h"
>  
> -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> -			const void *val, int len)
> +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> +					 const char *name, int namelen,
> +					 uint32_t index, const void *val,
> +					 int len)
>  {
>  	void *propval;
>  	int proplen;
>  
> -	propval = fdt_getprop_w(fdt, nodeoffset, name, &proplen);
> +	propval = fdt_getprop_namelen_w(fdt, nodeoffset, name, namelen,
> +					&proplen);
>  	if (!propval)
>  		return proplen;
>  
> -	if (proplen != len)
> +	if (proplen < (len + index))
>  		return -FDT_ERR_NOSPACE;
>  
> -	memcpy(propval, val, len);
> +	memcpy(propval + index, val, len);
>  	return 0;
>  }
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-26 15:47     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:47 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 24, 2016 at 04:27:53PM +0200, Maxime Ripard wrote:
> Add a namelen variant of fdt_path_offset to retrieve the node offset using
> only a fixed number of characters.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

Looks good for upstream.

> ---
>  include/libfdt.h    | 16 +++++++++++++++-
>  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
>  2 files changed, 25 insertions(+), 9 deletions(-)
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index 2c8a42bcb667..dbe8a0efca87 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -365,6 +365,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
>   */
>  int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
>  
> +/**
> + * fdt_path_offset_namelen - find a tree node based on substring
> + * @fdt: pointer to the device tree blob
> + * @path: full path of the node to locate
> + * @namelen: number of characters of name to consider
> + *
> + * Identical to fdt_path_offset(), but only examine the first
> + * namelen characters of path for matching the node path.
> + */
> +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
> +
>  /**
>   * fdt_path_offset - find a tree node by its full path
>   * @fdt: pointer to the device tree blob
> @@ -387,7 +398,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
>   *	-FDT_ERR_BADSTRUCTURE,
>   *	-FDT_ERR_TRUNCATED, standard meanings.
>   */
> -int fdt_path_offset(const void *fdt, const char *path);
> +static inline int fdt_path_offset(const void *fdt, const char *path)
> +{
> +	return fdt_path_offset_namelen(fdt, path, strlen(path));
> +}
>  
>  /**
>   * fdt_get_name - retrieve the name of a given node
> diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
> index 503150ef1dc5..05344d3eebfe 100644
> --- a/lib/libfdt/fdt_ro.c
> +++ b/lib/libfdt/fdt_ro.c
> @@ -145,10 +145,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
>   * "foo/bar:option" and "bar:option/otheroption", both of which happen, so
>   * first searching for either ':' or '/' does not work.
>   */
> -static const char *fdt_path_next_seperator(const char *path)
> +static const char *fdt_path_next_seperator(const void *path, int len)

Not in scope for this patch, but I should fix that mispelling of 'separator'.

>  {
> -	const char *sep1 = strchr(path, '/');
> -	const char *sep2 = strchr(path, ':');
> +	const void *sep1 = memchr(path, '/', len);
> +	const void *sep2 = memchr(path, ':', len);
>  
>  	if (sep1 && sep2)
>  		return (sep1 < sep2) ? sep1 : sep2;
> @@ -158,9 +158,9 @@ static const char *fdt_path_next_seperator(const char *path)
>  		return sep2;
>  }
>  
> -int fdt_path_offset(const void *fdt, const char *path)
> +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
>  {
> -	const char *end = path + strlen(path);
> +	const char *end = path + namelen;
>  	const char *p = path;
>  	int offset = 0;
>  
> @@ -168,7 +168,7 @@ int fdt_path_offset(const void *fdt, const char *path)
>  
>  	/* see if we have an alias */
>  	if (*path != '/') {
> -		const char *q = fdt_path_next_seperator(path);
> +		const char *q = fdt_path_next_seperator(path, namelen);
>  
>  		if (!q)
>  			q = end;
> @@ -181,14 +181,16 @@ int fdt_path_offset(const void *fdt, const char *path)
>  		p = q;
>  	}
>  
> -	while (*p) {
> +	while (*p && (p < end)) {
>  		const char *q;
>  
>  		while (*p == '/')
>  			p++;
> +
>  		if (*p == '\0' || *p == ':')
>  			return offset;
> -		q = fdt_path_next_seperator(p);
> +
> +		q = fdt_path_next_seperator(p, end - p);
>  		if (!q)
>  			q = end;
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/e766b777/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-26 15:47     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:47 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 3986 bytes --]

On Fri, Jun 24, 2016 at 04:27:53PM +0200, Maxime Ripard wrote:
> Add a namelen variant of fdt_path_offset to retrieve the node offset using
> only a fixed number of characters.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

Looks good for upstream.

> ---
>  include/libfdt.h    | 16 +++++++++++++++-
>  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
>  2 files changed, 25 insertions(+), 9 deletions(-)
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index 2c8a42bcb667..dbe8a0efca87 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -365,6 +365,17 @@ int fdt_subnode_offset_namelen(const void *fdt, int parentoffset,
>   */
>  int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
>  
> +/**
> + * fdt_path_offset_namelen - find a tree node based on substring
> + * @fdt: pointer to the device tree blob
> + * @path: full path of the node to locate
> + * @namelen: number of characters of name to consider
> + *
> + * Identical to fdt_path_offset(), but only examine the first
> + * namelen characters of path for matching the node path.
> + */
> +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen);
> +
>  /**
>   * fdt_path_offset - find a tree node by its full path
>   * @fdt: pointer to the device tree blob
> @@ -387,7 +398,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset, const char *name);
>   *	-FDT_ERR_BADSTRUCTURE,
>   *	-FDT_ERR_TRUNCATED, standard meanings.
>   */
> -int fdt_path_offset(const void *fdt, const char *path);
> +static inline int fdt_path_offset(const void *fdt, const char *path)
> +{
> +	return fdt_path_offset_namelen(fdt, path, strlen(path));
> +}
>  
>  /**
>   * fdt_get_name - retrieve the name of a given node
> diff --git a/lib/libfdt/fdt_ro.c b/lib/libfdt/fdt_ro.c
> index 503150ef1dc5..05344d3eebfe 100644
> --- a/lib/libfdt/fdt_ro.c
> +++ b/lib/libfdt/fdt_ro.c
> @@ -145,10 +145,10 @@ int fdt_subnode_offset(const void *fdt, int parentoffset,
>   * "foo/bar:option" and "bar:option/otheroption", both of which happen, so
>   * first searching for either ':' or '/' does not work.
>   */
> -static const char *fdt_path_next_seperator(const char *path)
> +static const char *fdt_path_next_seperator(const void *path, int len)

Not in scope for this patch, but I should fix that mispelling of 'separator'.

>  {
> -	const char *sep1 = strchr(path, '/');
> -	const char *sep2 = strchr(path, ':');
> +	const void *sep1 = memchr(path, '/', len);
> +	const void *sep2 = memchr(path, ':', len);
>  
>  	if (sep1 && sep2)
>  		return (sep1 < sep2) ? sep1 : sep2;
> @@ -158,9 +158,9 @@ static const char *fdt_path_next_seperator(const char *path)
>  		return sep2;
>  }
>  
> -int fdt_path_offset(const void *fdt, const char *path)
> +int fdt_path_offset_namelen(const void *fdt, const char *path, int namelen)
>  {
> -	const char *end = path + strlen(path);
> +	const char *end = path + namelen;
>  	const char *p = path;
>  	int offset = 0;
>  
> @@ -168,7 +168,7 @@ int fdt_path_offset(const void *fdt, const char *path)
>  
>  	/* see if we have an alias */
>  	if (*path != '/') {
> -		const char *q = fdt_path_next_seperator(path);
> +		const char *q = fdt_path_next_seperator(path, namelen);
>  
>  		if (!q)
>  			q = end;
> @@ -181,14 +181,16 @@ int fdt_path_offset(const void *fdt, const char *path)
>  		p = q;
>  	}
>  
> -	while (*p) {
> +	while (*p && (p < end)) {
>  		const char *q;
>  
>  		while (*p == '/')
>  			p++;
> +
>  		if (*p == '\0' || *p == ':')
>  			return offset;
> -		q = fdt_path_next_seperator(p);
> +
> +		q = fdt_path_next_seperator(p, end - p);
>  		if (!q)
>  			q = end;
>  

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
  2016-06-24 14:27   ` Maxime Ripard
@ 2016-06-26 15:49     ` David Gibson
  -1 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:49 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 24, 2016 at 04:27:54PM +0200, Maxime Ripard wrote:
> Add a function to retrieve a writeable property only by the first
> characters of its name.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index dbe8a0efca87..b8758de3ae54 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
>   */
>  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>  				const char *name, int namelen, int *lenp);
> +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> +					  const char *name, int namelen,
> +					  int *lenp)
> +{
> +	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> +						      namelen, lenp);
> +}

I believe you used this in your new setprop_inpace implementation.  So
the series needs to be re-ordered to avoid breaking bisection.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/d84cadc0/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-26 15:49     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-26 15:49 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Thomas Petazzoni, Tom Rini, u-boot, Pantelis Antoniou,
	Alexander Kaplan, devicetree-compiler


[-- Attachment #1.1: Type: text/plain, Size: 1262 bytes --]

On Fri, Jun 24, 2016 at 04:27:54PM +0200, Maxime Ripard wrote:
> Add a function to retrieve a writeable property only by the first
> characters of its name.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h | 7 +++++++
>  1 file changed, 7 insertions(+)
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index dbe8a0efca87..b8758de3ae54 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
>   */
>  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
>  				const char *name, int namelen, int *lenp);
> +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> +					  const char *name, int namelen,
> +					  int *lenp)
> +{
> +	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> +						      namelen, lenp);
> +}

I believe you used this in your new setprop_inpace implementation.  So
the series needs to be re-ordered to avoid breaking bisection.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 134 bytes --]

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-27  5:26     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-27  5:26 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 24, 2016 at 04:27:55PM +0200, Maxime Ripard wrote:
> The device tree overlays are a good way to deal with user-modifyable
> boards or boards with some kind of an expansion mechanism where we can
> easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).
> 
> Add a new function to merge overlays with a base device tree.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> ---
>  include/libfdt.h         |  30 ++++
>  lib/Kconfig              |   5 +
>  lib/libfdt/Makefile      |   2 +
>  lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 418 insertions(+)
>  create mode 100644 lib/libfdt/fdt_overlay.c
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index b8758de3ae54..039ecb0c1ba7 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -1747,6 +1747,36 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
>   */
>  int fdt_del_node(void *fdt, int nodeoffset);
>  
> +/**
> + * fdt_overlay_apply - Applies a DT overlay on a base DT
> + * @fdt: pointer to the base device tree blob
> + * @fdto: pointer to the device tree overlay blob
> + *
> + * fdt_overlay_apply() will apply the given device tree overlay on the
> + * given base device tree.
> + *
> + * Expect the base device tree to be modified, even if the function
> + * returns an error.
> + *
> + * returns:
> + *	0, on success
> + *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
> + *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
> + *		properties in the base DT
> + *	-FDT_ERR_BADPHANDLE, the phandles in the overlay do not have the right
> + *		magic
> + *	-FDT_ERR_INTERNAL,
> + *	-FDT_ERR_BADLAYOUT,
> + *	-FDT_ERR_BADMAGIC,
> + *	-FDT_ERR_BADOFFSET,
> + *	-FDT_ERR_BADPATH,
> + *	-FDT_ERR_BADVERSION,
> + *	-FDT_ERR_BADSTRUCTURE,
> + *	-FDT_ERR_BADSTATE,
> + *	-FDT_ERR_TRUNCATED, standard meanings
> + */
> +int fdt_overlay_apply(void *fdt, void *fdto);
> +
>  /**********************************************************************/
>  /* Debugging / informational functions                                */
>  /**********************************************************************/
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 02ca4058d37e..16ff01a2cd37 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -139,6 +139,11 @@ config OF_LIBFDT
>  	  particular compatible nodes. The library operates on a flattened
>  	  version of the device tree.
>  
> +config OF_LIBFDT_OVERLAY
> +	bool "Enable the FDT library overlay support"
> +	help
> +	  This enables the FDT library (libfdt) overlay support.
> +
>  config SPL_OF_LIBFDT
>  	bool "Enable the FDT library for SPL"
>  	default y if SPL_OF_CONTROL
> diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
> index 8b86c15904cb..6ef8290f4e09 100644
> --- a/lib/libfdt/Makefile
> +++ b/lib/libfdt/Makefile
> @@ -15,3 +15,5 @@ obj-y += \
>  	fdt_empty_tree.o \
>  	fdt_addresses.o \
>  	fdt_region.o
> +
> +obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
> diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
> new file mode 100644
> index 000000000000..5835a90afafe
> --- /dev/null
> +++ b/lib/libfdt/fdt_overlay.c
> @@ -0,0 +1,381 @@
> +#include "libfdt_env.h"
> +
> +#include <fdt.h>
> +#include <libfdt.h>
> +
> +#include "libfdt_internal.h"
> +
> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> +{
> +	const uint32_t *val;
> +	int len;
> +
> +	val = fdt_getprop(fdto, fragment, "target", &len);
> +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> +		return 0;

This doesn't distinguish between a missing property (which may
indicate a valid overlay using a target-path or some other method)
and a badly formatted 'target' property, which is definitely an error
in the overlay.

I think those should be treated differently.

> +	return fdt32_to_cpu(*val);
> +}
> +
> +static int overlay_get_target(const void *fdt, const void *fdto,
> +			      int fragment)
> +{
> +	uint32_t phandle;
> +	const char *path;
> +
> +	/* Try first to do a phandle based lookup */
> +	phandle = overlay_get_target_phandle(fdto, fragment);
> +	if (phandle)
> +		return fdt_node_offset_by_phandle(fdt, phandle);
> +
> +	/* And then a path based lookup */
> +	path = fdt_getprop(fdto, fragment, "target-path", NULL);
> +	if (!path)
> +		return -FDT_ERR_NOTFOUND;
> +
> +	return fdt_path_offset(fdt, path);
> +}
> +
> +static int overlay_phandle_add_offset(void *fdt, int node,
> +				      const char *name, uint32_t delta)
> +{
> +	const uint32_t *val;
> +	uint32_t adj_val;
> +	int len;
> +
> +	val = fdt_getprop(fdt, node, name, &len);
> +	if (!val)
> +		return len;
> +
> +	if (len != sizeof(*val))
> +		return -FDT_ERR_BADSTRUCTURE;
> +
> +	adj_val = fdt32_to_cpu(*val);
> +	adj_val += delta;

You should probably check for overflow here.

> +
> +	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> +}
> +
> +static int overlay_adjust_node_phandles(void *fdto, int node,
> +					uint32_t delta)
> +{
> +	bool found = false;
> +	int child;
> +	int ret;
> +
> +	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> +	if (ret && ret != -FDT_ERR_NOTFOUND)
> +		return ret;
> +
> +	if (!ret)
> +		found = true;
> +
> +	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> +	if (ret && ret != -FDT_ERR_NOTFOUND)
> +		return ret;

I think the check for phandle vs. linux,phandle should be folded into
overlay_phandle_add_offset().

> +	/*
> +	 * If neither phandle nor linux,phandle have been found return
> +	 * an error.
> +	 */
> +	if (!found && !ret)
> +		return ret;
> +
> +	fdt_for_each_subnode(fdto, child, node)
> +		overlay_adjust_node_phandles(fdto, child, delta);
> +
> +	return 0;
> +}
> +
> +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> +{
> +	/*
> +	 * Start adjusting the phandles from the overlay root
> +	 */
> +	return overlay_adjust_node_phandles(fdto, 0, delta);
> +}
> +
> +static int overlay_update_local_node_references(void *fdto,
> +						int tree_node,
> +						int fixup_node,
> +						uint32_t delta)
> +{
> +	int fixup_prop;
> +	int fixup_child;
> +	int ret;
> +
> +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> +		const uint32_t *val = NULL;
> +		uint32_t adj_val, index;
> +		const char *name;
> +		int fixup_len;
> +		int tree_len;
> +
> +		val = fdt_getprop_by_offset(fdto, fixup_prop,
> +					    &name, &fixup_len);
> +		if (!val)
> +			return fixup_len;
> +		index = fdt32_to_cpu(*val);

This still doesn't handle the case of multiple fixups within the same
property.  That would be entirely plausible for something like an
interrupt-map property.

> +		val = fdt_getprop(fdto, tree_node, name, &tree_len);
> +		if (!val)
> +			return tree_len;
> +
> +		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));

phandle values need not be aligned within the property containint them
(e.g. properties which mix strings and integer values).  So you're
going to need to work directly with a byte offset here.

> +		adj_val += delta;
> +		adj_val = cpu_to_fdt32(adj_val);
> +
> +		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> +							   name, strlen(name),
> +							   index, &adj_val,
> +							   sizeof(adj_val));
> +		if (ret)
> +			return ret;
> +	}
> +
> +	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> +							    NULL);
> +		int tree_child;
> +
> +		tree_child = fdt_subnode_offset(fdto, tree_node,
> +						fixup_child_name);
> +		if (tree_child < 0)
> +			return tree_child;
> +
> +		ret = overlay_update_local_node_references(fdto,
> +							   tree_child,
> +							   fixup_child,
> +							   delta);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int overlay_update_local_references(void *dto, uint32_t delta)
> +{
> +	int fixups;
> +
> +	fixups = fdt_path_offset(dto, "/__local_fixups__");
> +	if (fixups < 0) {
> +		/*
> +		 * There's no local phandles to adjust, bail out
> +		 */
> +		if (fixups == -FDT_ERR_NOTFOUND)
> +			return 0;
> +
> +		return fixups;
> +	}
> +
> +	/*
> +	 * Update our local references from the root of the tree
> +	 */
> +	return overlay_update_local_node_references(dto, 0, fixups,
> +						    delta);
> +}
> +
> +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> +				     int symbols_off,
> +				     const char *path, uint32_t path_len,
> +				     const char *name, uint32_t name_len,
> +				     int index, const char *label)
> +{
> +	const char *symbol_path;
> +	uint32_t phandle;
> +	int symbol_off, fixup_off;
> +	int prop_len;
> +
> +	symbol_path = fdt_getprop(fdt, symbols_off, label,
> +				  &prop_len);
> +	if (!symbol_path)
> +		return -FDT_ERR_NOTFOUND;
> +
> +	symbol_off = fdt_path_offset(fdt, symbol_path);
> +	if (symbol_off < 0)
> +		return symbol_off;
> +
> +	phandle = fdt_get_phandle(fdt, symbol_off);
> +	if (!phandle)
> +		return -FDT_ERR_NOTFOUND;
> +
> +	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> +	if (fixup_off < 0)
> +		return fixup_off;
> +
> +	phandle = cpu_to_fdt32(phandle);
> +	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> +						    name, name_len, index,
> +						    &phandle, sizeof(phandle));

This will be broken on BE systems because fdt_get_phandle() byteswaps
to native order, but setprop_inplace doesn't byteswap back (because
it's input is a byte array, not a u32).

> +};
> +
> +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> +				 int property)
> +{
> +	const char *value;
> +	const char *label;
> +	int len;
> +
> +	value = fdt_getprop_by_offset(fdto, property,
> +				      &label, &len);
> +	if (!value)
> +		return len;
> +
> +	do {
> +		const char *prop_string = value;
> +		const char *path, *name;
> +		uint32_t path_len, name_len;
> +		char *sep, *endptr;
> +		int index;
> +		int ret;
> +
> +		path = prop_string;
> +		sep = strchr(prop_string, ':');
> +		path_len = sep - path;

You need to check for strchr() returning NULL (indicating a badly
formatted fixup missing a separator).

Also... strchr() is not safe.  Again, if the fixup string is badly
formatted and doesn't have a terminating \0, this could overrun, so
you want memchr() instead.

> +		name = sep + 1;
> +		sep = strchr(name, ':');
> +		name_len = sep - name;

And again.

> +		index = strtoul(sep + 1, &endptr, 10);
> +		if (endptr <= (sep + 1))
> +			return -FDT_ERR_BADSTRUCTURE;

IIRC the index value is supposed to go to the end of that portion of
the fixup, so you should be able to check for *endptr == '\0'.

Except.. strtoul() could also overrun if the fixup property doesn't
contain a \0 like it should.

So I think you'd be better off using a memchr() (or strnlen()) to
search for the \0 before you attempt parsing the innards of a single
fixup string.

Ugh.  I hate that we're parsing text numbers in decimal here, but
we're pretty much stuck with that format here.  Doubly so that it's a
gratuitously different way of encoding the (node, property, offset)
tuple from local_fixups.

> +		index = strtoul(sep + 1, &endptr, 10);
> +		if (endptr <= (sep + 1))
> +			return -FDT_ERR_BADSTRUCTURE;
> +
> +		len -= strlen(prop_string) + 1;
> +		value += strlen(prop_string) + 1;

Please don't double call strlen() on the same string - remember it's
O(n) in C.

> +
> +		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> +						path, path_len, name, name_len,
> +						index, label);
> +		if (ret)
> +			return ret;
> +	} while (len > 0);
> +
> +	return 0;
> +}
> +
> +static int overlay_fixup_phandles(void *dt, void *dto)
> +{
> +	int fixups_off, symbols_off;
> +	int property;
> +
> +	symbols_off = fdt_path_offset(dt, "/__symbols__");
> +	fixups_off = fdt_path_offset(dto, "/__fixups__");
> +
> +	fdt_for_each_property_offset(property, dto, fixups_off)
> +		overlay_fixup_phandle(dt, dto, symbols_off, property);
> +
> +	return 0;
> +}
> +
> +static int apply_overlay_node(void *dt, int target,
> +			      void *dto, int overlay)

I think 'overlay' should be 'fragment' here for consistency?

> +{
> +	int property;
> +	int node;
> +
> +	fdt_for_each_property_offset(property, dto, overlay) {
> +		const char *name;
> +		const void *prop;
> +		int prop_len;
> +		int ret;
> +
> +		prop = fdt_getprop_by_offset(dto, property, &name,
> +					     &prop_len);
> +		if (!prop)
> +			return -FDT_ERR_INTERNAL;

Actually, you probably should check the error code returned in
prop_len.  Getting a NOTFOUND would indicate an internal error, but
you could also get BADSTRUCTURE or similar errors which would indicate
an error in input.

> +
> +		ret = fdt_setprop(dt, target, name, prop, prop_len);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	fdt_for_each_subnode(dto, node, overlay) {
> +		const char *name = fdt_get_name(dto, node, NULL);
> +		int nnode;
> +		int ret;
> +
> +		nnode = fdt_add_subnode(dt, target, name);
> +		if (nnode == -FDT_ERR_EXISTS)
> +			nnode = fdt_subnode_offset(dt, target, name);
> +
> +		if (nnode < 0)
> +			return nnode;
> +
> +		ret = apply_overlay_node(dt, nnode, dto, node);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int overlay_merge(void *dt, void *dto)
> +{
> +	int fragment;
> +
> +	fdt_for_each_subnode(dto, fragment, 0) {
> +		int overlay;
> +		int target;
> +		int ret;
> +
> +		target = overlay_get_target(dt, dto, fragment);
> +		if (target < 0)
> +			continue;
> +
> +		overlay = fdt_subnode_offset(dto, fragment, "__overlay__");
> +		if (overlay < 0)
> +			return overlay;
> +
> +		ret = apply_overlay_node(dt, target, dto, overlay);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +int fdt_overlay_apply(void *fdt, void *fdto)
> +{
> +	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> +	int ret;
> +
> +	FDT_CHECK_HEADER(fdt);
> +	FDT_CHECK_HEADER(fdto);
> +
> +	ret = overlay_adjust_local_phandles(fdto, delta);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_update_local_references(fdto, delta);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_fixup_phandles(fdt, fdto);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_merge(fdt, fdto);
> +	if (!ret)
> +		goto out;
> +
> +err:

This is a confusing use of gotos - this looks like it is in the exit
path for both success and failure cases, but it's not due to the
easy-to-miss goto out above.

> +	/*
> +	 * The base device tree might have been damaged, erase its
> +	 * magic.
> +	 */
> +	fdt_set_magic(fdt, ~0);
> +
> +out:
> +	/*
> +	 * The overlay has been damaged, erase its magic.
> +	 */
> +	fdt_set_magic(fdto, ~0);
> +
> +	return ret;
> +}

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/80acaab9/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-27  5:26     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-27  5:26 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 15408 bytes --]

On Fri, Jun 24, 2016 at 04:27:55PM +0200, Maxime Ripard wrote:
> The device tree overlays are a good way to deal with user-modifyable
> boards or boards with some kind of an expansion mechanism where we can
> easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).
> 
> Add a new function to merge overlays with a base device tree.
> 
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> ---
>  include/libfdt.h         |  30 ++++
>  lib/Kconfig              |   5 +
>  lib/libfdt/Makefile      |   2 +
>  lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
>  4 files changed, 418 insertions(+)
>  create mode 100644 lib/libfdt/fdt_overlay.c
> 
> diff --git a/include/libfdt.h b/include/libfdt.h
> index b8758de3ae54..039ecb0c1ba7 100644
> --- a/include/libfdt.h
> +++ b/include/libfdt.h
> @@ -1747,6 +1747,36 @@ int fdt_add_subnode(void *fdt, int parentoffset, const char *name);
>   */
>  int fdt_del_node(void *fdt, int nodeoffset);
>  
> +/**
> + * fdt_overlay_apply - Applies a DT overlay on a base DT
> + * @fdt: pointer to the base device tree blob
> + * @fdto: pointer to the device tree overlay blob
> + *
> + * fdt_overlay_apply() will apply the given device tree overlay on the
> + * given base device tree.
> + *
> + * Expect the base device tree to be modified, even if the function
> + * returns an error.
> + *
> + * returns:
> + *	0, on success
> + *	-FDT_ERR_NOSPACE, there's not enough space in the base device tree
> + *	-FDT_ERR_NOTFOUND, the overlay points to some inexistant nodes or
> + *		properties in the base DT
> + *	-FDT_ERR_BADPHANDLE, the phandles in the overlay do not have the right
> + *		magic
> + *	-FDT_ERR_INTERNAL,
> + *	-FDT_ERR_BADLAYOUT,
> + *	-FDT_ERR_BADMAGIC,
> + *	-FDT_ERR_BADOFFSET,
> + *	-FDT_ERR_BADPATH,
> + *	-FDT_ERR_BADVERSION,
> + *	-FDT_ERR_BADSTRUCTURE,
> + *	-FDT_ERR_BADSTATE,
> + *	-FDT_ERR_TRUNCATED, standard meanings
> + */
> +int fdt_overlay_apply(void *fdt, void *fdto);
> +
>  /**********************************************************************/
>  /* Debugging / informational functions                                */
>  /**********************************************************************/
> diff --git a/lib/Kconfig b/lib/Kconfig
> index 02ca4058d37e..16ff01a2cd37 100644
> --- a/lib/Kconfig
> +++ b/lib/Kconfig
> @@ -139,6 +139,11 @@ config OF_LIBFDT
>  	  particular compatible nodes. The library operates on a flattened
>  	  version of the device tree.
>  
> +config OF_LIBFDT_OVERLAY
> +	bool "Enable the FDT library overlay support"
> +	help
> +	  This enables the FDT library (libfdt) overlay support.
> +
>  config SPL_OF_LIBFDT
>  	bool "Enable the FDT library for SPL"
>  	default y if SPL_OF_CONTROL
> diff --git a/lib/libfdt/Makefile b/lib/libfdt/Makefile
> index 8b86c15904cb..6ef8290f4e09 100644
> --- a/lib/libfdt/Makefile
> +++ b/lib/libfdt/Makefile
> @@ -15,3 +15,5 @@ obj-y += \
>  	fdt_empty_tree.o \
>  	fdt_addresses.o \
>  	fdt_region.o
> +
> +obj-$(CONFIG_OF_LIBFDT_OVERLAY) += fdt_overlay.o
> diff --git a/lib/libfdt/fdt_overlay.c b/lib/libfdt/fdt_overlay.c
> new file mode 100644
> index 000000000000..5835a90afafe
> --- /dev/null
> +++ b/lib/libfdt/fdt_overlay.c
> @@ -0,0 +1,381 @@
> +#include "libfdt_env.h"
> +
> +#include <fdt.h>
> +#include <libfdt.h>
> +
> +#include "libfdt_internal.h"
> +
> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> +{
> +	const uint32_t *val;
> +	int len;
> +
> +	val = fdt_getprop(fdto, fragment, "target", &len);
> +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> +		return 0;

This doesn't distinguish between a missing property (which may
indicate a valid overlay using a target-path or some other method)
and a badly formatted 'target' property, which is definitely an error
in the overlay.

I think those should be treated differently.

> +	return fdt32_to_cpu(*val);
> +}
> +
> +static int overlay_get_target(const void *fdt, const void *fdto,
> +			      int fragment)
> +{
> +	uint32_t phandle;
> +	const char *path;
> +
> +	/* Try first to do a phandle based lookup */
> +	phandle = overlay_get_target_phandle(fdto, fragment);
> +	if (phandle)
> +		return fdt_node_offset_by_phandle(fdt, phandle);
> +
> +	/* And then a path based lookup */
> +	path = fdt_getprop(fdto, fragment, "target-path", NULL);
> +	if (!path)
> +		return -FDT_ERR_NOTFOUND;
> +
> +	return fdt_path_offset(fdt, path);
> +}
> +
> +static int overlay_phandle_add_offset(void *fdt, int node,
> +				      const char *name, uint32_t delta)
> +{
> +	const uint32_t *val;
> +	uint32_t adj_val;
> +	int len;
> +
> +	val = fdt_getprop(fdt, node, name, &len);
> +	if (!val)
> +		return len;
> +
> +	if (len != sizeof(*val))
> +		return -FDT_ERR_BADSTRUCTURE;
> +
> +	adj_val = fdt32_to_cpu(*val);
> +	adj_val += delta;

You should probably check for overflow here.

> +
> +	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> +}
> +
> +static int overlay_adjust_node_phandles(void *fdto, int node,
> +					uint32_t delta)
> +{
> +	bool found = false;
> +	int child;
> +	int ret;
> +
> +	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> +	if (ret && ret != -FDT_ERR_NOTFOUND)
> +		return ret;
> +
> +	if (!ret)
> +		found = true;
> +
> +	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> +	if (ret && ret != -FDT_ERR_NOTFOUND)
> +		return ret;

I think the check for phandle vs. linux,phandle should be folded into
overlay_phandle_add_offset().

> +	/*
> +	 * If neither phandle nor linux,phandle have been found return
> +	 * an error.
> +	 */
> +	if (!found && !ret)
> +		return ret;
> +
> +	fdt_for_each_subnode(fdto, child, node)
> +		overlay_adjust_node_phandles(fdto, child, delta);
> +
> +	return 0;
> +}
> +
> +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> +{
> +	/*
> +	 * Start adjusting the phandles from the overlay root
> +	 */
> +	return overlay_adjust_node_phandles(fdto, 0, delta);
> +}
> +
> +static int overlay_update_local_node_references(void *fdto,
> +						int tree_node,
> +						int fixup_node,
> +						uint32_t delta)
> +{
> +	int fixup_prop;
> +	int fixup_child;
> +	int ret;
> +
> +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> +		const uint32_t *val = NULL;
> +		uint32_t adj_val, index;
> +		const char *name;
> +		int fixup_len;
> +		int tree_len;
> +
> +		val = fdt_getprop_by_offset(fdto, fixup_prop,
> +					    &name, &fixup_len);
> +		if (!val)
> +			return fixup_len;
> +		index = fdt32_to_cpu(*val);

This still doesn't handle the case of multiple fixups within the same
property.  That would be entirely plausible for something like an
interrupt-map property.

> +		val = fdt_getprop(fdto, tree_node, name, &tree_len);
> +		if (!val)
> +			return tree_len;
> +
> +		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));

phandle values need not be aligned within the property containint them
(e.g. properties which mix strings and integer values).  So you're
going to need to work directly with a byte offset here.

> +		adj_val += delta;
> +		adj_val = cpu_to_fdt32(adj_val);
> +
> +		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> +							   name, strlen(name),
> +							   index, &adj_val,
> +							   sizeof(adj_val));
> +		if (ret)
> +			return ret;
> +	}
> +
> +	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> +							    NULL);
> +		int tree_child;
> +
> +		tree_child = fdt_subnode_offset(fdto, tree_node,
> +						fixup_child_name);
> +		if (tree_child < 0)
> +			return tree_child;
> +
> +		ret = overlay_update_local_node_references(fdto,
> +							   tree_child,
> +							   fixup_child,
> +							   delta);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int overlay_update_local_references(void *dto, uint32_t delta)
> +{
> +	int fixups;
> +
> +	fixups = fdt_path_offset(dto, "/__local_fixups__");
> +	if (fixups < 0) {
> +		/*
> +		 * There's no local phandles to adjust, bail out
> +		 */
> +		if (fixups == -FDT_ERR_NOTFOUND)
> +			return 0;
> +
> +		return fixups;
> +	}
> +
> +	/*
> +	 * Update our local references from the root of the tree
> +	 */
> +	return overlay_update_local_node_references(dto, 0, fixups,
> +						    delta);
> +}
> +
> +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> +				     int symbols_off,
> +				     const char *path, uint32_t path_len,
> +				     const char *name, uint32_t name_len,
> +				     int index, const char *label)
> +{
> +	const char *symbol_path;
> +	uint32_t phandle;
> +	int symbol_off, fixup_off;
> +	int prop_len;
> +
> +	symbol_path = fdt_getprop(fdt, symbols_off, label,
> +				  &prop_len);
> +	if (!symbol_path)
> +		return -FDT_ERR_NOTFOUND;
> +
> +	symbol_off = fdt_path_offset(fdt, symbol_path);
> +	if (symbol_off < 0)
> +		return symbol_off;
> +
> +	phandle = fdt_get_phandle(fdt, symbol_off);
> +	if (!phandle)
> +		return -FDT_ERR_NOTFOUND;
> +
> +	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> +	if (fixup_off < 0)
> +		return fixup_off;
> +
> +	phandle = cpu_to_fdt32(phandle);
> +	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> +						    name, name_len, index,
> +						    &phandle, sizeof(phandle));

This will be broken on BE systems because fdt_get_phandle() byteswaps
to native order, but setprop_inplace doesn't byteswap back (because
it's input is a byte array, not a u32).

> +};
> +
> +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> +				 int property)
> +{
> +	const char *value;
> +	const char *label;
> +	int len;
> +
> +	value = fdt_getprop_by_offset(fdto, property,
> +				      &label, &len);
> +	if (!value)
> +		return len;
> +
> +	do {
> +		const char *prop_string = value;
> +		const char *path, *name;
> +		uint32_t path_len, name_len;
> +		char *sep, *endptr;
> +		int index;
> +		int ret;
> +
> +		path = prop_string;
> +		sep = strchr(prop_string, ':');
> +		path_len = sep - path;

You need to check for strchr() returning NULL (indicating a badly
formatted fixup missing a separator).

Also... strchr() is not safe.  Again, if the fixup string is badly
formatted and doesn't have a terminating \0, this could overrun, so
you want memchr() instead.

> +		name = sep + 1;
> +		sep = strchr(name, ':');
> +		name_len = sep - name;

And again.

> +		index = strtoul(sep + 1, &endptr, 10);
> +		if (endptr <= (sep + 1))
> +			return -FDT_ERR_BADSTRUCTURE;

IIRC the index value is supposed to go to the end of that portion of
the fixup, so you should be able to check for *endptr == '\0'.

Except.. strtoul() could also overrun if the fixup property doesn't
contain a \0 like it should.

So I think you'd be better off using a memchr() (or strnlen()) to
search for the \0 before you attempt parsing the innards of a single
fixup string.

Ugh.  I hate that we're parsing text numbers in decimal here, but
we're pretty much stuck with that format here.  Doubly so that it's a
gratuitously different way of encoding the (node, property, offset)
tuple from local_fixups.

> +		index = strtoul(sep + 1, &endptr, 10);
> +		if (endptr <= (sep + 1))
> +			return -FDT_ERR_BADSTRUCTURE;
> +
> +		len -= strlen(prop_string) + 1;
> +		value += strlen(prop_string) + 1;

Please don't double call strlen() on the same string - remember it's
O(n) in C.

> +
> +		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> +						path, path_len, name, name_len,
> +						index, label);
> +		if (ret)
> +			return ret;
> +	} while (len > 0);
> +
> +	return 0;
> +}
> +
> +static int overlay_fixup_phandles(void *dt, void *dto)
> +{
> +	int fixups_off, symbols_off;
> +	int property;
> +
> +	symbols_off = fdt_path_offset(dt, "/__symbols__");
> +	fixups_off = fdt_path_offset(dto, "/__fixups__");
> +
> +	fdt_for_each_property_offset(property, dto, fixups_off)
> +		overlay_fixup_phandle(dt, dto, symbols_off, property);
> +
> +	return 0;
> +}
> +
> +static int apply_overlay_node(void *dt, int target,
> +			      void *dto, int overlay)

I think 'overlay' should be 'fragment' here for consistency?

> +{
> +	int property;
> +	int node;
> +
> +	fdt_for_each_property_offset(property, dto, overlay) {
> +		const char *name;
> +		const void *prop;
> +		int prop_len;
> +		int ret;
> +
> +		prop = fdt_getprop_by_offset(dto, property, &name,
> +					     &prop_len);
> +		if (!prop)
> +			return -FDT_ERR_INTERNAL;

Actually, you probably should check the error code returned in
prop_len.  Getting a NOTFOUND would indicate an internal error, but
you could also get BADSTRUCTURE or similar errors which would indicate
an error in input.

> +
> +		ret = fdt_setprop(dt, target, name, prop, prop_len);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	fdt_for_each_subnode(dto, node, overlay) {
> +		const char *name = fdt_get_name(dto, node, NULL);
> +		int nnode;
> +		int ret;
> +
> +		nnode = fdt_add_subnode(dt, target, name);
> +		if (nnode == -FDT_ERR_EXISTS)
> +			nnode = fdt_subnode_offset(dt, target, name);
> +
> +		if (nnode < 0)
> +			return nnode;
> +
> +		ret = apply_overlay_node(dt, nnode, dto, node);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +static int overlay_merge(void *dt, void *dto)
> +{
> +	int fragment;
> +
> +	fdt_for_each_subnode(dto, fragment, 0) {
> +		int overlay;
> +		int target;
> +		int ret;
> +
> +		target = overlay_get_target(dt, dto, fragment);
> +		if (target < 0)
> +			continue;
> +
> +		overlay = fdt_subnode_offset(dto, fragment, "__overlay__");
> +		if (overlay < 0)
> +			return overlay;
> +
> +		ret = apply_overlay_node(dt, target, dto, overlay);
> +		if (ret)
> +			return ret;
> +	}
> +
> +	return 0;
> +}
> +
> +int fdt_overlay_apply(void *fdt, void *fdto)
> +{
> +	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> +	int ret;
> +
> +	FDT_CHECK_HEADER(fdt);
> +	FDT_CHECK_HEADER(fdto);
> +
> +	ret = overlay_adjust_local_phandles(fdto, delta);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_update_local_references(fdto, delta);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_fixup_phandles(fdt, fdto);
> +	if (ret)
> +		goto err;
> +
> +	ret = overlay_merge(fdt, fdto);
> +	if (!ret)
> +		goto out;
> +
> +err:

This is a confusing use of gotos - this looks like it is in the exit
path for both success and failure cases, but it's not due to the
easy-to-miss goto out above.

> +	/*
> +	 * The base device tree might have been damaged, erase its
> +	 * magic.
> +	 */
> +	fdt_set_magic(fdt, ~0);
> +
> +out:
> +	/*
> +	 * The overlay has been damaged, erase its magic.
> +	 */
> +	fdt_set_magic(fdto, ~0);
> +
> +	return ret;
> +}

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 12/12] tests: Introduce DT overlay tests
@ 2016-06-27  5:26     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-27  5:26 UTC (permalink / raw)
  To: u-boot

On Fri, Jun 24, 2016 at 04:27:57PM +0200, Maxime Ripard wrote:
> This adds a bunch of unit tests for the "fdt apply" command.
> 
> They've all been run successfully in the sandbox. However, as you still
> require an out-of-tree dtc with overlay support, this is disabled by
> default.
> 
> Acked-by: Simon Glass <sjg@chromium.org>
> Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>

These tests are geared for the u-boot tree, but for upstream
application we really need testcases that fit within dtc/libfdt as
well.  It would be good if you can adapt some or all of these tests to
work in that context.

> ---
>  Makefile                          |   1 +
>  include/test/overlay.h            |  16 +++
>  include/test/suites.h             |   1 +
>  test/Kconfig                      |   1 +
>  test/cmd_ut.c                     |   6 +
>  test/overlay/Kconfig              |  11 ++
>  test/overlay/Makefile             |  15 +++
>  test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++++++++++++++++
>  test/overlay/test-fdt-base.dts    |  21 ++++
>  test/overlay/test-fdt-overlay.dts |  88 ++++++++++++++
>  10 files changed, 403 insertions(+)
>  create mode 100644 include/test/overlay.h
>  create mode 100644 test/overlay/Kconfig
>  create mode 100644 test/overlay/Makefile
>  create mode 100644 test/overlay/cmd_ut_overlay.c
>  create mode 100644 test/overlay/test-fdt-base.dts
>  create mode 100644 test/overlay/test-fdt-overlay.dts
> 
> diff --git a/Makefile b/Makefile
> index d0e7a8a4ecc7..88353d091be8 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -665,6 +665,7 @@ libs-$(CONFIG_HAS_POST) += post/
>  libs-y += test/
>  libs-y += test/dm/
>  libs-$(CONFIG_UT_ENV) += test/env/
> +libs-$(CONFIG_UT_OVERLAY) += test/overlay/
>  
>  libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
>  
> diff --git a/include/test/overlay.h b/include/test/overlay.h
> new file mode 100644
> index 000000000000..392f28ff8405
> --- /dev/null
> +++ b/include/test/overlay.h
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __TEST_OVERLAY_H__
> +#define __TEST_OVERLAY_H__
> +
> +#include <test/test.h>
> +
> +/* Declare a new environment test */
> +#define OVERLAY_TEST(_name, _flags)	UNIT_TEST(_name, _flags, overlay_test)
> +
> +#endif /* __TEST_OVERLAY_H__ */
> diff --git a/include/test/suites.h b/include/test/suites.h
> index f5790333ff8e..0e94feb07a79 100644
> --- a/include/test/suites.h
> +++ b/include/test/suites.h
> @@ -10,6 +10,7 @@
>  
>  int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
>  int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
> +int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
>  int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
>  
>  #endif /* __TEST_SUITES_H__ */
> diff --git a/test/Kconfig b/test/Kconfig
> index d71c332eee27..3643761bc6ef 100644
> --- a/test/Kconfig
> +++ b/test/Kconfig
> @@ -17,3 +17,4 @@ config UT_TIME
>  
>  source "test/dm/Kconfig"
>  source "test/env/Kconfig"
> +source "test/overlay/Kconfig"
> diff --git a/test/cmd_ut.c b/test/cmd_ut.c
> index f6e1f413db7f..14333423a178 100644
> --- a/test/cmd_ut.c
> +++ b/test/cmd_ut.c
> @@ -19,6 +19,9 @@ static cmd_tbl_t cmd_ut_sub[] = {
>  #if defined(CONFIG_UT_ENV)
>  	U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""),
>  #endif
> +#ifdef CONFIG_UT_OVERLAY
> +	U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""),
> +#endif
>  #ifdef CONFIG_UT_TIME
>  	U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
>  #endif
> @@ -68,6 +71,9 @@ static char ut_help_text[] =
>  #ifdef CONFIG_UT_ENV
>  	"ut env [test-name]\n"
>  #endif
> +#ifdef CONFIG_UT_OVERLAY
> +	"ut overlay [test-name]\n"
> +#endif
>  #ifdef CONFIG_UT_TIME
>  	"ut time - Very basic test of time functions\n"
>  #endif
> diff --git a/test/overlay/Kconfig b/test/overlay/Kconfig
> new file mode 100644
> index 000000000000..13c85428cbaa
> --- /dev/null
> +++ b/test/overlay/Kconfig
> @@ -0,0 +1,11 @@
> +config UT_OVERLAY
> +	bool "Enable Device Tree Overlays Unit Tests"
> +	depends on OF_LIBFDT_OVERLAY
> +	depends on UNIT_TEST
> +	help
> +	  This enables the 'ut overlay' command which runs a series of unit
> +	  tests on the fdt overlay code.
> +	  If all is well then all tests pass although there will be a few
> +	  messages printed along the way.
> +	  Be warned that it requires an out-of-tree dtc compiler with patches
> +	  to support the DT overlays, otherwise it will fail.
> diff --git a/test/overlay/Makefile b/test/overlay/Makefile
> new file mode 100644
> index 000000000000..907f08544619
> --- /dev/null
> +++ b/test/overlay/Makefile
> @@ -0,0 +1,15 @@
> +#
> +# Copyright (c) 2016 NextThing Co
> +# Copyright (c) 2016 Free Electrons
> +#
> +# SPDX-License-Identifier:	GPL-2.0+
> +#
> +
> +# Test files
> +obj-y += cmd_ut_overlay.o
> +
> +DTC_FLAGS += -@
> +
> +# DT overlays
> +obj-y += test-fdt-base.dtb.o
> +obj-y += test-fdt-overlay.dtb.o
> diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
> new file mode 100644
> index 000000000000..4a9b3398d119
> --- /dev/null
> +++ b/test/overlay/cmd_ut_overlay.c
> @@ -0,0 +1,243 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <errno.h>
> +#include <malloc.h>
> +
> +#include <linux/sizes.h>
> +
> +#include <test/ut.h>
> +#include <test/overlay.h>
> +
> +/* 4k ought to be enough for anybody */
> +#define FDT_COPY_SIZE	(4 * SZ_1K)
> +
> +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,
> +				    const char *name, int index,
> +				    u32 *out)
> +{
> +	const fdt32_t *val;
> +	int node_off;
> +	int len;
> +
> +	node_off = fdt_path_offset(fdt, path);
> +	if (node_off < 0)
> +		return node_off;
> +
> +	val = fdt_getprop(fdt, node_off, name, &len);
> +	if (!val || (len < (sizeof(uint32_t) * (index + 1))))
> +		return -FDT_ERR_NOTFOUND;
> +
> +	*out = fdt32_to_cpu(*(val + index));
> +
> +	return 0;
> +}
> +
> +static int fdt_getprop_u32(void *fdt, const char *path, const char *name,
> +			   u32 *out)
> +{
> +	return fdt_getprop_u32_by_index(fdt, path, name, 0, out);
> +}
> +
> +static int fdt_getprop_str(void *fdt, const char *path, const char *name,
> +			   const char **out)
> +{
> +	int node_off;
> +
> +	node_off = fdt_path_offset(fdt, path);
> +	if (node_off < 0)
> +		return node_off;
> +
> +	return fdt_get_string(fdt, node_off, name, out);
> +}
> +
> +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",
> +				    &val));
> +	ut_asserteq(43, val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_change_int_property, 0);
> +
> +static int fdt_overlay_change_str_property(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	const char *val = NULL;
> +
> +	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
> +				    &val));
> +	ut_asserteq_str("foobar", val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_change_str_property, 0);
> +
> +static int fdt_overlay_add_str_property(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	const char *val = NULL;
> +
> +	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
> +				    &val));
> +	ut_asserteq_str("foobar2", val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_str_property, 0);
> +
> +static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/test-node/new-node");
> +	ut_assert(off >= 0);
> +
> +	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
> +
> +static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/new-node");
> +	ut_assert(off >= 0);
> +
> +	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
> +
> +static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/test-node/sub-test-node");
> +	ut_assert(off >= 0);
> +
> +	ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
> +	ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
> +
> +static int fdt_overlay_local_phandle(struct unit_test_state *uts)
> +{
> +	uint32_t local_phandle, test_phandle;
> +	void *fdt = uts->priv;
> +	u32 val = 0;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/new-local-node");
> +	ut_assert(off >= 0);
> +
> +	local_phandle = fdt_get_phandle(fdt, off);
> +	ut_assert(local_phandle);
> +
> +	off = fdt_path_offset(fdt, "/test-node");
> +	ut_assert(off >= 0);
> +
> +	test_phandle = fdt_get_phandle(fdt, off);
> +	ut_assert(test_phandle);
> +
> +	ut_assertok(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,
> +					     &val));
> +	ut_asserteq(local_phandle, val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_local_phandle, 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,
> +						 overlay_test);
> +	const int n_ents = ll_entry_count(struct unit_test, overlay_test);
> +	struct unit_test_state *uts;
> +	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;
> +
> +	ut_assertok(fdt_check_header(fdt_base));
> +	ut_assertok(fdt_check_header(fdt_overlay));
> +
> +	uts = calloc(1, sizeof(*uts));
> +	if (!uts)
> +		return -ENOMEM;
> +
> +	fdt_base_copy = malloc(FDT_COPY_SIZE);
> +	if (!fdt_base_copy)
> +		return -ENOMEM;
> +	uts->priv = fdt_base_copy;
> +
> +	fdt_overlay_copy = malloc(FDT_COPY_SIZE);
> +	if (!fdt_overlay_copy)
> +		return -ENOMEM;
> +
> +	/*
> +	 * Resize the FDT 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_base, fdt_base_copy, FDT_COPY_SIZE));
> +
> +	/*
> +	 * Resize the 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, fdt_overlay_copy,
> +				  FDT_COPY_SIZE));
> +
> +	/* Apply the overlay */
> +	ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
> +
> +	if (argc == 1)
> +		printf("Running %d environment tests\n", n_ents);
> +
> +	for (test = tests; test < tests + n_ents; test++) {
> +		if (argc > 1 && strcmp(argv[1], test->name))
> +			continue;
> +		printf("Test: %s\n", test->name);
> +
> +		uts->start = mallinfo();
> +
> +		test->func(uts);
> +	}
> +
> +	printf("Failures: %d\n", uts->fail_count);
> +
> +	free(fdt_overlay_copy);
> +	free(fdt_base_copy);
> +	free(uts);
> +
> +	return uts->fail_count ? CMD_RET_FAILURE : 0;
> +}
> diff --git a/test/overlay/test-fdt-base.dts b/test/overlay/test-fdt-base.dts
> new file mode 100644
> index 000000000000..2603adb6821e
> --- /dev/null
> +++ b/test/overlay/test-fdt-base.dts
> @@ -0,0 +1,21 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +/dts-v1/;
> +
> +/ {
> +	test: test-node {
> +		test-int-property = <42>;
> +		test-str-property = "foo";
> +
> +		subtest: sub-test-node {
> +			sub-test-property;
> +		};
> +	};
> +};
> +
> +
> diff --git a/test/overlay/test-fdt-overlay.dts b/test/overlay/test-fdt-overlay.dts
> new file mode 100644
> index 000000000000..199aa5797ef4
> --- /dev/null
> +++ b/test/overlay/test-fdt-overlay.dts
> @@ -0,0 +1,88 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +
> +/ {
> +	/* Test that we can change an int by another */
> +	fragment at 0 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			test-int-property = <43>;
> +		};
> +	};
> +
> +	/* Test that we can replace a string by a longer one */
> +	fragment at 1 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			test-str-property = "foobar";
> +		};
> +	};
> +
> +	/* Test that we add a new property */
> +	fragment at 2 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			test-str-property-2 = "foobar2";
> +		};
> +	};
> +
> +	/* Test that we add a new node (by phandle) */
> +	fragment at 3 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			new-node {
> +				new-property;
> +			};
> +		};
> +	};
> +
> +	/* Test that we add a new node (by path) */
> +	fragment at 4 {
> +		target-path = "/";
> +
> +		__overlay__ {
> +			new-node {
> +				new-property;
> +			};
> +		};
> +	};
> +
> +	fragment at 5 {
> +		target-path = "/";
> +
> +		__overlay__ {
> +			local: new-local-node {
> +				new-property;
> +			};
> +		};
> +	};
> +
> +	fragment at 6 {
> +		target-path = "/";
> +
> +		__overlay__ {
> +			test-phandle = <&test>, <&local>;
> +		};
> +	};
> +
> +	fragment at 7 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			sub-test-node {
> +				new-sub-test-property;
> +			};
> +		};
> +	};
> +};

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/75d7c068/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 12/12] tests: Introduce DT overlay tests
@ 2016-06-27  5:26     ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-27  5:26 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 14863 bytes --]

On Fri, Jun 24, 2016 at 04:27:57PM +0200, Maxime Ripard wrote:
> This adds a bunch of unit tests for the "fdt apply" command.
> 
> They've all been run successfully in the sandbox. However, as you still
> require an out-of-tree dtc with overlay support, this is disabled by
> default.
> 
> Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>

These tests are geared for the u-boot tree, but for upstream
application we really need testcases that fit within dtc/libfdt as
well.  It would be good if you can adapt some or all of these tests to
work in that context.

> ---
>  Makefile                          |   1 +
>  include/test/overlay.h            |  16 +++
>  include/test/suites.h             |   1 +
>  test/Kconfig                      |   1 +
>  test/cmd_ut.c                     |   6 +
>  test/overlay/Kconfig              |  11 ++
>  test/overlay/Makefile             |  15 +++
>  test/overlay/cmd_ut_overlay.c     | 243 ++++++++++++++++++++++++++++++++++++++
>  test/overlay/test-fdt-base.dts    |  21 ++++
>  test/overlay/test-fdt-overlay.dts |  88 ++++++++++++++
>  10 files changed, 403 insertions(+)
>  create mode 100644 include/test/overlay.h
>  create mode 100644 test/overlay/Kconfig
>  create mode 100644 test/overlay/Makefile
>  create mode 100644 test/overlay/cmd_ut_overlay.c
>  create mode 100644 test/overlay/test-fdt-base.dts
>  create mode 100644 test/overlay/test-fdt-overlay.dts
> 
> diff --git a/Makefile b/Makefile
> index d0e7a8a4ecc7..88353d091be8 100644
> --- a/Makefile
> +++ b/Makefile
> @@ -665,6 +665,7 @@ libs-$(CONFIG_HAS_POST) += post/
>  libs-y += test/
>  libs-y += test/dm/
>  libs-$(CONFIG_UT_ENV) += test/env/
> +libs-$(CONFIG_UT_OVERLAY) += test/overlay/
>  
>  libs-y += $(if $(BOARDDIR),board/$(BOARDDIR)/)
>  
> diff --git a/include/test/overlay.h b/include/test/overlay.h
> new file mode 100644
> index 000000000000..392f28ff8405
> --- /dev/null
> +++ b/include/test/overlay.h
> @@ -0,0 +1,16 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#ifndef __TEST_OVERLAY_H__
> +#define __TEST_OVERLAY_H__
> +
> +#include <test/test.h>
> +
> +/* Declare a new environment test */
> +#define OVERLAY_TEST(_name, _flags)	UNIT_TEST(_name, _flags, overlay_test)
> +
> +#endif /* __TEST_OVERLAY_H__ */
> diff --git a/include/test/suites.h b/include/test/suites.h
> index f5790333ff8e..0e94feb07a79 100644
> --- a/include/test/suites.h
> +++ b/include/test/suites.h
> @@ -10,6 +10,7 @@
>  
>  int do_ut_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
>  int do_ut_env(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
> +int do_ut_overlay(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
>  int do_ut_time(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[]);
>  
>  #endif /* __TEST_SUITES_H__ */
> diff --git a/test/Kconfig b/test/Kconfig
> index d71c332eee27..3643761bc6ef 100644
> --- a/test/Kconfig
> +++ b/test/Kconfig
> @@ -17,3 +17,4 @@ config UT_TIME
>  
>  source "test/dm/Kconfig"
>  source "test/env/Kconfig"
> +source "test/overlay/Kconfig"
> diff --git a/test/cmd_ut.c b/test/cmd_ut.c
> index f6e1f413db7f..14333423a178 100644
> --- a/test/cmd_ut.c
> +++ b/test/cmd_ut.c
> @@ -19,6 +19,9 @@ static cmd_tbl_t cmd_ut_sub[] = {
>  #if defined(CONFIG_UT_ENV)
>  	U_BOOT_CMD_MKENT(env, CONFIG_SYS_MAXARGS, 1, do_ut_env, "", ""),
>  #endif
> +#ifdef CONFIG_UT_OVERLAY
> +	U_BOOT_CMD_MKENT(overlay, CONFIG_SYS_MAXARGS, 1, do_ut_overlay, "", ""),
> +#endif
>  #ifdef CONFIG_UT_TIME
>  	U_BOOT_CMD_MKENT(time, CONFIG_SYS_MAXARGS, 1, do_ut_time, "", ""),
>  #endif
> @@ -68,6 +71,9 @@ static char ut_help_text[] =
>  #ifdef CONFIG_UT_ENV
>  	"ut env [test-name]\n"
>  #endif
> +#ifdef CONFIG_UT_OVERLAY
> +	"ut overlay [test-name]\n"
> +#endif
>  #ifdef CONFIG_UT_TIME
>  	"ut time - Very basic test of time functions\n"
>  #endif
> diff --git a/test/overlay/Kconfig b/test/overlay/Kconfig
> new file mode 100644
> index 000000000000..13c85428cbaa
> --- /dev/null
> +++ b/test/overlay/Kconfig
> @@ -0,0 +1,11 @@
> +config UT_OVERLAY
> +	bool "Enable Device Tree Overlays Unit Tests"
> +	depends on OF_LIBFDT_OVERLAY
> +	depends on UNIT_TEST
> +	help
> +	  This enables the 'ut overlay' command which runs a series of unit
> +	  tests on the fdt overlay code.
> +	  If all is well then all tests pass although there will be a few
> +	  messages printed along the way.
> +	  Be warned that it requires an out-of-tree dtc compiler with patches
> +	  to support the DT overlays, otherwise it will fail.
> diff --git a/test/overlay/Makefile b/test/overlay/Makefile
> new file mode 100644
> index 000000000000..907f08544619
> --- /dev/null
> +++ b/test/overlay/Makefile
> @@ -0,0 +1,15 @@
> +#
> +# Copyright (c) 2016 NextThing Co
> +# Copyright (c) 2016 Free Electrons
> +#
> +# SPDX-License-Identifier:	GPL-2.0+
> +#
> +
> +# Test files
> +obj-y += cmd_ut_overlay.o
> +
> +DTC_FLAGS += -@
> +
> +# DT overlays
> +obj-y += test-fdt-base.dtb.o
> +obj-y += test-fdt-overlay.dtb.o
> diff --git a/test/overlay/cmd_ut_overlay.c b/test/overlay/cmd_ut_overlay.c
> new file mode 100644
> index 000000000000..4a9b3398d119
> --- /dev/null
> +++ b/test/overlay/cmd_ut_overlay.c
> @@ -0,0 +1,243 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +#include <common.h>
> +#include <command.h>
> +#include <errno.h>
> +#include <malloc.h>
> +
> +#include <linux/sizes.h>
> +
> +#include <test/ut.h>
> +#include <test/overlay.h>
> +
> +/* 4k ought to be enough for anybody */
> +#define FDT_COPY_SIZE	(4 * SZ_1K)
> +
> +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,
> +				    const char *name, int index,
> +				    u32 *out)
> +{
> +	const fdt32_t *val;
> +	int node_off;
> +	int len;
> +
> +	node_off = fdt_path_offset(fdt, path);
> +	if (node_off < 0)
> +		return node_off;
> +
> +	val = fdt_getprop(fdt, node_off, name, &len);
> +	if (!val || (len < (sizeof(uint32_t) * (index + 1))))
> +		return -FDT_ERR_NOTFOUND;
> +
> +	*out = fdt32_to_cpu(*(val + index));
> +
> +	return 0;
> +}
> +
> +static int fdt_getprop_u32(void *fdt, const char *path, const char *name,
> +			   u32 *out)
> +{
> +	return fdt_getprop_u32_by_index(fdt, path, name, 0, out);
> +}
> +
> +static int fdt_getprop_str(void *fdt, const char *path, const char *name,
> +			   const char **out)
> +{
> +	int node_off;
> +
> +	node_off = fdt_path_offset(fdt, path);
> +	if (node_off < 0)
> +		return node_off;
> +
> +	return fdt_get_string(fdt, node_off, name, out);
> +}
> +
> +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",
> +				    &val));
> +	ut_asserteq(43, val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_change_int_property, 0);
> +
> +static int fdt_overlay_change_str_property(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	const char *val = NULL;
> +
> +	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property",
> +				    &val));
> +	ut_asserteq_str("foobar", val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_change_str_property, 0);
> +
> +static int fdt_overlay_add_str_property(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	const char *val = NULL;
> +
> +	ut_assertok(fdt_getprop_str(fdt, "/test-node", "test-str-property-2",
> +				    &val));
> +	ut_asserteq_str("foobar2", val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_str_property, 0);
> +
> +static int fdt_overlay_add_node_by_phandle(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/test-node/new-node");
> +	ut_assert(off >= 0);
> +
> +	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_node_by_phandle, 0);
> +
> +static int fdt_overlay_add_node_by_path(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/new-node");
> +	ut_assert(off >= 0);
> +
> +	ut_assertnonnull(fdt_getprop(fdt, off, "new-property", NULL));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_node_by_path, 0);
> +
> +static int fdt_overlay_add_subnode_property(struct unit_test_state *uts)
> +{
> +	void *fdt = uts->priv;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/test-node/sub-test-node");
> +	ut_assert(off >= 0);
> +
> +	ut_assertnonnull(fdt_getprop(fdt, off, "sub-test-property", NULL));
> +	ut_assertnonnull(fdt_getprop(fdt, off, "new-sub-test-property", NULL));
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_add_subnode_property, 0);
> +
> +static int fdt_overlay_local_phandle(struct unit_test_state *uts)
> +{
> +	uint32_t local_phandle, test_phandle;
> +	void *fdt = uts->priv;
> +	u32 val = 0;
> +	int off;
> +
> +	off = fdt_path_offset(fdt, "/new-local-node");
> +	ut_assert(off >= 0);
> +
> +	local_phandle = fdt_get_phandle(fdt, off);
> +	ut_assert(local_phandle);
> +
> +	off = fdt_path_offset(fdt, "/test-node");
> +	ut_assert(off >= 0);
> +
> +	test_phandle = fdt_get_phandle(fdt, off);
> +	ut_assert(test_phandle);
> +
> +	ut_assertok(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,
> +					     &val));
> +	ut_asserteq(local_phandle, val);
> +
> +	return CMD_RET_SUCCESS;
> +}
> +OVERLAY_TEST(fdt_overlay_local_phandle, 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,
> +						 overlay_test);
> +	const int n_ents = ll_entry_count(struct unit_test, overlay_test);
> +	struct unit_test_state *uts;
> +	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;
> +
> +	ut_assertok(fdt_check_header(fdt_base));
> +	ut_assertok(fdt_check_header(fdt_overlay));
> +
> +	uts = calloc(1, sizeof(*uts));
> +	if (!uts)
> +		return -ENOMEM;
> +
> +	fdt_base_copy = malloc(FDT_COPY_SIZE);
> +	if (!fdt_base_copy)
> +		return -ENOMEM;
> +	uts->priv = fdt_base_copy;
> +
> +	fdt_overlay_copy = malloc(FDT_COPY_SIZE);
> +	if (!fdt_overlay_copy)
> +		return -ENOMEM;
> +
> +	/*
> +	 * Resize the FDT 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_base, fdt_base_copy, FDT_COPY_SIZE));
> +
> +	/*
> +	 * Resize the 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, fdt_overlay_copy,
> +				  FDT_COPY_SIZE));
> +
> +	/* Apply the overlay */
> +	ut_assertok(fdt_overlay_apply(fdt_base_copy, fdt_overlay_copy));
> +
> +	if (argc == 1)
> +		printf("Running %d environment tests\n", n_ents);
> +
> +	for (test = tests; test < tests + n_ents; test++) {
> +		if (argc > 1 && strcmp(argv[1], test->name))
> +			continue;
> +		printf("Test: %s\n", test->name);
> +
> +		uts->start = mallinfo();
> +
> +		test->func(uts);
> +	}
> +
> +	printf("Failures: %d\n", uts->fail_count);
> +
> +	free(fdt_overlay_copy);
> +	free(fdt_base_copy);
> +	free(uts);
> +
> +	return uts->fail_count ? CMD_RET_FAILURE : 0;
> +}
> diff --git a/test/overlay/test-fdt-base.dts b/test/overlay/test-fdt-base.dts
> new file mode 100644
> index 000000000000..2603adb6821e
> --- /dev/null
> +++ b/test/overlay/test-fdt-base.dts
> @@ -0,0 +1,21 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +/dts-v1/;
> +
> +/ {
> +	test: test-node {
> +		test-int-property = <42>;
> +		test-str-property = "foo";
> +
> +		subtest: sub-test-node {
> +			sub-test-property;
> +		};
> +	};
> +};
> +
> +
> diff --git a/test/overlay/test-fdt-overlay.dts b/test/overlay/test-fdt-overlay.dts
> new file mode 100644
> index 000000000000..199aa5797ef4
> --- /dev/null
> +++ b/test/overlay/test-fdt-overlay.dts
> @@ -0,0 +1,88 @@
> +/*
> + * Copyright (c) 2016 NextThing Co
> + * Copyright (c) 2016 Free Electrons
> + *
> + * SPDX-License-Identifier:	GPL-2.0+
> + */
> +
> +/dts-v1/;
> +/plugin/;
> +
> +/ {
> +	/* Test that we can change an int by another */
> +	fragment@0 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			test-int-property = <43>;
> +		};
> +	};
> +
> +	/* Test that we can replace a string by a longer one */
> +	fragment@1 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			test-str-property = "foobar";
> +		};
> +	};
> +
> +	/* Test that we add a new property */
> +	fragment@2 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			test-str-property-2 = "foobar2";
> +		};
> +	};
> +
> +	/* Test that we add a new node (by phandle) */
> +	fragment@3 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			new-node {
> +				new-property;
> +			};
> +		};
> +	};
> +
> +	/* Test that we add a new node (by path) */
> +	fragment@4 {
> +		target-path = "/";
> +
> +		__overlay__ {
> +			new-node {
> +				new-property;
> +			};
> +		};
> +	};
> +
> +	fragment@5 {
> +		target-path = "/";
> +
> +		__overlay__ {
> +			local: new-local-node {
> +				new-property;
> +			};
> +		};
> +	};
> +
> +	fragment@6 {
> +		target-path = "/";
> +
> +		__overlay__ {
> +			test-phandle = <&test>, <&local>;
> +		};
> +	};
> +
> +	fragment@7 {
> +		target = <&test>;
> +
> +		__overlay__ {
> +			sub-test-node {
> +				new-sub-test-property;
> +			};
> +		};
> +	};
> +};

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
@ 2016-06-27  6:29     ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  6:29 UTC (permalink / raw)
  To: u-boot

Hi David,

On Mon, Jun 27, 2016 at 01:37:19AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:45PM +0200, Maxime Ripard wrote:
> > Hi,
> > 
> > The device tree overlays are a great solution to the issue raised by
> > the bunch expandable boards we find everywhere these days, like the
> > Beaglebone, Raspberry Pi or CHIP.
> > 
> > However, most of the time, the overlays are applied through a
> > mechanism involving the firmware request interface in Linux, that is
> > only fully functional once the userspace has been mounted and is
> > running.
> > 
> > Some expansion boards might need to be enabled before that, because
> > they simply need to patch the DT early on, or need to be initialized
> > early in order to be fully functional, or because they provide access
> > to the root filesystem.
> > 
> > In these cases, having the bootloader applying the overlay before
> > Linux starts seems like the easiest solution.
> > 
> > This implementation doesn't provide all the Linux fancyness though,
> > there's no transactional application, which means that if the overlay
> > cannot be applied for a reason while you're still halfway through the
> > application, you're probably screwed. It also cannot remove an
> > overlay, but I don't think that it is currently a use-case.
> > 
> > There's still a bunch of work to extend the libfdt unit tests to test
> > the new functions introduced, but these patches will be submitted
> > in a near future.
> 
> Are you planning to send a new version of (the relevant portions of)
> these against upstream libfdt?

Of course, I just only have to work on the test cases now.

Simon wanted to merge this in U-Boot for the next merge window, and
then sync with libfdt when it would be merged, hence why I posted it
first.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/15eedd6d/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
@ 2016-06-27  6:29     ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  6:29 UTC (permalink / raw)
  To: David Gibson
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1940 bytes --]

Hi David,

On Mon, Jun 27, 2016 at 01:37:19AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:45PM +0200, Maxime Ripard wrote:
> > Hi,
> > 
> > The device tree overlays are a great solution to the issue raised by
> > the bunch expandable boards we find everywhere these days, like the
> > Beaglebone, Raspberry Pi or CHIP.
> > 
> > However, most of the time, the overlays are applied through a
> > mechanism involving the firmware request interface in Linux, that is
> > only fully functional once the userspace has been mounted and is
> > running.
> > 
> > Some expansion boards might need to be enabled before that, because
> > they simply need to patch the DT early on, or need to be initialized
> > early in order to be fully functional, or because they provide access
> > to the root filesystem.
> > 
> > In these cases, having the bootloader applying the overlay before
> > Linux starts seems like the easiest solution.
> > 
> > This implementation doesn't provide all the Linux fancyness though,
> > there's no transactional application, which means that if the overlay
> > cannot be applied for a reason while you're still halfway through the
> > application, you're probably screwed. It also cannot remove an
> > overlay, but I don't think that it is currently a use-case.
> > 
> > There's still a bunch of work to extend the libfdt unit tests to test
> > the new functions introduced, but these patches will be submitted
> > in a near future.
> 
> Are you planning to send a new version of (the relevant portions of)
> these against upstream libfdt?

Of course, I just only have to work on the test cases now.

Simon wanted to merge this in U-Boot for the next merge window, and
then sync with libfdt when it would be merged, hence why I posted it
first.

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 12/12] tests: Introduce DT overlay tests
@ 2016-06-27  6:30       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  6:30 UTC (permalink / raw)
  To: u-boot

Hi David,

On Mon, Jun 27, 2016 at 03:26:58PM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:57PM +0200, Maxime Ripard wrote:
> > This adds a bunch of unit tests for the "fdt apply" command.
> > 
> > They've all been run successfully in the sandbox. However, as you still
> > require an out-of-tree dtc with overlay support, this is disabled by
> > default.
> > 
> > Acked-by: Simon Glass <sjg@chromium.org>
> > Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> These tests are geared for the u-boot tree, but for upstream
> application we really need testcases that fit within dtc/libfdt as
> well.  It would be good if you can adapt some or all of these tests to
> work in that context.

That's the plan ! :)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/c8ef02bd/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 12/12] tests: Introduce DT overlay tests
@ 2016-06-27  6:30       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  6:30 UTC (permalink / raw)
  To: David Gibson
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1035 bytes --]

Hi David,

On Mon, Jun 27, 2016 at 03:26:58PM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:57PM +0200, Maxime Ripard wrote:
> > This adds a bunch of unit tests for the "fdt apply" command.
> > 
> > They've all been run successfully in the sandbox. However, as you still
> > require an out-of-tree dtc with overlay support, this is disabled by
> > default.
> > 
> > Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> > Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> 
> These tests are geared for the u-boot tree, but for upstream
> application we really need testcases that fit within dtc/libfdt as
> well.  It would be good if you can adapt some or all of these tests to
> work in that context.

That's the plan ! :)

Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 12/12] tests: Introduce DT overlay tests
  2016-06-27  6:30       ` Maxime Ripard
@ 2016-06-27  6:47         ` David Gibson
  -1 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-27  6:47 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 27, 2016 at 08:30:28AM +0200, Maxime Ripard wrote:
> Hi David,
> 
> On Mon, Jun 27, 2016 at 03:26:58PM +1000, David Gibson wrote:
> > On Fri, Jun 24, 2016 at 04:27:57PM +0200, Maxime Ripard wrote:
> > > This adds a bunch of unit tests for the "fdt apply" command.
> > > 
> > > They've all been run successfully in the sandbox. However, as you still
> > > require an out-of-tree dtc with overlay support, this is disabled by
> > > default.
> > > 
> > > Acked-by: Simon Glass <sjg@chromium.org>
> > > Acked-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > 
> > These tests are geared for the u-boot tree, but for upstream
> > application we really need testcases that fit within dtc/libfdt as
> > well.  It would be good if you can adapt some or all of these tests to
> > work in that context.
> 
> That's the plan ! :)

Ok, great.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/8828b5ad/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 12/12] tests: Introduce DT overlay tests
@ 2016-06-27  6:47         ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-27  6:47 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1226 bytes --]

On Mon, Jun 27, 2016 at 08:30:28AM +0200, Maxime Ripard wrote:
> Hi David,
> 
> On Mon, Jun 27, 2016 at 03:26:58PM +1000, David Gibson wrote:
> > On Fri, Jun 24, 2016 at 04:27:57PM +0200, Maxime Ripard wrote:
> > > This adds a bunch of unit tests for the "fdt apply" command.
> > > 
> > > They've all been run successfully in the sandbox. However, as you still
> > > require an out-of-tree dtc with overlay support, this is disabled by
> > > default.
> > > 
> > > Acked-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>
> > > Acked-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> > > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > 
> > These tests are geared for the u-boot tree, but for upstream
> > application we really need testcases that fit within dtc/libfdt as
> > well.  It would be good if you can adapt some or all of these tests to
> > work in that context.
> 
> That's the plan ! :)

Ok, great.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-27  7:13       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  7:13 UTC (permalink / raw)
  To: u-boot

Hi Simon,

On Sat, Jun 25, 2016 at 08:53:58PM -0600, Simon Glass wrote:
> Hi Maxime,
> 
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard@free-electrons.com> wrote:
> > The device tree overlays are a good way to deal with user-modifyable
> > boards or boards with some kind of an expansion mechanism where we can
> > easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).
> >
> > Add a new function to merge overlays with a base device tree.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  include/libfdt.h         |  30 ++++
> >  lib/Kconfig              |   5 +
> >  lib/libfdt/Makefile      |   2 +
> >  lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 418 insertions(+)
> >  create mode 100644 lib/libfdt/fdt_overlay.c
> >
> 
> Is there a change log?

Yes, in the cover letter.

> > +static int overlay_update_local_node_references(void *fdto,
> > +                                               int tree_node,
> > +                                               int fixup_node,
> > +                                               uint32_t delta)
> > +{
> 
> Please add function comments for all of these.

Ack

> > +static int overlay_update_local_references(void *dto, uint32_t delta)
> > +{
> > +       int fixups;
> > +
> > +       fixups = fdt_path_offset(dto, "/__local_fixups__");
> > +       if (fixups < 0) {
> > +               /*
> > +                * There's no local phandles to adjust, bail out
> 
> On on line:
> 
> /* There's not local ... */

Ok.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/cdad4f28/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-27  7:13       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  7:13 UTC (permalink / raw)
  To: Simon Glass
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1828 bytes --]

Hi Simon,

On Sat, Jun 25, 2016 at 08:53:58PM -0600, Simon Glass wrote:
> Hi Maxime,
> 
> On 24 June 2016 at 08:27, Maxime Ripard
> <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> > The device tree overlays are a good way to deal with user-modifyable
> > boards or boards with some kind of an expansion mechanism where we can
> > easily plug new board in (like the BBB, the Raspberry Pi or the CHIP).
> >
> > Add a new function to merge overlays with a base device tree.
> >
> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > ---
> >  include/libfdt.h         |  30 ++++
> >  lib/Kconfig              |   5 +
> >  lib/libfdt/Makefile      |   2 +
> >  lib/libfdt/fdt_overlay.c | 381 +++++++++++++++++++++++++++++++++++++++++++++++
> >  4 files changed, 418 insertions(+)
> >  create mode 100644 lib/libfdt/fdt_overlay.c
> >
> 
> Is there a change log?

Yes, in the cover letter.

> > +static int overlay_update_local_node_references(void *fdto,
> > +                                               int tree_node,
> > +                                               int fixup_node,
> > +                                               uint32_t delta)
> > +{
> 
> Please add function comments for all of these.

Ack

> > +static int overlay_update_local_references(void *dto, uint32_t delta)
> > +{
> > +       int fixups;
> > +
> > +       fixups = fdt_path_offset(dto, "/__local_fixups__");
> > +       if (fixups < 0) {
> > +               /*
> > +                * There's no local phandles to adjust, bail out
> 
> On on line:
> 
> /* There's not local ... */

Ok.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-27  7:25       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  7:25 UTC (permalink / raw)
  To: u-boot

Hi David,

On Mon, Jun 27, 2016 at 01:39:06AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:49PM +0200, Maxime Ripard wrote:
> > The libfdt overlay support introduces a bunch of new includes and
> > functions.
> > 
> > Make sure we are able to build it by adding the needed glue.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> 
> Is this intended only for downstream u-boot only, or also for upstream
> libfdt?

U-Boot only.

> If it's u-boot only, you don't really need the #ifdef UBOOT.

Unfortunately, libfdt_env.h is also included by some userspace tools
in U-Boot, which make use of strtoul while simple_strtoul is not
defined there (and we should rely on libc's anyway), leading to
link errors.

Maxime


-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/e21dca99/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-27  7:25       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  7:25 UTC (permalink / raw)
  To: David Gibson
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 920 bytes --]

Hi David,

On Mon, Jun 27, 2016 at 01:39:06AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:49PM +0200, Maxime Ripard wrote:
> > The libfdt overlay support introduces a bunch of new includes and
> > functions.
> > 
> > Make sure we are able to build it by adding the needed glue.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> 
> Is this intended only for downstream u-boot only, or also for upstream
> libfdt?

U-Boot only.

> If it's u-boot only, you don't really need the #ifdef UBOOT.

Unfortunately, libfdt_env.h is also included by some userspace tools
in U-Boot, which make use of strtoul while simple_strtoul is not
defined there (and we should rely on libc's anyway), leading to
link errors.

Maxime


-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-27  7:29       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  7:29 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 27, 2016 at 01:49:29AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:54PM +0200, Maxime Ripard wrote:
> > Add a function to retrieve a writeable property only by the first
> > characters of its name.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  include/libfdt.h | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index dbe8a0efca87..b8758de3ae54 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> >   */
> >  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> >  				const char *name, int namelen, int *lenp);
> > +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> > +					  const char *name, int namelen,
> > +					  int *lenp)
> > +{
> > +	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> > +						      namelen, lenp);
> > +}
> 
> I believe you used this in your new setprop_inpace implementation.  So
> the series needs to be re-ordered to avoid breaking bisection.

You're right, sorry for that.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/1602826b/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w
@ 2016-06-27  7:29       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  7:29 UTC (permalink / raw)
  To: David Gibson
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1379 bytes --]

On Mon, Jun 27, 2016 at 01:49:29AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:54PM +0200, Maxime Ripard wrote:
> > Add a function to retrieve a writeable property only by the first
> > characters of its name.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > ---
> >  include/libfdt.h | 7 +++++++
> >  1 file changed, 7 insertions(+)
> > 
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index dbe8a0efca87..b8758de3ae54 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -619,6 +619,13 @@ const void *fdt_getprop_by_offset(const void *fdt, int offset,
> >   */
> >  const void *fdt_getprop_namelen(const void *fdt, int nodeoffset,
> >  				const char *name, int namelen, int *lenp);
> > +static inline void *fdt_getprop_namelen_w(void *fdt, int nodeoffset,
> > +					  const char *name, int namelen,
> > +					  int *lenp)
> > +{
> > +	return (void *)(uintptr_t)fdt_getprop_namelen(fdt, nodeoffset, name,
> > +						      namelen, lenp);
> > +}
> 
> I believe you used this in your new setprop_inpace implementation.  So
> the series needs to be re-ordered to avoid breaking bisection.

You're right, sorry for that.

Thanks!
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-27  9:16       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  9:16 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 27, 2016 at 01:45:11AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:52PM +0200, Maxime Ripard wrote:
> > Add a function to modify inplace a property starting from a given index.
> > 
> > This is especially useful when the property is an array of values, and you
> > want to update one of them without changing the DT size.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > ---
> >  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
> >  lib/libfdt/fdt_wip.c | 13 ++++++++-----
> >  2 files changed, 39 insertions(+), 8 deletions(-)
> > 
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index 4643be5adf39..2c8a42bcb667 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> >  /* Write-in-place functions                                           */
> >  /**********************************************************************/
> >  
> > +/**
> > + * fdt_setprop_inplace_namelen_by_index - change a property's value,
> > + *                                        but not its size
> > + * @fdt: pointer to the device tree blob
> > + * @nodeoffset: offset of the node whose property to change
> > + * @name: name of the property to change
> > + * @namelen: number of characters of name to consider
> > + * @index: index of the property to change in the array
> > + * @val: pointer to data to replace the property value with
> > + * @len: length of the property value
> > + *
> > + * Identical to fdt_setprop_inplace(), but modifies the given property
> > + * starting from the given index, and using only the first characters
> > + * of the name. It is useful when you want to manipulate only one value of
> > + * an array and you have a string that doesn't end with \0.
> > + */
> > +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> > +					 const char *name, int namelen,
> > +					 uint32_t index, const void *val,
> > +					 int len);
> 
> This looks like a good addition to upstream, but I don't like the
> name.  I'd suggest fdt_setprop_inplace_namelen_partial() because it
> only overwrite part of the existing property value.

Ack.

> > +
> >  /**
> >   * fdt_setprop_inplace - change a property's value, but not its size
> >   * @fdt: pointer to the device tree blob
> > @@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> >   *	-FDT_ERR_BADSTRUCTURE,
> >   *	-FDT_ERR_TRUNCATED, standard meanings
> >   */
> > -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> > -			const void *val, int len);
> > +static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
> > +				      const char *name, const void *val,
> > +				      int len)
> > +{
> > +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
> > +						    strlen(name), 0, val, len);
> 
> This effectively removes the error if len is not equal to the existing
> property length, so that needs to be put back.

So I'm not really sure what you want me to do.

I can't check for the property length, since it would prevent that
function from working, I can't check for the length + index, since we
might update only a few bytes in the middle, and we want to keep that
error case.

Or should I just forgive about merging the two functions and just
duplicate the two?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/63db912e/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-27  9:16       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27  9:16 UTC (permalink / raw)
  To: David Gibson
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 3617 bytes --]

On Mon, Jun 27, 2016 at 01:45:11AM +1000, David Gibson wrote:
> On Fri, Jun 24, 2016 at 04:27:52PM +0200, Maxime Ripard wrote:
> > Add a function to modify inplace a property starting from a given index.
> > 
> > This is especially useful when the property is an array of values, and you
> > want to update one of them without changing the DT size.
> > 
> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > ---
> >  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
> >  lib/libfdt/fdt_wip.c | 13 ++++++++-----
> >  2 files changed, 39 insertions(+), 8 deletions(-)
> > 
> > diff --git a/include/libfdt.h b/include/libfdt.h
> > index 4643be5adf39..2c8a42bcb667 100644
> > --- a/include/libfdt.h
> > +++ b/include/libfdt.h
> > @@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> >  /* Write-in-place functions                                           */
> >  /**********************************************************************/
> >  
> > +/**
> > + * fdt_setprop_inplace_namelen_by_index - change a property's value,
> > + *                                        but not its size
> > + * @fdt: pointer to the device tree blob
> > + * @nodeoffset: offset of the node whose property to change
> > + * @name: name of the property to change
> > + * @namelen: number of characters of name to consider
> > + * @index: index of the property to change in the array
> > + * @val: pointer to data to replace the property value with
> > + * @len: length of the property value
> > + *
> > + * Identical to fdt_setprop_inplace(), but modifies the given property
> > + * starting from the given index, and using only the first characters
> > + * of the name. It is useful when you want to manipulate only one value of
> > + * an array and you have a string that doesn't end with \0.
> > + */
> > +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> > +					 const char *name, int namelen,
> > +					 uint32_t index, const void *val,
> > +					 int len);
> 
> This looks like a good addition to upstream, but I don't like the
> name.  I'd suggest fdt_setprop_inplace_namelen_partial() because it
> only overwrite part of the existing property value.

Ack.

> > +
> >  /**
> >   * fdt_setprop_inplace - change a property's value, but not its size
> >   * @fdt: pointer to the device tree blob
> > @@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> >   *	-FDT_ERR_BADSTRUCTURE,
> >   *	-FDT_ERR_TRUNCATED, standard meanings
> >   */
> > -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> > -			const void *val, int len);
> > +static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
> > +				      const char *name, const void *val,
> > +				      int len)
> > +{
> > +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
> > +						    strlen(name), 0, val, len);
> 
> This effectively removes the error if len is not equal to the existing
> property length, so that needs to be put back.

So I'm not really sure what you want me to do.

I can't check for the property length, since it would prevent that
function from working, I can't check for the length + index, since we
might update only a few bytes in the middle, and we want to keep that
error case.

Or should I just forgive about merging the two functions and just
duplicate the two?

Thanks,
Maxime

-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-27 11:40       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27 11:40 UTC (permalink / raw)
  To: u-boot

Hi David,

On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
> > +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> > +{
> > +	const uint32_t *val;
> > +	int len;
> > +
> > +	val = fdt_getprop(fdto, fragment, "target", &len);
> > +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> > +		return 0;
> 
> This doesn't distinguish between a missing property (which may
> indicate a valid overlay using a target-path or some other method)
> and a badly formatted 'target' property, which is definitely an error
> in the overlay.
> 
> I think those should be treated differently.

AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
to cover the two cases, we would need to have some error code, but
that doesn't really work with returning a uint32_t.

Or maybe we can simply remove all the checks but the missing property,
and let fdt_node_offset_by_phandle deal with the improper values?

> 
> > +	return fdt32_to_cpu(*val);
> > +}
> > +
> > +static int overlay_get_target(const void *fdt, const void *fdto,
> > +			      int fragment)
> > +{
> > +	uint32_t phandle;
> > +	const char *path;
> > +
> > +	/* Try first to do a phandle based lookup */
> > +	phandle = overlay_get_target_phandle(fdto, fragment);
> > +	if (phandle)
> > +		return fdt_node_offset_by_phandle(fdt, phandle);
> > +
> > +	/* And then a path based lookup */
> > +	path = fdt_getprop(fdto, fragment, "target-path", NULL);
> > +	if (!path)
> > +		return -FDT_ERR_NOTFOUND;
> > +
> > +	return fdt_path_offset(fdt, path);
> > +}
> > +
> > +static int overlay_phandle_add_offset(void *fdt, int node,
> > +				      const char *name, uint32_t delta)
> > +{
> > +	const uint32_t *val;
> > +	uint32_t adj_val;
> > +	int len;
> > +
> > +	val = fdt_getprop(fdt, node, name, &len);
> > +	if (!val)
> > +		return len;
> > +
> > +	if (len != sizeof(*val))
> > +		return -FDT_ERR_BADSTRUCTURE;
> > +
> > +	adj_val = fdt32_to_cpu(*val);
> > +	adj_val += delta;
> 
> You should probably check for overflow here.
> 
> > +
> > +	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> > +}
> > +
> > +static int overlay_adjust_node_phandles(void *fdto, int node,
> > +					uint32_t delta)
> > +{
> > +	bool found = false;
> > +	int child;
> > +	int ret;
> > +
> > +	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > +		return ret;
> > +
> > +	if (!ret)
> > +		found = true;
> > +
> > +	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > +		return ret;
> 
> I think the check for phandle vs. linux,phandle should be folded into
> overlay_phandle_add_offset().

I created overlay_phandle_add_offset to avoid duplicating the getprop,
offset, setprop, pattern which I don't think is a good idea.

And we'll have to have that kind of errors construct anyway to know if
we modified any of the two, which is a success, or none, which is a
failure.

> > +	/*
> > +	 * If neither phandle nor linux,phandle have been found return
> > +	 * an error.
> > +	 */
> > +	if (!found && !ret)
> > +		return ret;
> > +
> > +	fdt_for_each_subnode(fdto, child, node)
> > +		overlay_adjust_node_phandles(fdto, child, delta);
> > +
> > +	return 0;
> > +}
> > +
> > +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> > +{
> > +	/*
> > +	 * Start adjusting the phandles from the overlay root
> > +	 */
> > +	return overlay_adjust_node_phandles(fdto, 0, delta);
> > +}
> > +
> > +static int overlay_update_local_node_references(void *fdto,
> > +						int tree_node,
> > +						int fixup_node,
> > +						uint32_t delta)
> > +{
> > +	int fixup_prop;
> > +	int fixup_child;
> > +	int ret;
> > +
> > +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> > +		const uint32_t *val = NULL;
> > +		uint32_t adj_val, index;
> > +		const char *name;
> > +		int fixup_len;
> > +		int tree_len;
> > +
> > +		val = fdt_getprop_by_offset(fdto, fixup_prop,
> > +					    &name, &fixup_len);
> > +		if (!val)
> > +			return fixup_len;
> > +		index = fdt32_to_cpu(*val);
> 
> This still doesn't handle the case of multiple fixups within the same
> property.  That would be entirely plausible for something like an
> interrupt-map property.

Good point, I'll fix that and add a test case for it.

> > +		val = fdt_getprop(fdto, tree_node, name, &tree_len);
> > +		if (!val)
> > +			return tree_len;
> > +
> > +		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
> 
> phandle values need not be aligned within the property containint them
> (e.g. properties which mix strings and integer values).  So you're
> going to need to work directly with a byte offset here.

I didn't even know it was something that was valid.

It would probably require a temporary variable and a memcpy though to
deal with architectures that cannot do unaligned accesses.

> 
> > +		adj_val += delta;
> > +		adj_val = cpu_to_fdt32(adj_val);
> > +
> > +		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> > +							   name, strlen(name),
> > +							   index, &adj_val,
> > +							   sizeof(adj_val));
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> > +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> > +							    NULL);
> > +		int tree_child;
> > +
> > +		tree_child = fdt_subnode_offset(fdto, tree_node,
> > +						fixup_child_name);
> > +		if (tree_child < 0)
> > +			return tree_child;
> > +
> > +		ret = overlay_update_local_node_references(fdto,
> > +							   tree_child,
> > +							   fixup_child,
> > +							   delta);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int overlay_update_local_references(void *dto, uint32_t delta)
> > +{
> > +	int fixups;
> > +
> > +	fixups = fdt_path_offset(dto, "/__local_fixups__");
> > +	if (fixups < 0) {
> > +		/*
> > +		 * There's no local phandles to adjust, bail out
> > +		 */
> > +		if (fixups == -FDT_ERR_NOTFOUND)
> > +			return 0;
> > +
> > +		return fixups;
> > +	}
> > +
> > +	/*
> > +	 * Update our local references from the root of the tree
> > +	 */
> > +	return overlay_update_local_node_references(dto, 0, fixups,
> > +						    delta);
> > +}
> > +
> > +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> > +				     int symbols_off,
> > +				     const char *path, uint32_t path_len,
> > +				     const char *name, uint32_t name_len,
> > +				     int index, const char *label)
> > +{
> > +	const char *symbol_path;
> > +	uint32_t phandle;
> > +	int symbol_off, fixup_off;
> > +	int prop_len;
> > +
> > +	symbol_path = fdt_getprop(fdt, symbols_off, label,
> > +				  &prop_len);
> > +	if (!symbol_path)
> > +		return -FDT_ERR_NOTFOUND;
> > +
> > +	symbol_off = fdt_path_offset(fdt, symbol_path);
> > +	if (symbol_off < 0)
> > +		return symbol_off;
> > +
> > +	phandle = fdt_get_phandle(fdt, symbol_off);
> > +	if (!phandle)
> > +		return -FDT_ERR_NOTFOUND;
> > +
> > +	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> > +	if (fixup_off < 0)
> > +		return fixup_off;
> > +
> > +	phandle = cpu_to_fdt32(phandle);
> > +	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> > +						    name, name_len, index,
> > +						    &phandle, sizeof(phandle));
> 
> This will be broken on BE systems because fdt_get_phandle() byteswaps
> to native order, but setprop_inplace doesn't byteswap back (because
> it's input is a byte array, not a u32).

Hmmmm, so calling cpu_to_fdt32 is not enough? I'm not sure what the
proper fix for that would be.

> > +};
> > +
> > +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> > +				 int property)
> > +{
> > +	const char *value;
> > +	const char *label;
> > +	int len;
> > +
> > +	value = fdt_getprop_by_offset(fdto, property,
> > +				      &label, &len);
> > +	if (!value)
> > +		return len;
> > +
> > +	do {
> > +		const char *prop_string = value;
> > +		const char *path, *name;
> > +		uint32_t path_len, name_len;
> > +		char *sep, *endptr;
> > +		int index;
> > +		int ret;
> > +
> > +		path = prop_string;
> > +		sep = strchr(prop_string, ':');
> > +		path_len = sep - path;
> 
> You need to check for strchr() returning NULL (indicating a badly
> formatted fixup missing a separator).
> 
> Also... strchr() is not safe.  Again, if the fixup string is badly
> formatted and doesn't have a terminating \0, this could overrun, so
> you want memchr() instead.

Ok

> > +		name = sep + 1;
> > +		sep = strchr(name, ':');
> > +		name_len = sep - name;
> 
> And again.
> 
> > +		index = strtoul(sep + 1, &endptr, 10);
> > +		if (endptr <= (sep + 1))
> > +			return -FDT_ERR_BADSTRUCTURE;
> 
> IIRC the index value is supposed to go to the end of that portion of
> the fixup, so you should be able to check for *endptr == '\0'.
> 
> Except.. strtoul() could also overrun if the fixup property doesn't
> contain a \0 like it should.
> 
> So I think you'd be better off using a memchr() (or strnlen()) to
> search for the \0 before you attempt parsing the innards of a single
> fixup string.

Ok

> Ugh.  I hate that we're parsing text numbers in decimal here, but
> we're pretty much stuck with that format here.  Doubly so that it's a
> gratuitously different way of encoding the (node, property, offset)
> tuple from local_fixups.

I'm not sure to get what you're saying here. Is that a general remark
on the format used by the overlays, or an hint that my code should be
reworked to deal with this differently?

> 
> > +		index = strtoul(sep + 1, &endptr, 10);
> > +		if (endptr <= (sep + 1))
> > +			return -FDT_ERR_BADSTRUCTURE;
> > +
> > +		len -= strlen(prop_string) + 1;
> > +		value += strlen(prop_string) + 1;
> 
> Please don't double call strlen() on the same string - remember it's
> O(n) in C.

Ok

> > +
> > +		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> > +						path, path_len, name, name_len,
> > +						index, label);
> > +		if (ret)
> > +			return ret;
> > +	} while (len > 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int overlay_fixup_phandles(void *dt, void *dto)
> > +{
> > +	int fixups_off, symbols_off;
> > +	int property;
> > +
> > +	symbols_off = fdt_path_offset(dt, "/__symbols__");
> > +	fixups_off = fdt_path_offset(dto, "/__fixups__");
> > +
> > +	fdt_for_each_property_offset(property, dto, fixups_off)
> > +		overlay_fixup_phandle(dt, dto, symbols_off, property);
> > +
> > +	return 0;
> > +}
> > +
> > +static int apply_overlay_node(void *dt, int target,
> > +			      void *dto, int overlay)
> 
> I think 'overlay' should be 'fragment' here for consistency?

Ok.

> > +{
> > +	int property;
> > +	int node;
> > +
> > +	fdt_for_each_property_offset(property, dto, overlay) {
> > +		const char *name;
> > +		const void *prop;
> > +		int prop_len;
> > +		int ret;
> > +
> > +		prop = fdt_getprop_by_offset(dto, property, &name,
> > +					     &prop_len);
> > +		if (!prop)
> > +			return -FDT_ERR_INTERNAL;
> 
> Actually, you probably should check the error code returned in
> prop_len.  Getting a NOTFOUND would indicate an internal error, but
> you could also get BADSTRUCTURE or similar errors which would indicate
> an error in input.

Ok.

> > +int fdt_overlay_apply(void *fdt, void *fdto)
> > +{
> > +	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> > +	int ret;
> > +
> > +	FDT_CHECK_HEADER(fdt);
> > +	FDT_CHECK_HEADER(fdto);
> > +
> > +	ret = overlay_adjust_local_phandles(fdto, delta);
> > +	if (ret)
> > +		goto err;
> > +
> > +	ret = overlay_update_local_references(fdto, delta);
> > +	if (ret)
> > +		goto err;
> > +
> > +	ret = overlay_fixup_phandles(fdt, fdto);
> > +	if (ret)
> > +		goto err;
> > +
> > +	ret = overlay_merge(fdt, fdto);
> > +	if (!ret)
> > +		goto out;
> > +
> > +err:
> 
> This is a confusing use of gotos - this looks like it is in the exit
> path for both success and failure cases, but it's not due to the
> easy-to-miss goto out above.

I know, but I couldn't really come up with something better to avoid
code duplication.

Or maybe it's too small to care?

Thanks a lot for your review,
Maxime



-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160627/9a2bda55/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-27 11:40       ` Maxime Ripard
  0 siblings, 0 replies; 90+ messages in thread
From: Maxime Ripard @ 2016-06-27 11:40 UTC (permalink / raw)
  To: David Gibson
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 12651 bytes --]

Hi David,

On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
> > +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> > +{
> > +	const uint32_t *val;
> > +	int len;
> > +
> > +	val = fdt_getprop(fdto, fragment, "target", &len);
> > +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> > +		return 0;
> 
> This doesn't distinguish between a missing property (which may
> indicate a valid overlay using a target-path or some other method)
> and a badly formatted 'target' property, which is definitely an error
> in the overlay.
> 
> I think those should be treated differently.

AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
to cover the two cases, we would need to have some error code, but
that doesn't really work with returning a uint32_t.

Or maybe we can simply remove all the checks but the missing property,
and let fdt_node_offset_by_phandle deal with the improper values?

> 
> > +	return fdt32_to_cpu(*val);
> > +}
> > +
> > +static int overlay_get_target(const void *fdt, const void *fdto,
> > +			      int fragment)
> > +{
> > +	uint32_t phandle;
> > +	const char *path;
> > +
> > +	/* Try first to do a phandle based lookup */
> > +	phandle = overlay_get_target_phandle(fdto, fragment);
> > +	if (phandle)
> > +		return fdt_node_offset_by_phandle(fdt, phandle);
> > +
> > +	/* And then a path based lookup */
> > +	path = fdt_getprop(fdto, fragment, "target-path", NULL);
> > +	if (!path)
> > +		return -FDT_ERR_NOTFOUND;
> > +
> > +	return fdt_path_offset(fdt, path);
> > +}
> > +
> > +static int overlay_phandle_add_offset(void *fdt, int node,
> > +				      const char *name, uint32_t delta)
> > +{
> > +	const uint32_t *val;
> > +	uint32_t adj_val;
> > +	int len;
> > +
> > +	val = fdt_getprop(fdt, node, name, &len);
> > +	if (!val)
> > +		return len;
> > +
> > +	if (len != sizeof(*val))
> > +		return -FDT_ERR_BADSTRUCTURE;
> > +
> > +	adj_val = fdt32_to_cpu(*val);
> > +	adj_val += delta;
> 
> You should probably check for overflow here.
> 
> > +
> > +	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> > +}
> > +
> > +static int overlay_adjust_node_phandles(void *fdto, int node,
> > +					uint32_t delta)
> > +{
> > +	bool found = false;
> > +	int child;
> > +	int ret;
> > +
> > +	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > +		return ret;
> > +
> > +	if (!ret)
> > +		found = true;
> > +
> > +	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > +		return ret;
> 
> I think the check for phandle vs. linux,phandle should be folded into
> overlay_phandle_add_offset().

I created overlay_phandle_add_offset to avoid duplicating the getprop,
offset, setprop, pattern which I don't think is a good idea.

And we'll have to have that kind of errors construct anyway to know if
we modified any of the two, which is a success, or none, which is a
failure.

> > +	/*
> > +	 * If neither phandle nor linux,phandle have been found return
> > +	 * an error.
> > +	 */
> > +	if (!found && !ret)
> > +		return ret;
> > +
> > +	fdt_for_each_subnode(fdto, child, node)
> > +		overlay_adjust_node_phandles(fdto, child, delta);
> > +
> > +	return 0;
> > +}
> > +
> > +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> > +{
> > +	/*
> > +	 * Start adjusting the phandles from the overlay root
> > +	 */
> > +	return overlay_adjust_node_phandles(fdto, 0, delta);
> > +}
> > +
> > +static int overlay_update_local_node_references(void *fdto,
> > +						int tree_node,
> > +						int fixup_node,
> > +						uint32_t delta)
> > +{
> > +	int fixup_prop;
> > +	int fixup_child;
> > +	int ret;
> > +
> > +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> > +		const uint32_t *val = NULL;
> > +		uint32_t adj_val, index;
> > +		const char *name;
> > +		int fixup_len;
> > +		int tree_len;
> > +
> > +		val = fdt_getprop_by_offset(fdto, fixup_prop,
> > +					    &name, &fixup_len);
> > +		if (!val)
> > +			return fixup_len;
> > +		index = fdt32_to_cpu(*val);
> 
> This still doesn't handle the case of multiple fixups within the same
> property.  That would be entirely plausible for something like an
> interrupt-map property.

Good point, I'll fix that and add a test case for it.

> > +		val = fdt_getprop(fdto, tree_node, name, &tree_len);
> > +		if (!val)
> > +			return tree_len;
> > +
> > +		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
> 
> phandle values need not be aligned within the property containint them
> (e.g. properties which mix strings and integer values).  So you're
> going to need to work directly with a byte offset here.

I didn't even know it was something that was valid.

It would probably require a temporary variable and a memcpy though to
deal with architectures that cannot do unaligned accesses.

> 
> > +		adj_val += delta;
> > +		adj_val = cpu_to_fdt32(adj_val);
> > +
> > +		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> > +							   name, strlen(name),
> > +							   index, &adj_val,
> > +							   sizeof(adj_val));
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> > +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> > +							    NULL);
> > +		int tree_child;
> > +
> > +		tree_child = fdt_subnode_offset(fdto, tree_node,
> > +						fixup_child_name);
> > +		if (tree_child < 0)
> > +			return tree_child;
> > +
> > +		ret = overlay_update_local_node_references(fdto,
> > +							   tree_child,
> > +							   fixup_child,
> > +							   delta);
> > +		if (ret)
> > +			return ret;
> > +	}
> > +
> > +	return 0;
> > +}
> > +
> > +static int overlay_update_local_references(void *dto, uint32_t delta)
> > +{
> > +	int fixups;
> > +
> > +	fixups = fdt_path_offset(dto, "/__local_fixups__");
> > +	if (fixups < 0) {
> > +		/*
> > +		 * There's no local phandles to adjust, bail out
> > +		 */
> > +		if (fixups == -FDT_ERR_NOTFOUND)
> > +			return 0;
> > +
> > +		return fixups;
> > +	}
> > +
> > +	/*
> > +	 * Update our local references from the root of the tree
> > +	 */
> > +	return overlay_update_local_node_references(dto, 0, fixups,
> > +						    delta);
> > +}
> > +
> > +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> > +				     int symbols_off,
> > +				     const char *path, uint32_t path_len,
> > +				     const char *name, uint32_t name_len,
> > +				     int index, const char *label)
> > +{
> > +	const char *symbol_path;
> > +	uint32_t phandle;
> > +	int symbol_off, fixup_off;
> > +	int prop_len;
> > +
> > +	symbol_path = fdt_getprop(fdt, symbols_off, label,
> > +				  &prop_len);
> > +	if (!symbol_path)
> > +		return -FDT_ERR_NOTFOUND;
> > +
> > +	symbol_off = fdt_path_offset(fdt, symbol_path);
> > +	if (symbol_off < 0)
> > +		return symbol_off;
> > +
> > +	phandle = fdt_get_phandle(fdt, symbol_off);
> > +	if (!phandle)
> > +		return -FDT_ERR_NOTFOUND;
> > +
> > +	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> > +	if (fixup_off < 0)
> > +		return fixup_off;
> > +
> > +	phandle = cpu_to_fdt32(phandle);
> > +	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> > +						    name, name_len, index,
> > +						    &phandle, sizeof(phandle));
> 
> This will be broken on BE systems because fdt_get_phandle() byteswaps
> to native order, but setprop_inplace doesn't byteswap back (because
> it's input is a byte array, not a u32).

Hmmmm, so calling cpu_to_fdt32 is not enough? I'm not sure what the
proper fix for that would be.

> > +};
> > +
> > +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> > +				 int property)
> > +{
> > +	const char *value;
> > +	const char *label;
> > +	int len;
> > +
> > +	value = fdt_getprop_by_offset(fdto, property,
> > +				      &label, &len);
> > +	if (!value)
> > +		return len;
> > +
> > +	do {
> > +		const char *prop_string = value;
> > +		const char *path, *name;
> > +		uint32_t path_len, name_len;
> > +		char *sep, *endptr;
> > +		int index;
> > +		int ret;
> > +
> > +		path = prop_string;
> > +		sep = strchr(prop_string, ':');
> > +		path_len = sep - path;
> 
> You need to check for strchr() returning NULL (indicating a badly
> formatted fixup missing a separator).
> 
> Also... strchr() is not safe.  Again, if the fixup string is badly
> formatted and doesn't have a terminating \0, this could overrun, so
> you want memchr() instead.

Ok

> > +		name = sep + 1;
> > +		sep = strchr(name, ':');
> > +		name_len = sep - name;
> 
> And again.
> 
> > +		index = strtoul(sep + 1, &endptr, 10);
> > +		if (endptr <= (sep + 1))
> > +			return -FDT_ERR_BADSTRUCTURE;
> 
> IIRC the index value is supposed to go to the end of that portion of
> the fixup, so you should be able to check for *endptr == '\0'.
> 
> Except.. strtoul() could also overrun if the fixup property doesn't
> contain a \0 like it should.
> 
> So I think you'd be better off using a memchr() (or strnlen()) to
> search for the \0 before you attempt parsing the innards of a single
> fixup string.

Ok

> Ugh.  I hate that we're parsing text numbers in decimal here, but
> we're pretty much stuck with that format here.  Doubly so that it's a
> gratuitously different way of encoding the (node, property, offset)
> tuple from local_fixups.

I'm not sure to get what you're saying here. Is that a general remark
on the format used by the overlays, or an hint that my code should be
reworked to deal with this differently?

> 
> > +		index = strtoul(sep + 1, &endptr, 10);
> > +		if (endptr <= (sep + 1))
> > +			return -FDT_ERR_BADSTRUCTURE;
> > +
> > +		len -= strlen(prop_string) + 1;
> > +		value += strlen(prop_string) + 1;
> 
> Please don't double call strlen() on the same string - remember it's
> O(n) in C.

Ok

> > +
> > +		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> > +						path, path_len, name, name_len,
> > +						index, label);
> > +		if (ret)
> > +			return ret;
> > +	} while (len > 0);
> > +
> > +	return 0;
> > +}
> > +
> > +static int overlay_fixup_phandles(void *dt, void *dto)
> > +{
> > +	int fixups_off, symbols_off;
> > +	int property;
> > +
> > +	symbols_off = fdt_path_offset(dt, "/__symbols__");
> > +	fixups_off = fdt_path_offset(dto, "/__fixups__");
> > +
> > +	fdt_for_each_property_offset(property, dto, fixups_off)
> > +		overlay_fixup_phandle(dt, dto, symbols_off, property);
> > +
> > +	return 0;
> > +}
> > +
> > +static int apply_overlay_node(void *dt, int target,
> > +			      void *dto, int overlay)
> 
> I think 'overlay' should be 'fragment' here for consistency?

Ok.

> > +{
> > +	int property;
> > +	int node;
> > +
> > +	fdt_for_each_property_offset(property, dto, overlay) {
> > +		const char *name;
> > +		const void *prop;
> > +		int prop_len;
> > +		int ret;
> > +
> > +		prop = fdt_getprop_by_offset(dto, property, &name,
> > +					     &prop_len);
> > +		if (!prop)
> > +			return -FDT_ERR_INTERNAL;
> 
> Actually, you probably should check the error code returned in
> prop_len.  Getting a NOTFOUND would indicate an internal error, but
> you could also get BADSTRUCTURE or similar errors which would indicate
> an error in input.

Ok.

> > +int fdt_overlay_apply(void *fdt, void *fdto)
> > +{
> > +	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> > +	int ret;
> > +
> > +	FDT_CHECK_HEADER(fdt);
> > +	FDT_CHECK_HEADER(fdto);
> > +
> > +	ret = overlay_adjust_local_phandles(fdto, delta);
> > +	if (ret)
> > +		goto err;
> > +
> > +	ret = overlay_update_local_references(fdto, delta);
> > +	if (ret)
> > +		goto err;
> > +
> > +	ret = overlay_fixup_phandles(fdt, fdto);
> > +	if (ret)
> > +		goto err;
> > +
> > +	ret = overlay_merge(fdt, fdto);
> > +	if (!ret)
> > +		goto out;
> > +
> > +err:
> 
> This is a confusing use of gotos - this looks like it is in the exit
> path for both success and failure cases, but it's not due to the
> easy-to-miss goto out above.

I know, but I couldn't really come up with something better to avoid
code duplication.

Or maybe it's too small to care?

Thanks a lot for your review,
Maxime



-- 
Maxime Ripard, Free Electrons
Embedded Linux, Kernel and Android engineering
http://free-electrons.com

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 04/12] libfdt: Add new headers and defines
  2016-06-27  7:25       ` Maxime Ripard
@ 2016-06-28  3:02         ` David Gibson
  -1 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-28  3:02 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 27, 2016 at 09:25:27AM +0200, Maxime Ripard wrote:
> Hi David,
> 
> On Mon, Jun 27, 2016 at 01:39:06AM +1000, David Gibson wrote:
> > On Fri, Jun 24, 2016 at 04:27:49PM +0200, Maxime Ripard wrote:
> > > The libfdt overlay support introduces a bunch of new includes and
> > > functions.
> > > 
> > > Make sure we are able to build it by adding the needed glue.
> > > 
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > 
> > Is this intended only for downstream u-boot only, or also for upstream
> > libfdt?
> 
> U-Boot only.
> 
> > If it's u-boot only, you don't really need the #ifdef UBOOT.
> 
> Unfortunately, libfdt_env.h is also included by some userspace tools
> in U-Boot, which make use of strtoul while simple_strtoul is not
> defined there (and we should rely on libc's anyway), leading to
> link errors.

Ah, ok.  The ifdef makes sense then.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160628/db9d594b/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 04/12] libfdt: Add new headers and defines
@ 2016-06-28  3:02         ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-28  3:02 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 1139 bytes --]

On Mon, Jun 27, 2016 at 09:25:27AM +0200, Maxime Ripard wrote:
> Hi David,
> 
> On Mon, Jun 27, 2016 at 01:39:06AM +1000, David Gibson wrote:
> > On Fri, Jun 24, 2016 at 04:27:49PM +0200, Maxime Ripard wrote:
> > > The libfdt overlay support introduces a bunch of new includes and
> > > functions.
> > > 
> > > Make sure we are able to build it by adding the needed glue.
> > > 
> > > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > 
> > Is this intended only for downstream u-boot only, or also for upstream
> > libfdt?
> 
> U-Boot only.
> 
> > If it's u-boot only, you don't really need the #ifdef UBOOT.
> 
> Unfortunately, libfdt_env.h is also included by some userspace tools
> in U-Boot, which make use of strtoul while simple_strtoul is not
> defined there (and we should rely on libc's anyway), leading to
> link errors.

Ah, ok.  The ifdef makes sense then.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
  2016-06-27  9:16       ` Maxime Ripard
@ 2016-06-28  3:05         ` David Gibson
  -1 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-28  3:05 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 27, 2016 at 11:16:52AM +0200, Maxime Ripard wrote:
> On Mon, Jun 27, 2016 at 01:45:11AM +1000, David Gibson wrote:
> > On Fri, Jun 24, 2016 at 04:27:52PM +0200, Maxime Ripard wrote:
> > > Add a function to modify inplace a property starting from a given index.
> > > 
> > > This is especially useful when the property is an array of values, and you
> > > want to update one of them without changing the DT size.
> > > 
> > > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
> > > ---
> > >  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
> > >  lib/libfdt/fdt_wip.c | 13 ++++++++-----
> > >  2 files changed, 39 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/include/libfdt.h b/include/libfdt.h
> > > index 4643be5adf39..2c8a42bcb667 100644
> > > --- a/include/libfdt.h
> > > +++ b/include/libfdt.h
> > > @@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> > >  /* Write-in-place functions                                           */
> > >  /**********************************************************************/
> > >  
> > > +/**
> > > + * fdt_setprop_inplace_namelen_by_index - change a property's value,
> > > + *                                        but not its size
> > > + * @fdt: pointer to the device tree blob
> > > + * @nodeoffset: offset of the node whose property to change
> > > + * @name: name of the property to change
> > > + * @namelen: number of characters of name to consider
> > > + * @index: index of the property to change in the array
> > > + * @val: pointer to data to replace the property value with
> > > + * @len: length of the property value
> > > + *
> > > + * Identical to fdt_setprop_inplace(), but modifies the given property
> > > + * starting from the given index, and using only the first characters
> > > + * of the name. It is useful when you want to manipulate only one value of
> > > + * an array and you have a string that doesn't end with \0.
> > > + */
> > > +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> > > +					 const char *name, int namelen,
> > > +					 uint32_t index, const void *val,
> > > +					 int len);
> > 
> > This looks like a good addition to upstream, but I don't like the
> > name.  I'd suggest fdt_setprop_inplace_namelen_partial() because it
> > only overwrite part of the existing property value.
> 
> Ack.
> 
> > > +
> > >  /**
> > >   * fdt_setprop_inplace - change a property's value, but not its size
> > >   * @fdt: pointer to the device tree blob
> > > @@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> > >   *	-FDT_ERR_BADSTRUCTURE,
> > >   *	-FDT_ERR_TRUNCATED, standard meanings
> > >   */
> > > -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> > > -			const void *val, int len);
> > > +static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
> > > +				      const char *name, const void *val,
> > > +				      int len)
> > > +{
> > > +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
> > > +						    strlen(name), 0, val, len);
> > 
> > This effectively removes the error if len is not equal to the existing
> > property length, so that needs to be put back.
> 
> So I'm not really sure what you want me to do.
> 
> I can't check for the property length, since it would prevent that
> function from working, I can't check for the length + index, since we
> might update only a few bytes in the middle, and we want to keep that
> error case.
> 
> Or should I just forgive about merging the two functions and just
> duplicate the two?

No, what I'm suggesting is that fdt_setprop_inplace(), whether or not
it is implemented using fdt_setprop_inplace_partial() *also* checks
that the existing property length exactly matches the replacement
length, and fails otherwise.

Doing this without too much code duplication might involve a private
internal function, or maybe it's just simpler to duplicate.  But those
are the semantics they should have.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160628/931bac5e/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index
@ 2016-06-28  3:05         ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-28  3:05 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 4319 bytes --]

On Mon, Jun 27, 2016 at 11:16:52AM +0200, Maxime Ripard wrote:
> On Mon, Jun 27, 2016 at 01:45:11AM +1000, David Gibson wrote:
> > On Fri, Jun 24, 2016 at 04:27:52PM +0200, Maxime Ripard wrote:
> > > Add a function to modify inplace a property starting from a given index.
> > > 
> > > This is especially useful when the property is an array of values, and you
> > > want to update one of them without changing the DT size.
> > > 
> > > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
> > > ---
> > >  include/libfdt.h     | 34 +++++++++++++++++++++++++++++++---
> > >  lib/libfdt/fdt_wip.c | 13 ++++++++-----
> > >  2 files changed, 39 insertions(+), 8 deletions(-)
> > > 
> > > diff --git a/include/libfdt.h b/include/libfdt.h
> > > index 4643be5adf39..2c8a42bcb667 100644
> > > --- a/include/libfdt.h
> > > +++ b/include/libfdt.h
> > > @@ -1032,6 +1032,27 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> > >  /* Write-in-place functions                                           */
> > >  /**********************************************************************/
> > >  
> > > +/**
> > > + * fdt_setprop_inplace_namelen_by_index - change a property's value,
> > > + *                                        but not its size
> > > + * @fdt: pointer to the device tree blob
> > > + * @nodeoffset: offset of the node whose property to change
> > > + * @name: name of the property to change
> > > + * @namelen: number of characters of name to consider
> > > + * @index: index of the property to change in the array
> > > + * @val: pointer to data to replace the property value with
> > > + * @len: length of the property value
> > > + *
> > > + * Identical to fdt_setprop_inplace(), but modifies the given property
> > > + * starting from the given index, and using only the first characters
> > > + * of the name. It is useful when you want to manipulate only one value of
> > > + * an array and you have a string that doesn't end with \0.
> > > + */
> > > +int fdt_setprop_inplace_namelen_by_index(void *fdt, int nodeoffset,
> > > +					 const char *name, int namelen,
> > > +					 uint32_t index, const void *val,
> > > +					 int len);
> > 
> > This looks like a good addition to upstream, but I don't like the
> > name.  I'd suggest fdt_setprop_inplace_namelen_partial() because it
> > only overwrite part of the existing property value.
> 
> Ack.
> 
> > > +
> > >  /**
> > >   * fdt_setprop_inplace - change a property's value, but not its size
> > >   * @fdt: pointer to the device tree blob
> > > @@ -1060,8 +1081,13 @@ int fdt_size_cells(const void *fdt, int nodeoffset);
> > >   *	-FDT_ERR_BADSTRUCTURE,
> > >   *	-FDT_ERR_TRUNCATED, standard meanings
> > >   */
> > > -int fdt_setprop_inplace(void *fdt, int nodeoffset, const char *name,
> > > -			const void *val, int len);
> > > +static inline int fdt_setprop_inplace(void *fdt, int nodeoffset,
> > > +				      const char *name, const void *val,
> > > +				      int len)
> > > +{
> > > +	return fdt_setprop_inplace_namelen_by_index(fdt, nodeoffset, name,
> > > +						    strlen(name), 0, val, len);
> > 
> > This effectively removes the error if len is not equal to the existing
> > property length, so that needs to be put back.
> 
> So I'm not really sure what you want me to do.
> 
> I can't check for the property length, since it would prevent that
> function from working, I can't check for the length + index, since we
> might update only a few bytes in the middle, and we want to keep that
> error case.
> 
> Or should I just forgive about merging the two functions and just
> duplicate the two?

No, what I'm suggesting is that fdt_setprop_inplace(), whether or not
it is implemented using fdt_setprop_inplace_partial() *also* checks
that the existing property length exactly matches the replacement
length, and fails otherwise.

Doing this without too much code duplication might involve a private
internal function, or maybe it's just simpler to duplicate.  But those
are the semantics they should have.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
  2016-06-27 11:40       ` Maxime Ripard
@ 2016-06-28  3:12         ` David Gibson
  -1 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-28  3:12 UTC (permalink / raw)
  To: u-boot

On Mon, Jun 27, 2016 at 01:40:00PM +0200, Maxime Ripard wrote:
> Hi David,
> 
> On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
> > > +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> > > +{
> > > +	const uint32_t *val;
> > > +	int len;
> > > +
> > > +	val = fdt_getprop(fdto, fragment, "target", &len);
> > > +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> > > +		return 0;
> > 
> > This doesn't distinguish between a missing property (which may
> > indicate a valid overlay using a target-path or some other method)
> > and a badly formatted 'target' property, which is definitely an error
> > in the overlay.
> > 
> > I think those should be treated differently.
> 
> AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
> to cover the two cases, we would need to have some error code, but
> that doesn't really work with returning a uint32_t.

Actually phandles can have any value except 0xffffffff *or* 0.  So you
can use 0 for "couldn't find" and -1 for "badly formatted".

> Or maybe we can simply remove all the checks but the missing property,
> and let fdt_node_offset_by_phandle deal with the improper values?
> 
> > 
> > > +	return fdt32_to_cpu(*val);
> > > +}
> > > +
> > > +static int overlay_get_target(const void *fdt, const void *fdto,
> > > +			      int fragment)
> > > +{
> > > +	uint32_t phandle;
> > > +	const char *path;
> > > +
> > > +	/* Try first to do a phandle based lookup */
> > > +	phandle = overlay_get_target_phandle(fdto, fragment);
> > > +	if (phandle)
> > > +		return fdt_node_offset_by_phandle(fdt, phandle);
> > > +
> > > +	/* And then a path based lookup */
> > > +	path = fdt_getprop(fdto, fragment, "target-path", NULL);
> > > +	if (!path)
> > > +		return -FDT_ERR_NOTFOUND;
> > > +
> > > +	return fdt_path_offset(fdt, path);
> > > +}
> > > +
> > > +static int overlay_phandle_add_offset(void *fdt, int node,
> > > +				      const char *name, uint32_t delta)
> > > +{
> > > +	const uint32_t *val;
> > > +	uint32_t adj_val;
> > > +	int len;
> > > +
> > > +	val = fdt_getprop(fdt, node, name, &len);
> > > +	if (!val)
> > > +		return len;
> > > +
> > > +	if (len != sizeof(*val))
> > > +		return -FDT_ERR_BADSTRUCTURE;
> > > +
> > > +	adj_val = fdt32_to_cpu(*val);
> > > +	adj_val += delta;
> > 
> > You should probably check for overflow here.
> > 
> > > +
> > > +	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> > > +}
> > > +
> > > +static int overlay_adjust_node_phandles(void *fdto, int node,
> > > +					uint32_t delta)
> > > +{
> > > +	bool found = false;
> > > +	int child;
> > > +	int ret;
> > > +
> > > +	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> > > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > > +		return ret;
> > > +
> > > +	if (!ret)
> > > +		found = true;
> > > +
> > > +	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> > > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > > +		return ret;
> > 
> > I think the check for phandle vs. linux,phandle should be folded into
> > overlay_phandle_add_offset().
> 
> I created overlay_phandle_add_offset to avoid duplicating the getprop,
> offset, setprop, pattern which I don't think is a good idea.
> 
> And we'll have to have that kind of errors construct anyway to know if
> we modified any of the two, which is a success, or none, which is a
> failure.

Hm.. ok, you convinced me.

> > > +	/*
> > > +	 * If neither phandle nor linux,phandle have been found return
> > > +	 * an error.
> > > +	 */
> > > +	if (!found && !ret)
> > > +		return ret;
> > > +
> > > +	fdt_for_each_subnode(fdto, child, node)
> > > +		overlay_adjust_node_phandles(fdto, child, delta);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> > > +{
> > > +	/*
> > > +	 * Start adjusting the phandles from the overlay root
> > > +	 */
> > > +	return overlay_adjust_node_phandles(fdto, 0, delta);
> > > +}
> > > +
> > > +static int overlay_update_local_node_references(void *fdto,
> > > +						int tree_node,
> > > +						int fixup_node,
> > > +						uint32_t delta)
> > > +{
> > > +	int fixup_prop;
> > > +	int fixup_child;
> > > +	int ret;
> > > +
> > > +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> > > +		const uint32_t *val = NULL;
> > > +		uint32_t adj_val, index;
> > > +		const char *name;
> > > +		int fixup_len;
> > > +		int tree_len;
> > > +
> > > +		val = fdt_getprop_by_offset(fdto, fixup_prop,
> > > +					    &name, &fixup_len);
> > > +		if (!val)
> > > +			return fixup_len;
> > > +		index = fdt32_to_cpu(*val);
> > 
> > This still doesn't handle the case of multiple fixups within the same
> > property.  That would be entirely plausible for something like an
> > interrupt-map property.
> 
> Good point, I'll fix that and add a test case for it.
> 
> > > +		val = fdt_getprop(fdto, tree_node, name, &tree_len);
> > > +		if (!val)
> > > +			return tree_len;
> > > +
> > > +		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
> > 
> > phandle values need not be aligned within the property containint them
> > (e.g. properties which mix strings and integer values).  So you're
> > going to need to work directly with a byte offset here.
> 
> I didn't even know it was something that was valid.

I'm afraid so.  In general, property values are treated as packed
bytestrings and never have internal alignment constraints.

> It would probably require a temporary variable and a memcpy though to
> deal with architectures that cannot do unaligned accesses.

Alas, yes.  Make sure you put a comment there to explain this, because
it will appear unnecessary to people only familiar with archs that
allow unaligned access (which includes both x86 and Power).

> 
> > 
> > > +		adj_val += delta;
> > > +		adj_val = cpu_to_fdt32(adj_val);
> > > +
> > > +		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> > > +							   name, strlen(name),
> > > +							   index, &adj_val,
> > > +							   sizeof(adj_val));
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > > +	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> > > +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> > > +							    NULL);
> > > +		int tree_child;
> > > +
> > > +		tree_child = fdt_subnode_offset(fdto, tree_node,
> > > +						fixup_child_name);
> > > +		if (tree_child < 0)
> > > +			return tree_child;
> > > +
> > > +		ret = overlay_update_local_node_references(fdto,
> > > +							   tree_child,
> > > +							   fixup_child,
> > > +							   delta);
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int overlay_update_local_references(void *dto, uint32_t delta)
> > > +{
> > > +	int fixups;
> > > +
> > > +	fixups = fdt_path_offset(dto, "/__local_fixups__");
> > > +	if (fixups < 0) {
> > > +		/*
> > > +		 * There's no local phandles to adjust, bail out
> > > +		 */
> > > +		if (fixups == -FDT_ERR_NOTFOUND)
> > > +			return 0;
> > > +
> > > +		return fixups;
> > > +	}
> > > +
> > > +	/*
> > > +	 * Update our local references from the root of the tree
> > > +	 */
> > > +	return overlay_update_local_node_references(dto, 0, fixups,
> > > +						    delta);
> > > +}
> > > +
> > > +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> > > +				     int symbols_off,
> > > +				     const char *path, uint32_t path_len,
> > > +				     const char *name, uint32_t name_len,
> > > +				     int index, const char *label)
> > > +{
> > > +	const char *symbol_path;
> > > +	uint32_t phandle;
> > > +	int symbol_off, fixup_off;
> > > +	int prop_len;
> > > +
> > > +	symbol_path = fdt_getprop(fdt, symbols_off, label,
> > > +				  &prop_len);
> > > +	if (!symbol_path)
> > > +		return -FDT_ERR_NOTFOUND;
> > > +
> > > +	symbol_off = fdt_path_offset(fdt, symbol_path);
> > > +	if (symbol_off < 0)
> > > +		return symbol_off;
> > > +
> > > +	phandle = fdt_get_phandle(fdt, symbol_off);
> > > +	if (!phandle)
> > > +		return -FDT_ERR_NOTFOUND;
> > > +
> > > +	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> > > +	if (fixup_off < 0)
> > > +		return fixup_off;
> > > +
> > > +	phandle = cpu_to_fdt32(phandle);
> > > +	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> > > +						    name, name_len, index,
> > > +						    &phandle, sizeof(phandle));
> > 
> > This will be broken on BE systems because fdt_get_phandle() byteswaps
> > to native order, but setprop_inplace doesn't byteswap back (because
> > it's input is a byte array, not a u32).
> 
> Hmmmm, so calling cpu_to_fdt32 is not enough? I'm not sure what the
> proper fix for that would be.

Oh, sorry, I just missed the cpu_to_fdt32().

> > > +};
> > > +
> > > +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> > > +				 int property)
> > > +{
> > > +	const char *value;
> > > +	const char *label;
> > > +	int len;
> > > +
> > > +	value = fdt_getprop_by_offset(fdto, property,
> > > +				      &label, &len);
> > > +	if (!value)
> > > +		return len;
> > > +
> > > +	do {
> > > +		const char *prop_string = value;
> > > +		const char *path, *name;
> > > +		uint32_t path_len, name_len;
> > > +		char *sep, *endptr;
> > > +		int index;
> > > +		int ret;
> > > +
> > > +		path = prop_string;
> > > +		sep = strchr(prop_string, ':');
> > > +		path_len = sep - path;
> > 
> > You need to check for strchr() returning NULL (indicating a badly
> > formatted fixup missing a separator).
> > 
> > Also... strchr() is not safe.  Again, if the fixup string is badly
> > formatted and doesn't have a terminating \0, this could overrun, so
> > you want memchr() instead.
> 
> Ok
> 
> > > +		name = sep + 1;
> > > +		sep = strchr(name, ':');
> > > +		name_len = sep - name;
> > 
> > And again.
> > 
> > > +		index = strtoul(sep + 1, &endptr, 10);
> > > +		if (endptr <= (sep + 1))
> > > +			return -FDT_ERR_BADSTRUCTURE;
> > 
> > IIRC the index value is supposed to go to the end of that portion of
> > the fixup, so you should be able to check for *endptr == '\0'.
> > 
> > Except.. strtoul() could also overrun if the fixup property doesn't
> > contain a \0 like it should.
> > 
> > So I think you'd be better off using a memchr() (or strnlen()) to
> > search for the \0 before you attempt parsing the innards of a single
> > fixup string.
> 
> Ok
> 
> > Ugh.  I hate that we're parsing text numbers in decimal here, but
> > we're pretty much stuck with that format here.  Doubly so that it's a
> > gratuitously different way of encoding the (node, property, offset)
> > tuple from local_fixups.
> 
> I'm not sure to get what you're saying here. Is that a general remark
> on the format used by the overlays, or an hint that my code should be
> reworked to deal with this differently?

Just a general remark on the format.

> 
> > 
> > > +		index = strtoul(sep + 1, &endptr, 10);
> > > +		if (endptr <= (sep + 1))
> > > +			return -FDT_ERR_BADSTRUCTURE;
> > > +
> > > +		len -= strlen(prop_string) + 1;
> > > +		value += strlen(prop_string) + 1;
> > 
> > Please don't double call strlen() on the same string - remember it's
> > O(n) in C.
> 
> Ok
> 
> > > +
> > > +		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> > > +						path, path_len, name, name_len,
> > > +						index, label);
> > > +		if (ret)
> > > +			return ret;
> > > +	} while (len > 0);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int overlay_fixup_phandles(void *dt, void *dto)
> > > +{
> > > +	int fixups_off, symbols_off;
> > > +	int property;
> > > +
> > > +	symbols_off = fdt_path_offset(dt, "/__symbols__");
> > > +	fixups_off = fdt_path_offset(dto, "/__fixups__");
> > > +
> > > +	fdt_for_each_property_offset(property, dto, fixups_off)
> > > +		overlay_fixup_phandle(dt, dto, symbols_off, property);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int apply_overlay_node(void *dt, int target,
> > > +			      void *dto, int overlay)
> > 
> > I think 'overlay' should be 'fragment' here for consistency?
> 
> Ok.
> 
> > > +{
> > > +	int property;
> > > +	int node;
> > > +
> > > +	fdt_for_each_property_offset(property, dto, overlay) {
> > > +		const char *name;
> > > +		const void *prop;
> > > +		int prop_len;
> > > +		int ret;
> > > +
> > > +		prop = fdt_getprop_by_offset(dto, property, &name,
> > > +					     &prop_len);
> > > +		if (!prop)
> > > +			return -FDT_ERR_INTERNAL;
> > 
> > Actually, you probably should check the error code returned in
> > prop_len.  Getting a NOTFOUND would indicate an internal error, but
> > you could also get BADSTRUCTURE or similar errors which would indicate
> > an error in input.
> 
> Ok.
> 
> > > +int fdt_overlay_apply(void *fdt, void *fdto)
> > > +{
> > > +	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> > > +	int ret;
> > > +
> > > +	FDT_CHECK_HEADER(fdt);
> > > +	FDT_CHECK_HEADER(fdto);
> > > +
> > > +	ret = overlay_adjust_local_phandles(fdto, delta);
> > > +	if (ret)
> > > +		goto err;
> > > +
> > > +	ret = overlay_update_local_references(fdto, delta);
> > > +	if (ret)
> > > +		goto err;
> > > +
> > > +	ret = overlay_fixup_phandles(fdt, fdto);
> > > +	if (ret)
> > > +		goto err;
> > > +
> > > +	ret = overlay_merge(fdt, fdto);
> > > +	if (!ret)
> > > +		goto out;
> > > +
> > > +err:
> > 
> > This is a confusing use of gotos - this looks like it is in the exit
> > path for both success and failure cases, but it's not due to the
> > easy-to-miss goto out above.
> 
> I know, but I couldn't really come up with something better to avoid
> code duplication.
> 
> Or maybe it's too small to care?

I think a little duplicated code is the lesser evil here.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160628/afa64d39/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-28  3:12         ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-28  3:12 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

[-- Attachment #1: Type: text/plain, Size: 14247 bytes --]

On Mon, Jun 27, 2016 at 01:40:00PM +0200, Maxime Ripard wrote:
> Hi David,
> 
> On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
> > > +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> > > +{
> > > +	const uint32_t *val;
> > > +	int len;
> > > +
> > > +	val = fdt_getprop(fdto, fragment, "target", &len);
> > > +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> > > +		return 0;
> > 
> > This doesn't distinguish between a missing property (which may
> > indicate a valid overlay using a target-path or some other method)
> > and a badly formatted 'target' property, which is definitely an error
> > in the overlay.
> > 
> > I think those should be treated differently.
> 
> AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
> to cover the two cases, we would need to have some error code, but
> that doesn't really work with returning a uint32_t.

Actually phandles can have any value except 0xffffffff *or* 0.  So you
can use 0 for "couldn't find" and -1 for "badly formatted".

> Or maybe we can simply remove all the checks but the missing property,
> and let fdt_node_offset_by_phandle deal with the improper values?
> 
> > 
> > > +	return fdt32_to_cpu(*val);
> > > +}
> > > +
> > > +static int overlay_get_target(const void *fdt, const void *fdto,
> > > +			      int fragment)
> > > +{
> > > +	uint32_t phandle;
> > > +	const char *path;
> > > +
> > > +	/* Try first to do a phandle based lookup */
> > > +	phandle = overlay_get_target_phandle(fdto, fragment);
> > > +	if (phandle)
> > > +		return fdt_node_offset_by_phandle(fdt, phandle);
> > > +
> > > +	/* And then a path based lookup */
> > > +	path = fdt_getprop(fdto, fragment, "target-path", NULL);
> > > +	if (!path)
> > > +		return -FDT_ERR_NOTFOUND;
> > > +
> > > +	return fdt_path_offset(fdt, path);
> > > +}
> > > +
> > > +static int overlay_phandle_add_offset(void *fdt, int node,
> > > +				      const char *name, uint32_t delta)
> > > +{
> > > +	const uint32_t *val;
> > > +	uint32_t adj_val;
> > > +	int len;
> > > +
> > > +	val = fdt_getprop(fdt, node, name, &len);
> > > +	if (!val)
> > > +		return len;
> > > +
> > > +	if (len != sizeof(*val))
> > > +		return -FDT_ERR_BADSTRUCTURE;
> > > +
> > > +	adj_val = fdt32_to_cpu(*val);
> > > +	adj_val += delta;
> > 
> > You should probably check for overflow here.
> > 
> > > +
> > > +	return fdt_setprop_inplace_u32(fdt, node, name, adj_val);
> > > +}
> > > +
> > > +static int overlay_adjust_node_phandles(void *fdto, int node,
> > > +					uint32_t delta)
> > > +{
> > > +	bool found = false;
> > > +	int child;
> > > +	int ret;
> > > +
> > > +	ret = overlay_phandle_add_offset(fdto, node, "phandle", delta);
> > > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > > +		return ret;
> > > +
> > > +	if (!ret)
> > > +		found = true;
> > > +
> > > +	ret = overlay_phandle_add_offset(fdto, node, "linux,phandle", delta);
> > > +	if (ret && ret != -FDT_ERR_NOTFOUND)
> > > +		return ret;
> > 
> > I think the check for phandle vs. linux,phandle should be folded into
> > overlay_phandle_add_offset().
> 
> I created overlay_phandle_add_offset to avoid duplicating the getprop,
> offset, setprop, pattern which I don't think is a good idea.
> 
> And we'll have to have that kind of errors construct anyway to know if
> we modified any of the two, which is a success, or none, which is a
> failure.

Hm.. ok, you convinced me.

> > > +	/*
> > > +	 * If neither phandle nor linux,phandle have been found return
> > > +	 * an error.
> > > +	 */
> > > +	if (!found && !ret)
> > > +		return ret;
> > > +
> > > +	fdt_for_each_subnode(fdto, child, node)
> > > +		overlay_adjust_node_phandles(fdto, child, delta);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int overlay_adjust_local_phandles(void *fdto, uint32_t delta)
> > > +{
> > > +	/*
> > > +	 * Start adjusting the phandles from the overlay root
> > > +	 */
> > > +	return overlay_adjust_node_phandles(fdto, 0, delta);
> > > +}
> > > +
> > > +static int overlay_update_local_node_references(void *fdto,
> > > +						int tree_node,
> > > +						int fixup_node,
> > > +						uint32_t delta)
> > > +{
> > > +	int fixup_prop;
> > > +	int fixup_child;
> > > +	int ret;
> > > +
> > > +	fdt_for_each_property_offset(fixup_prop, fdto, fixup_node) {
> > > +		const uint32_t *val = NULL;
> > > +		uint32_t adj_val, index;
> > > +		const char *name;
> > > +		int fixup_len;
> > > +		int tree_len;
> > > +
> > > +		val = fdt_getprop_by_offset(fdto, fixup_prop,
> > > +					    &name, &fixup_len);
> > > +		if (!val)
> > > +			return fixup_len;
> > > +		index = fdt32_to_cpu(*val);
> > 
> > This still doesn't handle the case of multiple fixups within the same
> > property.  That would be entirely plausible for something like an
> > interrupt-map property.
> 
> Good point, I'll fix that and add a test case for it.
> 
> > > +		val = fdt_getprop(fdto, tree_node, name, &tree_len);
> > > +		if (!val)
> > > +			return tree_len;
> > > +
> > > +		adj_val = fdt32_to_cpu(*(val + (index / sizeof(uint32_t))));
> > 
> > phandle values need not be aligned within the property containint them
> > (e.g. properties which mix strings and integer values).  So you're
> > going to need to work directly with a byte offset here.
> 
> I didn't even know it was something that was valid.

I'm afraid so.  In general, property values are treated as packed
bytestrings and never have internal alignment constraints.

> It would probably require a temporary variable and a memcpy though to
> deal with architectures that cannot do unaligned accesses.

Alas, yes.  Make sure you put a comment there to explain this, because
it will appear unnecessary to people only familiar with archs that
allow unaligned access (which includes both x86 and Power).

> 
> > 
> > > +		adj_val += delta;
> > > +		adj_val = cpu_to_fdt32(adj_val);
> > > +
> > > +		ret = fdt_setprop_inplace_namelen_by_index(fdto, tree_node,
> > > +							   name, strlen(name),
> > > +							   index, &adj_val,
> > > +							   sizeof(adj_val));
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > > +	fdt_for_each_subnode(fdto, fixup_child, fixup_node) {
> > > +		const char *fixup_child_name = fdt_get_name(fdto, fixup_child,
> > > +							    NULL);
> > > +		int tree_child;
> > > +
> > > +		tree_child = fdt_subnode_offset(fdto, tree_node,
> > > +						fixup_child_name);
> > > +		if (tree_child < 0)
> > > +			return tree_child;
> > > +
> > > +		ret = overlay_update_local_node_references(fdto,
> > > +							   tree_child,
> > > +							   fixup_child,
> > > +							   delta);
> > > +		if (ret)
> > > +			return ret;
> > > +	}
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int overlay_update_local_references(void *dto, uint32_t delta)
> > > +{
> > > +	int fixups;
> > > +
> > > +	fixups = fdt_path_offset(dto, "/__local_fixups__");
> > > +	if (fixups < 0) {
> > > +		/*
> > > +		 * There's no local phandles to adjust, bail out
> > > +		 */
> > > +		if (fixups == -FDT_ERR_NOTFOUND)
> > > +			return 0;
> > > +
> > > +		return fixups;
> > > +	}
> > > +
> > > +	/*
> > > +	 * Update our local references from the root of the tree
> > > +	 */
> > > +	return overlay_update_local_node_references(dto, 0, fixups,
> > > +						    delta);
> > > +}
> > > +
> > > +static int overlay_fixup_one_phandle(void *fdt, void *fdto,
> > > +				     int symbols_off,
> > > +				     const char *path, uint32_t path_len,
> > > +				     const char *name, uint32_t name_len,
> > > +				     int index, const char *label)
> > > +{
> > > +	const char *symbol_path;
> > > +	uint32_t phandle;
> > > +	int symbol_off, fixup_off;
> > > +	int prop_len;
> > > +
> > > +	symbol_path = fdt_getprop(fdt, symbols_off, label,
> > > +				  &prop_len);
> > > +	if (!symbol_path)
> > > +		return -FDT_ERR_NOTFOUND;
> > > +
> > > +	symbol_off = fdt_path_offset(fdt, symbol_path);
> > > +	if (symbol_off < 0)
> > > +		return symbol_off;
> > > +
> > > +	phandle = fdt_get_phandle(fdt, symbol_off);
> > > +	if (!phandle)
> > > +		return -FDT_ERR_NOTFOUND;
> > > +
> > > +	fixup_off = fdt_path_offset_namelen(fdto, path, path_len);
> > > +	if (fixup_off < 0)
> > > +		return fixup_off;
> > > +
> > > +	phandle = cpu_to_fdt32(phandle);
> > > +	return fdt_setprop_inplace_namelen_by_index(fdto, fixup_off,
> > > +						    name, name_len, index,
> > > +						    &phandle, sizeof(phandle));
> > 
> > This will be broken on BE systems because fdt_get_phandle() byteswaps
> > to native order, but setprop_inplace doesn't byteswap back (because
> > it's input is a byte array, not a u32).
> 
> Hmmmm, so calling cpu_to_fdt32 is not enough? I'm not sure what the
> proper fix for that would be.

Oh, sorry, I just missed the cpu_to_fdt32().

> > > +};
> > > +
> > > +static int overlay_fixup_phandle(void *fdt, void *fdto, int symbols_off,
> > > +				 int property)
> > > +{
> > > +	const char *value;
> > > +	const char *label;
> > > +	int len;
> > > +
> > > +	value = fdt_getprop_by_offset(fdto, property,
> > > +				      &label, &len);
> > > +	if (!value)
> > > +		return len;
> > > +
> > > +	do {
> > > +		const char *prop_string = value;
> > > +		const char *path, *name;
> > > +		uint32_t path_len, name_len;
> > > +		char *sep, *endptr;
> > > +		int index;
> > > +		int ret;
> > > +
> > > +		path = prop_string;
> > > +		sep = strchr(prop_string, ':');
> > > +		path_len = sep - path;
> > 
> > You need to check for strchr() returning NULL (indicating a badly
> > formatted fixup missing a separator).
> > 
> > Also... strchr() is not safe.  Again, if the fixup string is badly
> > formatted and doesn't have a terminating \0, this could overrun, so
> > you want memchr() instead.
> 
> Ok
> 
> > > +		name = sep + 1;
> > > +		sep = strchr(name, ':');
> > > +		name_len = sep - name;
> > 
> > And again.
> > 
> > > +		index = strtoul(sep + 1, &endptr, 10);
> > > +		if (endptr <= (sep + 1))
> > > +			return -FDT_ERR_BADSTRUCTURE;
> > 
> > IIRC the index value is supposed to go to the end of that portion of
> > the fixup, so you should be able to check for *endptr == '\0'.
> > 
> > Except.. strtoul() could also overrun if the fixup property doesn't
> > contain a \0 like it should.
> > 
> > So I think you'd be better off using a memchr() (or strnlen()) to
> > search for the \0 before you attempt parsing the innards of a single
> > fixup string.
> 
> Ok
> 
> > Ugh.  I hate that we're parsing text numbers in decimal here, but
> > we're pretty much stuck with that format here.  Doubly so that it's a
> > gratuitously different way of encoding the (node, property, offset)
> > tuple from local_fixups.
> 
> I'm not sure to get what you're saying here. Is that a general remark
> on the format used by the overlays, or an hint that my code should be
> reworked to deal with this differently?

Just a general remark on the format.

> 
> > 
> > > +		index = strtoul(sep + 1, &endptr, 10);
> > > +		if (endptr <= (sep + 1))
> > > +			return -FDT_ERR_BADSTRUCTURE;
> > > +
> > > +		len -= strlen(prop_string) + 1;
> > > +		value += strlen(prop_string) + 1;
> > 
> > Please don't double call strlen() on the same string - remember it's
> > O(n) in C.
> 
> Ok
> 
> > > +
> > > +		ret = overlay_fixup_one_phandle(fdt, fdto, symbols_off,
> > > +						path, path_len, name, name_len,
> > > +						index, label);
> > > +		if (ret)
> > > +			return ret;
> > > +	} while (len > 0);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int overlay_fixup_phandles(void *dt, void *dto)
> > > +{
> > > +	int fixups_off, symbols_off;
> > > +	int property;
> > > +
> > > +	symbols_off = fdt_path_offset(dt, "/__symbols__");
> > > +	fixups_off = fdt_path_offset(dto, "/__fixups__");
> > > +
> > > +	fdt_for_each_property_offset(property, dto, fixups_off)
> > > +		overlay_fixup_phandle(dt, dto, symbols_off, property);
> > > +
> > > +	return 0;
> > > +}
> > > +
> > > +static int apply_overlay_node(void *dt, int target,
> > > +			      void *dto, int overlay)
> > 
> > I think 'overlay' should be 'fragment' here for consistency?
> 
> Ok.
> 
> > > +{
> > > +	int property;
> > > +	int node;
> > > +
> > > +	fdt_for_each_property_offset(property, dto, overlay) {
> > > +		const char *name;
> > > +		const void *prop;
> > > +		int prop_len;
> > > +		int ret;
> > > +
> > > +		prop = fdt_getprop_by_offset(dto, property, &name,
> > > +					     &prop_len);
> > > +		if (!prop)
> > > +			return -FDT_ERR_INTERNAL;
> > 
> > Actually, you probably should check the error code returned in
> > prop_len.  Getting a NOTFOUND would indicate an internal error, but
> > you could also get BADSTRUCTURE or similar errors which would indicate
> > an error in input.
> 
> Ok.
> 
> > > +int fdt_overlay_apply(void *fdt, void *fdto)
> > > +{
> > > +	uint32_t delta = fdt_get_max_phandle(fdt) + 1;
> > > +	int ret;
> > > +
> > > +	FDT_CHECK_HEADER(fdt);
> > > +	FDT_CHECK_HEADER(fdto);
> > > +
> > > +	ret = overlay_adjust_local_phandles(fdto, delta);
> > > +	if (ret)
> > > +		goto err;
> > > +
> > > +	ret = overlay_update_local_references(fdto, delta);
> > > +	if (ret)
> > > +		goto err;
> > > +
> > > +	ret = overlay_fixup_phandles(fdt, fdto);
> > > +	if (ret)
> > > +		goto err;
> > > +
> > > +	ret = overlay_merge(fdt, fdto);
> > > +	if (!ret)
> > > +		goto out;
> > > +
> > > +err:
> > 
> > This is a confusing use of gotos - this looks like it is in the exit
> > path for both success and failure cases, but it's not due to the
> > easy-to-miss goto out above.
> 
> I know, but I couldn't really come up with something better to avoid
> code duplication.
> 
> Or maybe it's too small to care?

I think a little duplicated code is the lesser evil here.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
  2016-06-26  8:10       ` Maxime Ripard
@ 2016-06-29  3:27         ` Simon Glass
  -1 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-29  3:27 UTC (permalink / raw)
  To: u-boot

On 26 June 2016 at 01:10, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi,
>
> On Sat, Jun 25, 2016 at 08:53:53PM -0600, Simon Glass wrote:
>> On 24 June 2016 at 08:27, Maxime Ripard
>> <maxime.ripard@free-electrons.com> wrote:
>> > Add a namelen variant of fdt_path_offset to retrieve the node offset using
>> > only a fixed number of characters.
>> >
>> > Signed-off-by: Maxime Ripard <maxime.ripard@free-electrons.com>
>> > ---
>> >  include/libfdt.h    | 16 +++++++++++++++-
>> >  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
>> >  2 files changed, 25 insertions(+), 9 deletions(-)
>>
>> fdt_setprop_inplace
>
> What do you mean?

That was a mistake. I meant:

Reviewed-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen
@ 2016-06-29  3:27         ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-29  3:27 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: Pantelis Antoniou, Boris Brezillon, Alexander Kaplan,
	Thomas Petazzoni, Devicetree Compiler, Antoine Ténart,
	Hans de Goede, Tom Rini, U-Boot Mailing List, Stefan Agner

On 26 June 2016 at 01:10, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Hi,
>
> On Sat, Jun 25, 2016 at 08:53:53PM -0600, Simon Glass wrote:
>> On 24 June 2016 at 08:27, Maxime Ripard
>> <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
>> > Add a namelen variant of fdt_path_offset to retrieve the node offset using
>> > only a fixed number of characters.
>> >
>> > Signed-off-by: Maxime Ripard <maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org>
>> > ---
>> >  include/libfdt.h    | 16 +++++++++++++++-
>> >  lib/libfdt/fdt_ro.c | 18 ++++++++++--------
>> >  2 files changed, 25 insertions(+), 9 deletions(-)
>>
>> fdt_setprop_inplace
>
> What do you mean?

That was a mistake. I meant:

Reviewed-by: Simon Glass <sjg-F7+t8E8rja9g9hUCZPvPmw@public.gmane.org>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
  2016-06-27  6:29     ` Maxime Ripard
@ 2016-06-29  3:28       ` Simon Glass
  -1 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-29  3:28 UTC (permalink / raw)
  To: u-boot

Hi Maxime,

On 26 June 2016 at 23:29, Maxime Ripard
<maxime.ripard@free-electrons.com> wrote:
> Hi David,
>
> On Mon, Jun 27, 2016 at 01:37:19AM +1000, David Gibson wrote:
>> On Fri, Jun 24, 2016 at 04:27:45PM +0200, Maxime Ripard wrote:
>> > Hi,
>> >
>> > The device tree overlays are a great solution to the issue raised by
>> > the bunch expandable boards we find everywhere these days, like the
>> > Beaglebone, Raspberry Pi or CHIP.
>> >
>> > However, most of the time, the overlays are applied through a
>> > mechanism involving the firmware request interface in Linux, that is
>> > only fully functional once the userspace has been mounted and is
>> > running.
>> >
>> > Some expansion boards might need to be enabled before that, because
>> > they simply need to patch the DT early on, or need to be initialized
>> > early in order to be fully functional, or because they provide access
>> > to the root filesystem.
>> >
>> > In these cases, having the bootloader applying the overlay before
>> > Linux starts seems like the easiest solution.
>> >
>> > This implementation doesn't provide all the Linux fancyness though,
>> > there's no transactional application, which means that if the overlay
>> > cannot be applied for a reason while you're still halfway through the
>> > application, you're probably screwed. It also cannot remove an
>> > overlay, but I don't think that it is currently a use-case.
>> >
>> > There's still a bunch of work to extend the libfdt unit tests to test
>> > the new functions introduced, but these patches will be submitted
>> > in a near future.
>>
>> Are you planning to send a new version of (the relevant portions of)
>> these against upstream libfdt?
>
> Of course, I just only have to work on the test cases now.
>
> Simon wanted to merge this in U-Boot for the next merge window, and
> then sync with libfdt when it would be merged, hence why I posted it
> first.

Yes I'll wait until after the current release as it is too close. Feel
free to send a fix-up patch (or whatever means you prefer) once this
is applied upstream.

Regards,
Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 00/12] cmd: fdt: Add device tree overlays support
@ 2016-06-29  3:28       ` Simon Glass
  0 siblings, 0 replies; 90+ messages in thread
From: Simon Glass @ 2016-06-29  3:28 UTC (permalink / raw)
  To: Maxime Ripard
  Cc: David Gibson, Pantelis Antoniou, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni, Devicetree Compiler,
	Antoine Ténart, Hans de Goede, Tom Rini,
	U-Boot Mailing List, Stefan Agner

Hi Maxime,

On 26 June 2016 at 23:29, Maxime Ripard
<maxime.ripard-wi1+55ScJUtKEb57/3fJTNBPR1lH4CV8@public.gmane.org> wrote:
> Hi David,
>
> On Mon, Jun 27, 2016 at 01:37:19AM +1000, David Gibson wrote:
>> On Fri, Jun 24, 2016 at 04:27:45PM +0200, Maxime Ripard wrote:
>> > Hi,
>> >
>> > The device tree overlays are a great solution to the issue raised by
>> > the bunch expandable boards we find everywhere these days, like the
>> > Beaglebone, Raspberry Pi or CHIP.
>> >
>> > However, most of the time, the overlays are applied through a
>> > mechanism involving the firmware request interface in Linux, that is
>> > only fully functional once the userspace has been mounted and is
>> > running.
>> >
>> > Some expansion boards might need to be enabled before that, because
>> > they simply need to patch the DT early on, or need to be initialized
>> > early in order to be fully functional, or because they provide access
>> > to the root filesystem.
>> >
>> > In these cases, having the bootloader applying the overlay before
>> > Linux starts seems like the easiest solution.
>> >
>> > This implementation doesn't provide all the Linux fancyness though,
>> > there's no transactional application, which means that if the overlay
>> > cannot be applied for a reason while you're still halfway through the
>> > application, you're probably screwed. It also cannot remove an
>> > overlay, but I don't think that it is currently a use-case.
>> >
>> > There's still a bunch of work to extend the libfdt unit tests to test
>> > the new functions introduced, but these patches will be submitted
>> > in a near future.
>>
>> Are you planning to send a new version of (the relevant portions of)
>> these against upstream libfdt?
>
> Of course, I just only have to work on the test cases now.
>
> Simon wanted to merge this in U-Boot for the next merge window, and
> then sync with libfdt when it would be merged, hence why I posted it
> first.

Yes I'll wait until after the current release as it is too close. Feel
free to send a fix-up patch (or whatever means you prefer) once this
is applied upstream.

Regards,
Simon

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-30  2:34           ` Frank Rowand
  0 siblings, 0 replies; 90+ messages in thread
From: Frank Rowand @ 2016-06-30  2:34 UTC (permalink / raw)
  To: u-boot

On 06/27/16 20:12, David Gibson wrote:
> On Mon, Jun 27, 2016 at 01:40:00PM +0200, Maxime Ripard wrote:
>> Hi David,
>>
>> On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
>>>> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
>>>> +{
>>>> +	const uint32_t *val;
>>>> +	int len;
>>>> +
>>>> +	val = fdt_getprop(fdto, fragment, "target", &len);
>>>> +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
>>>> +		return 0;
>>>
>>> This doesn't distinguish between a missing property (which may
>>> indicate a valid overlay using a target-path or some other method)
>>> and a badly formatted 'target' property, which is definitely an error
>>> in the overlay.
>>>
>>> I think those should be treated differently.
>>
>> AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
>> to cover the two cases, we would need to have some error code, but
>> that doesn't really work with returning a uint32_t.
> 
> Actually phandles can have any value except 0xffffffff *or* 0.  So you
> can use 0 for "couldn't find" and -1 for "badly formatted".

< snip >

Hi David,

I would like to capture this for the specification.

It seems like I could say that a value of 0 in the FDT is not allowed.

Then thinking of what Pantelis is doing with overlays, it seems like a
value of 0xffffffff is allowed in the FDT, but it means not a valid
phandle, so do not try to de-reference it.

Does that sound good?

-Frank

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-30  2:34           ` Frank Rowand
  0 siblings, 0 replies; 90+ messages in thread
From: Frank Rowand @ 2016-06-30  2:34 UTC (permalink / raw)
  To: David Gibson, Maxime Ripard
  Cc: Pantelis Antoniou, Simon Glass, Boris Brezillon,
	Alexander Kaplan, Thomas Petazzoni,
	devicetree-compiler-u79uwXL29TY76Z2rM5mHXA, Antoine Ténart,
	Hans de Goede, Tom Rini, u-boot-0aAXYlwwYIKGBzrmiIFOJg,
	Stefan Agner

On 06/27/16 20:12, David Gibson wrote:
> On Mon, Jun 27, 2016 at 01:40:00PM +0200, Maxime Ripard wrote:
>> Hi David,
>>
>> On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
>>>> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
>>>> +{
>>>> +	const uint32_t *val;
>>>> +	int len;
>>>> +
>>>> +	val = fdt_getprop(fdto, fragment, "target", &len);
>>>> +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
>>>> +		return 0;
>>>
>>> This doesn't distinguish between a missing property (which may
>>> indicate a valid overlay using a target-path or some other method)
>>> and a badly formatted 'target' property, which is definitely an error
>>> in the overlay.
>>>
>>> I think those should be treated differently.
>>
>> AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
>> to cover the two cases, we would need to have some error code, but
>> that doesn't really work with returning a uint32_t.
> 
> Actually phandles can have any value except 0xffffffff *or* 0.  So you
> can use 0 for "couldn't find" and -1 for "badly formatted".

< snip >

Hi David,

I would like to capture this for the specification.

It seems like I could say that a value of 0 in the FDT is not allowed.

Then thinking of what Pantelis is doing with overlays, it seems like a
value of 0xffffffff is allowed in the FDT, but it means not a valid
phandle, so do not try to de-reference it.

Does that sound good?

-Frank

^ permalink raw reply	[flat|nested] 90+ messages in thread

* [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function
  2016-06-30  2:34           ` Frank Rowand
@ 2016-06-30  5:08             ` David Gibson
  -1 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-30  5:08 UTC (permalink / raw)
  To: u-boot

On Wed, Jun 29, 2016 at 07:34:54PM -0700, Frank Rowand wrote:
> On 06/27/16 20:12, David Gibson wrote:
> > On Mon, Jun 27, 2016 at 01:40:00PM +0200, Maxime Ripard wrote:
> >> Hi David,
> >>
> >> On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
> >>>> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> >>>> +{
> >>>> +	const uint32_t *val;
> >>>> +	int len;
> >>>> +
> >>>> +	val = fdt_getprop(fdto, fragment, "target", &len);
> >>>> +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> >>>> +		return 0;
> >>>
> >>> This doesn't distinguish between a missing property (which may
> >>> indicate a valid overlay using a target-path or some other method)
> >>> and a badly formatted 'target' property, which is definitely an error
> >>> in the overlay.
> >>>
> >>> I think those should be treated differently.
> >>
> >> AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
> >> to cover the two cases, we would need to have some error code, but
> >> that doesn't really work with returning a uint32_t.
> > 
> > Actually phandles can have any value except 0xffffffff *or* 0.  So you
> > can use 0 for "couldn't find" and -1 for "badly formatted".
> 
> < snip >
> 
> Hi David,
> 
> I would like to capture this for the specification.
> 
> It seems like I could say that a value of 0 in the FDT is not allowed.
> 
> Then thinking of what Pantelis is doing with overlays, it seems like a
> value of 0xffffffff is allowed in the FDT, but it means not a valid
> phandle, so do not try to de-reference it.
> 
> Does that sound good?

That should be ok.  Basically both 0 and -1 are invalid phandle
values, so it's up to us if we want to assign them specific "error"
meanings.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson
-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 819 bytes
Desc: not available
URL: <http://lists.denx.de/pipermail/u-boot/attachments/20160630/eaac3896/attachment.sig>

^ permalink raw reply	[flat|nested] 90+ messages in thread

* Re: [PATCH v3 10/12] libfdt: Add overlay application function
@ 2016-06-30  5:08             ` David Gibson
  0 siblings, 0 replies; 90+ messages in thread
From: David Gibson @ 2016-06-30  5:08 UTC (permalink / raw)
  To: Frank Rowand
  Cc: Thomas Petazzoni, u-boot, Pantelis Antoniou, Tom Rini,
	Alexander Kaplan, devicetree-compiler


[-- Attachment #1.1: Type: text/plain, Size: 1975 bytes --]

On Wed, Jun 29, 2016 at 07:34:54PM -0700, Frank Rowand wrote:
> On 06/27/16 20:12, David Gibson wrote:
> > On Mon, Jun 27, 2016 at 01:40:00PM +0200, Maxime Ripard wrote:
> >> Hi David,
> >>
> >> On Mon, Jun 27, 2016 at 03:26:07PM +1000, David Gibson wrote:
> >>>> +static uint32_t overlay_get_target_phandle(const void *fdto, int fragment)
> >>>> +{
> >>>> +	const uint32_t *val;
> >>>> +	int len;
> >>>> +
> >>>> +	val = fdt_getprop(fdto, fragment, "target", &len);
> >>>> +	if (!val || (*val == 0xffffffff) || (len != sizeof(*val)))
> >>>> +		return 0;
> >>>
> >>> This doesn't distinguish between a missing property (which may
> >>> indicate a valid overlay using a target-path or some other method)
> >>> and a badly formatted 'target' property, which is definitely an error
> >>> in the overlay.
> >>>
> >>> I think those should be treated differently.
> >>
> >> AFAIK, phandles can have any 32 bits values but 0xffffffff. In order
> >> to cover the two cases, we would need to have some error code, but
> >> that doesn't really work with returning a uint32_t.
> > 
> > Actually phandles can have any value except 0xffffffff *or* 0.  So you
> > can use 0 for "couldn't find" and -1 for "badly formatted".
> 
> < snip >
> 
> Hi David,
> 
> I would like to capture this for the specification.
> 
> It seems like I could say that a value of 0 in the FDT is not allowed.
> 
> Then thinking of what Pantelis is doing with overlays, it seems like a
> value of 0xffffffff is allowed in the FDT, but it means not a valid
> phandle, so do not try to de-reference it.
> 
> Does that sound good?

That should be ok.  Basically both 0 and -1 are invalid phandle
values, so it's up to us if we want to assign them specific "error"
meanings.

-- 
David Gibson			| I'll have my music baroque, and my code
david AT gibson.dropbear.id.au	| minimalist, thank you.  NOT _the_ _other_
				| _way_ _around_!
http://www.ozlabs.org/~dgibson

[-- Attachment #1.2: signature.asc --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

[-- Attachment #2: Type: text/plain, Size: 134 bytes --]

_______________________________________________
U-Boot mailing list
U-Boot@lists.denx.de
http://lists.denx.de/mailman/listinfo/u-boot

^ permalink raw reply	[flat|nested] 90+ messages in thread

end of thread, other threads:[~2016-06-30  5:08 UTC | newest]

Thread overview: 90+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-24 14:27 [U-Boot] [PATCH v3 00/12] cmd: fdt: Add device tree overlays support Maxime Ripard
2016-06-24 14:27 ` Maxime Ripard
2016-06-24 14:27 ` [U-Boot] [PATCH v3 01/12] cmd: fdt: Narrow the check for fdt addr Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-24 14:27 ` [U-Boot] [PATCH v3 02/12] scripts: Makefile.lib: Sanitize DTB names Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-24 14:27 ` [U-Boot] [PATCH v3 03/12] vsprintf: Include stdarg for va_list Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-24 14:27 ` [U-Boot] [PATCH v3 04/12] libfdt: Add new headers and defines Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-26  2:53   ` [U-Boot] " Simon Glass
2016-06-26  2:53     ` Simon Glass
2016-06-26 15:39   ` [U-Boot] " David Gibson
2016-06-26 15:39     ` David Gibson
2016-06-27  7:25     ` [U-Boot] " Maxime Ripard
2016-06-27  7:25       ` Maxime Ripard
2016-06-28  3:02       ` [U-Boot] " David Gibson
2016-06-28  3:02         ` David Gibson
2016-06-24 14:27 ` [U-Boot] [PATCH v3 05/12] libfdt: Add iterator over properties Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-26  2:53   ` [U-Boot] " Simon Glass
2016-06-26  2:53     ` Simon Glass
2016-06-24 14:27 ` [U-Boot] [PATCH v3 06/12] libfdt: Add max phandle retrieval function Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-26  2:53   ` [U-Boot] " Simon Glass
2016-06-26  2:53     ` Simon Glass
2016-06-24 14:27 ` [U-Boot] [PATCH v3 07/12] libfdt: Add fdt_setprop_inplace_by_index Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-26  2:53   ` [U-Boot] " Simon Glass
2016-06-26  2:53     ` Simon Glass
2016-06-26  8:09     ` [U-Boot] " Maxime Ripard
2016-06-26  8:09       ` Maxime Ripard
2016-06-26 15:45   ` [U-Boot] " David Gibson
2016-06-26 15:45     ` David Gibson
2016-06-27  9:16     ` [U-Boot] " Maxime Ripard
2016-06-27  9:16       ` Maxime Ripard
2016-06-28  3:05       ` [U-Boot] " David Gibson
2016-06-28  3:05         ` David Gibson
2016-06-24 14:27 ` [U-Boot] [PATCH v3 08/12] libfdt: Add fdt_path_offset_namelen Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-26  2:53   ` [U-Boot] " Simon Glass
2016-06-26  2:53     ` Simon Glass
2016-06-26  8:10     ` [U-Boot] " Maxime Ripard
2016-06-26  8:10       ` Maxime Ripard
2016-06-29  3:27       ` [U-Boot] " Simon Glass
2016-06-29  3:27         ` Simon Glass
2016-06-26 15:47   ` [U-Boot] " David Gibson
2016-06-26 15:47     ` David Gibson
2016-06-24 14:27 ` [U-Boot] [PATCH v3 09/12] libfdt: Add fdt_getprop_namelen_w Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-26  2:53   ` [U-Boot] " Simon Glass
2016-06-26  2:53     ` Simon Glass
2016-06-26  8:11     ` [U-Boot] " Maxime Ripard
2016-06-26  8:11       ` Maxime Ripard
2016-06-26 15:49   ` [U-Boot] " David Gibson
2016-06-26 15:49     ` David Gibson
2016-06-27  7:29     ` [U-Boot] " Maxime Ripard
2016-06-27  7:29       ` Maxime Ripard
2016-06-24 14:27 ` [U-Boot] [PATCH v3 10/12] libfdt: Add overlay application function Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-26  2:53   ` [U-Boot] " Simon Glass
2016-06-26  2:53     ` Simon Glass
2016-06-27  7:13     ` [U-Boot] " Maxime Ripard
2016-06-27  7:13       ` Maxime Ripard
2016-06-27  5:26   ` [U-Boot] " David Gibson
2016-06-27  5:26     ` David Gibson
2016-06-27 11:40     ` [U-Boot] " Maxime Ripard
2016-06-27 11:40       ` Maxime Ripard
2016-06-28  3:12       ` [U-Boot] " David Gibson
2016-06-28  3:12         ` David Gibson
2016-06-30  2:34         ` [U-Boot] " Frank Rowand
2016-06-30  2:34           ` Frank Rowand
2016-06-30  5:08           ` [U-Boot] " David Gibson
2016-06-30  5:08             ` David Gibson
2016-06-24 14:27 ` [U-Boot] [PATCH v3 11/12] cmd: fdt: add fdt overlay application subcommand Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-24 14:27 ` [U-Boot] [PATCH v3 12/12] tests: Introduce DT overlay tests Maxime Ripard
2016-06-24 14:27   ` Maxime Ripard
2016-06-27  5:26   ` [U-Boot] " David Gibson
2016-06-27  5:26     ` David Gibson
2016-06-27  6:30     ` [U-Boot] " Maxime Ripard
2016-06-27  6:30       ` Maxime Ripard
2016-06-27  6:47       ` [U-Boot] " David Gibson
2016-06-27  6:47         ` David Gibson
2016-06-26 15:37 ` [U-Boot] [PATCH v3 00/12] cmd: fdt: Add device tree overlays support David Gibson
2016-06-26 15:37   ` David Gibson
2016-06-27  6:29   ` [U-Boot] " Maxime Ripard
2016-06-27  6:29     ` Maxime Ripard
2016-06-29  3:28     ` [U-Boot] " Simon Glass
2016-06-29  3:28       ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.