A valid FDT consists of a FDT that was created using libfdt being
retrieved via 'current_machine->fdt' in device_tree.c. This condition is
met by most FDT users in QEMU.
Cc: Dr. David Alan Gilbert <dgilb...@redhat.com>
Signed-off-by: Daniel Henrique Barboza <danielhb...@gmail.com>
---
hmp-commands.hx | 13 +++++++++++++
include/sysemu/device_tree.h | 2 ++
monitor/misc.c | 13 +++++++++++++
softmmu/device_tree.c | 18 ++++++++++++++++++
4 files changed, 46 insertions(+)
diff --git a/hmp-commands.hx b/hmp-commands.hx
index c9d465735a..3c134cf652 100644
--- a/hmp-commands.hx
+++ b/hmp-commands.hx
@@ -1768,3 +1768,16 @@ ERST
"\n\t\t\t -b to specify dirty bitmap as method of
calculation)",
.cmd = hmp_calc_dirty_rate,
},
+
+ {
+ .name = "fdt-save",
+ .args_type = "filename:s",
+ .params = "[filename] file to save the FDT",
+ .help = "save the FDT in the 'filename' file to be decoded using
dtc",
+ .cmd = hmp_fdt_save,
+ },
+
+SRST
+``fdt-save`` *filename*
+ Save the FDT in the 'filename' file to be decoded using dtc
+ERST
diff --git a/include/sysemu/device_tree.h b/include/sysemu/device_tree.h
index ef060a9759..1397adb21c 100644
--- a/include/sysemu/device_tree.h
+++ b/include/sysemu/device_tree.h
@@ -123,6 +123,8 @@ int qemu_fdt_nop_node(void *fdt, const char *node_path);
int qemu_fdt_add_subnode(void *fdt, const char *name);
int qemu_fdt_add_path(void *fdt, const char *path);
+void fdt_save(const char *filename, Error **errp);
+
#define qemu_fdt_setprop_cells(fdt, node_path, property, ...) \
do { \
uint32_t qdt_tmp[] = { __VA_ARGS__ }; \
diff --git a/monitor/misc.c b/monitor/misc.c
index 3d2312ba8d..145285cec0 100644
--- a/monitor/misc.c
+++ b/monitor/misc.c
@@ -78,6 +78,7 @@
#include "qapi/qmp-event.h"
#include "sysemu/cpus.h"
#include "qemu/cutils.h"
+#include "sysemu/device_tree.h"
#if defined(TARGET_S390X)
#include "hw/s390x/storage-keys.h"
@@ -936,6 +937,18 @@ static void hmp_boot_set(Monitor *mon, const QDict *qdict)
}
}
+static void hmp_fdt_save(Monitor *mon, const QDict *qdict)
+{
+ const char *path = qdict_get_str(qdict, "filename");
+ Error *local_err = NULL;
+
+ fdt_save(path, &local_err);
+
+ if (local_err) {
+ error_report_err(local_err);
+ }
+}
+
static void hmp_info_mtree(Monitor *mon, const QDict *qdict)
{
bool flatview = qdict_get_try_bool(qdict, "flatview", false);
diff --git a/softmmu/device_tree.c b/softmmu/device_tree.c
index 6ca3fad285..eeab6a5ef0 100644
--- a/softmmu/device_tree.c
+++ b/softmmu/device_tree.c
@@ -643,3 +643,21 @@ out:
g_free(propcells);
return ret;
}
+
+void fdt_save(const char *filename, Error **errp)
+{
+ int size;
+
+ if (!current_machine->fdt) {
+ error_setg(errp, "Unable to find the machine FDT");
+ return;
+ }
+
+ size = fdt_totalsize(current_machine->fdt);
+
+ if (g_file_set_contents(filename, current_machine->fdt, size, NULL)) {
+ return;
+ }
+
+ error_setg(errp, "Error when saving machine FDT to file %s", filename);
+}