From 01da541815d0408f473529a436339f5965c3c8d3 Mon Sep 17 00:00:00 2001 From: Geoffrey McRae Date: Thu, 31 Oct 2019 23:45:08 +1100 Subject: [PATCH] [porthole] update in accordance with the recent windows driver changes --- VERSION | 2 +- porthole/include/porthole/device.h | 21 ++++++---- porthole/src/msg.h | 54 -------------------------- porthole/src/phmsg.h | 62 ++++++++++++++++++++++++++++++ porthole/src/windows/device.c | 34 ++++++++-------- porthole/src/windows/driver.h | 13 ++----- 6 files changed, 98 insertions(+), 88 deletions(-) delete mode 100644 porthole/src/msg.h create mode 100644 porthole/src/phmsg.h diff --git a/VERSION b/VERSION index 95407fa5..f43569cf 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -B1-18-g438548c427+1 \ No newline at end of file +B1-19-g9d6bb57eff+1 \ No newline at end of file diff --git a/porthole/include/porthole/device.h b/porthole/include/porthole/device.h index 6d5c61fd..df1af02d 100644 --- a/porthole/include/porthole/device.h +++ b/porthole/include/porthole/device.h @@ -21,6 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include typedef struct PortholeDev *PortholeDev; +typedef int PortholeID; /** * Open the porthole device @@ -49,7 +50,7 @@ void porthole_dev_close(PortholeDev *handle); * @param type The type * @param buffer The buffer to share * @param size The size of the buffer - * @returns true on success + * @returns the porthole mapping ID, or -1 on failure * * This function locks the supplied buffer in RAM via the porthole device * driver and is then shared with the device for use outside the guest. @@ -63,23 +64,27 @@ void porthole_dev_close(PortholeDev *handle); * This is an expensive operation, the idea is that you allocate fixed buffers * and share them with the host at initialization. * - * @note the driver is hard limited to 32 shares. + * @note the device & driver are hard limited to 32 shares. */ -bool porthole_dev_share(PortholeDev handle, const uint32_t type, void *buffer, size_t size); +PortholeID porthole_dev_map(PortholeDev handle, const uint32_t type, void *buffer, size_t size); /** - * Unlock a previously shared buffer + * Unmap a previously shared buffer * * @param handle The porthole device - * @param buffer The buffer to unlock - * @param size The size of the buffer + * @param id The porthole map id returned by porthole_dev_share * @returns true on success * - * Unlocks a previously shared buffer. Once this has been done the buffer can + * Unmaps a previously shared buffer. Once this has been done the buffer can * be freed or re-used. The client application should no longer attempt to * access this buffer as it may be paged out of RAM. * * Note that this is not strictly required as closing the device will cause * the driver to cleanup any prior locked buffers. + * + * The client application will be notified that the mapping is about to become + * invalid and is expected to clean up and notify when it is done. If your + * application hangs calling this method the issue is very likely with your + * client application. */ -bool porthole_dev_unlock(PortholeDev handle, void *buffer, size_t size); \ No newline at end of file +bool porthole_dev_unmap(PortholeDev handle, PortholeID id); \ No newline at end of file diff --git a/porthole/src/msg.h b/porthole/src/msg.h deleted file mode 100644 index 824371e9..00000000 --- a/porthole/src/msg.h +++ /dev/null @@ -1,54 +0,0 @@ -/* -Looking Glass - KVM FrameRelay (KVMFR) Client -Copyright (C) 2017-2019 Geoffrey McRae -https://looking-glass.hostfission.com - -This program is free software; you can redistribute it and/or modify it under -the terms of the GNU General Public License as published by the Free Software -Foundation; either version 2 of the License, or (at your option) any later -version. - -This program is distributed in the hope that it will be useful, but WITHOUT ANY -WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A -PARTICULAR PURPOSE. See the GNU General Public License for more details. - -You should have received a copy of the GNU General Public License along with -this program; if not, write to the Free Software Foundation, Inc., 59 Temple -Place, Suite 330, Boston, MA 02111-1307 USA -*/ - -#include - -typedef struct { - uint64_t id; -} __attribute__ ((packed)) MsgFd; - -typedef struct { - uint64_t fd_id; - uint64_t addr; - uint32_t size; -} __attribute__ ((packed)) MsgSegment; - -typedef struct { - uint32_t type; -} __attribute__ ((packed)) MsgFinish; - -typedef struct { - uint32_t msg; - union - { - MsgFd fd; - MsgSegment segment; - MsgFinish finish; - } u; -} __attribute__ ((packed)) Msg; - -#define INTRO_MSG_RESET 0x1 -#define INTRO_MSG_FD 0x2 -#define INTRO_MSG_SEGMENT 0x3 -#define INTRO_MSG_FINISH 0x4 - -#define INTRO_MSG_RESET_SIZE (sizeof(uint32_t)) -#define INTRO_MSG_FD_SIZE (sizeof(uint32_t) + sizeof(MsgFd)) -#define INTRO_MSG_SEGMENT_SIZE (sizeof(uint32_t) + sizeof(MsgSegment)) -#define INTRO_MSG_FINISH_SIZE (sizeof(uint32_t) + sizeof(MsgFinish)) \ No newline at end of file diff --git a/porthole/src/phmsg.h b/porthole/src/phmsg.h new file mode 100644 index 00000000..79e4497b --- /dev/null +++ b/porthole/src/phmsg.h @@ -0,0 +1,62 @@ +/* +Looking Glass - KVM FrameRelay (KVMFR) Client +Copyright (C) 2017-2019 Geoffrey McRae +https://looking-glass.hostfission.com + +This program is free software; you can redistribute it and/or modify it under +the terms of the GNU General Public License as published by the Free Software +Foundation; either version 2 of the License, or (at your option) any later +version. + +This program is distributed in the hope that it will be useful, but WITHOUT ANY +WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A +PARTICULAR PURPOSE. See the GNU General Public License for more details. + +You should have received a copy of the GNU General Public License along with +this program; if not, write to the Free Software Foundation, Inc., 59 Temple +Place, Suite 330, Boston, MA 02111-1307 USA +*/ + +#include + +typedef struct { + uint32_t id; // the ID of the FD +} __attribute__ ((packed)) PHMsgFd; + +typedef struct { + uint32_t fd_id; // the ID of the FD for this segment + uint32_t size; // the size of this segment + uint64_t addr; // the base address of this segment +} __attribute__ ((packed)) PHMsgSegment; + +typedef struct { + uint32_t type; // the application defined type + uint32_t id; // the ID of the new mapping +} __attribute__ ((packed)) PHMsgFinish; + +typedef struct { + uint32_t id; // the mapping ID +} __attribute__ ((packed)) PHMsgUnmap; + +typedef struct { + uint32_t msg; + union + { + PHMsgFd fd; + PHMsgSegment segment; + PHMsgFinish finish; + PHMsgUnmap unmap; + } u; +} __attribute__ ((packed)) PHMsg; + +#define PH_MSG_MAP 0x1 // start of a map sequence +#define PH_MSG_FD 0x2 // file descriptor +#define PH_MSG_SEGMENT 0x3 // map segment +#define PH_MSG_FINISH 0x4 // finish of map sequence +#define PH_MSG_UNMAP 0x5 // unmap a previous map + +#define PH_MSG_MAP_SIZE (sizeof(uint32_t)) +#define PH_MSG_FD_SIZE (sizeof(uint32_t) + sizeof(PHMsgFd)) +#define PH_MSG_SEGMENT_SIZE (sizeof(uint32_t) + sizeof(PHMsgSegment)) +#define PH_MSG_FINISH_SIZE (sizeof(uint32_t) + sizeof(PHMsgFinish)) +#define PH_MSG_UNMAP_SIZE (sizeof(uint32_t) + sizeof(PHMsgUnmap)) \ No newline at end of file diff --git a/porthole/src/windows/device.c b/porthole/src/windows/device.c index 274bc8c7..8b1a0d50 100644 --- a/porthole/src/windows/device.c +++ b/porthole/src/windows/device.c @@ -24,6 +24,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA #include #include +#include struct PortholeDev { @@ -37,11 +38,7 @@ bool porthole_dev_open(PortholeDev *handle, const uint32_t vendor_id) SP_DEVICE_INTERFACE_DATA devInfData = {0}; HANDLE dev; - if (!handle) - { - DEBUG_ERROR("Invalid buffer provided"); - return false; - } + assert(handle); devInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE); devInfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); @@ -121,13 +118,17 @@ bool porthole_dev_open(PortholeDev *handle, const uint32_t vendor_id) void porthole_dev_close(PortholeDev *handle) { + assert(handle && *handle); + CloseHandle((*handle)->dev); free(*handle); *handle = NULL; } -bool porthole_dev_share(PortholeDev handle, const uint32_t type, void *buffer, size_t size) +PortholeID porthole_dev_map(PortholeDev handle, const uint32_t type, void *buffer, size_t size) { + assert(handle); + DWORD returned; PortholeMsg msg = { @@ -136,22 +137,23 @@ bool porthole_dev_share(PortholeDev handle, const uint32_t type, void *buffer, s .size = size }; - if (!DeviceIoControl(handle->dev, IOCTL_PORTHOLE_SEND_MSG, &msg, sizeof(PortholeMsg), NULL, 0, &returned, NULL)) - return false; + PortholeMapID out; - return true; + if (!DeviceIoControl(handle->dev, IOCTL_PORTHOLE_SEND_MSG, &msg, sizeof(PortholeMsg), &out, sizeof(PortholeMapID), &returned, NULL)) + return -1; + + PortholeID ret = out; + return ret; } -bool porthole_dev_unlock(PortholeDev handle, void *buffer, size_t size) +bool porthole_dev_unmap(PortholeDev handle, PortholeID id) { + assert(handle); + DWORD returned; - PortholeLockMsg msg = { - .addr = buffer, - .size = size - }; - - if (!DeviceIoControl(handle->dev, IOCTL_PORTHOLE_UNLOCK_BUFFER, &msg , sizeof(PortholeLockMsg), NULL, 0, &returned, NULL)) + PortholeMapID msg = id; + if (!DeviceIoControl(handle->dev, IOCTL_PORTHOLE_UNLOCK_BUFFER, &msg, sizeof(PortholeMapID), NULL, 0, &returned, NULL)) return false; return true; diff --git a/porthole/src/windows/driver.h b/porthole/src/windows/driver.h index dbc8ee63..70965337 100644 --- a/porthole/src/windows/driver.h +++ b/porthole/src/windows/driver.h @@ -7,18 +7,13 @@ DEFINE_GUID (GUID_DEVINTERFACE_PORTHOLE, typedef struct _PortholeMsg { - UINT32 type; - PVOID addr; - UINT32 size; + UINT32 type; + PVOID addr; + UINT32 size; } PortholeMsg, *PPortholeMsg; -typedef struct _PortholeLockMsg -{ - PVOID addr; - UINT32 size; -} -PortholeLockMsg, *PPortholeLockMsg; +typedef int PortholeMapID, *PPortholeMapID; #define IOCTL_PORTHOLE_SEND_MSG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) #define IOCTL_PORTHOLE_UNLOCK_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS) \ No newline at end of file