summaryrefslogtreecommitdiff
path: root/sys/dev/ofw
diff options
context:
space:
mode:
authorPatrick Wildt <patrick@cvs.openbsd.org>2016-04-03 12:32:14 +0000
committerPatrick Wildt <patrick@cvs.openbsd.org>2016-04-03 12:32:14 +0000
commit46d09009cf7d250de1cb18476b3227471b3ca285 (patch)
tree2b2e98648f17674592c723b826ac6dc6c1caeb64 /sys/dev/ofw
parentcc46d7897478b2e8ad89339f96964992c93eca22 (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.c94
-rw-r--r--sys/dev/ofw/fdt.h9
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);