qemu-devel
[Top][All Lists]
Advanced

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

[Qemu-devel] [PATCH] qom: add option -dt-printf wich writes DeviceClass


From: goremykin
Subject: [Qemu-devel] [PATCH] qom: add option -dt-printf wich writes DeviceClass hierarchy in file
Date: Tue, 12 Jul 2016 18:33:17 +0300

From: goremykin <address@hidden>

Option -dt-printf 'file' writes Device Tree (DiveceClass hierarchy) to
'file' using Json format. This helps developers visualize the hierarchy
of DeviceClass and its properties.

Signed-off-by: Oleg Goremykin <address@hidden>
---
 include/qom/qom-dt.h |  22 ++++++++
 qemu-options.hx      |  16 ++++++
 qom/Makefile.objs    |   1 +
 qom/qom-dt.c         | 142 +++++++++++++++++++++++++++++++++++++++++++++++++++
 vl.c                 |   4 ++
 5 files changed, 185 insertions(+)
 create mode 100644 include/qom/qom-dt.h
 create mode 100644 qom/qom-dt.c

diff --git a/include/qom/qom-dt.h b/include/qom/qom-dt.h
new file mode 100644
index 0000000..bb641f0
--- /dev/null
+++ b/include/qom/qom-dt.h
@@ -0,0 +1,22 @@
+/*
+ * Device Tree (DeviceClass hierarchy)
+ *
+ * Copyright ISP RAS, 2016
+ *
+ * Created on: Jul 6, 2016
+ *     Author: Oleg Goremykin <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#ifndef INCLUDE_QOM_QOM_DT_H_
+#define INCLUDE_QOM_QOM_DT_H_
+
+/**
+ * dt_printf: writes Device Tree (DiveceClass hierarchy) to @file_name
+ * @file_name: output file name
+ */
+int dt_printf(const char *file_name);
+
+#endif /* INCLUDE_QOM_QOM_DT_H_ */
diff --git a/qemu-options.hx b/qemu-options.hx
index 9692e53..0140bc4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -96,6 +96,22 @@ STEXI
 Select CPU model (@code{-cpu help} for list and additional feature selection)
 ETEXI
 
