VBOX: add host/guest communication interface
This interface can be used by other system processes by means of the newly provided vbox API in libsys.
This commit is contained in:
@@ -115,6 +115,7 @@ SRCS= \
|
||||
timers.c \
|
||||
timing.c \
|
||||
tsc_util.c \
|
||||
vbox.c \
|
||||
vm_brk.c \
|
||||
vm_dmacalls.c \
|
||||
vm_exec_newmem.c \
|
||||
|
||||
256
lib/libsys/vbox.c
Normal file
256
lib/libsys/vbox.c
Normal file
@@ -0,0 +1,256 @@
|
||||
/* VBOX driver interface - synchronous version - by D.C. van Moolenbroek */
|
||||
|
||||
#include <minix/drivers.h>
|
||||
#include <minix/vboxtype.h>
|
||||
#include <minix/vboxif.h>
|
||||
#include <minix/vbox.h>
|
||||
#include <minix/ds.h>
|
||||
#include <assert.h>
|
||||
|
||||
static endpoint_t vbox_endpt = NONE;
|
||||
|
||||
int vbox_init(void)
|
||||
{
|
||||
/* Initialize the library, by resolving the VBOX driver endpoint.
|
||||
*/
|
||||
int r;
|
||||
|
||||
if ((r = ds_retrieve_label_endpt("vbox", &vbox_endpt)) != OK) {
|
||||
printf("libvbox: unable to obtain VBOX endpoint (%d)\n", r);
|
||||
|
||||
return EINVAL;
|
||||
}
|
||||
|
||||
return OK;
|
||||
}
|
||||
|
||||
vbox_conn_t vbox_open(char *name)
|
||||
{
|
||||
/* Open a VirtualBox HGCM connection.
|
||||
*/
|
||||
message m;
|
||||
cp_grant_id_t grant;
|
||||
size_t len;
|
||||
int r;
|
||||
|
||||
if (vbox_endpt == NONE)
|
||||
return EDEADSRCDST;
|
||||
|
||||
len = strlen(name) + 1;
|
||||
grant = cpf_grant_direct(vbox_endpt, (vir_bytes) name, len, CPF_READ);
|
||||
if (!GRANT_VALID(grant))
|
||||
return ENOMEM;
|
||||
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.m_type = VBOX_OPEN;
|
||||
m.VBOX_GRANT = grant;
|
||||
m.VBOX_COUNT = len;
|
||||
m.VBOX_ID = 0;
|
||||
|
||||
r = sendrec(vbox_endpt, &m);
|
||||
|
||||
cpf_revoke(grant);
|
||||
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
if (m.VBOX_ID != 0)
|
||||
return EINVAL;
|
||||
|
||||
return m.VBOX_RESULT;
|
||||
}
|
||||
|
||||
int vbox_close(vbox_conn_t conn)
|
||||
{
|
||||
/* Close a VirtualBox HGCM connection.
|
||||
*/
|
||||
message m;
|
||||
int r;
|
||||
|
||||
if (vbox_endpt == NONE)
|
||||
return EDEADSRCDST;
|
||||
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.m_type = VBOX_CLOSE;
|
||||
m.VBOX_CONN = conn;
|
||||
m.VBOX_ID = 0;
|
||||
|
||||
r = sendrec(vbox_endpt, &m);
|
||||
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
if (m.VBOX_ID != 0)
|
||||
return EINVAL;
|
||||
|
||||
return m.VBOX_RESULT;
|
||||
}
|
||||
|
||||
int vbox_call(vbox_conn_t conn, u32_t function, vbox_param_t *param, int count,
|
||||
int *code)
|
||||
{
|
||||
/* Call a VirtualBox HGCM function. The caller must set up all buffer grants.
|
||||
*/
|
||||
cp_grant_id_t grant = GRANT_INVALID;
|
||||
message m;
|
||||
int i, r;
|
||||
|
||||
if (vbox_endpt == NONE) {
|
||||
vbox_put(param, count);
|
||||
|
||||
return EDEADSRCDST;
|
||||
}
|
||||
|
||||
/* Check whether all parameters are initialized correctly. */
|
||||
for (i = 0; i < count; i++) {
|
||||
switch (param[i].type) {
|
||||
case VBOX_TYPE_U32:
|
||||
case VBOX_TYPE_U64:
|
||||
case VBOX_TYPE_PTR:
|
||||
break;
|
||||
|
||||
default:
|
||||
vbox_put(param, count);
|
||||
|
||||
return ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
if (count > 0) {
|
||||
grant = cpf_grant_direct(vbox_endpt, (vir_bytes) param,
|
||||
sizeof(param[0]) * count, CPF_READ | CPF_WRITE);
|
||||
if (!GRANT_VALID(grant)) {
|
||||
vbox_put(param, count);
|
||||
|
||||
return ENOMEM;
|
||||
}
|
||||
}
|
||||
|
||||
memset(&m, 0, sizeof(m));
|
||||
m.m_type = VBOX_CALL;
|
||||
m.VBOX_CONN = conn;
|
||||
m.VBOX_GRANT = grant;
|
||||
m.VBOX_COUNT = count;
|
||||
m.VBOX_ID = 0;
|
||||
m.VBOX_FUNCTION = function;
|
||||
|
||||
r = sendrec(vbox_endpt, &m);
|
||||
|
||||
if (GRANT_VALID(grant))
|
||||
cpf_revoke(grant);
|
||||
|
||||
vbox_put(param, count);
|
||||
|
||||
if (r != OK)
|
||||
return r;
|
||||
|
||||
if (m.VBOX_ID != 0)
|
||||
return EINVAL;
|
||||
|
||||
if (code != NULL)
|
||||
*code = m.VBOX_CODE;
|
||||
|
||||
return m.VBOX_RESULT;
|
||||
}
|
||||
|
||||
void vbox_set_u32(vbox_param_t *param, u32_t value)
|
||||
{
|
||||
/* Set the given parameter to a 32-bit value.
|
||||
*/
|
||||
|
||||
param->type = VBOX_TYPE_U32;
|
||||
param->u32 = value;
|
||||
}
|
||||
|
||||
void vbox_set_u64(vbox_param_t *param, u64_t value)
|
||||
{
|
||||
/* Set the given parameter to a 32-bit value.
|
||||
*/
|
||||
|
||||
param->type = VBOX_TYPE_U64;
|
||||
param->u64 = value;
|
||||
}
|
||||
|
||||
void vbox_set_ptr(vbox_param_t *param, void *ptr, size_t size,
|
||||
unsigned int dir)
|
||||
{
|
||||
/* Set the given parameter to a grant for the given local pointer.
|
||||
*/
|
||||
cp_grant_id_t grant = GRANT_INVALID;
|
||||
int flags;
|
||||
|
||||
flags = 0;
|
||||
if (dir & VBOX_DIR_IN) flags |= CPF_WRITE;
|
||||
if (dir & VBOX_DIR_OUT) flags |= CPF_READ;
|
||||
|
||||
if (size > 0) {
|
||||
grant = cpf_grant_direct(vbox_endpt, (vir_bytes) ptr, size, flags);
|
||||
if (!GRANT_VALID(grant)) {
|
||||
param->type = VBOX_TYPE_INVALID;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
param->type = VBOX_TYPE_PTR;
|
||||
param->ptr.grant = grant;
|
||||
param->ptr.off = 0;
|
||||
param->ptr.size = size;
|
||||
param->ptr.dir = dir;
|
||||
}
|
||||
|
||||
void vbox_set_grant(vbox_param_t *param, endpoint_t endpt, cp_grant_id_t grant,
|
||||
size_t off, size_t size, unsigned int dir)
|
||||
{
|
||||
/* Set the given parameter to an indirect grant for the given grant.
|
||||
*/
|
||||
cp_grant_id_t indir_grant;
|
||||
|
||||
/* Unfortunately, the current implementation of indirect grants does not
|
||||
* support making smaller subgrants out of larger original grants. Therefore,
|
||||
* we are forced to grant more access than we would like.
|
||||
*/
|
||||
indir_grant = cpf_grant_indirect(vbox_endpt, endpt, grant);
|
||||
if (!GRANT_VALID(indir_grant)) {
|
||||
param->type = VBOX_TYPE_INVALID;
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
param->type = VBOX_TYPE_PTR;
|
||||
param->ptr.grant = indir_grant;
|
||||
param->ptr.off = off;
|
||||
param->ptr.size = size;
|
||||
param->ptr.dir = dir;
|
||||
}
|
||||
|
||||
void vbox_put(vbox_param_t *param, int count)
|
||||
{
|
||||
/* Free all resources used for the given parameters.
|
||||
*/
|
||||
|
||||
while (count--) {
|
||||
if (param->type == VBOX_TYPE_PTR && GRANT_VALID(param->ptr.grant))
|
||||
cpf_revoke(param->ptr.grant);
|
||||
|
||||
param++;
|
||||
}
|
||||
}
|
||||
|
||||
u32_t vbox_get_u32(vbox_param_t *param)
|
||||
{
|
||||
/* Retrieve the 32-bit value from the given parameter.
|
||||
*/
|
||||
|
||||
assert(param->type == VBOX_TYPE_U32);
|
||||
return param->u32;
|
||||
}
|
||||
|
||||
u64_t vbox_get_u64(vbox_param_t *param)
|
||||
{
|
||||
/* Retrieve the 64-bit value from the given parameter.
|
||||
*/
|
||||
|
||||
assert(param->type == VBOX_TYPE_U64);
|
||||
return param->u64;
|
||||
}
|
||||
Reference in New Issue
Block a user