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