+DEF("dt-printf", HAS_ARG, QEMU_OPTION_dt_printf,
+    "-dt-printf create FILE with device tree\n", QEMU_ARCH_ALL)
+STEXI
address@hidden -dt-printf @var{file}
address@hidden -dt-printf
+Write DeviceClass hierarchy to @var{file} in JSON format.
+The @var{file} contains a list of DeviceClass.
+Each DeviceClass is a collection with following fields:
+-children: list of DeviceClass to which current class is parent_class
+-type: name of device (string)
+-property: list of device properties where each property is a collection
+Each property in list has following fields:
+-name: property name (string)
+-type: property qtype (number)
+ETEXI
+
 DEF("smp", HAS_ARG, QEMU_OPTION_smp,
     "-smp 
[cpus=]n[,maxcpus=cpus][,cores=cores][,threads=threads][,sockets=sockets]\n"
     "                set the number of CPUs to 'n' [default=1]\n"
diff --git a/qom/Makefile.objs b/qom/Makefile.objs
index 516349e..6df3a1e 100644
--- a/qom/Makefile.objs
+++ b/qom/Makefile.objs
@@ -1,4 +1,5 @@
 qom-obj-y = object.o container.o qom-qobject.o
 qom-obj-y += object_interfaces.o
+qom-obj-y += qom-dt.o
 
 common-obj-y = cpu.o
diff --git a/qom/qom-dt.c b/qom/qom-dt.c
new file mode 100644
index 0000000..81b5bec
--- /dev/null
+++ b/qom/qom-dt.c
@@ -0,0 +1,142 @@
+/*
+ * Device Tree (DeviceClass hierarchy)
+ *
+ * Copyright ISP RAS, 2016
+ *
+ * Created on: Jul 6, 2016
+ *     Author: Oleg Goremykin <address@hidden>
+ *
+ * This work is licensed under the terms of the GNU GPL, version 2 or later.
+ * See the COPYING file in the top-level directory.
+ */
+
+#include "qemu/osdep.h"
+#include "qom/qom-dt.h"
+
+#include "qapi/qmp/qjson.h"
+#include "qapi/qmp/qint.h"
+#include "hw/qdev-core.h"
+
+#define DT_PROPERTY "property"
+#define DT_NAME "name"
+#define DT_TYPE "type"
+#define DT_CHILDREN "children"
+
+typedef struct _QOMTreeData QOMTreeData;
+
+struct _QOMTreeData {
+    ObjectClass *root_class;
+    QOMTreeData *prev;
+    QList *list;
+};
+
+static void dt_put_props(Property *props, QDict *device)
+{
+    if (!props) {
+        return;
+    }
+
+    QList *props_list = qlist_new();
+    QString *prop_name;
+    QInt *prop_type;
+    QDict *prop;
+
+    while (props->name) {
+        prop = qdict_new();
+        prop_name = qstring_from_str(props->name);
+        qdict_put_obj(prop, DT_NAME, QOBJECT(prop_name));
+        prop_type = qint_from_int(props->qtype);
+        qdict_put_obj(prop, DT_TYPE, QOBJECT(prop_type));
+        qlist_append_obj(props_list, QOBJECT(prop));
+
+        props++;
+    }
+
+    qdict_put_obj(device, DT_PROPERTY, QOBJECT(props_list));
+}
+
+static void dt_create_tree(ObjectClass *cur_class, void *opaque)
+{
+    QOMTreeData *cur_data = (QOMTreeData *) opaque;
+    QOMTreeData data;
+    QString *qstring;
+    const char *dev_type;
+
+    if (object_class_get_parent(cur_class) != cur_data->root_class) {
+        return;
+    }
+
+    dev_type = object_class_get_name(cur_class);
+
+    if (object_class_dynamic_cast(cur_class, TYPE_DEVICE)) {
+        QList *child_list = qlist_new();
+        QDict *device = qdict_new();
+
+        qstring = qstring_from_str(dev_type);
+
+        qdict_put_obj(device, DT_TYPE, QOBJECT(qstring));
+        qdict_put_obj(device, DT_CHILDREN, QOBJECT(child_list));
+        dt_put_props(DEVICE_CLASS(cur_class)->props, device);
+
+        qlist_append_obj(cur_data->list, QOBJECT(device));
+
+        data.list = child_list;
+    } else {
+        data.list = cur_data->list;
+    }
+
+    data.prev = cur_data;
+    data.root_class = cur_class;
+
+    object_class_foreach(dt_create_tree, 
object_class_get_name(data.root_class),
+                         1, (void *) &data);
+}
+
+static void dt_del_empty_child(QList *device_list, QDict *device)
+{
+    const QListEntry *entry;
+    if (device) {
+        if (qlist_size(device_list) == 0) {
+            qdict_del(device, DT_CHILDREN);
+            return;
+        }
+    }
+
+    if (device_list) {
+        entry = qlist_first(device_list);
+        while (entry) {
+            device = qobject_to_qdict(qlist_entry_obj(entry));
+            dt_del_empty_child(qobject_to_qlist(qdict_get(device, 
DT_CHILDREN)),
+                               device);
+            entry = qlist_next(entry);
+        }
+    }
+}
+
+int dt_printf(const char *file_name)
+{
+    FILE *output_file = fopen(file_name, "w");
+
+    if (!output_file) {
+        fprintf(stderr, "Couldn't open \"%s\": %s", file_name, 
strerror(errno));
+        return 1;
+    }
+
+    QOMTreeData data;
+    QString *str_json;
+
+    data.prev = 0;
+    data.root_class = NULL;
+    data.list = qlist_new();
+
+    object_class_foreach(dt_create_tree, NULL, 1, (void *) &data);
+    dt_del_empty_child(data.list, NULL);
+
+    str_json = qobject_to_json_pretty(QOBJECT(data.list));
+    fprintf(output_file, "%s\n", qstring_get_str(str_json));
+
+    QDECREF(data.list);
+
+    fclose(output_file);
+    return 0;
+}
diff --git a/vl.c b/vl.c
index 5cd0f2a..2ee097c 100644
--- a/vl.c
+++ b/vl.c
@@ -115,6 +115,7 @@ int main(int argc, char **argv)
 #include "ui/qemu-spice.h"
 #include "qapi/string-input-visitor.h"
 #include "qapi/opts-visitor.h"
+#include "qom/qom-dt.h"
 #include "qom/object_interfaces.h"
 #include "qapi-event.h"
 #include "exec/semihost.h"
@@ -3065,6 +3066,9 @@ int main(int argc, char **argv, char **envp)
                 /* hw initialization will check this */
                 cpu_model = optarg;
                 break;
+            case QEMU_OPTION_dt_printf:
+                exit(dt_printf(optarg));
+                break;
             case QEMU_OPTION_hda:
                 {
                     char buf[256];
-- 
1.9.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]