/* VBOX driver interface - synchronous version - by D.C. van Moolenbroek */ #include #include #include #include #include #include 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 = ipc_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 = ipc_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 = ipc_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; }