[Crosstoolchain-logs] [device-tree-compiler] 05/357: First cut at a "libdt" set of routines for extracting things from the flattened tree. Could be used in firmware.

Hector Oron zumbi at moszumanska.debian.org
Thu Dec 8 17:05:41 UTC 2016


This is an automated email from the git hooks/post-receive script.

zumbi pushed a commit to branch upstream/1.3.x
in repository device-tree-compiler.

commit ab870cadb4e0933e3fa6958c2b64f423c478c225
Author: David Gibson <dgibson at sneetch.(none)>
Date:   Thu Jun 23 15:45:13 2005 +1000

    First cut at a "libdt" set of routines for extracting things from the
    flattened tree.  Could be used in firmware.
---
 Makefile   |   2 +-
 flat_dt.h  |  44 +++++++++++++
 flattree.c |  34 +---------
 libdt.c    | 213 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 259 insertions(+), 34 deletions(-)

diff --git a/Makefile b/Makefile
index f9a1050..8cd8a12 100644
--- a/Makefile
+++ b/Makefile
@@ -21,7 +21,7 @@ lex.yy.c: dtc-lexer.l
 
 lex.yy.o: lex.yy.c dtc-parser.tab.h
 
-dtc-parser.c:	dtc-lexer.c
+livetree.o:	flat_dt.h
 
 check: all
 	cd tests && $(MAKE) check
diff --git a/flat_dt.h b/flat_dt.h
new file mode 100644
index 0000000..28b4d03
--- /dev/null
+++ b/flat_dt.h
@@ -0,0 +1,44 @@
+#ifndef _FLAT_DT_H_
+#define _FLAT_DT_H_
+
+
+#define OF_DT_HEADER            0xd00dfeed      /* 4: version, 4: total size */
+
+#define OF_DT_BEGIN_NODE	0x1             /* Start node: full name */
+#define OF_DT_END_NODE		0x2             /* End node */
+#define OF_DT_PROP		0x3             /* Property: name off,
+                                                   size, content */
+#define OF_DT_END               0x9
+
+struct boot_param_header {
+	uint32_t magic;                  /* magic word OF_DT_HEADER */
+	uint32_t totalsize;              /* total size of DT block */
+	uint32_t off_dt_struct;          /* offset to structure */
+	uint32_t off_dt_strings;         /* offset to strings */
+	uint32_t off_mem_rsvmap;         /* offset to memory reserve map */
+	uint32_t version;                /* format version */
+	uint32_t last_comp_version;      /* last compatible version */
+
+        /* version 2 fields below */
+	uint32_t boot_cpuid_phys;        /* Which physical CPU id we're
+					    booting on */
+	/* version 3 fields below */
+        uint32_t size_dt_strings;        /* size of the strings block */
+};
+
+#define BPH_V1_SIZE	(7*sizeof(uint32_t))
+#define BPH_V2_SIZE	(BPH_V1_SIZE + sizeof(uint32_t))
+#define BPH_V3_SIZE	(BPH_V2_SIZE + sizeof(uint32_t))
+
+struct reserve_entry {
+	uint64_t address;
+	uint64_t size;
+};
+
+struct flat_dt_property {
+	uint32_t nameoff;
+	uint32_t len;
+	char data[0];
+};
+
+#endif /* _FLAT_DT_H_ */
diff --git a/flattree.c b/flattree.c
index 28427ab..2b8efdd 100644
--- a/flattree.c
+++ b/flattree.c
@@ -19,39 +19,7 @@
  */
 
 #include "dtc.h"
-
-#define OF_DT_HEADER            0xd00dfeed      /* 4: version, 4: total size */
-
-#define OF_DT_BEGIN_NODE	0x1             /* Start node: full name */
-#define OF_DT_END_NODE		0x2             /* End node */
-#define OF_DT_PROP		0x3             /* Property: name off,
-                                                   size, content */
-#define OF_DT_END               0x9
-
-struct boot_param_header {
-	u32 magic;                  /* magic word OF_DT_HEADER */
-	u32 totalsize;              /* total size of DT block */
-	u32 off_dt_struct;          /* offset to structure */
-	u32 off_dt_strings;         /* offset to strings */
-	u32 off_mem_rsvmap;         /* offset to memory reserve map */
-	u32 version;                /* format version */
-	u32 last_comp_version;      /* last compatible version */
-
-        /* version 2 fields below */
-	u32 boot_cpuid_phys;        /* Which physical CPU id we're
-					    booting on */
-	/* version 3 fields below */
-        u32 size_dt_strings;        /* size of the strings block */
-};
-
-#define BPH_V1_SIZE	(7*sizeof(u32))
-#define BPH_V2_SIZE	(BPH_V1_SIZE + sizeof(u32))
-#define BPH_V3_SIZE	(BPH_V2_SIZE + sizeof(u32))
-
-struct reserve_entry {
-	u64 address;
-	u64 size;
-};
+#include "flat_dt.h"
 
 #define FTF_FULLPATH	0x1
 #define FTF_VARALIGN	0x2
