[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
- [Qemu-devel] [PATCH] qom: add option -dt-printf wich writes DeviceClass hierarchy in file,
goremykin <=