1f1b3ccfaSKevin Wolf /* 2f1b3ccfaSKevin Wolf * QEMU Management Protocol commands 3f1b3ccfaSKevin Wolf * 4f1b3ccfaSKevin Wolf * Copyright IBM, Corp. 2011 5f1b3ccfaSKevin Wolf * 6f1b3ccfaSKevin Wolf * Authors: 7f1b3ccfaSKevin Wolf * Anthony Liguori <aliguori@us.ibm.com> 8f1b3ccfaSKevin Wolf * 9f1b3ccfaSKevin Wolf * This work is licensed under the terms of the GNU GPL, version 2. See 10f1b3ccfaSKevin Wolf * the COPYING file in the top-level directory. 11f1b3ccfaSKevin Wolf * 12f1b3ccfaSKevin Wolf * Contributions after 2012-01-13 are licensed under the terms of the 13f1b3ccfaSKevin Wolf * GNU GPL, version 2 or (at your option) any later version. 14f1b3ccfaSKevin Wolf */ 15f1b3ccfaSKevin Wolf 16f1b3ccfaSKevin Wolf #include "qemu/osdep.h" 17f1b3ccfaSKevin Wolf #include "qemu-common.h" 18f1b3ccfaSKevin Wolf #include "qemu-version.h" 19f1b3ccfaSKevin Wolf #include "qemu/cutils.h" 20f1b3ccfaSKevin Wolf #include "qemu/option.h" 21f1b3ccfaSKevin Wolf #include "monitor/monitor.h" 22f1b3ccfaSKevin Wolf #include "sysemu/sysemu.h" 23f1b3ccfaSKevin Wolf #include "qemu/config-file.h" 24f1b3ccfaSKevin Wolf #include "qemu/uuid.h" 25f1b3ccfaSKevin Wolf #include "chardev/char.h" 26f1b3ccfaSKevin Wolf #include "ui/qemu-spice.h" 27f1b3ccfaSKevin Wolf #include "ui/vnc.h" 28f1b3ccfaSKevin Wolf #include "sysemu/kvm.h" 29f1b3ccfaSKevin Wolf #include "sysemu/arch_init.h" 30f1b3ccfaSKevin Wolf #include "hw/qdev.h" 31f1b3ccfaSKevin Wolf #include "sysemu/blockdev.h" 32f1b3ccfaSKevin Wolf #include "sysemu/block-backend.h" 33f1b3ccfaSKevin Wolf #include "qom/qom-qobject.h" 34f1b3ccfaSKevin Wolf #include "qapi/error.h" 35f1b3ccfaSKevin Wolf #include "qapi/qapi-commands-block-core.h" 36f1b3ccfaSKevin Wolf #include "qapi/qapi-commands-misc.h" 37f1b3ccfaSKevin Wolf #include "qapi/qapi-commands-ui.h" 38f1b3ccfaSKevin Wolf #include "qapi/qmp/qdict.h" 39f1b3ccfaSKevin Wolf #include "qapi/qmp/qerror.h" 40f1b3ccfaSKevin Wolf #include "qapi/qobject-input-visitor.h" 41f1b3ccfaSKevin Wolf #include "hw/boards.h" 42f1b3ccfaSKevin Wolf #include "qom/object_interfaces.h" 43f1b3ccfaSKevin Wolf #include "hw/mem/memory-device.h" 44f1b3ccfaSKevin Wolf #include "hw/acpi/acpi_dev_interface.h" 45f1b3ccfaSKevin Wolf 46f1b3ccfaSKevin Wolf NameInfo *qmp_query_name(Error **errp) 47f1b3ccfaSKevin Wolf { 48f1b3ccfaSKevin Wolf NameInfo *info = g_malloc0(sizeof(*info)); 49f1b3ccfaSKevin Wolf 50f1b3ccfaSKevin Wolf if (qemu_name) { 51f1b3ccfaSKevin Wolf info->has_name = true; 52f1b3ccfaSKevin Wolf info->name = g_strdup(qemu_name); 53f1b3ccfaSKevin Wolf } 54f1b3ccfaSKevin Wolf 55f1b3ccfaSKevin Wolf return info; 56f1b3ccfaSKevin Wolf } 57f1b3ccfaSKevin Wolf 58f1b3ccfaSKevin Wolf VersionInfo *qmp_query_version(Error **errp) 59f1b3ccfaSKevin Wolf { 60f1b3ccfaSKevin Wolf VersionInfo *info = g_new0(VersionInfo, 1); 61f1b3ccfaSKevin Wolf 62f1b3ccfaSKevin Wolf info->qemu = g_new0(VersionTriple, 1); 63f1b3ccfaSKevin Wolf info->qemu->major = QEMU_VERSION_MAJOR; 64f1b3ccfaSKevin Wolf info->qemu->minor = QEMU_VERSION_MINOR; 65f1b3ccfaSKevin Wolf info->qemu->micro = QEMU_VERSION_MICRO; 66f1b3ccfaSKevin Wolf info->package = g_strdup(QEMU_PKGVERSION); 67f1b3ccfaSKevin Wolf 68f1b3ccfaSKevin Wolf return info; 69f1b3ccfaSKevin Wolf } 70f1b3ccfaSKevin Wolf 71f1b3ccfaSKevin Wolf KvmInfo *qmp_query_kvm(Error **errp) 72f1b3ccfaSKevin Wolf { 73f1b3ccfaSKevin Wolf KvmInfo *info = g_malloc0(sizeof(*info)); 74f1b3ccfaSKevin Wolf 75f1b3ccfaSKevin Wolf info->enabled = kvm_enabled(); 76f1b3ccfaSKevin Wolf info->present = kvm_available(); 77f1b3ccfaSKevin Wolf 78f1b3ccfaSKevin Wolf return info; 79f1b3ccfaSKevin Wolf } 80f1b3ccfaSKevin Wolf 81f1b3ccfaSKevin Wolf UuidInfo *qmp_query_uuid(Error **errp) 82f1b3ccfaSKevin Wolf { 83f1b3ccfaSKevin Wolf UuidInfo *info = g_malloc0(sizeof(*info)); 84f1b3ccfaSKevin Wolf 85f1b3ccfaSKevin Wolf info->UUID = qemu_uuid_unparse_strdup(&qemu_uuid); 86f1b3ccfaSKevin Wolf return info; 87f1b3ccfaSKevin Wolf } 88f1b3ccfaSKevin Wolf 89f1b3ccfaSKevin Wolf void qmp_quit(Error **errp) 90f1b3ccfaSKevin Wolf { 91f1b3ccfaSKevin Wolf no_shutdown = 0; 92f1b3ccfaSKevin Wolf qemu_system_shutdown_request(SHUTDOWN_CAUSE_HOST_QMP_QUIT); 93f1b3ccfaSKevin Wolf } 94f1b3ccfaSKevin Wolf 95f1b3ccfaSKevin Wolf void qmp_stop(Error **errp) 96f1b3ccfaSKevin Wolf { 97f1b3ccfaSKevin Wolf /* if there is a dump in background, we should wait until the dump 98f1b3ccfaSKevin Wolf * finished */ 99f1b3ccfaSKevin Wolf if (dump_in_progress()) { 100f1b3ccfaSKevin Wolf error_setg(errp, "There is a dump in process, please wait."); 101f1b3ccfaSKevin Wolf return; 102f1b3ccfaSKevin Wolf } 103f1b3ccfaSKevin Wolf 104f1b3ccfaSKevin Wolf if (runstate_check(RUN_STATE_INMIGRATE)) { 105f1b3ccfaSKevin Wolf autostart = 0; 106f1b3ccfaSKevin Wolf } else { 107f1b3ccfaSKevin Wolf vm_stop(RUN_STATE_PAUSED); 108f1b3ccfaSKevin Wolf } 109f1b3ccfaSKevin Wolf } 110f1b3ccfaSKevin Wolf 111f1b3ccfaSKevin Wolf void qmp_system_reset(Error **errp) 112f1b3ccfaSKevin Wolf { 113f1b3ccfaSKevin Wolf qemu_system_reset_request(SHUTDOWN_CAUSE_HOST_QMP_SYSTEM_RESET); 114f1b3ccfaSKevin Wolf } 115f1b3ccfaSKevin Wolf 116f1b3ccfaSKevin Wolf void qmp_system_powerdown(Error **erp) 117f1b3ccfaSKevin Wolf { 118f1b3ccfaSKevin Wolf qemu_system_powerdown_request(); 119f1b3ccfaSKevin Wolf } 120f1b3ccfaSKevin Wolf 121f1b3ccfaSKevin Wolf void qmp_cpu_add(int64_t id, Error **errp) 122f1b3ccfaSKevin Wolf { 123f1b3ccfaSKevin Wolf MachineClass *mc; 124f1b3ccfaSKevin Wolf 125f1b3ccfaSKevin Wolf mc = MACHINE_GET_CLASS(current_machine); 126f1b3ccfaSKevin Wolf if (mc->hot_add_cpu) { 127f1b3ccfaSKevin Wolf mc->hot_add_cpu(id, errp); 128f1b3ccfaSKevin Wolf } else { 129f1b3ccfaSKevin Wolf error_setg(errp, "Not supported"); 130f1b3ccfaSKevin Wolf } 131f1b3ccfaSKevin Wolf } 132f1b3ccfaSKevin Wolf 133f1b3ccfaSKevin Wolf void qmp_x_exit_preconfig(Error **errp) 134f1b3ccfaSKevin Wolf { 135f1b3ccfaSKevin Wolf if (!runstate_check(RUN_STATE_PRECONFIG)) { 136f1b3ccfaSKevin Wolf error_setg(errp, "The command is permitted only in '%s' state", 137f1b3ccfaSKevin Wolf RunState_str(RUN_STATE_PRECONFIG)); 138f1b3ccfaSKevin Wolf return; 139f1b3ccfaSKevin Wolf } 140f1b3ccfaSKevin Wolf qemu_exit_preconfig_request(); 141f1b3ccfaSKevin Wolf } 142f1b3ccfaSKevin Wolf 143f1b3ccfaSKevin Wolf void qmp_cont(Error **errp) 144f1b3ccfaSKevin Wolf { 145f1b3ccfaSKevin Wolf BlockBackend *blk; 146*68d00e42SVladimir Sementsov-Ogievskiy BlockJob *job; 147f1b3ccfaSKevin Wolf Error *local_err = NULL; 148f1b3ccfaSKevin Wolf 149f1b3ccfaSKevin Wolf /* if there is a dump in background, we should wait until the dump 150f1b3ccfaSKevin Wolf * finished */ 151f1b3ccfaSKevin Wolf if (dump_in_progress()) { 152f1b3ccfaSKevin Wolf error_setg(errp, "There is a dump in process, please wait."); 153f1b3ccfaSKevin Wolf return; 154f1b3ccfaSKevin Wolf } 155f1b3ccfaSKevin Wolf 156f1b3ccfaSKevin Wolf if (runstate_needs_reset()) { 157f1b3ccfaSKevin Wolf error_setg(errp, "Resetting the Virtual Machine is required"); 158f1b3ccfaSKevin Wolf return; 159f1b3ccfaSKevin Wolf } else if (runstate_check(RUN_STATE_SUSPENDED)) { 160f1b3ccfaSKevin Wolf return; 161f1b3ccfaSKevin Wolf } else if (runstate_check(RUN_STATE_FINISH_MIGRATE)) { 162f1b3ccfaSKevin Wolf error_setg(errp, "Migration is not finalized yet"); 163f1b3ccfaSKevin Wolf return; 164f1b3ccfaSKevin Wolf } 165f1b3ccfaSKevin Wolf 166f1b3ccfaSKevin Wolf for (blk = blk_next(NULL); blk; blk = blk_next(blk)) { 167f1b3ccfaSKevin Wolf blk_iostatus_reset(blk); 168f1b3ccfaSKevin Wolf } 169f1b3ccfaSKevin Wolf 170*68d00e42SVladimir Sementsov-Ogievskiy for (job = block_job_next(NULL); job; job = block_job_next(job)) { 171*68d00e42SVladimir Sementsov-Ogievskiy block_job_iostatus_reset(job); 172*68d00e42SVladimir Sementsov-Ogievskiy } 173*68d00e42SVladimir Sementsov-Ogievskiy 174f1b3ccfaSKevin Wolf /* Continuing after completed migration. Images have been inactivated to 175f1b3ccfaSKevin Wolf * allow the destination to take control. Need to get control back now. 176f1b3ccfaSKevin Wolf * 177f1b3ccfaSKevin Wolf * If there are no inactive block nodes (e.g. because the VM was just 178f1b3ccfaSKevin Wolf * paused rather than completing a migration), bdrv_inactivate_all() simply 179f1b3ccfaSKevin Wolf * doesn't do anything. */ 180f1b3ccfaSKevin Wolf bdrv_invalidate_cache_all(&local_err); 181f1b3ccfaSKevin Wolf if (local_err) { 182f1b3ccfaSKevin Wolf error_propagate(errp, local_err); 183f1b3ccfaSKevin Wolf return; 184f1b3ccfaSKevin Wolf } 185f1b3ccfaSKevin Wolf 186f1b3ccfaSKevin Wolf if (runstate_check(RUN_STATE_INMIGRATE)) { 187f1b3ccfaSKevin Wolf autostart = 1; 188f1b3ccfaSKevin Wolf } else { 189f1b3ccfaSKevin Wolf vm_start(); 190f1b3ccfaSKevin Wolf } 191f1b3ccfaSKevin Wolf } 192f1b3ccfaSKevin Wolf 193f1b3ccfaSKevin Wolf void qmp_system_wakeup(Error **errp) 194f1b3ccfaSKevin Wolf { 195f1b3ccfaSKevin Wolf if (!qemu_wakeup_suspend_enabled()) { 196f1b3ccfaSKevin Wolf error_setg(errp, 197f1b3ccfaSKevin Wolf "wake-up from suspend is not supported by this guest"); 198f1b3ccfaSKevin Wolf return; 199f1b3ccfaSKevin Wolf } 200f1b3ccfaSKevin Wolf 201f1b3ccfaSKevin Wolf qemu_system_wakeup_request(QEMU_WAKEUP_REASON_OTHER, errp); 202f1b3ccfaSKevin Wolf } 203f1b3ccfaSKevin Wolf 204f1b3ccfaSKevin Wolf ObjectPropertyInfoList *qmp_qom_list(const char *path, Error **errp) 205f1b3ccfaSKevin Wolf { 206f1b3ccfaSKevin Wolf Object *obj; 207f1b3ccfaSKevin Wolf bool ambiguous = false; 208f1b3ccfaSKevin Wolf ObjectPropertyInfoList *props = NULL; 209f1b3ccfaSKevin Wolf ObjectProperty *prop; 210f1b3ccfaSKevin Wolf ObjectPropertyIterator iter; 211f1b3ccfaSKevin Wolf 212f1b3ccfaSKevin Wolf obj = object_resolve_path(path, &ambiguous); 213f1b3ccfaSKevin Wolf if (obj == NULL) { 214f1b3ccfaSKevin Wolf if (ambiguous) { 215f1b3ccfaSKevin Wolf error_setg(errp, "Path '%s' is ambiguous", path); 216f1b3ccfaSKevin Wolf } else { 217f1b3ccfaSKevin Wolf error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 218f1b3ccfaSKevin Wolf "Device '%s' not found", path); 219f1b3ccfaSKevin Wolf } 220f1b3ccfaSKevin Wolf return NULL; 221f1b3ccfaSKevin Wolf } 222f1b3ccfaSKevin Wolf 223f1b3ccfaSKevin Wolf object_property_iter_init(&iter, obj); 224f1b3ccfaSKevin Wolf while ((prop = object_property_iter_next(&iter))) { 225f1b3ccfaSKevin Wolf ObjectPropertyInfoList *entry = g_malloc0(sizeof(*entry)); 226f1b3ccfaSKevin Wolf 227f1b3ccfaSKevin Wolf entry->value = g_malloc0(sizeof(ObjectPropertyInfo)); 228f1b3ccfaSKevin Wolf entry->next = props; 229f1b3ccfaSKevin Wolf props = entry; 230f1b3ccfaSKevin Wolf 231f1b3ccfaSKevin Wolf entry->value->name = g_strdup(prop->name); 232f1b3ccfaSKevin Wolf entry->value->type = g_strdup(prop->type); 233f1b3ccfaSKevin Wolf } 234f1b3ccfaSKevin Wolf 235f1b3ccfaSKevin Wolf return props; 236f1b3ccfaSKevin Wolf } 237f1b3ccfaSKevin Wolf 238f1b3ccfaSKevin Wolf void qmp_qom_set(const char *path, const char *property, QObject *value, 239f1b3ccfaSKevin Wolf Error **errp) 240f1b3ccfaSKevin Wolf { 241f1b3ccfaSKevin Wolf Object *obj; 242f1b3ccfaSKevin Wolf 243f1b3ccfaSKevin Wolf obj = object_resolve_path(path, NULL); 244f1b3ccfaSKevin Wolf if (!obj) { 245f1b3ccfaSKevin Wolf error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 246f1b3ccfaSKevin Wolf "Device '%s' not found", path); 247f1b3ccfaSKevin Wolf return; 248f1b3ccfaSKevin Wolf } 249f1b3ccfaSKevin Wolf 250f1b3ccfaSKevin Wolf object_property_set_qobject(obj, value, property, errp); 251f1b3ccfaSKevin Wolf } 252f1b3ccfaSKevin Wolf 253f1b3ccfaSKevin Wolf QObject *qmp_qom_get(const char *path, const char *property, Error **errp) 254f1b3ccfaSKevin Wolf { 255f1b3ccfaSKevin Wolf Object *obj; 256f1b3ccfaSKevin Wolf 257f1b3ccfaSKevin Wolf obj = object_resolve_path(path, NULL); 258f1b3ccfaSKevin Wolf if (!obj) { 259f1b3ccfaSKevin Wolf error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 260f1b3ccfaSKevin Wolf "Device '%s' not found", path); 261f1b3ccfaSKevin Wolf return NULL; 262f1b3ccfaSKevin Wolf } 263f1b3ccfaSKevin Wolf 264f1b3ccfaSKevin Wolf return object_property_get_qobject(obj, property, errp); 265f1b3ccfaSKevin Wolf } 266f1b3ccfaSKevin Wolf 267f1b3ccfaSKevin Wolf void qmp_set_password(const char *protocol, const char *password, 268f1b3ccfaSKevin Wolf bool has_connected, const char *connected, Error **errp) 269f1b3ccfaSKevin Wolf { 270f1b3ccfaSKevin Wolf int disconnect_if_connected = 0; 271f1b3ccfaSKevin Wolf int fail_if_connected = 0; 272f1b3ccfaSKevin Wolf int rc; 273f1b3ccfaSKevin Wolf 274f1b3ccfaSKevin Wolf if (has_connected) { 275f1b3ccfaSKevin Wolf if (strcmp(connected, "fail") == 0) { 276f1b3ccfaSKevin Wolf fail_if_connected = 1; 277f1b3ccfaSKevin Wolf } else if (strcmp(connected, "disconnect") == 0) { 278f1b3ccfaSKevin Wolf disconnect_if_connected = 1; 279f1b3ccfaSKevin Wolf } else if (strcmp(connected, "keep") == 0) { 280f1b3ccfaSKevin Wolf /* nothing */ 281f1b3ccfaSKevin Wolf } else { 282f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER, "connected"); 283f1b3ccfaSKevin Wolf return; 284f1b3ccfaSKevin Wolf } 285f1b3ccfaSKevin Wolf } 286f1b3ccfaSKevin Wolf 287f1b3ccfaSKevin Wolf if (strcmp(protocol, "spice") == 0) { 288f1b3ccfaSKevin Wolf if (!qemu_using_spice(errp)) { 289f1b3ccfaSKevin Wolf return; 290f1b3ccfaSKevin Wolf } 291f1b3ccfaSKevin Wolf rc = qemu_spice_set_passwd(password, fail_if_connected, 292f1b3ccfaSKevin Wolf disconnect_if_connected); 293f1b3ccfaSKevin Wolf if (rc != 0) { 294f1b3ccfaSKevin Wolf error_setg(errp, QERR_SET_PASSWD_FAILED); 295f1b3ccfaSKevin Wolf } 296f1b3ccfaSKevin Wolf return; 297f1b3ccfaSKevin Wolf } 298f1b3ccfaSKevin Wolf 299f1b3ccfaSKevin Wolf if (strcmp(protocol, "vnc") == 0) { 300f1b3ccfaSKevin Wolf if (fail_if_connected || disconnect_if_connected) { 301f1b3ccfaSKevin Wolf /* vnc supports "connected=keep" only */ 302f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER, "connected"); 303f1b3ccfaSKevin Wolf return; 304f1b3ccfaSKevin Wolf } 305f1b3ccfaSKevin Wolf /* Note that setting an empty password will not disable login through 306f1b3ccfaSKevin Wolf * this interface. */ 307f1b3ccfaSKevin Wolf rc = vnc_display_password(NULL, password); 308f1b3ccfaSKevin Wolf if (rc < 0) { 309f1b3ccfaSKevin Wolf error_setg(errp, QERR_SET_PASSWD_FAILED); 310f1b3ccfaSKevin Wolf } 311f1b3ccfaSKevin Wolf return; 312f1b3ccfaSKevin Wolf } 313f1b3ccfaSKevin Wolf 314f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER, "protocol"); 315f1b3ccfaSKevin Wolf } 316f1b3ccfaSKevin Wolf 317f1b3ccfaSKevin Wolf void qmp_expire_password(const char *protocol, const char *whenstr, 318f1b3ccfaSKevin Wolf Error **errp) 319f1b3ccfaSKevin Wolf { 320f1b3ccfaSKevin Wolf time_t when; 321f1b3ccfaSKevin Wolf int rc; 322f1b3ccfaSKevin Wolf 323f1b3ccfaSKevin Wolf if (strcmp(whenstr, "now") == 0) { 324f1b3ccfaSKevin Wolf when = 0; 325f1b3ccfaSKevin Wolf } else if (strcmp(whenstr, "never") == 0) { 326f1b3ccfaSKevin Wolf when = TIME_MAX; 327f1b3ccfaSKevin Wolf } else if (whenstr[0] == '+') { 328f1b3ccfaSKevin Wolf when = time(NULL) + strtoull(whenstr+1, NULL, 10); 329f1b3ccfaSKevin Wolf } else { 330f1b3ccfaSKevin Wolf when = strtoull(whenstr, NULL, 10); 331f1b3ccfaSKevin Wolf } 332f1b3ccfaSKevin Wolf 333f1b3ccfaSKevin Wolf if (strcmp(protocol, "spice") == 0) { 334f1b3ccfaSKevin Wolf if (!qemu_using_spice(errp)) { 335f1b3ccfaSKevin Wolf return; 336f1b3ccfaSKevin Wolf } 337f1b3ccfaSKevin Wolf rc = qemu_spice_set_pw_expire(when); 338f1b3ccfaSKevin Wolf if (rc != 0) { 339f1b3ccfaSKevin Wolf error_setg(errp, QERR_SET_PASSWD_FAILED); 340f1b3ccfaSKevin Wolf } 341f1b3ccfaSKevin Wolf return; 342f1b3ccfaSKevin Wolf } 343f1b3ccfaSKevin Wolf 344f1b3ccfaSKevin Wolf if (strcmp(protocol, "vnc") == 0) { 345f1b3ccfaSKevin Wolf rc = vnc_display_pw_expire(NULL, when); 346f1b3ccfaSKevin Wolf if (rc != 0) { 347f1b3ccfaSKevin Wolf error_setg(errp, QERR_SET_PASSWD_FAILED); 348f1b3ccfaSKevin Wolf } 349f1b3ccfaSKevin Wolf return; 350f1b3ccfaSKevin Wolf } 351f1b3ccfaSKevin Wolf 352f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER, "protocol"); 353f1b3ccfaSKevin Wolf } 354f1b3ccfaSKevin Wolf 355f1b3ccfaSKevin Wolf #ifdef CONFIG_VNC 356f1b3ccfaSKevin Wolf void qmp_change_vnc_password(const char *password, Error **errp) 357f1b3ccfaSKevin Wolf { 358f1b3ccfaSKevin Wolf if (vnc_display_password(NULL, password) < 0) { 359f1b3ccfaSKevin Wolf error_setg(errp, QERR_SET_PASSWD_FAILED); 360f1b3ccfaSKevin Wolf } 361f1b3ccfaSKevin Wolf } 362f1b3ccfaSKevin Wolf 363f1b3ccfaSKevin Wolf static void qmp_change_vnc_listen(const char *target, Error **errp) 364f1b3ccfaSKevin Wolf { 365f1b3ccfaSKevin Wolf QemuOptsList *olist = qemu_find_opts("vnc"); 366f1b3ccfaSKevin Wolf QemuOpts *opts; 367f1b3ccfaSKevin Wolf 368f1b3ccfaSKevin Wolf if (strstr(target, "id=")) { 369f1b3ccfaSKevin Wolf error_setg(errp, "id not supported"); 370f1b3ccfaSKevin Wolf return; 371f1b3ccfaSKevin Wolf } 372f1b3ccfaSKevin Wolf 373f1b3ccfaSKevin Wolf opts = qemu_opts_find(olist, "default"); 374f1b3ccfaSKevin Wolf if (opts) { 375f1b3ccfaSKevin Wolf qemu_opts_del(opts); 376f1b3ccfaSKevin Wolf } 377f1b3ccfaSKevin Wolf opts = vnc_parse(target, errp); 378f1b3ccfaSKevin Wolf if (!opts) { 379f1b3ccfaSKevin Wolf return; 380f1b3ccfaSKevin Wolf } 381f1b3ccfaSKevin Wolf 382f1b3ccfaSKevin Wolf vnc_display_open("default", errp); 383f1b3ccfaSKevin Wolf } 384f1b3ccfaSKevin Wolf 385f1b3ccfaSKevin Wolf static void qmp_change_vnc(const char *target, bool has_arg, const char *arg, 386f1b3ccfaSKevin Wolf Error **errp) 387f1b3ccfaSKevin Wolf { 388f1b3ccfaSKevin Wolf if (strcmp(target, "passwd") == 0 || strcmp(target, "password") == 0) { 389f1b3ccfaSKevin Wolf if (!has_arg) { 390f1b3ccfaSKevin Wolf error_setg(errp, QERR_MISSING_PARAMETER, "password"); 391f1b3ccfaSKevin Wolf } else { 392f1b3ccfaSKevin Wolf qmp_change_vnc_password(arg, errp); 393f1b3ccfaSKevin Wolf } 394f1b3ccfaSKevin Wolf } else { 395f1b3ccfaSKevin Wolf qmp_change_vnc_listen(target, errp); 396f1b3ccfaSKevin Wolf } 397f1b3ccfaSKevin Wolf } 398f1b3ccfaSKevin Wolf #endif /* !CONFIG_VNC */ 399f1b3ccfaSKevin Wolf 400f1b3ccfaSKevin Wolf void qmp_change(const char *device, const char *target, 401f1b3ccfaSKevin Wolf bool has_arg, const char *arg, Error **errp) 402f1b3ccfaSKevin Wolf { 403f1b3ccfaSKevin Wolf if (strcmp(device, "vnc") == 0) { 404f1b3ccfaSKevin Wolf #ifdef CONFIG_VNC 405f1b3ccfaSKevin Wolf qmp_change_vnc(target, has_arg, arg, errp); 406f1b3ccfaSKevin Wolf #else 407f1b3ccfaSKevin Wolf error_setg(errp, QERR_FEATURE_DISABLED, "vnc"); 408f1b3ccfaSKevin Wolf #endif 409f1b3ccfaSKevin Wolf } else { 410f1b3ccfaSKevin Wolf qmp_blockdev_change_medium(true, device, false, NULL, target, 411f1b3ccfaSKevin Wolf has_arg, arg, false, 0, errp); 412f1b3ccfaSKevin Wolf } 413f1b3ccfaSKevin Wolf } 414f1b3ccfaSKevin Wolf 415f1b3ccfaSKevin Wolf static void qom_list_types_tramp(ObjectClass *klass, void *data) 416f1b3ccfaSKevin Wolf { 417f1b3ccfaSKevin Wolf ObjectTypeInfoList *e, **pret = data; 418f1b3ccfaSKevin Wolf ObjectTypeInfo *info; 419f1b3ccfaSKevin Wolf ObjectClass *parent = object_class_get_parent(klass); 420f1b3ccfaSKevin Wolf 421f1b3ccfaSKevin Wolf info = g_malloc0(sizeof(*info)); 422f1b3ccfaSKevin Wolf info->name = g_strdup(object_class_get_name(klass)); 423f1b3ccfaSKevin Wolf info->has_abstract = info->abstract = object_class_is_abstract(klass); 424f1b3ccfaSKevin Wolf if (parent) { 425f1b3ccfaSKevin Wolf info->has_parent = true; 426f1b3ccfaSKevin Wolf info->parent = g_strdup(object_class_get_name(parent)); 427f1b3ccfaSKevin Wolf } 428f1b3ccfaSKevin Wolf 429f1b3ccfaSKevin Wolf e = g_malloc0(sizeof(*e)); 430f1b3ccfaSKevin Wolf e->value = info; 431f1b3ccfaSKevin Wolf e->next = *pret; 432f1b3ccfaSKevin Wolf *pret = e; 433f1b3ccfaSKevin Wolf } 434f1b3ccfaSKevin Wolf 435f1b3ccfaSKevin Wolf ObjectTypeInfoList *qmp_qom_list_types(bool has_implements, 436f1b3ccfaSKevin Wolf const char *implements, 437f1b3ccfaSKevin Wolf bool has_abstract, 438f1b3ccfaSKevin Wolf bool abstract, 439f1b3ccfaSKevin Wolf Error **errp) 440f1b3ccfaSKevin Wolf { 441f1b3ccfaSKevin Wolf ObjectTypeInfoList *ret = NULL; 442f1b3ccfaSKevin Wolf 443f1b3ccfaSKevin Wolf object_class_foreach(qom_list_types_tramp, implements, abstract, &ret); 444f1b3ccfaSKevin Wolf 445f1b3ccfaSKevin Wolf return ret; 446f1b3ccfaSKevin Wolf } 447f1b3ccfaSKevin Wolf 448f1b3ccfaSKevin Wolf /* Return a DevicePropertyInfo for a qdev property. 449f1b3ccfaSKevin Wolf * 450f1b3ccfaSKevin Wolf * If a qdev property with the given name does not exist, use the given default 451f1b3ccfaSKevin Wolf * type. If the qdev property info should not be shown, return NULL. 452f1b3ccfaSKevin Wolf * 453f1b3ccfaSKevin Wolf * The caller must free the return value. 454f1b3ccfaSKevin Wolf */ 455f1b3ccfaSKevin Wolf static ObjectPropertyInfo *make_device_property_info(ObjectClass *klass, 456f1b3ccfaSKevin Wolf const char *name, 457f1b3ccfaSKevin Wolf const char *default_type, 458f1b3ccfaSKevin Wolf const char *description) 459f1b3ccfaSKevin Wolf { 460f1b3ccfaSKevin Wolf ObjectPropertyInfo *info; 461f1b3ccfaSKevin Wolf Property *prop; 462f1b3ccfaSKevin Wolf 463f1b3ccfaSKevin Wolf do { 464f1b3ccfaSKevin Wolf for (prop = DEVICE_CLASS(klass)->props; prop && prop->name; prop++) { 465f1b3ccfaSKevin Wolf if (strcmp(name, prop->name) != 0) { 466f1b3ccfaSKevin Wolf continue; 467f1b3ccfaSKevin Wolf } 468f1b3ccfaSKevin Wolf 469f1b3ccfaSKevin Wolf /* 470f1b3ccfaSKevin Wolf * TODO Properties without a parser are just for dirty hacks. 471f1b3ccfaSKevin Wolf * qdev_prop_ptr is the only such PropertyInfo. It's marked 472f1b3ccfaSKevin Wolf * for removal. This conditional should be removed along with 473f1b3ccfaSKevin Wolf * it. 474f1b3ccfaSKevin Wolf */ 475f1b3ccfaSKevin Wolf if (!prop->info->set && !prop->info->create) { 476f1b3ccfaSKevin Wolf return NULL; /* no way to set it, don't show */ 477f1b3ccfaSKevin Wolf } 478f1b3ccfaSKevin Wolf 479f1b3ccfaSKevin Wolf info = g_malloc0(sizeof(*info)); 480f1b3ccfaSKevin Wolf info->name = g_strdup(prop->name); 481f1b3ccfaSKevin Wolf info->type = default_type ? g_strdup(default_type) 482f1b3ccfaSKevin Wolf : g_strdup(prop->info->name); 483f1b3ccfaSKevin Wolf info->has_description = !!prop->info->description; 484f1b3ccfaSKevin Wolf info->description = g_strdup(prop->info->description); 485f1b3ccfaSKevin Wolf return info; 486f1b3ccfaSKevin Wolf } 487f1b3ccfaSKevin Wolf klass = object_class_get_parent(klass); 488f1b3ccfaSKevin Wolf } while (klass != object_class_by_name(TYPE_DEVICE)); 489f1b3ccfaSKevin Wolf 490f1b3ccfaSKevin Wolf /* Not a qdev property, use the default type */ 491f1b3ccfaSKevin Wolf info = g_malloc0(sizeof(*info)); 492f1b3ccfaSKevin Wolf info->name = g_strdup(name); 493f1b3ccfaSKevin Wolf info->type = g_strdup(default_type); 494f1b3ccfaSKevin Wolf info->has_description = !!description; 495f1b3ccfaSKevin Wolf info->description = g_strdup(description); 496f1b3ccfaSKevin Wolf 497f1b3ccfaSKevin Wolf return info; 498f1b3ccfaSKevin Wolf } 499f1b3ccfaSKevin Wolf 500f1b3ccfaSKevin Wolf ObjectPropertyInfoList *qmp_device_list_properties(const char *typename, 501f1b3ccfaSKevin Wolf Error **errp) 502f1b3ccfaSKevin Wolf { 503f1b3ccfaSKevin Wolf ObjectClass *klass; 504f1b3ccfaSKevin Wolf Object *obj; 505f1b3ccfaSKevin Wolf ObjectProperty *prop; 506f1b3ccfaSKevin Wolf ObjectPropertyIterator iter; 507f1b3ccfaSKevin Wolf ObjectPropertyInfoList *prop_list = NULL; 508f1b3ccfaSKevin Wolf 509f1b3ccfaSKevin Wolf klass = object_class_by_name(typename); 510f1b3ccfaSKevin Wolf if (klass == NULL) { 511f1b3ccfaSKevin Wolf error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 512f1b3ccfaSKevin Wolf "Device '%s' not found", typename); 513f1b3ccfaSKevin Wolf return NULL; 514f1b3ccfaSKevin Wolf } 515f1b3ccfaSKevin Wolf 516f1b3ccfaSKevin Wolf klass = object_class_dynamic_cast(klass, TYPE_DEVICE); 517f1b3ccfaSKevin Wolf if (klass == NULL) { 518f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_DEVICE); 519f1b3ccfaSKevin Wolf return NULL; 520f1b3ccfaSKevin Wolf } 521f1b3ccfaSKevin Wolf 522f1b3ccfaSKevin Wolf if (object_class_is_abstract(klass)) { 523f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", 524f1b3ccfaSKevin Wolf "non-abstract device type"); 525f1b3ccfaSKevin Wolf return NULL; 526f1b3ccfaSKevin Wolf } 527f1b3ccfaSKevin Wolf 528f1b3ccfaSKevin Wolf obj = object_new(typename); 529f1b3ccfaSKevin Wolf 530f1b3ccfaSKevin Wolf object_property_iter_init(&iter, obj); 531f1b3ccfaSKevin Wolf while ((prop = object_property_iter_next(&iter))) { 532f1b3ccfaSKevin Wolf ObjectPropertyInfo *info; 533f1b3ccfaSKevin Wolf ObjectPropertyInfoList *entry; 534f1b3ccfaSKevin Wolf 535f1b3ccfaSKevin Wolf /* Skip Object and DeviceState properties */ 536f1b3ccfaSKevin Wolf if (strcmp(prop->name, "type") == 0 || 537f1b3ccfaSKevin Wolf strcmp(prop->name, "realized") == 0 || 538f1b3ccfaSKevin Wolf strcmp(prop->name, "hotpluggable") == 0 || 539f1b3ccfaSKevin Wolf strcmp(prop->name, "hotplugged") == 0 || 540f1b3ccfaSKevin Wolf strcmp(prop->name, "parent_bus") == 0) { 541f1b3ccfaSKevin Wolf continue; 542f1b3ccfaSKevin Wolf } 543f1b3ccfaSKevin Wolf 544f1b3ccfaSKevin Wolf /* Skip legacy properties since they are just string versions of 545f1b3ccfaSKevin Wolf * properties that we already list. 546f1b3ccfaSKevin Wolf */ 547f1b3ccfaSKevin Wolf if (strstart(prop->name, "legacy-", NULL)) { 548f1b3ccfaSKevin Wolf continue; 549f1b3ccfaSKevin Wolf } 550f1b3ccfaSKevin Wolf 551f1b3ccfaSKevin Wolf info = make_device_property_info(klass, prop->name, prop->type, 552f1b3ccfaSKevin Wolf prop->description); 553f1b3ccfaSKevin Wolf if (!info) { 554f1b3ccfaSKevin Wolf continue; 555f1b3ccfaSKevin Wolf } 556f1b3ccfaSKevin Wolf 557f1b3ccfaSKevin Wolf entry = g_malloc0(sizeof(*entry)); 558f1b3ccfaSKevin Wolf entry->value = info; 559f1b3ccfaSKevin Wolf entry->next = prop_list; 560f1b3ccfaSKevin Wolf prop_list = entry; 561f1b3ccfaSKevin Wolf } 562f1b3ccfaSKevin Wolf 563f1b3ccfaSKevin Wolf object_unref(obj); 564f1b3ccfaSKevin Wolf 565f1b3ccfaSKevin Wolf return prop_list; 566f1b3ccfaSKevin Wolf } 567f1b3ccfaSKevin Wolf 568f1b3ccfaSKevin Wolf ObjectPropertyInfoList *qmp_qom_list_properties(const char *typename, 569f1b3ccfaSKevin Wolf Error **errp) 570f1b3ccfaSKevin Wolf { 571f1b3ccfaSKevin Wolf ObjectClass *klass; 572f1b3ccfaSKevin Wolf Object *obj = NULL; 573f1b3ccfaSKevin Wolf ObjectProperty *prop; 574f1b3ccfaSKevin Wolf ObjectPropertyIterator iter; 575f1b3ccfaSKevin Wolf ObjectPropertyInfoList *prop_list = NULL; 576f1b3ccfaSKevin Wolf 577f1b3ccfaSKevin Wolf klass = object_class_by_name(typename); 578f1b3ccfaSKevin Wolf if (klass == NULL) { 579f1b3ccfaSKevin Wolf error_set(errp, ERROR_CLASS_DEVICE_NOT_FOUND, 580f1b3ccfaSKevin Wolf "Class '%s' not found", typename); 581f1b3ccfaSKevin Wolf return NULL; 582f1b3ccfaSKevin Wolf } 583f1b3ccfaSKevin Wolf 584f1b3ccfaSKevin Wolf klass = object_class_dynamic_cast(klass, TYPE_OBJECT); 585f1b3ccfaSKevin Wolf if (klass == NULL) { 586f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER_VALUE, "typename", TYPE_OBJECT); 587f1b3ccfaSKevin Wolf return NULL; 588f1b3ccfaSKevin Wolf } 589f1b3ccfaSKevin Wolf 590f1b3ccfaSKevin Wolf if (object_class_is_abstract(klass)) { 591f1b3ccfaSKevin Wolf object_class_property_iter_init(&iter, klass); 592f1b3ccfaSKevin Wolf } else { 593f1b3ccfaSKevin Wolf obj = object_new(typename); 594f1b3ccfaSKevin Wolf object_property_iter_init(&iter, obj); 595f1b3ccfaSKevin Wolf } 596f1b3ccfaSKevin Wolf while ((prop = object_property_iter_next(&iter))) { 597f1b3ccfaSKevin Wolf ObjectPropertyInfo *info; 598f1b3ccfaSKevin Wolf ObjectPropertyInfoList *entry; 599f1b3ccfaSKevin Wolf 600f1b3ccfaSKevin Wolf info = g_malloc0(sizeof(*info)); 601f1b3ccfaSKevin Wolf info->name = g_strdup(prop->name); 602f1b3ccfaSKevin Wolf info->type = g_strdup(prop->type); 603f1b3ccfaSKevin Wolf info->has_description = !!prop->description; 604f1b3ccfaSKevin Wolf info->description = g_strdup(prop->description); 605f1b3ccfaSKevin Wolf 606f1b3ccfaSKevin Wolf entry = g_malloc0(sizeof(*entry)); 607f1b3ccfaSKevin Wolf entry->value = info; 608f1b3ccfaSKevin Wolf entry->next = prop_list; 609f1b3ccfaSKevin Wolf prop_list = entry; 610f1b3ccfaSKevin Wolf } 611f1b3ccfaSKevin Wolf 612f1b3ccfaSKevin Wolf object_unref(obj); 613f1b3ccfaSKevin Wolf 614f1b3ccfaSKevin Wolf return prop_list; 615f1b3ccfaSKevin Wolf } 616f1b3ccfaSKevin Wolf 617f1b3ccfaSKevin Wolf void qmp_add_client(const char *protocol, const char *fdname, 618f1b3ccfaSKevin Wolf bool has_skipauth, bool skipauth, bool has_tls, bool tls, 619f1b3ccfaSKevin Wolf Error **errp) 620f1b3ccfaSKevin Wolf { 621f1b3ccfaSKevin Wolf Chardev *s; 622f1b3ccfaSKevin Wolf int fd; 623f1b3ccfaSKevin Wolf 624f1b3ccfaSKevin Wolf fd = monitor_get_fd(cur_mon, fdname, errp); 625f1b3ccfaSKevin Wolf if (fd < 0) { 626f1b3ccfaSKevin Wolf return; 627f1b3ccfaSKevin Wolf } 628f1b3ccfaSKevin Wolf 629f1b3ccfaSKevin Wolf if (strcmp(protocol, "spice") == 0) { 630f1b3ccfaSKevin Wolf if (!qemu_using_spice(errp)) { 631f1b3ccfaSKevin Wolf close(fd); 632f1b3ccfaSKevin Wolf return; 633f1b3ccfaSKevin Wolf } 634f1b3ccfaSKevin Wolf skipauth = has_skipauth ? skipauth : false; 635f1b3ccfaSKevin Wolf tls = has_tls ? tls : false; 636f1b3ccfaSKevin Wolf if (qemu_spice_display_add_client(fd, skipauth, tls) < 0) { 637f1b3ccfaSKevin Wolf error_setg(errp, "spice failed to add client"); 638f1b3ccfaSKevin Wolf close(fd); 639f1b3ccfaSKevin Wolf } 640f1b3ccfaSKevin Wolf return; 641f1b3ccfaSKevin Wolf #ifdef CONFIG_VNC 642f1b3ccfaSKevin Wolf } else if (strcmp(protocol, "vnc") == 0) { 643f1b3ccfaSKevin Wolf skipauth = has_skipauth ? skipauth : false; 644f1b3ccfaSKevin Wolf vnc_display_add_client(NULL, fd, skipauth); 645f1b3ccfaSKevin Wolf return; 646f1b3ccfaSKevin Wolf #endif 647f1b3ccfaSKevin Wolf } else if ((s = qemu_chr_find(protocol)) != NULL) { 648f1b3ccfaSKevin Wolf if (qemu_chr_add_client(s, fd) < 0) { 649f1b3ccfaSKevin Wolf error_setg(errp, "failed to add client"); 650f1b3ccfaSKevin Wolf close(fd); 651f1b3ccfaSKevin Wolf return; 652f1b3ccfaSKevin Wolf } 653f1b3ccfaSKevin Wolf return; 654f1b3ccfaSKevin Wolf } 655f1b3ccfaSKevin Wolf 656f1b3ccfaSKevin Wolf error_setg(errp, "protocol '%s' is invalid", protocol); 657f1b3ccfaSKevin Wolf close(fd); 658f1b3ccfaSKevin Wolf } 659f1b3ccfaSKevin Wolf 660f1b3ccfaSKevin Wolf 661f1b3ccfaSKevin Wolf void qmp_object_add(const char *type, const char *id, 662f1b3ccfaSKevin Wolf bool has_props, QObject *props, Error **errp) 663f1b3ccfaSKevin Wolf { 664f1b3ccfaSKevin Wolf QDict *pdict; 665f1b3ccfaSKevin Wolf Visitor *v; 666f1b3ccfaSKevin Wolf Object *obj; 667f1b3ccfaSKevin Wolf 668f1b3ccfaSKevin Wolf if (props) { 669f1b3ccfaSKevin Wolf pdict = qobject_to(QDict, props); 670f1b3ccfaSKevin Wolf if (!pdict) { 671f1b3ccfaSKevin Wolf error_setg(errp, QERR_INVALID_PARAMETER_TYPE, "props", "dict"); 672f1b3ccfaSKevin Wolf return; 673f1b3ccfaSKevin Wolf } 674f1b3ccfaSKevin Wolf qobject_ref(pdict); 675f1b3ccfaSKevin Wolf } else { 676f1b3ccfaSKevin Wolf pdict = qdict_new(); 677f1b3ccfaSKevin Wolf } 678f1b3ccfaSKevin Wolf 679f1b3ccfaSKevin Wolf v = qobject_input_visitor_new(QOBJECT(pdict)); 680f1b3ccfaSKevin Wolf obj = user_creatable_add_type(type, id, pdict, v, errp); 681f1b3ccfaSKevin Wolf visit_free(v); 682f1b3ccfaSKevin Wolf if (obj) { 683f1b3ccfaSKevin Wolf object_unref(obj); 684f1b3ccfaSKevin Wolf } 685f1b3ccfaSKevin Wolf qobject_unref(pdict); 686f1b3ccfaSKevin Wolf } 687f1b3ccfaSKevin Wolf 688f1b3ccfaSKevin Wolf void qmp_object_del(const char *id, Error **errp) 689f1b3ccfaSKevin Wolf { 690f1b3ccfaSKevin Wolf user_creatable_del(id, errp); 691f1b3ccfaSKevin Wolf } 692f1b3ccfaSKevin Wolf 693f1b3ccfaSKevin Wolf MemoryDeviceInfoList *qmp_query_memory_devices(Error **errp) 694f1b3ccfaSKevin Wolf { 695f1b3ccfaSKevin Wolf return qmp_memory_device_list(); 696f1b3ccfaSKevin Wolf } 697f1b3ccfaSKevin Wolf 698f1b3ccfaSKevin Wolf ACPIOSTInfoList *qmp_query_acpi_ospm_status(Error **errp) 699f1b3ccfaSKevin Wolf { 700f1b3ccfaSKevin Wolf bool ambig; 701f1b3ccfaSKevin Wolf ACPIOSTInfoList *head = NULL; 702f1b3ccfaSKevin Wolf ACPIOSTInfoList **prev = &head; 703f1b3ccfaSKevin Wolf Object *obj = object_resolve_path_type("", TYPE_ACPI_DEVICE_IF, &ambig); 704f1b3ccfaSKevin Wolf 705f1b3ccfaSKevin Wolf if (obj) { 706f1b3ccfaSKevin Wolf AcpiDeviceIfClass *adevc = ACPI_DEVICE_IF_GET_CLASS(obj); 707f1b3ccfaSKevin Wolf AcpiDeviceIf *adev = ACPI_DEVICE_IF(obj); 708f1b3ccfaSKevin Wolf 709f1b3ccfaSKevin Wolf adevc->ospm_status(adev, &prev); 710f1b3ccfaSKevin Wolf } else { 711f1b3ccfaSKevin Wolf error_setg(errp, "command is not supported, missing ACPI device"); 712f1b3ccfaSKevin Wolf } 713f1b3ccfaSKevin Wolf 714f1b3ccfaSKevin Wolf return head; 715f1b3ccfaSKevin Wolf } 716f1b3ccfaSKevin Wolf 717f1b3ccfaSKevin Wolf MemoryInfo *qmp_query_memory_size_summary(Error **errp) 718f1b3ccfaSKevin Wolf { 719f1b3ccfaSKevin Wolf MemoryInfo *mem_info = g_malloc0(sizeof(MemoryInfo)); 720f1b3ccfaSKevin Wolf 721f1b3ccfaSKevin Wolf mem_info->base_memory = ram_size; 722f1b3ccfaSKevin Wolf 723f1b3ccfaSKevin Wolf mem_info->plugged_memory = get_plugged_memory_size(); 724f1b3ccfaSKevin Wolf mem_info->has_plugged_memory = 725f1b3ccfaSKevin Wolf mem_info->plugged_memory != (uint64_t)-1; 726f1b3ccfaSKevin Wolf 727f1b3ccfaSKevin Wolf return mem_info; 728f1b3ccfaSKevin Wolf } 729