qga: added GuestPCIAddress information
PCIAddress inforfation is obtained via SetupApi, which provides the information about address, bus, etc. We look throught entire device tree in the system and try to find device object for given volume. For this PDO SetupDiGetDeviceRegistryProperty is called, which reads PCI configuration for a given devicei if it is possible. This is the most convinient way for a userspace service. The lookup is performed for every volume available. However, this information is not mandatory for vss-provider. In order to use SetupApi we need to notify linker about it. We do not need to install additional libs, so we do not make separate configuration option to use libsetupapi.su SetupApi gives as the same information as kernel driver with IRP_MN_QUERY_INTERFACE. https://support.microsoft.com/en-us/kb/253232 Signed-off-by: Olga Krishtal <okrishtal@virtuozzo.com> Signed-off-by: Denis V. Lunev <den@openvz.org> CC: Eric Blake <eblake@redhat.com> CC: Michael Roth <mdroth@linux.vnet.ibm.com> * stub out get_pci_info if !CONFIG_QGA_NTDDSCSI Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
This commit is contained in:
parent
a3ef3b2272
commit
c54e1eb492
1
configure
vendored
1
configure
vendored
@ -3836,6 +3836,7 @@ int main(void) {
|
||||
EOF
|
||||
if compile_prog "" "" ; then
|
||||
guest_agent_ntddscsi=yes
|
||||
libs_qga="-lsetupapi $libs_qga"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
@ -23,6 +23,8 @@
|
||||
#ifdef CONFIG_QGA_NTDDSCSI
|
||||
#include <winioctl.h>
|
||||
#include <ntddscsi.h>
|
||||
#include <setupapi.h>
|
||||
#include <initguid.h>
|
||||
#endif
|
||||
#include "qga/guest-agent-core.h"
|
||||
#include "qga/vss-win32.h"
|
||||
@ -424,9 +426,102 @@ static GuestDiskBusType find_bus_type(STORAGE_BUS_TYPE bus)
|
||||
return win2qemu[(int)bus];
|
||||
}
|
||||
|
||||
DEFINE_GUID(GUID_DEVINTERFACE_VOLUME,
|
||||
0x53f5630dL, 0xb6bf, 0x11d0, 0x94, 0xf2,
|
||||
0x00, 0xa0, 0xc9, 0x1e, 0xfb, 0x8b);
|
||||
|
||||
static GuestPCIAddress *get_pci_info(char *guid, Error **errp)
|
||||
{
|
||||
return NULL;
|
||||
HDEVINFO dev_info;
|
||||
SP_DEVINFO_DATA dev_info_data;
|
||||
DWORD size = 0;
|
||||
int i;
|
||||
char dev_name[MAX_PATH];
|
||||
char *buffer = NULL;
|
||||
GuestPCIAddress *pci = NULL;
|
||||
char *name = g_strdup(&guid[4]);
|
||||
|
||||
if (!QueryDosDevice(name, dev_name, ARRAY_SIZE(dev_name))) {
|
||||
error_setg_win32(errp, GetLastError(), "failed to get dos device name");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_info = SetupDiGetClassDevs(&GUID_DEVINTERFACE_VOLUME, 0, 0,
|
||||
DIGCF_PRESENT | DIGCF_DEVICEINTERFACE);
|
||||
if (dev_info == INVALID_HANDLE_VALUE) {
|
||||
error_setg_win32(errp, GetLastError(), "failed to get devices tree");
|
||||
goto out;
|
||||
}
|
||||
|
||||
dev_info_data.cbSize = sizeof(SP_DEVINFO_DATA);
|
||||
for (i = 0; SetupDiEnumDeviceInfo(dev_info, i, &dev_info_data); i++) {
|
||||
DWORD addr, bus, slot, func, dev, data, size2;
|
||||
while (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
|
||||
SPDRP_PHYSICAL_DEVICE_OBJECT_NAME,
|
||||
&data, (PBYTE)buffer, size,
|
||||
&size2)) {
|
||||
size = MAX(size, size2);
|
||||
if (GetLastError() == ERROR_INSUFFICIENT_BUFFER) {
|
||||
g_free(buffer);
|
||||
/* Double the size to avoid problems on
|
||||
* W2k MBCS systems per KB 888609.
|
||||
* https://support.microsoft.com/en-us/kb/259695 */
|
||||
buffer = g_malloc(size * 2);
|
||||
} else {
|
||||
error_setg_win32(errp, GetLastError(),
|
||||
"failed to get device name");
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
if (g_strcmp0(buffer, dev_name)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
/* There is no need to allocate buffer in the next functions. The size
|
||||
* is known and ULONG according to
|
||||
* https://support.microsoft.com/en-us/kb/253232
|
||||
* https://msdn.microsoft.com/en-us/library/windows/hardware/ff543095(v=vs.85).aspx
|
||||
*/
|
||||
if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
|
||||
SPDRP_BUSNUMBER, &data, (PBYTE)&bus, size, NULL)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* The function retrieves the device's address. This value will be
|
||||
* transformed into device function and number */
|
||||
if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
|
||||
SPDRP_ADDRESS, &data, (PBYTE)&addr, size, NULL)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* This call returns UINumber of DEVICE_CAPABILITIES structure.
|
||||
* This number is typically a user-perceived slot number. */
|
||||
if (!SetupDiGetDeviceRegistryProperty(dev_info, &dev_info_data,
|
||||
SPDRP_UI_NUMBER, &data, (PBYTE)&slot, size, NULL)) {
|
||||
break;
|
||||
}
|
||||
|
||||
/* SetupApi gives us the same information as driver with
|
||||
* IoGetDeviceProperty. According to Microsoft
|
||||
* https://support.microsoft.com/en-us/kb/253232
|
||||
* FunctionNumber = (USHORT)((propertyAddress) & 0x0000FFFF);
|
||||
* DeviceNumber = (USHORT)(((propertyAddress) >> 16) & 0x0000FFFF);
|
||||
* SPDRP_ADDRESS is propertyAddress, so we do the same.*/
|
||||
|
||||
func = addr & 0x0000FFFF;
|
||||
dev = (addr >> 16) & 0x0000FFFF;
|
||||
pci = g_malloc0(sizeof(*pci));
|
||||
pci->domain = dev;
|
||||
pci->slot = slot;
|
||||
pci->function = func;
|
||||
pci->bus = bus;
|
||||
break;
|
||||
}
|
||||
out:
|
||||
g_free(buffer);
|
||||
g_free(name);
|
||||
return pci;
|
||||
}
|
||||
|
||||
static int get_disk_bus_type(HANDLE vol_h, Error **errp)
|
||||
|
Loading…
Reference in New Issue
Block a user