diff options
author | Patrick Wildt <patrick@cvs.openbsd.org> | 2016-04-03 12:32:14 +0000 |
---|---|---|
committer | Patrick Wildt <patrick@cvs.openbsd.org> | 2016-04-03 12:32:14 +0000 |
commit | 46d09009cf7d250de1cb18476b3227471b3ca285 (patch) | |
tree | 2b2e98648f17674592c723b826ac6dc6c1caeb64 /sys/dev/ofw | |
parent | cc46d7897478b2e8ad89339f96964992c93eca22 (diff) |
Implement a way to extract memory information from a node. This can be
used to extract information about how much RAM is available or where a
controller is in the address space and how big its IO space is.
Add a way to get the device tree's size. This is helpful to find out
how much you need to copy if you want to move the tree somewhere else.
Also add helpers to easily retrieve integers from a property.
ok jsg@
Diffstat (limited to 'sys/dev/ofw')
-rw-r--r-- | sys/dev/ofw/fdt.c | 94 | ||||
-rw-r--r-- | sys/dev/ofw/fdt.h | 9 |
2 files changed, 101 insertions, 2 deletions
diff --git a/sys/dev/ofw/fdt.c b/sys/dev/ofw/fdt.c index 984c2b127b8..c430a1eac48 100644 --- a/sys/dev/ofw/fdt.c +++ b/sys/dev/ofw/fdt.c @@ -1,4 +1,4 @@ -/* $OpenBSD: fdt.c,v 1.4 2016/04/03 11:22:51 patrick Exp $ */ +/* $OpenBSD: fdt.c,v 1.5 2016/04/03 12:32:13 patrick Exp $ */ /* * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net> @@ -32,6 +32,8 @@ void *skip_props(u_int32_t *); void *skip_node_name(u_int32_t *); void *skip_node(void *); void *fdt_parent_node_recurse(void *, void *); +int fdt_node_property_int(void *, char *, int *); +int fdt_node_property_ints(void *, char *, int *, int); #ifdef DEBUG void fdt_print_node_recurse(void *, int); #endif @@ -96,6 +98,21 @@ fdt_init(void *fdt) return version; } + /* + * Return the size of the FDT. + */ +size_t +fdt_get_size(void *fdt) +{ + if (!fdt) + return 0; + + if (!fdt_check_head(fdt)) + return 0; + + return betoh32(((struct fdt_head *)fdt)->fh_size); +} + /* * Retrieve string pointer from strings table. */ @@ -235,6 +252,35 @@ fdt_next_node(void *node) } /* + * Retrieves node property as integers and puts them in the given + * integer array. + */ +int +fdt_node_property_ints(void *node, char *name, int *out, int outlen) +{ + int *data; + int i, inlen; + + inlen = fdt_node_property(node, name, (char **)&data) / sizeof(int); + if (inlen <= 0) + return -1; + + for (i = 0; i < inlen && i < outlen; i++) + out[i] = betoh32(data[i]); + + return i; +} + +/* + * Retrieves node property as an integer. + */ +int +fdt_node_property_int(void *node, char *name, int *out) +{ + return fdt_node_property_ints(node, name, out, 1); +} + +/* * Retrieves next node, skipping all the children nodes of the pointed node */ void * @@ -343,6 +389,52 @@ fdt_parent_node(void *node) return fdt_parent_node_recurse(pnode, node); } +/* + * Parse the memory address and size of a node. + */ +int +fdt_get_memory_address(void *node, int idx, struct fdt_memory *mem) +{ + void *parent; + int ac, sc, off, ret, *in, inlen; + + if (node == NULL) + return 1; + + parent = fdt_parent_node(node); + if (parent == NULL) + return 1; + + /* We only support 32-bit (1), and 64-bit (2) wide addresses here. */ + ret = fdt_node_property_int(parent, "#address-cells", &ac); + if (ret != 1 || ac <= 0 || ac > 2) + return 1; + + /* We only support 32-bit (1), and 64-bit (2) wide sizes here. */ + ret = fdt_node_property_int(parent, "#size-cells", &sc); + if (ret != 1 || sc <= 0 || sc > 2) + return 1; + + inlen = fdt_node_property(node, "reg", (char **)&in) / sizeof(int); + if (inlen < ((idx + 1) * (ac + sc))) + return 1; + + off = idx * (ac + sc); + + mem->addr = betoh32(in[off]); + if (ac == 2) + mem->addr = (mem->addr << 32) + betoh32(in[off + 1]); + + mem->size = betoh32(in[off + ac]); + if (sc == 2) + mem->size = (mem->size << 32) + betoh32(in[off + ac + 1]); + + /* TODO: translate memory address in ranges */ + //return fdt_translate_memory_address(parent, mem); + + return 0; +} + #ifdef DEBUG /* * Debug methods for printing whole tree, particular odes and properies diff --git a/sys/dev/ofw/fdt.h b/sys/dev/ofw/fdt.h index 6a2123962fb..ff5ef0d13c3 100644 --- a/sys/dev/ofw/fdt.h +++ b/sys/dev/ofw/fdt.h @@ -1,4 +1,4 @@ -/* $OpenBSD: fdt.h,v 1.1 2016/03/03 02:42:16 bmercer Exp $ */ +/* $OpenBSD: fdt.h,v 1.2 2016/04/03 12:32:13 patrick Exp $ */ /* * Copyright (c) 2009 Dariusz Swiderski <sfires@sfires.net> @@ -38,6 +38,11 @@ struct fdt { int strings_size; }; +struct fdt_memory { + uint64_t addr; + uint64_t size; +}; + #define FDT_MAGIC 0xd00dfeed #define FDT_NODE_BEGIN 0x01 #define FDT_NODE_END 0x02 @@ -48,12 +53,14 @@ struct fdt { #define FDT_CODE_VERSION 0x11 int fdt_init(void *); +size_t fdt_get_size(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 *); +int fdt_get_memory_address(void *, int, struct fdt_memory *); #ifdef DEBUG void *fdt_print_property(void *, int); void fdt_print_node(void *, int); |