[RFC PATCH v3 2/4] dtc: Add a live tree API

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]



The purpose of this API is to completely abstract away the internal live
tree implementation.

This API can traverse the tree and read its values. This is enough to
validate the tree in Python, for example. We could add more
functionality, documentation and tests, and turn it into a separate
library.

Signed-off-by: Andrei Ziureaev <andrei.ziureaev@xxxxxxx>
Signed-off-by: Andrei Ziureaev <andreiziureaev@xxxxxxxxx>
---
 Makefile.dtc |   1 +
 dt.c         | 158 +++++++++++++++++++++++++++++++++++++++++++++++++++
 dt.h         |  63 ++++++++++++++++++++
 3 files changed, 222 insertions(+)
 create mode 100644 dt.c
 create mode 100644 dt.h

diff --git a/Makefile.dtc b/Makefile.dtc
index 9c467b0..09b3123 100644
--- a/Makefile.dtc
+++ b/Makefile.dtc
@@ -7,6 +7,7 @@
 DTC_SRCS = \
 	checks.c \
 	data.c \
+	dt.c \
 	dtc.c \
 	flattree.c \
 	fstree.c \
diff --git a/dt.c b/dt.c
new file mode 100644
index 0000000..5024e63
--- /dev/null
+++ b/dt.c
@@ -0,0 +1,158 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+/*
+ * (C) Copyright Arm Holdings.  2020
+ */
+
+#include "dt.h"
+#include "dtc.h"
+
+struct node *dt_root(struct dt_info *dti)
+{
+	return dti->dt;
+}
+
+struct node *dt_first_child(struct node *node)
+{
+	return node->children;
+}
+
+struct node *dt_next_sibling(struct node *node)
+{
+	return node->next_sibling;
+}
+
+struct property *dt_first_property(struct node *node)
+{
+	return node->proplist;
+}
+
+struct property *dt_next_property(struct property *prop)
+{
+	return prop->next;
+}
+
+struct marker *dt_first_row(struct property *prop)
+{
+	return next_type_marker(prop->val.markers);
+}
+
+struct marker *dt_next_row(struct marker *row)
+{
+	return next_type_marker(row->next);
+}
+
+int dt_row_length(struct property *prop, struct marker *row)
+{
+	int length_bytes = type_marker_length(row) ? : prop->val.len - row->offset;
+	return length_bytes / dt_cell_width_bytes(row);
+}
+
+uint64_t dt_uint(struct property *prop, struct marker *row, int col)
+{
+	int width = dt_cell_width_bytes(row);
+	const char *p = &dt_string(prop, row)[col * width];
+
+	switch(width) {
+	case 2:
+		return dtb_ld16(p);
+	case 4:
+		return dtb_ld32(p);
+	case 8:
+		return dtb_ld64(p);
+	default:
+		return *(const uint8_t*)p;
+	}
+}
+
+bool dt_cell_is_phandle(struct property *prop, struct marker *row, int col)
+{
+	int width = dt_cell_width_bytes(row);
+	int off = row->offset + col * width;
+
+	if (width != 4)
+		return false;
+
+	return markers_have_type_at_offset(row, REF_PHANDLE, off);
+}
+
+const char *dt_string(struct property *prop, struct marker *row)
+{
+	return &prop->val.val[row->offset];
+}
+
+enum dt_type dt_row_type(struct marker *row)
+{
+	switch (row->type) {
+	/* fallthrough */
+	case TYPE_UINT8:
+	case TYPE_UINT16:
+	case TYPE_UINT32:
+	case TYPE_UINT64:
+		return DT_TYPE_UINT;
+	case TYPE_STRING:
+		return DT_TYPE_STRING;
+	default:
+		return DT_TYPE_NONE;
+	}
+}
+
+const char *dt_row_type_name(struct marker *row)
+{
+	switch (dt_row_type(row)) {
+	case DT_TYPE_UINT:
+		return "uint";
+	case DT_TYPE_STRING:
+		return "string";
+	default:
+		return "none";
+	}
+}
+
+int dt_cell_width_bytes(struct marker *row)
+{
+	switch (row->type) {
+	case TYPE_UINT16:
+		return 2;
+	case TYPE_UINT32:
+		return 4;
+	case TYPE_UINT64:
+		return 8;
+	default:
+		return 1;
+	}
+}
+
+const char *dt_node_name(struct node *node)
+{
+	return *node->name ? node->name : "/";
+}
+
+struct srcpos *dt_node_srcpos(struct node *node)
+{
+	return node->srcpos;
+}
+
+const char *dt_property_name(struct property *prop)
+{
+	return prop->name;
+}
+
+struct srcpos *dt_property_srcpos(struct property *prop)
+{
+	return prop->srcpos;
+}
+
+const char *dt_srcpos_dir(struct srcpos *srcpos)
+{
+	return srcpos->file->dir;
+}
+
+const char *dt_srcpos_file_name(struct srcpos *srcpos)
+{
+	return srcpos->file->name;
+}
+
+int dt_srcpos_first_line(struct srcpos *srcpos)
+{
+	return srcpos->first_line;
+}
diff --git a/dt.h b/dt.h
new file mode 100644
index 0000000..c6af112
--- /dev/null
+++ b/dt.h
@@ -0,0 +1,63 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#ifndef DT_H
+#define DT_H
+
+/*
+ * (C) Copyright Arm Holdings.  2020
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+
+#include "srcpos.h"
+
+struct dt_info;
+struct node;
+struct property;
+struct marker;
+
+enum dt_type {
+	DT_TYPE_NONE,
+	DT_TYPE_UINT,
+	DT_TYPE_STRING,
+};
+
+/* Traversal */
+struct node *dt_root(struct dt_info *dti);
+
+struct node *dt_first_child(struct node *node);
+struct node *dt_next_sibling(struct node *node);
+
+struct property *dt_first_property(struct node *node);
+struct property *dt_next_property(struct property *prop);
+
+/* A property value resembles a matrix (or a table). A marker with data
+ * type information can represent a row.
+ *
+ * So, each property has a linked list of rows. */
+struct marker *dt_first_row(struct property *prop);
+struct marker *dt_next_row(struct marker *row);
+
+/* Accessing data. Each row is an array of cells. */
+int dt_row_length(struct property *prop, struct marker *row);
+
+uint64_t dt_uint(struct property *prop, struct marker *row, int col);
+bool dt_cell_is_phandle(struct property *prop, struct marker *row, int col);
+const char *dt_string(struct property *prop, struct marker *row);
+
+/* Accessing metadata */
+enum dt_type dt_row_type(struct marker *row);
+const char *dt_row_type_name(struct marker *row);
+int dt_cell_width_bytes(struct marker *row);
+
+const char *dt_node_name(struct node *node);
+struct srcpos *dt_node_srcpos(struct node *node);
+
+const char *dt_property_name(struct property *prop);
+struct srcpos *dt_property_srcpos(struct property *prop);
+
+const char *dt_srcpos_dir(struct srcpos *srcpos);
+const char *dt_srcpos_file_name(struct srcpos *srcpos);
+int dt_srcpos_first_line(struct srcpos *srcpos);
+
+#endif /* DT_H */
-- 
2.17.1




[Index of Archives]     [Device Tree]     [Device Tree Spec]     [Linux Driver Backports]     [Video for Linux]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux