libfdt: Add phandle generation helper
authorThierry Reding <treding@nvidia.com>
Thu, 21 Mar 2019 18:09:58 +0000 (19:09 +0100)
committerSimon Glass <sjg@chromium.org>
Fri, 12 Apr 2019 02:10:50 +0000 (20:10 -0600)
The new fdt_generate_phandle() function can be used to generate a new,
unused phandle given a specific device tree blob. The implementation is
somewhat naive in that it simply walks the entire device tree to find
the highest phandle value and then returns a phandle value one higher
than that. A more clever implementation might try to find holes in the
current set of phandle values and fill them. But this implementation is
relatively simple and works reliably.

Also add a test that validates that phandles generated by this new API
are indeed unique.

Signed-off-by: Thierry Reding <treding@nvidia.com>
Reviewed-by: Simon Glass <sjg@chromium.org>
lib/libfdt/fdt_ro.c
scripts/dtc/libfdt/fdt_ro.c
scripts/dtc/libfdt/libfdt.h
scripts/dtc/libfdt/libfdt_env.h

index b6ca4e0..693de9a 100644 (file)
@@ -73,6 +73,37 @@ uint32_t fdt_get_max_phandle(const void *fdt)
        return 0;
 }
 
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+       uint32_t max = 0;
+       int offset = -1;
+
+       while (true) {
+               uint32_t value;
+
+               offset = fdt_next_node(fdt, offset, NULL);
+               if (offset < 0) {
+                       if (offset == -FDT_ERR_NOTFOUND)
+                               break;
+
+                       return offset;
+               }
+
+               value = fdt_get_phandle(fdt, offset);
+
+               if (value > max)
+                       max = value;
+       }
+
+       if (max == FDT_MAX_PHANDLE)
+               return -FDT_ERR_NOPHANDLES;
+
+       if (phandle)
+               *phandle = max + 1;
+
+       return 0;
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
        FDT_CHECK_HEADER(fdt);
index dfb3236..dc49988 100644 (file)
@@ -115,6 +115,37 @@ uint32_t fdt_get_max_phandle(const void *fdt)
        return 0;
 }
 
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle)
+{
+       uint32_t max = 0;
+       int offset = -1;
+
+       while (true) {
+               uint32_t value;
+
+               offset = fdt_next_node(fdt, offset, NULL);
+               if (offset < 0) {
+                       if (offset == -FDT_ERR_NOTFOUND)
+                               break;
+
+                       return offset;
+               }
+
+               value = fdt_get_phandle(fdt, offset);
+
+               if (value > max)
+                       max = value;
+       }
+
+       if (max == FDT_MAX_PHANDLE)
+               return -FDT_ERR_NOPHANDLES;
+
+       if (phandle)
+               *phandle = max + 1;
+
+       return 0;
+}
+
 int fdt_get_mem_rsv(const void *fdt, int n, uint64_t *address, uint64_t *size)
 {
        FDT_CHECK_HEADER(fdt);
index fd73688..cf86ddb 100644 (file)
 
 #define FDT_ERR_MAX            17
 
+/* constants */
+#define FDT_MAX_PHANDLE 0xfffffffe
+       /* Valid values for phandles range from 1 to 2^32-2. */
+
 /**********************************************************************/
 /* Low-level functions (you probably don't need these)                */
 /**********************************************************************/
@@ -314,6 +318,21 @@ const char *fdt_string(const void *fdt, int stroffset);
 uint32_t fdt_get_max_phandle(const void *fdt);
 
 /**
+ * fdt_generate_phandle - return a new, unused phandle for a device tree blob
+ * @fdt: pointer to the device tree blob
+ * @phandle: return location for the new phandle
+ *
+ * Walks the device tree blob and looks for the highest phandle value. On
+ * success, the new, unused phandle value (one higher than the previously
+ * highest phandle value in the device tree blob) will be returned in the
+ * @phandle parameter.
+ *
+ * Returns:
+ *   0 on success or a negative error-code on failure
+ */
+int fdt_generate_phandle(const void *fdt, uint32_t *phandle);
+
+/**
  * fdt_num_mem_rsv - retrieve the number of memory reserve map entries
  * @fdt: pointer to the device tree blob
  *
index bd24746..3ff9e28 100644 (file)
@@ -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>