diff --git a/libdt.c b/libdt.c
new file mode 100644
index 0000000..df50402
--- /dev/null
+++ b/libdt.c
@@ -0,0 +1,213 @@
+#include <stdint.h>
+#include <string.h>
+
+#include "flat_dt.h"
+
+typedef uint32_t u32;
+typedef uint64_t u64;
+
+#define ALIGN(x, a)	(((x) + ((a) - 1)) & ((a) - 1))
+#define PALIGN(p, a)	((void *)(ALIGN((unsigned long)(p), (a))))
+
+#define GET_CELL(p)	(p += 4, *((u32 *)(p-4)))
+
+static char *skip_name(char *p)
+{
+	while (*p != '\0')
+		p++;
+
+	return PALIGN(p, sizeof(u32));
+}
+
+static char *skip_prop(void *blob, char *p)
+{
+	struct boot_param_header *bph = blob;
+	u32 len, nameoff;
+
+	len = GET_CELL(p);
+	nameoff = GET_CELL(p);
+	if ((bph->version < 0x10) && (len >= sizeof(u64)))
+		p = PALIGN(p, sizeof(u64));
+	return PALIGN(p + len, sizeof(u32));
+}
+
+static char *get_unit(char *dtpath)
+{
+	char *p;
+
+	if (dtpath[0] != '/')
+		return dtpath;
+
+	p = dtpath + strlen(dtpath);
+	while (*p != '/')
+		p--;
+
+	return p+1;
+}
+
+static int first_seg_len(char *dtpath)
+{
+	int len = 0;
+
+	while ((dtpath[len] != '/') && (dtpath[len] != '\0'))
+		len++;
+
+	return len;
+}
+
+char *flat_dt_get_string(void *blob, u32 offset)
+{
+	struct boot_param_header *bph = blob;
+
+	return (char *)blob + bph->off_dt_strings + offset;
+}
+
+void *flat_dt_get_subnode(void *blob, void *node, char *uname, int unamelen)
+{
+	struct boot_param_header *bph = blob;
+	char *p = node;
+	u32 tag;
+	int depth = 0;
+	char *nuname;
+
+	if (! unamelen)
+		unamelen = strlen(uname);
+
+	do {
+		tag = GET_CELL(p);
+
+		switch (tag) {
+		case OF_DT_PROP:
+			p = skip_prop(blob, p);
+			break;
+
+		case OF_DT_BEGIN_NODE:
+			if (depth == 0) {
+				nuname = p;
+
+				if (bph->version < 0x10)
+					nuname = get_unit(nuname);
+
+				p = skip_name(p);
+
+				if (strncmp(nuname, uname, unamelen) == 0)
+					return p;
+			}
+			depth++;
+			break;
+
+		case OF_DT_END_NODE:
+			depth--;
+			break;
+
+		case OF_DT_END:
+			/* looks like a malformed tree */
+			return NULL;
+			break;
+
+		default:
+			/* FIXME: throw some sort of error */
+			return NULL;
+		}
+	} while (depth >= 0);
+
+	return NULL;
+}
+
+void *flat_dt_get_node(void *blob, char *path)
+{
+	struct boot_param_header *bph = blob;
+	char *node;
+	int seglen;
+
+	node = blob + bph->off_dt_struct;
+	node += sizeof(u32); /* skip initial OF_DT_BEGIN_NODE */
+	node = skip_name(node);	/* skip root node name */
+
+	while (node && (*path)) {
+		if (path[0] == '/')
+			path++;
+
+		seglen = first_seg_len(path);
+
+		node = flat_dt_get_subnode(blob, node, path, seglen);
+
+		path += seglen;
+	}
+
+	return node;
+}
+
+void flat_dt_traverse(void *blob, int (*fn)(void *blob, void *node, void *priv),
+		      void *private)
+{
+	struct boot_param_header *bph = blob;
+	char *p;
+	u32 tag;
+	int depth = 0;
+	char *uname;
+
+	p = (char *)blob + bph->off_dt_struct;
+
+	tag = GET_CELL(p);
+	while (tag != OF_DT_END) {
+		switch (tag) {
+		case OF_DT_BEGIN_NODE:
+			uname = p;
+
+			if (bph->version < 0x10)
+				uname = get_unit(uname);
+
+			p = skip_name(p);
+
+			(*fn)(blob, p, private);
+			depth++;
+			break;
+
+		case OF_DT_END_NODE:
+			depth--;
+			break;
+
+		case OF_DT_PROP:
+			p = skip_prop(blob, p);
+			break;
+
+		default:
+			/* FIXME: badly formed tree */
+			return;
+		}
+	}
+}
+
+void *flat_dt_get_prop(void *blob, void *node, char *name, u32 *len)
+{
+	struct boot_param_header *bph = blob;
+	char *p = node;
+
+	do {
+		u32 tag = GET_CELL(p);
+		u32 sz, noff;
+		const char *nstr;
+
+		if (tag != OF_DT_PROP)
+			return NULL;
+
+		sz = GET_CELL(p);
+		noff = GET_CELL(p);
+
+		/* Old versions have variable alignment of the
+		 * property value */
+		if ((bph->version < 0x10) && (sz >= 8))
+		    p = PALIGN(p, 8);
+
+		nstr = flat_dt_get_string(blob, noff);
+
+		if (strcmp(name, nstr) == 0) {
+			if (len)
+				*len = sz;
+			return (void *)p;
+		}
+
+		p = PALIGN(p + sz, sizeof(u32));
+	} while(1);
+}

-- 
Alioth's /usr/local/bin/git-commit-notice on /srv/git.debian.org/git/crosstoolchain/device-tree-compiler.git



More information about the Crosstoolchain-logs mailing list