For example: ./qemu-system -device virtio-blk,help
will raise the following error: qemu-system: -device virtio-blk,help: Device alias 'virtio-blk' is ambiguous without a selected machine Specify -machine <arch>-<machine-name> or an unambiguous <machine-name>, or use a concrete device name: virtio-blk-device virtio-blk-pci Signed-off-by: Yonggang Luo <[email protected]> --- include/monitor/qdev.h | 7 ++++++ system/qdev-monitor.c | 52 ++++++++++++++++++++++++++++++++++++++---- system/vl.c | 7 +++--- 3 files changed, 58 insertions(+), 8 deletions(-) diff --git a/include/monitor/qdev.h b/include/monitor/qdev.h index 8f7e2f616cf..92dd4e35351 100644 --- a/include/monitor/qdev.h +++ b/include/monitor/qdev.h @@ -10,6 +10,13 @@ void hmp_info_qtree(MonitorHMP *hmp, const QDict *qdict); void hmp_info_qdm(MonitorHMP *hmp, const QDict *qdict); void qmp_device_add(QDict *qdict, QObject **ret_data, Error **errp); +/** + * qdev_device_help: print device listing or property help when requested. + * @opts: device options + * + * Returns: 0 if no help was requested, 1 if handled, or -1 if an ambiguous + * alias prevented help. Other property-help errors retain the handled result. + */ int qdev_device_help(QemuOpts *opts); DeviceState *qdev_device_add(QemuOpts *opts, Error **errp); DeviceState *qdev_device_add_from_qdict(const QDict *opts, diff --git a/system/qdev-monitor.c b/system/qdev-monitor.c index b3ca619f3c9..8ab19568b0d 100644 --- a/system/qdev-monitor.c +++ b/system/qdev-monitor.c @@ -24,6 +24,8 @@ #include "monitor/monitor.h" #include "monitor/qdev.h" #include "qemu/base-arch-defs.h" +#include "qemu/target-info.h" +#include "qemu/target-info-def.h" #include "system/runstate.h" #include "qapi/error.h" #include "qapi/qapi-commands-qdev.h" @@ -217,10 +219,18 @@ static void qdev_print_devinfos(bool show_no_user) g_slist_free(list); } -static const char *find_typename_by_alias(const char *alias) +static const char *find_typename_by_alias(const char *alias, Error **errp) { + ERRP_GUARD(); + bool unselected = target_combined_binary() && !target_info(); + const char *match = NULL; + g_autoptr(GString) hints = NULL; + unsigned count = 0; int i; + if (unselected) { + hints = g_string_new(NULL); + } for (i = 0; qdev_alias_table[i].alias; i++) { if (qdev_alias_table[i].arch_mask && !qemu_arch_available(qdev_alias_table[i].arch_mask)) { @@ -228,11 +238,32 @@ static const char *find_typename_by_alias(const char *alias) } if (strcmp(qdev_alias_table[i].alias, alias) == 0) { - return qdev_alias_table[i].typename; + const char *typename = qdev_alias_table[i].typename; + + if (!unselected) { + return typename; + } + ObjectClass *oc = module_object_class_by_name(typename); + + if (!object_class_dynamic_cast(oc, TYPE_DEVICE) || + object_class_is_abstract(oc)) { + continue; + } + match = typename; + count++; + g_string_append_printf(hints, " %s\n", typename); } } - return NULL; + if (count > 1) { + error_setg(errp, "Device alias '%s' is ambiguous without a " + "selected machine", alias); + error_append_hint(errp, "Specify -machine <arch>-<machine-name> or " + "an unambiguous <machine-name>, or use a " + "concrete device name:\n%s", hints->str); + return NULL; + } + return match; } static DeviceClass *qdev_get_device_class(const char **driver, Error **errp) @@ -243,7 +274,13 @@ static DeviceClass *qdev_get_device_class(const char **driver, Error **errp) oc = module_object_class_by_name(*driver); if (!oc) { - const char *typename = find_typename_by_alias(*driver); + Error *local_err = NULL; + const char *typename = find_typename_by_alias(*driver, &local_err); + + if (local_err) { + error_propagate(errp, local_err); + return NULL; + } if (typename) { *driver = typename; @@ -308,7 +345,12 @@ int qdev_device_help(QemuOpts *opts) } if (!object_class_by_name(driver)) { - const char *typename = find_typename_by_alias(driver); + const char *typename = find_typename_by_alias(driver, &local_err); + + if (local_err) { + error_report_err(local_err); + return -1; + } if (typename) { driver = typename; diff --git a/system/vl.c b/system/vl.c index bad13393f24..068fa5e12ad 100644 --- a/system/vl.c +++ b/system/vl.c @@ -2795,9 +2795,10 @@ static void qemu_process_help_options(void) exit(0); } - if (qemu_opts_foreach(qemu_find_opts("device"), - device_help_func, NULL, NULL)) { - exit(0); + int device_help = qemu_opts_foreach(qemu_find_opts("device"), + device_help_func, NULL, NULL); + if (device_help) { + exit(device_help < 0 ? EXIT_FAILURE : EXIT_SUCCESS); } /* -L help lists the data directories and exits. */ -- 2.55.0.windows.3
