Hi,

to allow FDT to be used on ARM I think we should move the FDT code from
socppc to sys/dev/fdt/.  Opinions?

Could someone test this diff for me?

Patrick

diff --git sys/arch/socppc/conf/files.socppc sys/arch/socppc/conf/files.socppc
index d1fab5e..ade4e53 100644
--- sys/arch/socppc/conf/files.socppc
+++ sys/arch/socppc/conf/files.socppc
@@ -15,7 +15,7 @@ file  arch/socppc/socppc/machdep.c
 file   arch/socppc/socppc/mem.c
 file   dev/cninit.c
 file   arch/socppc/socppc/db_interface.c               ddb
-file   arch/socppc/socppc/fdt.c
+file   dev/fdt/fdt.c
 file   arch/socppc/socppc/n1200_dts.S
 
 
diff --git sys/arch/socppc/include/fdt.h sys/arch/socppc/include/fdt.h
deleted file mode 100644
index 849f6b2..0000000
--- sys/arch/socppc/include/fdt.h
+++ /dev/null
@@ -1,61 +0,0 @@
-/*     $OpenBSD: fdt.h,v 1.3 2009/10/01 20:21:05 dms Exp $     */
-
-/*
- * Copyright (c) 2009 Dariusz Swiderski <sfi...@sfires.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-struct fdt_head {
-       u_int32_t fh_magic;
-       u_int32_t fh_size;
-       u_int32_t fh_struct_off;
-       u_int32_t fh_strings_off;
-       u_int32_t fh_reserve_off;
-       u_int32_t fh_version;
-       u_int32_t fh_comp_ver;     /* last compatible version */
-       u_int32_t fh_boot_cpu_id;  /* fh_version >=2 */
-       u_int32_t fh_strings_size; /* fh_version >=3 */
-       u_int32_t fh_struct_size;  /* fh_version >=17 */
-};
-
-struct fdt {
-       struct fdt_head *header;
-       void *          tree;
-       void *          strings;
-       void *          memory;
-       int             version;
-       int             strings_size;
-};
-
-#define FDT_MAGIC      0xd00dfeed
-#define FDT_NODE_BEGIN 0x01
-#define FDT_NODE_END   0x02
-#define FDT_PROPERTY   0x03
-#define FDT_NOP                0x04
-#define FDT_END                0x09
-
-#define FDT_CODE_VERSION 0x11
-
-int     fdt_init(void *);
-void   *fdt_next_node(void *);
-void   *fdt_child_node(void *);
-char   *fdt_node_name(void *);
-void   *fdt_find_node(char *);
-int     fdt_node_property(void *, char *, char **);
-void   *fdt_parent_node(void *);
-#ifdef DEBUG
-void   *fdt_print_property(void *, int);
-void    fdt_print_node(void *, int);
-void    fdt_print_tree(void);
-#endif
diff --git sys/arch/socppc/socppc/fdt.c sys/arch/socppc/socppc/fdt.c
deleted file mode 100644
index 0dec4fb..0000000
--- sys/arch/socppc/socppc/fdt.c
+++ /dev/null
@@ -1,482 +0,0 @@
-/*     $OpenBSD: fdt.c,v 1.12 2016/02/28 12:39:40 mpi Exp $    */
-
-/*
- * Copyright (c) 2009 Dariusz Swiderski <sfi...@sfires.net>
- * Copyright (c) 2009 Mark Kettenis <kette...@sfires.net>
- *
- * Permission to use, copy, modify, and distribute this software for any
- * purpose with or without fee is hereby granted, provided that the above
- * copyright notice and this permission notice appear in all copies.
- *
- * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
- * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
- * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
- * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
- * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- */
-
-
-#include <sys/types.h>
-#include <sys/param.h>
-#include <sys/systm.h>
-
-#include <machine/fdt.h>
-
-#include <dev/ofw/openfirm.h>
-
-unsigned int fdt_check_head(void *);
-char   *fdt_get_str(u_int32_t);
-void   *skip_property(u_int32_t *);
-void   *skip_props(u_int32_t *);
-void   *skip_node_name(u_int32_t *);
-void   *fdt_parent_node_recurse(void *, void *);
-#ifdef DEBUG
-void    fdt_print_node_recurse(void *, int);
-#endif
-
-static int tree_inited = 0;
-static struct fdt tree;
-
-unsigned int
-fdt_check_head(void *fdt)
-{
-       struct fdt_head *fh;
-       u_int32_t *ptr;
-
-       fh = fdt;
-       ptr = (u_int32_t *)fdt;
-
-       if (betoh32(fh->fh_magic) != FDT_MAGIC)
-               return 0;
-
-       if (betoh32(fh->fh_version) > FDT_CODE_VERSION)
-               return 0;
-
-       if (betoh32(*(ptr + (betoh32(fh->fh_struct_off) / 4))) !=
-           FDT_NODE_BEGIN)
-               return 0;
-
-       /* check for end signature on version 17 blob */
-       if ((betoh32(fh->fh_version) >= 17) &&
-           (betoh32(*(ptr + betoh32(fh->fh_struct_size))) != FDT_END))
-               return 0;
-
-       return betoh32(fh->fh_version);
-}
-
-/*
- * Initializes internal structures of module.
- * Has to be called once, preferably in machdep.c.
- */
-int
-fdt_init(void *fdt)
-{
-       int version;
-
-       bzero(&tree, sizeof(struct fdt));
-       tree_inited = 0;
-
-       if (!fdt)
-               return 0;
-
-       if (!(version = fdt_check_head(fdt)))
-               return 0;
-
-       tree.header = (struct fdt_head *)fdt;
-       tree.tree = (char *)fdt + betoh32(tree.header->fh_struct_off);
-       tree.strings = (char *)fdt + betoh32(tree.header->fh_strings_off);
-       tree.memory = (char *)fdt + betoh32(tree.header->fh_reserve_off);
-       tree.version = version;
-       tree.strings_size = betoh32(tree.header->fh_strings_size);
-       tree_inited = 1;
-
-       return version;
-}
-
-/*
- * Retrieve string pointer from strings table.
- */
-char *
-fdt_get_str(u_int32_t num)
-{
-       if (num > tree.strings_size)
-               return NULL;
-       return (tree.strings) ? (tree.strings + num) : NULL;
-}
-
-/*
- * Utility functions for skipping parts of tree.
- */
-void *
-skip_property(u_int32_t *ptr)
-{
-       u_int32_t size;
-
-       size = betoh32(*(ptr + 1));
-       /* move forward by magic + size + nameid + rounded up property size */
-       ptr += 3 + roundup(size, sizeof(u_int32_t)) / sizeof(u_int32_t);
-
-       return ptr;
-}
-
-void *
-skip_props(u_int32_t *ptr)
-{
-       while (betoh32(*ptr) == FDT_PROPERTY) {
-               ptr = skip_property(ptr);
-       }
-       return ptr;
-}
-
-void *
-skip_node_name(u_int32_t *ptr)
-{
-       /* skip name, aligned to 4 bytes, this is NULL term., so must add 1 */
-       return ptr + roundup(strlen((char *)ptr) + 1,
-           sizeof(u_int32_t)) / sizeof(u_int32_t);
-}
-
-/*
- * Retrieves node property, the returned pointer is inside the fdt tree,
- * so we should not modify content pointed by it directly.
- */
-int
-fdt_node_property(void *node, char *name, char **out)
-{
-       u_int32_t *ptr;
-       u_int32_t nameid;
-       char *tmp;
-       
-       if (!tree_inited)
-               return 0;
-
-       ptr = (u_int32_t *)node;
-
-       if (betoh32(*ptr) != FDT_NODE_BEGIN)
-               return 0;
-
-       ptr = skip_node_name(ptr + 1);
-
-       while (betoh32(*ptr) == FDT_PROPERTY) {
-               nameid = betoh32(*(ptr + 2)); /* id of name in strings table */
-               tmp = fdt_get_str(nameid);
-               if (!strcmp(name, tmp)) {
-                       *out = (char *)(ptr + 3); /* beginning of the value */
-                       return betoh32(*(ptr + 1)); /* size of value */
-               }
-               ptr = skip_property(ptr);
-       }
-       return 0;
-}
-
-/*
- * Retrieves next node, skipping all the children nodes of the pointed node
- * if passed 0 wil return first node of the tree (root)
- */
-void *
-fdt_next_node(void *node)
-{
-       u_int32_t *ptr;
-
-       if (!tree_inited)
-               return NULL;
-
-       ptr = node;
-
-       if (!node) {
-               ptr = tree.tree;
-               return (betoh32(*ptr) == FDT_NODE_BEGIN) ? ptr : NULL;
-       }
-
-       if (betoh32(*ptr) != FDT_NODE_BEGIN)
-               return NULL;
-
-       ptr++;
-
-       ptr = skip_node_name(ptr);
-       ptr = skip_props(ptr);
-
-       /* skip children */
-       while (betoh32(*ptr) == FDT_NODE_BEGIN)
-               ptr = fdt_next_node(ptr);
-
-       return (betoh32(*ptr) == FDT_NODE_END) ? (ptr + 1) : NULL;
-}
-
-/*
- * Retrieves next node, skipping all the children nodes of the pointed node
- */
-void *
-fdt_child_node(void *node)
-{
-       u_int32_t *ptr;
-
-       if (!tree_inited)
-               return NULL;
-
-       ptr = node;
-
-       if (betoh32(*ptr) != FDT_NODE_BEGIN)
-               return NULL;
-
-       ptr++;
-
-       ptr = skip_node_name(ptr);
-       ptr = skip_props(ptr);
-       /* check if there is a child node */
-       return (betoh32(*ptr) == FDT_NODE_BEGIN) ? (ptr) : NULL;
-}
-
-/*
- * Retrieves node name.
- */
-char *
-fdt_node_name(void *node)
-{
-       u_int32_t *ptr;
-
-       if (!tree_inited)
-               return NULL;
-
-       ptr = node;
-
-       if (betoh32(*ptr) != FDT_NODE_BEGIN)
-               return NULL;
-
-       return (char *)(ptr + 1);
-}
-
-void *
-fdt_find_node(char *name)
-{
-       void *node = fdt_next_node(0);
-       const char *p = name;
-
-       if (!tree_inited)
-               return NULL;
-
-       if (*p != '/')
-               return NULL;
-
-       while (*p) {
-               void *child;
-               const char *q;
-
-               while (*p == '/')
-                       p++;
-               if (*p == 0)
-                       return node;
-               q = strchr(p, '/');
-               if (q == NULL)
-                       q = p + strlen(p);
-
-               for (child = fdt_child_node(node); child;
-                    child = fdt_next_node(child)) {
-                       if (strncmp(p, fdt_node_name(child), q - p) == 0) {
-                               node = child;
-                               break;
-                       }
-               }
-
-               p = q;
-       }
-
-       return node;
-}
-
-void *
-fdt_parent_node_recurse(void *pnode, void *child)
-{
-       void *node = fdt_child_node(pnode);
-       void *tmp;
-       
-       while (node && (node != child)) {
-               if ((tmp = fdt_parent_node_recurse(node, child)))
-                       return tmp;
-               node = fdt_next_node(node);
-       }
-       return (node) ? pnode : NULL;
-}
-
-void *
-fdt_parent_node(void *node)
-{
-       void *pnode = fdt_next_node(0);
-
-       if (!tree_inited)
-               return NULL;
-
-       return fdt_parent_node_recurse(pnode, node);
-}
-
-#ifdef DEBUG
-/*
- * Debug methods for printing whole tree, particular odes and properies
- */
-void *
-fdt_print_property(void *node, int level)
-{
-       u_int32_t *ptr;
-       char *tmp, *value;
-       int cnt;
-       u_int32_t nameid, size;
-
-       ptr = (u_int32_t *)node;
-
-       if (!tree_inited)
-               return NULL;
-
-       if (betoh32(*ptr) != FDT_PROPERTY)
-               return ptr; /* should never happen */
-
-       /* extract property name_id and size */
-       size = betoh32(*++ptr);
-       nameid = betoh32(*++ptr);
-
-       for (cnt = 0; cnt < level; cnt++)
-               printf("\t");
-
-       tmp = fdt_get_str(nameid);
-       printf("\t%s : ", tmp ? tmp : "NO_NAME");
-
-       ptr++;
-       value = (char *)ptr;
-
-       if (!strcmp(tmp, "device_type") || !strcmp(tmp, "compatible") ||
-           !strcmp(tmp, "model") || !strcmp(tmp, "bootargs") ||
-           !strcmp(tmp, "linux,stdout-path")) {
-               printf("%s", value);
-       } else if (!strcmp(tmp, "clock-frequency") ||
-           !strcmp(tmp, "timebase-frequency")) {
-               printf("%d", betoh32(*((unsigned int *)value)));
-       } else {
-               for (cnt = 0; cnt < size; cnt++) {
-                       if ((cnt % sizeof(u_int32_t)) == 0)
-                               printf(" ");
-                       printf("%02x", value[cnt]);
-               }
-       }
-       ptr += roundup(size, sizeof(u_int32_t)) / sizeof(u_int32_t);
-       printf("\n");
-
-       return ptr;
-}
-
-void
-fdt_print_node(void *node, int level)
-{
-       u_int32_t *ptr;
-       int cnt;
-       
-       ptr = (u_int32_t *)node;
-
-       if (betoh32(*ptr) != FDT_NODE_BEGIN)
-               return;
-
-       ptr++;
-
-       for (cnt = 0; cnt < level; cnt++)
-               printf("\t");
-       printf("%s :\n", fdt_node_name(node));
-       ptr = skip_node_name(ptr);
-
-       while (betoh32(*ptr) == FDT_PROPERTY)
-               ptr = fdt_print_property(ptr, level);
-}
-
-void
-fdt_print_node_recurse(void *node, int level)
-{
-       void *child;
-
-       fdt_print_node(node, level);
-       for (child = fdt_child_node(node); child; child = fdt_next_node(child))
-               fdt_print_node_recurse(child, level + 1);
-}
-
-void
-fdt_print_tree(void)
-{
-       fdt_print_node_recurse(fdt_next_node(0), 0);
-}
-#endif
-
-int
-OF_peer(int handle)
-{
-       void *node = (char *)tree.header + handle;
-
-       if (handle == 0)
-               node = fdt_find_node("/");
-       else
-               node = fdt_next_node(node);
-       return node ? ((char *)node - (char *)tree.header) : 0;
-}
-
-int
-OF_child(int handle)
-{
-       void *node = (char *)tree.header + handle;
-
-       node = fdt_child_node(node);
-       return node ? ((char *)node - (char *)tree.header) : 0;
-}
-
-int
-OF_parent(int handle)
-{
-       void *node = (char *)tree.header + handle;
-       
-       node = fdt_parent_node(node);
-       return node ? ((char *)node - (char *)tree.header) : 0;
-}
-
-int
-OF_finddevice(char *name)
-{
-       void *node;
-
-       node = fdt_find_node(name);
-       return node ? ((char *)node - (char *)tree.header) : -1;
-}
-
-int
-OF_getproplen(int handle, char *prop)
-{
-       void *node = (char *)tree.header + handle;
-       char *data;
-
-       return fdt_node_property(node, prop, &data);
-}
-
-int
-OF_getprop(int handle, char *prop, void *buf, int buflen)
-{
-       void *node = (char *)tree.header + handle;
-       char *data;
-       int len;
-
-       len = fdt_node_property(node, prop, &data);
-
-       /*
-        * The "name" property is optional since version 16 of the
-        * flattened device tree specification, so we synthesize one
-        * from the unit name of the node if it is missing.
-        */
-       if (len == 0 && strcmp(prop, "name") == 0) {
-               data = fdt_node_name(node);
-               if (data) {
-                       len = strlcpy(buf, data, buflen);
-                       data = strchr(buf, '@');
-                       if (data)
-                               *data = 0;
-                       return len + 1;
-               }
-       }
-
-       if (len > 0)
-               memcpy(buf, data, min(len, buflen));
-       return len;
-}
diff --git sys/arch/socppc/socppc/machdep.c sys/arch/socppc/socppc/machdep.c
index ffcf331..f3d4a07 100644
--- sys/arch/socppc/socppc/machdep.c
+++ sys/arch/socppc/socppc/machdep.c
@@ -52,7 +52,6 @@
 #include <uvm/uvm_extern.h>
 
 #include <machine/bus.h>
