1 /* VBOX driver interface - synchronous version - by D.C. van Moolenbroek */ 2 3 #include <minix/drivers.h> 4 #include <minix/vboxtype.h> 5 #include <minix/vboxif.h> 6 #include <minix/vbox.h> 7 #include <minix/ds.h> 8 #include <assert.h> 9 10 static endpoint_t vbox_endpt = NONE; 11 12 int vbox_init(void) 13 { 14 /* Initialize the library, by resolving the VBOX driver endpoint. 15 */ 16 int r; 17 18 if ((r = ds_retrieve_label_endpt("vbox", &vbox_endpt)) != OK) { 19 printf("libvbox: unable to obtain VBOX endpoint (%d)\n", r); 20 21 return EINVAL; 22 } 23 24 return OK; 25 } 26 27 vbox_conn_t vbox_open(char *name) 28 { 29 /* Open a VirtualBox HGCM connection. 30 */ 31 message m; 32 cp_grant_id_t grant; 33 size_t len; 34 int r; 35 36 if (vbox_endpt == NONE) 37 return EDEADSRCDST; 38 39 len = strlen(name) + 1; 40 grant = cpf_grant_direct(vbox_endpt, (vir_bytes) name, len, CPF_READ); 41 if (!GRANT_VALID(grant)) 42 return ENOMEM; 43 44 memset(&m, 0, sizeof(m)); 45 m.m_type = VBOX_OPEN; 46 m.VBOX_GRANT = grant; 47 m.VBOX_COUNT = len; 48 m.VBOX_ID = 0; 49 50 r = ipc_sendrec(vbox_endpt, &m); 51 52 cpf_revoke(grant); 53 54 if (r != OK) 55 return r; 56 57 if (m.VBOX_ID != 0) 58 return EINVAL; 59 60 return m.VBOX_RESULT; 61 } 62 63 int vbox_close(vbox_conn_t conn) 64 { 65 /* Close a VirtualBox HGCM connection. 66 */ 67 message m; 68 int r; 69 70 if (vbox_endpt == NONE) 71 return EDEADSRCDST; 72 73 memset(&m, 0, sizeof(m)); 74 m.m_type = VBOX_CLOSE; 75 m.VBOX_CONN = conn; 76 m.VBOX_ID = 0; 77 78 r = ipc_sendrec(vbox_endpt, &m); 79 80 if (r != OK) 81 return r; 82 83 if (m.VBOX_ID != 0) 84 return EINVAL; 85 86 return m.VBOX_RESULT; 87 } 88 89 int vbox_call(vbox_conn_t conn, u32_t function, vbox_param_t *param, int count, 90 int *code) 91 { 92 /* Call a VirtualBox HGCM function. The caller must set up all buffer grants. 93 */ 94 cp_grant_id_t grant = GRANT_INVALID; 95 message m; 96 int i, r; 97 98 if (vbox_endpt == NONE) { 99 vbox_put(param, count); 100 101 return EDEADSRCDST; 102 } 103 104 /* Check whether all parameters are initialized correctly. */ 105 for (i = 0; i < count; i++) { 106 switch (param[i].type) { 107 case VBOX_TYPE_U32: 108 case VBOX_TYPE_U64: 109 case VBOX_TYPE_PTR: 110 break; 111 112 default: 113 vbox_put(param, count); 114 115 return ENOMEM; 116 } 117 } 118 119 if (count > 0) { 120 grant = cpf_grant_direct(vbox_endpt, (vir_bytes) param, 121 sizeof(param[0]) * count, CPF_READ | CPF_WRITE); 122 if (!GRANT_VALID(grant)) { 123 vbox_put(param, count); 124 125 return ENOMEM; 126 } 127 } 128 129 memset(&m, 0, sizeof(m)); 130 m.m_type = VBOX_CALL; 131 m.VBOX_CONN = conn; 132 m.VBOX_GRANT = grant; 133 m.VBOX_COUNT = count; 134 m.VBOX_ID = 0; 135 m.VBOX_FUNCTION = function; 136 137 r = ipc_sendrec(vbox_endpt, &m); 138 139 if (GRANT_VALID(grant)) 140 cpf_revoke(grant); 141 142 vbox_put(param, count); 143 144 if (r != OK) 145 return r; 146 147 if (m.VBOX_ID != 0) 148 return EINVAL; 149 150 if (code != NULL) 151 *code = m.VBOX_CODE; 152 153 return m.VBOX_RESULT; 154 } 155 156 void vbox_set_u32(vbox_param_t *param, u32_t value) 157 { 158 /* Set the given parameter to a 32-bit value. 159 */ 160 161 param->type = VBOX_TYPE_U32; 162 param->u32 = value; 163 } 164 165 void vbox_set_u64(vbox_param_t *param, u64_t value) 166 { 167 /* Set the given parameter to a 32-bit value. 168 */ 169 170 param->type = VBOX_TYPE_U64; 171 param->u64 = value; 172 } 173 174 void vbox_set_ptr(vbox_param_t *param, void *ptr, size_t size, 175 unsigned int dir) 176 { 177 /* Set the given parameter to a grant for the given local pointer. 178 */ 179 cp_grant_id_t grant = GRANT_INVALID; 180 int flags; 181 182 flags = 0; 183 if (dir & VBOX_DIR_IN) flags |= CPF_WRITE; 184 if (dir & VBOX_DIR_OUT) flags |= CPF_READ; 185 186 if (size > 0) { 187 grant = cpf_grant_direct(vbox_endpt, (vir_bytes) ptr, size, flags); 188 if (!GRANT_VALID(grant)) { 189 param->type = VBOX_TYPE_INVALID; 190 191 return; 192 } 193 } 194 195 param->type = VBOX_TYPE_PTR; 196 param->ptr.grant = grant; 197 param->ptr.off = 0; 198 param->ptr.size = size; 199 param->ptr.dir = dir; 200 } 201 202 void vbox_set_grant(vbox_param_t *param, endpoint_t endpt, cp_grant_id_t grant, 203 size_t off, size_t size, unsigned int dir) 204 { 205 /* Set the given parameter to an indirect grant for the given grant. 206 */ 207 cp_grant_id_t indir_grant; 208 209 /* Unfortunately, the current implementation of indirect grants does not 210 * support making smaller subgrants out of larger original grants. Therefore, 211 * we are forced to grant more access than we would like. 212 */ 213 indir_grant = cpf_grant_indirect(vbox_endpt, endpt, grant); 214 if (!GRANT_VALID(indir_grant)) { 215 param->type = VBOX_TYPE_INVALID; 216 217 return; 218 } 219 220 param->type = VBOX_TYPE_PTR; 221 param->ptr.grant = indir_grant; 222 param->ptr.off = off; 223 param->ptr.size = size; 224 param->ptr.dir = dir; 225 } 226 227 void vbox_put(vbox_param_t *param, int count) 228 { 229 /* Free all resources used for the given parameters. 230 */ 231 232 while (count--) { 233 if (param->type == VBOX_TYPE_PTR && GRANT_VALID(param->ptr.grant)) 234 cpf_revoke(param->ptr.grant); 235 236 param++; 237 } 238 } 239 240 u32_t vbox_get_u32(vbox_param_t *param) 241 { 242 /* Retrieve the 32-bit value from the given parameter. 243 */ 244 245 assert(param->type == VBOX_TYPE_U32); 246 return param->u32; 247 } 248 249 u64_t vbox_get_u64(vbox_param_t *param) 250 { 251 /* Retrieve the 64-bit value from the given parameter. 252 */ 253 254 assert(param->type == VBOX_TYPE_U64); 255 return param->u64; 256 } 257