[porthole] update in accordance with the recent windows driver changes

This commit is contained in:
Geoffrey McRae 2019-10-31 23:45:08 +11:00
parent 9d6bb57eff
commit 01da541815
6 changed files with 98 additions and 88 deletions

View File

@ -1 +1 @@
B1-18-g438548c427+1 B1-19-g9d6bb57eff+1

View File

@ -21,6 +21,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <stdint.h> #include <stdint.h>
typedef struct PortholeDev *PortholeDev; typedef struct PortholeDev *PortholeDev;
typedef int PortholeID;
/** /**
* Open the porthole device * Open the porthole device
@ -49,7 +50,7 @@ void porthole_dev_close(PortholeDev *handle);
* @param type The type * @param type The type
* @param buffer The buffer to share * @param buffer The buffer to share
* @param size The size of the buffer * @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 * 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. * 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 * This is an expensive operation, the idea is that you allocate fixed buffers
* and share them with the host at initialization. * 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 handle The porthole device
* @param buffer The buffer to unlock * @param id The porthole map id returned by porthole_dev_share
* @param size The size of the buffer
* @returns true on success * @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 * be freed or re-used. The client application should no longer attempt to
* access this buffer as it may be paged out of RAM. * access this buffer as it may be paged out of RAM.
* *
* Note that this is not strictly required as closing the device will cause * Note that this is not strictly required as closing the device will cause
* the driver to cleanup any prior locked buffers. * 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); bool porthole_dev_unmap(PortholeDev handle, PortholeID id);

View File

@ -1,54 +0,0 @@
/*
Looking Glass - KVM FrameRelay (KVMFR) Client
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
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 <stdint.h>
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))

62
porthole/src/phmsg.h Normal file
View File

@ -0,0 +1,62 @@
/*
Looking Glass - KVM FrameRelay (KVMFR) Client
Copyright (C) 2017-2019 Geoffrey McRae <geoff@hostfission.com>
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 <stdint.h>
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))

View File

@ -24,6 +24,7 @@ Place, Suite 330, Boston, MA 02111-1307 USA
#include <windows.h> #include <windows.h>
#include <setupapi.h> #include <setupapi.h>
#include <assert.h>
struct PortholeDev struct PortholeDev
{ {
@ -37,11 +38,7 @@ bool porthole_dev_open(PortholeDev *handle, const uint32_t vendor_id)
SP_DEVICE_INTERFACE_DATA devInfData = {0}; SP_DEVICE_INTERFACE_DATA devInfData = {0};
HANDLE dev; HANDLE dev;
if (!handle) assert(handle);
{
DEBUG_ERROR("Invalid buffer provided");
return false;
}
devInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE); devInfo = SetupDiGetClassDevs(NULL, NULL, NULL, DIGCF_PRESENT | DIGCF_ALLCLASSES | DIGCF_DEVICEINTERFACE);
devInfData.cbSize = sizeof(SP_DEVICE_INTERFACE_DATA); 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) void porthole_dev_close(PortholeDev *handle)
{ {
assert(handle && *handle);
CloseHandle((*handle)->dev); CloseHandle((*handle)->dev);
free(*handle); free(*handle);
*handle = NULL; *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; DWORD returned;
PortholeMsg msg = { PortholeMsg msg = {
@ -136,22 +137,23 @@ bool porthole_dev_share(PortholeDev handle, const uint32_t type, void *buffer, s
.size = size .size = size
}; };
if (!DeviceIoControl(handle->dev, IOCTL_PORTHOLE_SEND_MSG, &msg, sizeof(PortholeMsg), NULL, 0, &returned, NULL)) PortholeMapID out;
return false;
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; DWORD returned;
PortholeLockMsg msg = { PortholeMapID msg = id;
.addr = buffer, if (!DeviceIoControl(handle->dev, IOCTL_PORTHOLE_UNLOCK_BUFFER, &msg, sizeof(PortholeMapID), NULL, 0, &returned, NULL))
.size = size
};
if (!DeviceIoControl(handle->dev, IOCTL_PORTHOLE_UNLOCK_BUFFER, &msg , sizeof(PortholeLockMsg), NULL, 0, &returned, NULL))
return false; return false;
return true; return true;

View File

@ -7,18 +7,13 @@ DEFINE_GUID (GUID_DEVINTERFACE_PORTHOLE,
typedef struct _PortholeMsg typedef struct _PortholeMsg
{ {
UINT32 type; UINT32 type;
PVOID addr; PVOID addr;
UINT32 size; UINT32 size;
} }
PortholeMsg, *PPortholeMsg; PortholeMsg, *PPortholeMsg;
typedef struct _PortholeLockMsg typedef int PortholeMapID, *PPortholeMapID;
{
PVOID addr;
UINT32 size;
}
PortholeLockMsg, *PPortholeLockMsg;
#define IOCTL_PORTHOLE_SEND_MSG CTL_CODE(FILE_DEVICE_UNKNOWN, 0x800, METHOD_BUFFERED, FILE_ANY_ACCESS) #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) #define IOCTL_PORTHOLE_UNLOCK_BUFFER CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_BUFFERED, FILE_ANY_ACCESS)