From nobody Tue May 21 15:42:25 2024 Delivered-To: importer@patchew.org Authentication-Results: mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1595346238; cv=none; d=zohomail.com; s=zohoarc; b=C9KKcBMxTJ66+h19nf2dKET3S6g/kVdhdkcgp7RgdwoiPvLk+zjSEs7UMTa3/6vL9rcEEI2M1/akMM7zsnHvJOqO8SuXV8EDIOoV7Mn6quTvRg0XpmyUOfSrjfaOZFf23j4U9FGJgSjgpZJxKRCoVuBwt7jkvBElaJ6pVWLN1Is= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1595346238; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:List-Subscribe:List-Post:List-Id:List-Archive:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:To; bh=mzQCmOqxa454LuAgpNeFbK0d95FnlBERa0ehc2C5aDE=; b=USAqrQGKnUuyW+qDdhL/4Kx1uWgj0jrAGvT/QIkHExrdUUlXoU7XTu6dh2atWLg2XuJ+m34McYNrr7ZSQJi8RPv8joAx55CYAhcExKED4esQhNiU4mA8L2xFjBE8oj01mPZsaBemvLcUOxmpa2LiQIwNiZx4DzTp/jVsKUyxidE= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=fail; spf=pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) smtp.mailfrom=qemu-devel-bounces+importer=patchew.org@nongnu.org; dmarc=fail header.from= (p=none dis=none) header.from= Return-Path: Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) by mx.zohomail.com with SMTPS id 159534623825592.32844859782142; Tue, 21 Jul 2020 08:43:58 -0700 (PDT) Received: from localhost ([::1]:54008 helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1jxuQu-0000vj-Ve for importer@patchew.org; Tue, 21 Jul 2020 11:43:57 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]:56180) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1jxuOP-0006Kn-M1 for qemu-devel@nongnu.org; Tue, 21 Jul 2020 11:41:21 -0400 Received: from us-smtp-1.mimecast.com ([205.139.110.61]:31548 helo=us-smtp-delivery-1.mimecast.com) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_CBC_SHA1:256) (Exim 4.90_1) (envelope-from ) id 1jxuON-00009v-7L for qemu-devel@nongnu.org; Tue, 21 Jul 2020 11:41:21 -0400 Received: from mail-wr1-f71.google.com (mail-wr1-f71.google.com [209.85.221.71]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-382-qkMlKHbIMEWuf_hVovt82g-1; Tue, 21 Jul 2020 11:40:45 -0400 Received: by mail-wr1-f71.google.com with SMTP id 5so2135484wrc.17 for ; Tue, 21 Jul 2020 08:40:45 -0700 (PDT) Received: from auriga.redhat.com (nat-pool-brq-t.redhat.com. [213.175.37.10]) by smtp.gmail.com with ESMTPSA id u2sm3682925wml.16.2020.07.21.08.40.42 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 21 Jul 2020 08:40:42 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=redhat.com; s=mimecast20190719; t=1595346078; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=mzQCmOqxa454LuAgpNeFbK0d95FnlBERa0ehc2C5aDE=; b=hv+HMTHU/EPiop5403/53SYQZwSOhnJbTPOtf9PGTy3kip6/KDboRaZ8ATeExIiFTp/KQi Zgh/hRI8Rjzt0yvhMt93sqGH2SdLvIA1RESYmEOYj30lqTU+tadcjZPauXwmOMQQrcuR49 NLQ+Fa8DVALUZTWwm80BEikbkMZZk9o= X-MC-Unique: qkMlKHbIMEWuf_hVovt82g-1 X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=mzQCmOqxa454LuAgpNeFbK0d95FnlBERa0ehc2C5aDE=; b=kwJIwkXsZIh0eCS8QhRFtZIEtQ7UDvo5xA8r1j1u/3KONNHdsqqGoI53C0fIgqLmeg M20YCEfaUvHegIqczoS0xKtCJS/Rrvu+KOha0Uje0aNbEtbsS0fR+OvtvqwjENyFJ3Br S8WUh7om681UKVnRpSBq7bUEO29svlz/n+jxcnoVRrVM5tPhd79uyfamAnJISuM9mPHk 8hhlmvPRd97WPB5otCSdDsz7SFw0JVk85Dou5q6PbdADwCRTTVFThEtqSZNKRzbMx3GO awGWmhCf214st1a8nIous55re8yjxSXBVMTNl6ZsbF6KBq05z9sp2u3WC+gArlC2CULm gjow== X-Gm-Message-State: AOAM5335dP7FczB2/aqfknjF6/j/vK/HAOyKH7dQ3ZgH3qMlAY425zeS aE9D6YaFTunaiskozpxjIAv+Drpib9jRQ4sNOQYHsjRpnR8Vd/CW7HqxzhlvN8zeLwObF+06Z8F 3IoykeRXuZdkJIJ0= X-Received: by 2002:a1c:4c0a:: with SMTP id z10mr4847243wmf.38.1595346043373; Tue, 21 Jul 2020 08:40:43 -0700 (PDT) X-Google-Smtp-Source: ABdhPJzt4A0rpGpJD7gwBgn2LQb480Juo3hFuctBj2GTZPJtHiewbjSx3vk4NhNPeB64Ezvp0Osccg== X-Received: by 2002:a1c:4c0a:: with SMTP id z10mr4847214wmf.38.1595346043036; Tue, 21 Jul 2020 08:40:43 -0700 (PDT) From: =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= To: qemu-devel@nongnu.org Subject: [PATCH v10] qga: add command guest-get-devices for reporting VirtIO devices Date: Tue, 21 Jul 2020 17:40:41 +0200 Message-Id: <24edfdd5ff980abc0b66889246d88ab25ebee1fa.1595345951.git.tgolembi@redhat.com> X-Mailer: git-send-email 2.25.0 MIME-Version: 1.0 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Received-SPF: pass (zohomail.com: domain of gnu.org designates 209.51.188.17 as permitted sender) client-ip=209.51.188.17; envelope-from=qemu-devel-bounces+importer=patchew.org@nongnu.org; helo=lists.gnu.org; Received-SPF: pass client-ip=205.139.110.61; envelope-from=tgolembi@redhat.com; helo=us-smtp-delivery-1.mimecast.com X-detected-operating-system: by eggs.gnu.org: First seen = 2020/07/21 10:17:05 X-ACL-Warn: Detected OS = Linux 2.2.x-3.x [generic] [fuzzy] X-Spam_score_int: -40 X-Spam_score: -4.1 X-Spam_bar: ---- X-Spam_report: (-4.1 / 5.0 requ) BAYES_00=-1.9, DKIMWL_WL_HIGH=-1, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, DKIM_VALID_AU=-0.1, DKIM_VALID_EF=-0.1, RCVD_IN_DNSWL_NONE=-0.0001, RCVD_IN_MSPIKE_H2=-1, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, URIBL_BLOCKED=0.001 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.23 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: =?UTF-8?q?Daniel=20P=2E=20Berrang=C3=A9?= , =?UTF-8?q?Philippe=20Mathieu-Daud=C3=A9?= , Michael Roth , =?UTF-8?q?Tom=C3=A1=C5=A1=20Golembiovsk=C3=BD?= , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= Errors-To: qemu-devel-bounces+importer=patchew.org@nongnu.org Sender: "Qemu-devel" X-ZohoMail-DKIM: fail (Header signature does not verify) Add command for reporting devices on Windows guest. The intent is not so much to report the devices but more importantly the driver (and its version) that is assigned to the device. This gives caller the information whether VirtIO drivers are installed and/or whether inadequate driver is used on a device (e.g. QXL device with base VGA driver). Example: [ { "driver-date": "2019-08-12", "driver-name": "Red Hat VirtIO SCSI controller", "driver-version": "100.80.104.17300", "address": { "type": "pci", "data": { "device-id": 4162, "vendor-id": 6900 } } }, ... ] Signed-off-by: Tom=C3=A1=C5=A1 Golembiovsk=C3=BD Reviewed-by: Marc-Andr=C3=A9 Lureau Reviewed-by: Philippe Mathieu-Daud=C3=A9 --- Changes in v10: - rebased to current master - changed `since` tag in schema to 5.2 qga/commands-posix.c | 9 ++ qga/commands-win32.c | 212 ++++++++++++++++++++++++++++++++++++++++++- qga/qapi-schema.json | 51 +++++++++++ 3 files changed, 271 insertions(+), 1 deletion(-) diff --git a/qga/commands-posix.c b/qga/commands-posix.c index 1a62a3a70d..f509a1f525 100644 --- a/qga/commands-posix.c +++ b/qga/commands-posix.c @@ -2761,6 +2761,8 @@ GList *ga_command_blacklist_init(GList *blacklist) blacklist =3D g_list_append(blacklist, g_strdup("guest-fstrim")); #endif =20 + blacklist =3D g_list_append(blacklist, g_strdup("guest-get-devices")); + return blacklist; } =20 @@ -2981,3 +2983,10 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp) =20 return info; } + +GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) +{ + error_setg(errp, QERR_UNSUPPORTED); + + return NULL; +} diff --git a/qga/commands-win32.c b/qga/commands-win32.c index aaa71f147b..1302bae9eb 100644 --- a/qga/commands-win32.c +++ b/qga/commands-win32.c @@ -21,10 +21,11 @@ #ifdef CONFIG_QGA_NTDDSCSI #include #include +#endif #include #include #include -#endif +#include #include #include #include @@ -39,6 +40,36 @@ #include "qemu/base64.h" #include "commands-common.h" =20 +/* + * The following should be in devpkey.h, but it isn't. The key names were + * prefixed to avoid (future) name clashes. Once the definitions get into + * mingw the following lines can be removed. + */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_NAME, 0xb725f130, 0x47ef, 0x101a, 0xa5, + 0xf1, 0x02, 0x60, 0x8c, 0x9e, 0xeb, 0xac, 10); + /* DEVPROP_TYPE_STRING */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_Device_HardwareIds, 0xa45c254e, 0xdf1c, + 0x4efd, 0x80, 0x20, 0x67, 0xd1, 0x46, 0xa8, 0x50, 0xe0, 3); + /* DEVPROP_TYPE_STRING_LIST */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_Device_DriverDate, 0xa8b865dd, 0x2e3d, + 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 2); + /* DEVPROP_TYPE_FILETIME */ +DEFINE_DEVPROPKEY(qga_DEVPKEY_Device_DriverVersion, 0xa8b865dd, 0x2e3d, + 0x4094, 0xad, 0x97, 0xe5, 0x93, 0xa7, 0xc, 0x75, 0xd6, 3); + /* DEVPROP_TYPE_STRING */ +/* The following shoud be in cfgmgr32.h, but it isn't */ +#ifndef CM_Get_DevNode_Property +CMAPI CONFIGRET WINAPI CM_Get_DevNode_PropertyW( + DEVINST dnDevInst, + CONST DEVPROPKEY * PropertyKey, + DEVPROPTYPE * PropertyType, + PBYTE PropertyBuffer, + PULONG PropertyBufferSize, + ULONG ulFlags +); +#define CM_Get_DevNode_Property CM_Get_DevNode_PropertyW +#endif + #ifndef SHTDN_REASON_FLAG_PLANNED #define SHTDN_REASON_FLAG_PLANNED 0x80000000 #endif @@ -93,6 +124,8 @@ static OpenFlags guest_file_open_modes[] =3D { g_free(suffix); \ } while (0) =20 +G_DEFINE_AUTOPTR_CLEANUP_FUNC(GuestDeviceInfo, qapi_free_GuestDeviceInfo) + static OpenFlags *find_open_flag(const char *mode_str) { int mode; @@ -2229,3 +2262,180 @@ GuestOSInfo *qmp_guest_get_osinfo(Error **errp) =20 return info; } + +/* + * Safely get device property. Returned strings are using wide characters. + * Caller is responsible for freeing the buffer. + */ +static LPBYTE cm_get_property(DEVINST devInst, const DEVPROPKEY *propName, + PDEVPROPTYPE propType) +{ + CONFIGRET cr; + g_autofree LPBYTE buffer =3D NULL; + ULONG buffer_len =3D 0; + + /* First query for needed space */ + cr =3D CM_Get_DevNode_PropertyW(devInst, propName, propType, + buffer, &buffer_len, 0); + if (cr !=3D CR_SUCCESS && cr !=3D CR_BUFFER_SMALL) { + + slog("failed to get property size, error=3D0x%lx", cr); + return NULL; + } + buffer =3D g_new0(BYTE, buffer_len + 1); + cr =3D CM_Get_DevNode_PropertyW(devInst, propName, propType, + buffer, &buffer_len, 0); + if (cr !=3D CR_SUCCESS) { + slog("failed to get device property, error=3D0x%lx", cr); + return NULL; + } + return g_steal_pointer(&buffer); +} + +static GStrv ga_get_hardware_ids(DEVINST devInstance) +{ + GArray *values =3D NULL; + DEVPROPTYPE cm_type; + LPWSTR id; + g_autofree LPWSTR property =3D (LPWSTR)cm_get_property(devInstance, + &qga_DEVPKEY_Device_HardwareIds, &cm_type); + if (property =3D=3D NULL) { + slog("failed to get hardware IDs"); + return NULL; + } + if (*property =3D=3D '\0') { + /* empty list */ + return NULL; + } + values =3D g_array_new(TRUE, TRUE, sizeof(gchar *)); + for (id =3D property; '\0' !=3D *id; id +=3D lstrlenW(id) + 1) { + gchar *id8 =3D g_utf16_to_utf8(id, -1, NULL, NULL, NULL); + g_array_append_val(values, id8); + } + return (GStrv)g_array_free(values, FALSE); +} + +/* + * https://docs.microsoft.com/en-us/windows-hardware/drivers/install/ident= ifiers-for-pci-devices + */ +#define DEVICE_PCI_RE "PCI\\\\VEN_(1AF4|1B36)&DEV_([0-9A-B]{4})(&|$)" + +GuestDeviceInfoList *qmp_guest_get_devices(Error **errp) +{ + GuestDeviceInfoList *head =3D NULL, *cur_item =3D NULL, *item =3D NULL; + HDEVINFO dev_info =3D INVALID_HANDLE_VALUE; + SP_DEVINFO_DATA dev_info_data; + int i, j; + GError *gerr =3D NULL; + g_autoptr(GRegex) device_pci_re =3D NULL; + DEVPROPTYPE cm_type; + + device_pci_re =3D g_regex_new(DEVICE_PCI_RE, + G_REGEX_ANCHORED | G_REGEX_OPTIMIZE, 0, + &gerr); + g_assert(device_pci_re !=3D NULL); + + dev_info_data.cbSize =3D sizeof(SP_DEVINFO_DATA); + dev_info =3D SetupDiGetClassDevs(0, 0, 0, DIGCF_PRESENT | DIGCF_ALLCLA= SSES); + if (dev_info =3D=3D INVALID_HANDLE_VALUE) { + error_setg(errp, "failed to get device tree"); + return NULL; + } + + slog("enumerating devices"); + for (i =3D 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++)= { + bool skip =3D true; + SYSTEMTIME utc_date; + g_autofree LPWSTR name =3D NULL; + g_autofree LPFILETIME date =3D NULL; + g_autofree LPWSTR version =3D NULL; + g_auto(GStrv) hw_ids =3D NULL; + g_autoptr(GuestDeviceInfo) device =3D g_new0(GuestDeviceInfo, 1); + g_autofree char *vendor_id =3D NULL; + g_autofree char *device_id =3D NULL; + + name =3D (LPWSTR)cm_get_property(dev_info_data.DevInst, + &qga_DEVPKEY_NAME, &cm_type); + if (name =3D=3D NULL) { + slog("failed to get device description"); + continue; + } + device->driver_name =3D g_utf16_to_utf8(name, -1, NULL, NULL, NULL= ); + if (device->driver_name =3D=3D NULL) { + error_setg(errp, "conversion to utf8 failed (driver name)"); + continue; + } + slog("querying device: %s", device->driver_name); + hw_ids =3D ga_get_hardware_ids(dev_info_data.DevInst); + if (hw_ids =3D=3D NULL) { + continue; + } + for (j =3D 0; hw_ids[j] !=3D NULL; j++) { + GMatchInfo *match_info; + GuestDeviceAddressPCI *address; + if (!g_regex_match(device_pci_re, hw_ids[j], 0, &match_info)) { + continue; + } + skip =3D false; + + address =3D g_new0(GuestDeviceAddressPCI, 1); + vendor_id =3D g_match_info_fetch(match_info, 1); + device_id =3D g_match_info_fetch(match_info, 2); + address->vendor_id =3D g_ascii_strtoull(vendor_id, NULL, 16); + address->device_id =3D g_ascii_strtoull(device_id, NULL, 16); + + device->address =3D g_new0(GuestDeviceAddress, 1); + device->has_address =3D true; + device->address->type =3D GUEST_DEVICE_ADDRESS_KIND_PCI; + device->address->u.pci.data =3D address; + + g_match_info_free(match_info); + break; + } + if (skip) { + continue; + } + + version =3D (LPWSTR)cm_get_property(dev_info_data.DevInst, + &qga_DEVPKEY_Device_DriverVersion, &cm_type); + if (version =3D=3D NULL) { + slog("failed to get driver version"); + continue; + } + device->driver_version =3D g_utf16_to_utf8(version, -1, NULL, + NULL, NULL); + if (device->driver_version =3D=3D NULL) { + error_setg(errp, "conversion to utf8 failed (driver version)"); + continue; + } + device->has_driver_version =3D true; + + date =3D (LPFILETIME)cm_get_property(dev_info_data.DevInst, + &qga_DEVPKEY_Device_DriverDate, &cm_type); + if (date =3D=3D NULL) { + slog("failed to get driver date"); + continue; + } + FileTimeToSystemTime(date, &utc_date); + device->driver_date =3D g_strdup_printf("%04d-%02d-%02d", + utc_date.wYear, utc_date.wMonth, utc_date.wDay); + device->has_driver_date =3D true; + + slog("driver: %s\ndriver version: %s,%s\n", device->driver_name, + device->driver_date, device->driver_version); + item =3D g_new0(GuestDeviceInfoList, 1); + item->value =3D g_steal_pointer(&device); + if (!cur_item) { + head =3D cur_item =3D item; + } else { + cur_item->next =3D item; + cur_item =3D item; + } + continue; + } + + if (dev_info !=3D INVALID_HANDLE_VALUE) { + SetupDiDestroyDeviceInfoList(dev_info); + } + return head; +} diff --git a/qga/qapi-schema.json b/qga/qapi-schema.json index 4be9aad48e..a1ebe1e91b 100644 --- a/qga/qapi-schema.json +++ b/qga/qapi-schema.json @@ -1252,3 +1252,54 @@ ## { 'command': 'guest-get-osinfo', 'returns': 'GuestOSInfo' } + +## +# @GuestDeviceAddressPCI: +# +# @vendor-id: vendor ID +# @device-id: device ID +# +# Since: 5.2 +## +{ 'struct': 'GuestDeviceAddressPCI', + 'data': { 'vendor-id': 'uint16', 'device-id': 'uint16' } } + +## +# @GuestDeviceAddress: +# +# Address of the device +# - @pci: address of PCI device, since: 5.2 +# +# Since: 5.2 +## +{ 'union': 'GuestDeviceAddress', + 'data': { 'pci': 'GuestDeviceAddressPCI' } } + +## +# @GuestDeviceInfo: +# +# @driver-name: name of the associated driver +# @driver-date: driver release date in format YYYY-MM-DD +# @driver-version: driver version +# +# Since: 5.2 +## +{ 'struct': 'GuestDeviceInfo', + 'data': { + 'driver-name': 'str', + '*driver-date': 'str', + '*driver-version': 'str', + '*address': 'GuestDeviceAddress' + } } + +## +# @guest-get-devices: +# +# Retrieve information about device drivers in Windows guest +# +# Returns: @GuestDeviceInfo +# +# Since: 5.2 +## +{ 'command': 'guest-get-devices', + 'returns': ['GuestDeviceInfo'] } --=20 2.25.0