[PATCH v4 1/3] libfdt: Add new maximum phandle lookup function

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



From: Thierry Reding <treding@xxxxxxxxxx>

The fdt_get_max_phandle() function has some shortcomings. On one hand it
returns a uint32_t phandle value via a signed return value. This means a
caller has to explicitly cast the return value to a uint32_t and perform
explicit checks against the error code (uint32_t)-1. In addition, the -1
is the only error code that can be returned, so a caller cannot tell the
difference between the various failures.

Fix this by adding a new fdt_find_max_phandle() function that returns an
error code on failure and 0 on success, just like other APIs, and stores
the maximum phandle value in an output argument on success.

This also refactors fdt_get_max_phandle() to use the new function. Add a
note pointing out that the new fdt_find_max_phandle() function should be
preferred over fdt_get_max_phandle().

Signed-off-by: Thierry Reding <treding@xxxxxxxxxx>
---
Changes in v4:
- new patch

 libfdt/fdt_ro.c     | 44 +++++++++++++++++++++++++++++---------------
 libfdt/libfdt.h     | 16 ++++++++++++++++
 libfdt/libfdt_env.h |  1 +
 libfdt/version.lds  |  1 +
 tests/get_phandle.c |  9 +++++++++
 5 files changed, 56 insertions(+), 15 deletions(-)

diff --git a/libfdt/fdt_ro.c b/libfdt/fdt_ro.c
index eafc14282892..1d0335ee7188 100644
--- a/libfdt/fdt_ro.c
+++ b/libfdt/fdt_ro.c
@@ -144,32 +144,46 @@ static int fdt_string_eq_(const void *fdt, int stroffset,
 	return p && (slen == len) && (memcmp(p, s, len) == 0);
 }
 
-uint32_t fdt_get_max_phandle(const void *fdt)
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle)
 {
-	uint32_t max_phandle = 0;
-	int offset;
+	uint32_t max = 0;
+	int offset = -1;
 
-	for (offset = fdt_next_node(fdt, -1, NULL);;
-	     offset = fdt_next_node(fdt, offset, NULL)) {
-		uint32_t phandle;
+	while (true) {
+		uint32_t value;
 
-		if (offset == -FDT_ERR_NOTFOUND)
-			return max_phandle;
+		offset = fdt_next_node(fdt, offset, NULL);
+		if (offset < 0) {
+			if (offset == -FDT_ERR_NOTFOUND)
+				break;
 
-		if (offset < 0)
-			return (uint32_t)-1;
+			return offset;
+		}
 
-		phandle = fdt_get_phandle(fdt, offset);
-		if (phandle == (uint32_t)-1)
-			continue;
+		value = fdt_get_phandle(fdt, offset);
 
-		if (phandle > max_phandle)
-			max_phandle = phandle;
+		if (value > max)
+			max = value;
 	}
 
+	if (phandle)
+		*phandle = max;
+
 	return 0;
 }
 
+uint32_t fdt_get_max_phandle(const void *fdt)
+{
+	uint32_t phandle;
+	int err;
+
+	err = fdt_find_max_phandle(fdt, &phandle);
+	if (err < 0)
+		return (uint32_t)-1;
+
+	return phandle;
+}
+
 static const struct fdt_reserve_entry *fdt_mem_rsv(const void *fdt, int n)
 {
 	int offset = n * sizeof(struct fdt_reserve_entry);
diff --git a/libfdt/libfdt.h b/libfdt/libfdt.h
index a470d1df6d2a..6fce659fd279 100644
--- a/libfdt/libfdt.h
+++ b/libfdt/libfdt.h
@@ -361,6 +361,20 @@ const char *fdt_get_string(const void *fdt, int stroffset, int *lenp);
  */
 const char *fdt_string(const void *fdt, int stroffset);
 
+/**
+ * fdt_find_max_phandle - find and return the highest phandle in a tree
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the highest phandle value found in the tree
+ *
+ * fdt_find_max_phandle() finds the highest phandle value in the given device
+ * tree. The value returned in @phandle is only valid if the function returns
+ * success.
+ *
+ * returns:
+ *     0 on success or a negative error code on failure
+ */
+int fdt_find_max_phandle(const void *fdt, uint32_t *phandle);
+
 /**
  * fdt_get_max_phandle - retrieves the highest phandle in a tree
  * @fdt: pointer to the device tree blob
@@ -369,6 +383,8 @@ const char *fdt_string(const void *fdt, int stroffset);
  * device tree. This will ignore badly formatted phandles, or phandles
  * with a value of 0 or -1.
  *
+ * This function is deprecated in favour of fdt_find_max_phandle().
+ *
  * returns:
  *      the highest phandle on success
  *      0, if no phandle was found in the device tree
diff --git a/libfdt/libfdt_env.h b/libfdt/libfdt_env.h
index eb2053845c9c..4d1cdfa58547 100644
--- a/libfdt/libfdt_env.h
+++ b/libfdt/libfdt_env.h
@@ -52,6 +52,7 @@
  *     EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  */
 
+#include <stdbool.h>
 #include <stddef.h>
 #include <stdint.h>
 #include <stdlib.h>
diff --git a/libfdt/version.lds b/libfdt/version.lds
index a5fe62d5c5ff..87bbb2fe54d3 100644
--- a/libfdt/version.lds
+++ b/libfdt/version.lds
@@ -66,6 +66,7 @@ LIBFDT_1.2 {
 		fdt_resize;
 		fdt_overlay_apply;
 		fdt_get_string;
+		fdt_find_max_phandle;
 		fdt_get_max_phandle;
 		fdt_check_full;
 		fdt_setprop_placeholder;
diff --git a/tests/get_phandle.c b/tests/get_phandle.c
index 22bd7b81b3f0..6973ee4caa17 100644
--- a/tests/get_phandle.c
+++ b/tests/get_phandle.c
@@ -46,6 +46,7 @@ int main(int argc, char *argv[])
 {
 	uint32_t max;
 	void *fdt;
+	int err;
 
 	test_init(argc, argv);
 	fdt = load_blob_arg(argc, argv);
@@ -54,6 +55,14 @@ int main(int argc, char *argv[])
 	check_phandle(fdt, "/subnode@2", PHANDLE_1);
 	check_phandle(fdt, "/subnode@2/subsubnode@0", PHANDLE_2);
 
+	err = fdt_find_max_phandle(fdt, &max);
+	if (err < 0)
+		FAIL("fdt_find_max_phandle returned %d instead of 0\n", err);
+
+	if (max != PHANDLE_2)
+		FAIL("fdt_find_max_phandle found 0x%x instead of 0x%x", max,
+		     PHANDLE_2);
+
 	max = fdt_get_max_phandle(fdt);
 	if (max != PHANDLE_2)
 		FAIL("fdt_get_max_phandle returned 0x%x instead of 0x%x\n",
-- 
2.21.0




[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux