On Wed, 2 Mar 2016, Patrick Wildt wrote:

> 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?

Sure --- it compiles and boots on socppc (RB600A). I applied patch to HEAD 
and removed the empty /usr/src/sys/arch/socppc/socppc/fdt.c

best, 
Richard. 

> 
> 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