-#include <machine/fdt.h>
 #include <machine/pio.h>
 #include <powerpc/powerpc.h>
 #include <machine/trap.h>
@@ -61,6 +60,8 @@
 
 #include <dev/ic/comvar.h>
 
+#include <dev/fdt/fdt.h>
+
 #ifdef DDB
 #include <machine/db_machdep.h>
 #include <ddb/db_extern.h>
diff --git sys/dev/fdt/fdt.c sys/dev/fdt/fdt.c
new file mode 100644
index 0000000..c29f6c1
--- /dev/null
+++ sys/dev/fdt/fdt.c
@@ -0,0 +1,482 @@
+/*     $OpenBSD: fdt.c,v 1.12 2016/02/28 12:39:40 mpi Exp $    */
+
+/*
+ * Copyright (c) 2009 Dariusz Swiderski <sfi...@sfires.net>
+ * Copyright (c) 2009 Mark Kettenis <kette...@sfires.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/systm.h>
+
+#include <dev/fdt/fdt.h>
+
+#include <dev/ofw/openfirm.h>
+
+unsigned int fdt_check_head(void *);
+char   *fdt_get_str(u_int32_t);
+void   *skip_property(u_int32_t *);
+void   *skip_props(u_int32_t *);
+void   *skip_node_name(u_int32_t *);
+void   *fdt_parent_node_recurse(void *, void *);
+#ifdef DEBUG
+void    fdt_print_node_recurse(void *, int);
+#endif
+
+static int tree_inited = 0;
+static struct fdt tree;
+
+unsigned int
+fdt_check_head(void *fdt)
+{
+       struct fdt_head *fh;
+       u_int32_t *ptr;
+
+       fh = fdt;
+       ptr = (u_int32_t *)fdt;
+
+       if (betoh32(fh->fh_magic) != FDT_MAGIC)
+               return 0;
+
+       if (betoh32(fh->fh_version) > FDT_CODE_VERSION)
+               return 0;
+
+       if (betoh32(*(ptr + (betoh32(fh->fh_struct_off) / 4))) !=
+           FDT_NODE_BEGIN)
+               return 0;
+
+       /* check for end signature on version 17 blob */
+       if ((betoh32(fh->fh_version) >= 17) &&
+           (betoh32(*(ptr + betoh32(fh->fh_struct_size))) != FDT_END))
+               return 0;
+
+       return betoh32(fh->fh_version);
+}
+
+/*
+ * Initializes internal structures of module.
+ * Has to be called once, preferably in machdep.c.
+ */
+int
+fdt_init(void *fdt)
+{
+       int version;
+
+       bzero(&tree, sizeof(struct fdt));
+       tree_inited = 0;
+
+       if (!fdt)
+               return 0;
+
+       if (!(version = fdt_check_head(fdt)))
+               return 0;
+
+       tree.header = (struct fdt_head *)fdt;
+       tree.tree = (char *)fdt + betoh32(tree.header->fh_struct_off);
+       tree.strings = (char *)fdt + betoh32(tree.header->fh_strings_off);
+       tree.memory = (char *)fdt + betoh32(tree.header->fh_reserve_off);
+       tree.version = version;
+       tree.strings_size = betoh32(tree.header->fh_strings_size);
+       tree_inited = 1;
+
+       return version;
+}
+
+/*
+ * Retrieve string pointer from strings table.
+ */
+char *
+fdt_get_str(u_int32_t num)
+{
+       if (num > tree.strings_size)
+               return NULL;
+       return (tree.strings) ? (tree.strings + num) : NULL;
+}
+
+/*
+ * Utility functions for skipping parts of tree.
+ */
+void *
+skip_property(u_int32_t *ptr)
+{
+       u_int32_t size;
+
+       size = betoh32(*(ptr + 1));
+       /* move forward by magic + size + nameid + rounded up property size */
+       ptr += 3 + roundup(size, sizeof(u_int32_t)) / sizeof(u_int32_t);
+
+       return ptr;
+}
+
+void *
+skip_props(u_int32_t *ptr)
+{
+       while (betoh32(*ptr) == FDT_PROPERTY) {
+               ptr = skip_property(ptr);
+       }
+       return ptr;
+}
+
+void *
+skip_node_name(u_int32_t *ptr)
+{
+       /* skip name, aligned to 4 bytes, this is NULL term., so must add 1 */
+       return ptr + roundup(strlen((char *)ptr) + 1,
+           sizeof(u_int32_t)) / sizeof(u_int32_t);
+}
+
+/*
+ * Retrieves node property, the returned pointer is inside the fdt tree,
+ * so we should not modify content pointed by it directly.
+ */
+int
+fdt_node_property(void *node, char *name, char **out)
+{
+       u_int32_t *ptr;
+       u_int32_t nameid;
+       char *tmp;
+       
+       if (!tree_inited)
+               return 0;
+
+       ptr = (u_int32_t *)node;
+
+       if (betoh32(*ptr) != FDT_NODE_BEGIN)
+               return 0;
+
+       ptr = skip_node_name(ptr + 1);
+
+       while (betoh32(*ptr) == FDT_PROPERTY) {
+               nameid = betoh32(*(ptr + 2)); /* id of name in strings table */
+               tmp = fdt_get_str(nameid);
+               if (!strcmp(name, tmp)) {
+                       *out = (char *)(ptr + 3); /* beginning of the value */
+                       return betoh32(*(ptr + 1)); /* size of value */
+               }
+               ptr = skip_property(ptr);
+       }
+       return 0;
+}
+
+/*
+ * Retrieves next node, skipping all the children nodes of the pointed node
+ * if passed 0 wil return first node of the tree (root)
+ */
+void *
+fdt_next_node(void *node)
+{
+       u_int32_t *ptr;
+
+       if (!tree_inited)
+               return NULL;
+
+       ptr = node;
+
+       if (!node) {
+               ptr = tree.tree;
+               return (betoh32(*ptr) == FDT_NODE_BEGIN) ? ptr : NULL;
+       }
+
+       if (betoh32(*ptr) != FDT_NODE_BEGIN)
+               return NULL;
+
+       ptr++;
+
+       ptr = skip_node_name(ptr);
+       ptr = skip_props(ptr);
+
+       /* skip children */
+       while (betoh32(*ptr) == FDT_NODE_BEGIN)
+               ptr = fdt_next_node(ptr);
+
+       return (betoh32(*ptr) == FDT_NODE_END) ? (ptr + 1) : NULL;
+}
+
+/*
+ * Retrieves next node, skipping all the children nodes of the pointed node
+ */
+void *
+fdt_child_node(void *node)
+{
+       u_int32_t *ptr;
+
+       if (!tree_inited)
+               return NULL;
+
+       ptr = node;
+
+       if (betoh32(*ptr) != FDT_NODE_BEGIN)
+               return NULL;
+
+       ptr++;
+
+       ptr = skip_node_name(ptr);
+       ptr = skip_props(ptr);
+       /* check if there is a child node */
+       return (betoh32(*ptr) == FDT_NODE_BEGIN) ? (ptr) : NULL;
+}
+
+/*
+ * Retrieves node name.
+ */
+char *
+fdt_node_name(void *node)
+{
+       u_int32_t *ptr;
+
+       if (!tree_inited)
+               return NULL;
+
+       ptr = node;
+
+       if (betoh32(*ptr) != FDT_NODE_BEGIN)
+               return NULL;
+
+       return (char *)(ptr + 1);
+}
+
+void *
+fdt_find_node(char *name)
+{
+       void *node = fdt_next_node(0);
+       const char *p = name;
+
+       if (!tree_inited)
+               return NULL;
+
+       if (*p != '/')
+               return NULL;
+
+       while (*p) {
+               void *child;
+               const char *q;
+
+               while (*p == '/')
+                       p++;
+               if (*p == 0)
+                       return node;
+               q = strchr(p, '/');
+               if (q == NULL)
+                       q = p + strlen(p);
+
+               for (child = fdt_child_node(node); child;
+                    child = fdt_next_node(child)) {
+                       if (strncmp(p, fdt_node_name(child), q - p) == 0) {
+                               node = child;
+                               break;
+                       }
+               }
+
+               p = q;
+       }
+
+       return node;
+}
+
+void *
+fdt_parent_node_recurse(void *pnode, void *child)
+{
+       void *node = fdt_child_node(pnode);
+       void *tmp;
+       
+       while (node && (node != child)) {
+               if ((tmp = fdt_parent_node_recurse(node, child)))
+                       return tmp;
+               node = fdt_next_node(node);
+       }
+       return (node) ? pnode : NULL;
+}
+
+void *
+fdt_parent_node(void *node)
+{
+       void *pnode = fdt_next_node(0);
+
+       if (!tree_inited)
+               return NULL;
+
+       return fdt_parent_node_recurse(pnode, node);
+}
+
+#ifdef DEBUG
+/*
+ * Debug methods for printing whole tree, particular odes and properies
+ */
+void *
+fdt_print_property(void *node, int level)
+{
+       u_int32_t *ptr;
+       char *tmp, *value;
+       int cnt;
+       u_int32_t nameid, size;
+
+       ptr = (u_int32_t *)node;
+
+       if (!tree_inited)
+               return NULL;
+
+       if (betoh32(*ptr) != FDT_PROPERTY)
+               return ptr; /* should never happen */
+
+       /* extract property name_id and size */
+       size = betoh32(*++ptr);
+       nameid = betoh32(*++ptr);
+
+       for (cnt = 0; cnt < level; cnt++)
+               printf("\t");
+
+       tmp = fdt_get_str(nameid);
+       printf("\t%s : ", tmp ? tmp : "NO_NAME");
+
+       ptr++;
+       value = (char *)ptr;
+
+       if (!strcmp(tmp, "device_type") || !strcmp(tmp, "compatible") ||
+           !strcmp(tmp, "model") || !strcmp(tmp, "bootargs") ||
+           !strcmp(tmp, "linux,stdout-path")) {
+               printf("%s", value);
+       } else if (!strcmp(tmp, "clock-frequency") ||
+           !strcmp(tmp, "timebase-frequency")) {
+               printf("%d", betoh32(*((unsigned int *)value)));
+       } else {
+               for (cnt = 0; cnt < size; cnt++) {
+                       if ((cnt % sizeof(u_int32_t)) == 0)
+                               printf(" ");
+                       printf("%02x", value[cnt]);
+               }
+       }
+       ptr += roundup(size, sizeof(u_int32_t)) / sizeof(u_int32_t);
+       printf("\n");
+
+       return ptr;
+}
+
+void
+fdt_print_node(void *node, int level)
+{
+       u_int32_t *ptr;
+       int cnt;
+       
+       ptr = (u_int32_t *)node;
+
+       if (betoh32(*ptr) != FDT_NODE_BEGIN)
+               return;
+
+       ptr++;
+
+       for (cnt = 0; cnt < level; cnt++)
+               printf("\t");
+       printf("%s :\n", fdt_node_name(node));
+       ptr = skip_node_name(ptr);
+
+       while (betoh32(*ptr) == FDT_PROPERTY)
+               ptr = fdt_print_property(ptr, level);
+}
+
+void
+fdt_print_node_recurse(void *node, int level)
+{
+       void *child;
+
+       fdt_print_node(node, level);
+       for (child = fdt_child_node(node); child; child = fdt_next_node(child))
+               fdt_print_node_recurse(child, level + 1);
+}
+
+void
+fdt_print_tree(void)
+{
+       fdt_print_node_recurse(fdt_next_node(0), 0);
+}
+#endif
+
+int
+OF_peer(int handle)
+{
+       void *node = (char *)tree.header + handle;
+
+       if (handle == 0)
+               node = fdt_find_node("/");
+       else
+               node = fdt_next_node(node);
+       return node ? ((char *)node - (char *)tree.header) : 0;
+}
+
+int
+OF_child(int handle)
+{
+       void *node = (char *)tree.header + handle;
+
+       node = fdt_child_node(node);
+       return node ? ((char *)node - (char *)tree.header) : 0;
+}
+
+int
+OF_parent(int handle)
+{
+       void *node = (char *)tree.header + handle;
+       
+       node = fdt_parent_node(node);
+       return node ? ((char *)node - (char *)tree.header) : 0;
+}
+
+int
+OF_finddevice(char *name)
+{
+       void *node;
+
+       node = fdt_find_node(name);
+       return node ? ((char *)node - (char *)tree.header) : -1;
+}
+
+int
+OF_getproplen(int handle, char *prop)
+{
+       void *node = (char *)tree.header + handle;
+       char *data;
+
+       return fdt_node_property(node, prop, &data);
+}
+
+int
+OF_getprop(int handle, char *prop, void *buf, int buflen)
+{
+       void *node = (char *)tree.header + handle;
+       char *data;
+       int len;
+
+       len = fdt_node_property(node, prop, &data);
+
+       /*
+        * The "name" property is optional since version 16 of the
+        * flattened device tree specification, so we synthesize one
+        * from the unit name of the node if it is missing.
+        */
+       if (len == 0 && strcmp(prop, "name") == 0) {
+               data = fdt_node_name(node);
+               if (data) {
+                       len = strlcpy(buf, data, buflen);
+                       data = strchr(buf, '@');
+                       if (data)
+                               *data = 0;
+                       return len + 1;
+               }
+       }
+
+       if (len > 0)
+               memcpy(buf, data, min(len, buflen));
+       return len;
+}
diff --git sys/dev/fdt/fdt.h sys/dev/fdt/fdt.h
new file mode 100644
index 0000000..849f6b2
--- /dev/null
+++ sys/dev/fdt/fdt.h
@@ -0,0 +1,61 @@
+/*     $OpenBSD: fdt.h,v 1.3 2009/10/01 20:21:05 dms Exp $     */
+
+/*
+ * Copyright (c) 2009 Dariusz Swiderski <sfi...@sfires.net>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+struct fdt_head {
+       u_int32_t fh_magic;
+       u_int32_t fh_size;
+       u_int32_t fh_struct_off;
+       u_int32_t fh_strings_off;
+       u_int32_t fh_reserve_off;
+       u_int32_t fh_version;
+       u_int32_t fh_comp_ver;     /* last compatible version */
+       u_int32_t fh_boot_cpu_id;  /* fh_version >=2 */
+       u_int32_t fh_strings_size; /* fh_version >=3 */
+       u_int32_t fh_struct_size;  /* fh_version >=17 */
+};
+
+struct fdt {
+       struct fdt_head *header;
+       void *          tree;
+       void *          strings;
+       void *          memory;
+       int             version;
+       int             strings_size;
+};
+
+#define FDT_MAGIC      0xd00dfeed
+#define FDT_NODE_BEGIN 0x01
+#define FDT_NODE_END   0x02
+#define FDT_PROPERTY   0x03
+#define FDT_NOP                0x04
+#define FDT_END                0x09
+
+#define FDT_CODE_VERSION 0x11
+
+int     fdt_init(void *);
+void   *fdt_next_node(void *);
+void   *fdt_child_node(void *);
+char   *fdt_node_name(void *);
+void   *fdt_find_node(char *);
+int     fdt_node_property(void *, char *, char **);
+void   *fdt_parent_node(void *);
+#ifdef DEBUG
+void   *fdt_print_property(void *, int);
+void    fdt_print_node(void *, int);
+void    fdt_print_tree(void);
+#endif

Reply via email to