qmp/hmp, device_tree.c: introduce dumpdtb
To save the FDT blob we have the '-machine dumpdtb=<file>' property. With this property set, the machine saves the FDT in <file> and exit. The created file can then be converted to plain text dts format using 'dtc'. There's nothing particularly sophisticated into saving the FDT that can't be done with the machine at any state, as long as the machine has a valid FDT to be saved. The 'dumpdtb' command receives a 'filename' parameter and, if the FDT is available via current_machine->fdt, save it in dtb format to 'filename'. In short, this is a '-machine dumpdtb' that can be fired on demand via QMP/HMP. This command will always be executed in-band (i.e. holding BQL), avoiding potential race conditions with machines that might change the FDT during runtime (e.g. PowerPC 'pseries' machine). Cc: Dr. David Alan Gilbert <dgilbert@redhat.com> Cc: Markus Armbruster <armbru@redhat.com> Cc: Alistair Francis <alistair.francis@wdc.com> Cc: David Gibson <david@gibson.dropbear.id.au> Acked-by: Dr. David Alan Gilbert <dgilbert@redhat.com> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Markus Armbruster <armbru@redhat.com> Signed-off-by: Daniel Henrique Barboza <danielhb413@gmail.com> Message-Id: <20220926173855.1159396-2-danielhb413@gmail.com>
This commit is contained in:
parent
0a3364043d
commit
bf353ad555
@ -1800,3 +1800,18 @@ ERST
|
|||||||
.sub_table = hmp_info_cmds,
|
.sub_table = hmp_info_cmds,
|
||||||
.flags = "p",
|
.flags = "p",
|
||||||
},
|
},
|
||||||
|
|
||||||
|
#if defined(CONFIG_FDT)
|
||||||
|
{
|
||||||
|
.name = "dumpdtb",
|
||||||
|
.args_type = "filename:F",
|
||||||
|
.params = "filename",
|
||||||
|
.help = "dump the FDT in dtb format to 'filename'",
|
||||||
|
.cmd = hmp_dumpdtb,
|
||||||
|
},
|
||||||
|
|
||||||
|
SRST
|
||||||
|
``dumpdtb`` *filename*
|
||||||
|
Dump the FDT in dtb format to *filename*.
|
||||||
|
ERST
|
||||||
|
#endif
|
||||||
|
@ -136,6 +136,7 @@ int qemu_fdt_add_path(void *fdt, const char *path);
|
|||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
void qemu_fdt_dumpdtb(void *fdt, int size);
|
void qemu_fdt_dumpdtb(void *fdt, int size);
|
||||||
|
void hmp_dumpdtb(Monitor *mon, const QDict *qdict);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* qemu_fdt_setprop_sized_cells_from_array:
|
* qemu_fdt_setprop_sized_cells_from_array:
|
||||||
|
@ -49,6 +49,7 @@
|
|||||||
#include "sysemu/blockdev.h"
|
#include "sysemu/blockdev.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "sysemu/tpm.h"
|
#include "sysemu/tpm.h"
|
||||||
|
#include "sysemu/device_tree.h"
|
||||||
#include "qapi/qmp/qdict.h"
|
#include "qapi/qmp/qdict.h"
|
||||||
#include "qapi/qmp/qerror.h"
|
#include "qapi/qmp/qerror.h"
|
||||||
#include "qapi/qmp/qstring.h"
|
#include "qapi/qmp/qstring.h"
|
||||||
|
@ -1664,3 +1664,21 @@
|
|||||||
'*size': 'size',
|
'*size': 'size',
|
||||||
'*max-size': 'size',
|
'*max-size': 'size',
|
||||||
'*slots': 'uint64' } }
|
'*slots': 'uint64' } }
|
||||||
|
|
||||||
|
##
|
||||||
|
# @dumpdtb:
|
||||||
|
#
|
||||||
|
# Save the FDT in dtb format.
|
||||||
|
#
|
||||||
|
# @filename: name of the dtb file to be created
|
||||||
|
#
|
||||||
|
# Since: 7.2
|
||||||
|
#
|
||||||
|
# Example:
|
||||||
|
# {"execute": "dumpdtb"}
|
||||||
|
# "arguments": { "filename": "fdt.dtb" } }
|
||||||
|
#
|
||||||
|
##
|
||||||
|
{ 'command': 'dumpdtb',
|
||||||
|
'data': { 'filename': 'str' },
|
||||||
|
'if': 'CONFIG_FDT' }
|
||||||
|
@ -26,6 +26,9 @@
|
|||||||
#include "hw/loader.h"
|
#include "hw/loader.h"
|
||||||
#include "hw/boards.h"
|
#include "hw/boards.h"
|
||||||
#include "qemu/config-file.h"
|
#include "qemu/config-file.h"
|
||||||
|
#include "qapi/qapi-commands-machine.h"
|
||||||
|
#include "qapi/qmp/qdict.h"
|
||||||
|
#include "monitor/hmp.h"
|
||||||
|
|
||||||
#include <libfdt.h>
|
#include <libfdt.h>
|
||||||
|
|
||||||
@ -643,3 +646,37 @@ out:
|
|||||||
g_free(propcells);
|
g_free(propcells);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void qmp_dumpdtb(const char *filename, Error **errp)
|
||||||
|
{
|
||||||
|
g_autoptr(GError) err = NULL;
|
||||||
|
uint32_t size;
|
||||||
|
|
||||||
|
if (!current_machine->fdt) {
|
||||||
|
error_setg(errp, "This machine doesn't have a FDT");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
size = fdt_totalsize(current_machine->fdt);
|
||||||
|
|
||||||
|
g_assert(size > 0);
|
||||||
|
|
||||||
|
if (!g_file_set_contents(filename, current_machine->fdt, size, &err)) {
|
||||||
|
error_setg(errp, "Error saving FDT to file %s: %s",
|
||||||
|
filename, err->message);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void hmp_dumpdtb(Monitor *mon, const QDict *qdict)
|
||||||
|
{
|
||||||
|
const char *filename = qdict_get_str(qdict, "filename");
|
||||||
|
Error *local_err = NULL;
|
||||||
|
|
||||||
|
qmp_dumpdtb(filename, &local_err);
|
||||||
|
|
||||||
|
if (hmp_handle_error(mon, local_err)) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
info_report("dtb dumped to %s", filename);
|
||||||
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user