xref: /minix3/minix/lib/libsys/arch/i386/vbox.c (revision 94e65446c4f963450ea94b8becc02cec062675cd)
1433d6423SLionel Sambuc /* VBOX driver interface - synchronous version - by D.C. van Moolenbroek */
2433d6423SLionel Sambuc 
3433d6423SLionel Sambuc #include <minix/drivers.h>
4433d6423SLionel Sambuc #include <minix/vboxtype.h>
5433d6423SLionel Sambuc #include <minix/vboxif.h>
6433d6423SLionel Sambuc #include <minix/vbox.h>
7433d6423SLionel Sambuc #include <minix/ds.h>
8433d6423SLionel Sambuc #include <assert.h>
9433d6423SLionel Sambuc 
10433d6423SLionel Sambuc static endpoint_t vbox_endpt = NONE;
11433d6423SLionel Sambuc 
vbox_init(void)12433d6423SLionel Sambuc int vbox_init(void)
13433d6423SLionel Sambuc {
14433d6423SLionel Sambuc /* Initialize the library, by resolving the VBOX driver endpoint.
15433d6423SLionel Sambuc  */
16433d6423SLionel Sambuc   int r;
17433d6423SLionel Sambuc 
18433d6423SLionel Sambuc   if ((r = ds_retrieve_label_endpt("vbox", &vbox_endpt)) != OK) {
19433d6423SLionel Sambuc 	printf("libvbox: unable to obtain VBOX endpoint (%d)\n", r);
20433d6423SLionel Sambuc 
21433d6423SLionel Sambuc 	return EINVAL;
22433d6423SLionel Sambuc   }
23433d6423SLionel Sambuc 
24433d6423SLionel Sambuc   return OK;
25433d6423SLionel Sambuc }
26433d6423SLionel Sambuc 
vbox_open(const char * name)27*94e65446SDavid van Moolenbroek vbox_conn_t vbox_open(const char *name)
28433d6423SLionel Sambuc {
29433d6423SLionel Sambuc /* Open a VirtualBox HGCM connection.
30433d6423SLionel Sambuc  */
31433d6423SLionel Sambuc   message m;
32433d6423SLionel Sambuc   cp_grant_id_t grant;
33433d6423SLionel Sambuc   size_t len;
34433d6423SLionel Sambuc   int r;
35433d6423SLionel Sambuc 
36433d6423SLionel Sambuc   if (vbox_endpt == NONE)
37433d6423SLionel Sambuc 	return EDEADSRCDST;
38433d6423SLionel Sambuc 
39433d6423SLionel Sambuc   len = strlen(name) + 1;
40433d6423SLionel Sambuc   grant = cpf_grant_direct(vbox_endpt, (vir_bytes) name, len, CPF_READ);
41433d6423SLionel Sambuc   if (!GRANT_VALID(grant))
42433d6423SLionel Sambuc 	return ENOMEM;
43433d6423SLionel Sambuc 
44433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
45433d6423SLionel Sambuc   m.m_type = VBOX_OPEN;
46433d6423SLionel Sambuc   m.VBOX_GRANT = grant;
47433d6423SLionel Sambuc   m.VBOX_COUNT = len;
48433d6423SLionel Sambuc   m.VBOX_ID = 0;
49433d6423SLionel Sambuc 
50433d6423SLionel Sambuc   r = ipc_sendrec(vbox_endpt, &m);
51433d6423SLionel Sambuc 
52433d6423SLionel Sambuc   cpf_revoke(grant);
53433d6423SLionel Sambuc 
54433d6423SLionel Sambuc   if (r != OK)
55433d6423SLionel Sambuc 	return r;
56433d6423SLionel Sambuc 
57433d6423SLionel Sambuc   if (m.VBOX_ID != 0)
58433d6423SLionel Sambuc 	return EINVAL;
59433d6423SLionel Sambuc 
60433d6423SLionel Sambuc   return m.VBOX_RESULT;
61433d6423SLionel Sambuc }
62433d6423SLionel Sambuc 
vbox_close(vbox_conn_t conn)63433d6423SLionel Sambuc int vbox_close(vbox_conn_t conn)
64433d6423SLionel Sambuc {
65433d6423SLionel Sambuc /* Close a VirtualBox HGCM connection.
66433d6423SLionel Sambuc  */
67433d6423SLionel Sambuc   message m;
68433d6423SLionel Sambuc   int r;
69433d6423SLionel Sambuc 
70433d6423SLionel Sambuc   if (vbox_endpt == NONE)
71433d6423SLionel Sambuc 	return EDEADSRCDST;
72433d6423SLionel Sambuc 
73433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
74433d6423SLionel Sambuc   m.m_type = VBOX_CLOSE;
75433d6423SLionel Sambuc   m.VBOX_CONN = conn;
76433d6423SLionel Sambuc   m.VBOX_ID = 0;
77433d6423SLionel Sambuc 
78433d6423SLionel Sambuc   r = ipc_sendrec(vbox_endpt, &m);
79433d6423SLionel Sambuc 
80433d6423SLionel Sambuc   if (r != OK)
81433d6423SLionel Sambuc 	return r;
82433d6423SLionel Sambuc 
83433d6423SLionel Sambuc   if (m.VBOX_ID != 0)
84433d6423SLionel Sambuc 	return EINVAL;
85433d6423SLionel Sambuc 
86433d6423SLionel Sambuc   return m.VBOX_RESULT;
87433d6423SLionel Sambuc }
88433d6423SLionel Sambuc 
vbox_call(vbox_conn_t conn,u32_t function,vbox_param_t * param,int count,int * code)89433d6423SLionel Sambuc int vbox_call(vbox_conn_t conn, u32_t function, vbox_param_t *param, int count,
90433d6423SLionel Sambuc   int *code)
91433d6423SLionel Sambuc {
92433d6423SLionel Sambuc /* Call a VirtualBox HGCM function. The caller must set up all buffer grants.
93433d6423SLionel Sambuc  */
94433d6423SLionel Sambuc   cp_grant_id_t grant = GRANT_INVALID;
95433d6423SLionel Sambuc   message m;
96433d6423SLionel Sambuc   int i, r;
97433d6423SLionel Sambuc 
98433d6423SLionel Sambuc   if (vbox_endpt == NONE) {
99433d6423SLionel Sambuc 	vbox_put(param, count);
100433d6423SLionel Sambuc 
101433d6423SLionel Sambuc 	return EDEADSRCDST;
102433d6423SLionel Sambuc   }
103433d6423SLionel Sambuc 
104433d6423SLionel Sambuc   /* Check whether all parameters are initialized correctly. */
105433d6423SLionel Sambuc   for (i = 0; i < count; i++) {
106433d6423SLionel Sambuc 	switch (param[i].type) {
107433d6423SLionel Sambuc 	case VBOX_TYPE_U32:
108433d6423SLionel Sambuc 	case VBOX_TYPE_U64:
109433d6423SLionel Sambuc 	case VBOX_TYPE_PTR:
110433d6423SLionel Sambuc 		break;
111433d6423SLionel Sambuc 
112433d6423SLionel Sambuc 	default:
113433d6423SLionel Sambuc 		vbox_put(param, count);
114433d6423SLionel Sambuc 
115433d6423SLionel Sambuc 		return ENOMEM;
116433d6423SLionel Sambuc 	}
117433d6423SLionel Sambuc   }
118433d6423SLionel Sambuc 
119433d6423SLionel Sambuc   if (count > 0) {
120433d6423SLionel Sambuc 	grant = cpf_grant_direct(vbox_endpt, (vir_bytes) param,
121433d6423SLionel Sambuc 		sizeof(param[0]) * count, CPF_READ | CPF_WRITE);
122433d6423SLionel Sambuc 	if (!GRANT_VALID(grant)) {
123433d6423SLionel Sambuc 		vbox_put(param, count);
124433d6423SLionel Sambuc 
125433d6423SLionel Sambuc 		return ENOMEM;
126433d6423SLionel Sambuc 	}
127433d6423SLionel Sambuc   }
128433d6423SLionel Sambuc 
129433d6423SLionel Sambuc   memset(&m, 0, sizeof(m));
130433d6423SLionel Sambuc   m.m_type = VBOX_CALL;
131433d6423SLionel Sambuc   m.VBOX_CONN = conn;
132433d6423SLionel Sambuc   m.VBOX_GRANT = grant;
133433d6423SLionel Sambuc   m.VBOX_COUNT = count;
134433d6423SLionel Sambuc   m.VBOX_ID = 0;
135433d6423SLionel Sambuc   m.VBOX_FUNCTION = function;
136433d6423SLionel Sambuc 
137433d6423SLionel Sambuc   r = ipc_sendrec(vbox_endpt, &m);
138433d6423SLionel Sambuc 
139433d6423SLionel Sambuc   if (GRANT_VALID(grant))
140433d6423SLionel Sambuc 	cpf_revoke(grant);
141433d6423SLionel Sambuc 
142433d6423SLionel Sambuc   vbox_put(param, count);
143433d6423SLionel Sambuc 
144433d6423SLionel Sambuc   if (r != OK)
145433d6423SLionel Sambuc 	return r;
146433d6423SLionel Sambuc 
147433d6423SLionel Sambuc   if (m.VBOX_ID != 0)
148433d6423SLionel Sambuc 	return EINVAL;
149433d6423SLionel Sambuc 
150433d6423SLionel Sambuc   if (code != NULL)
151433d6423SLionel Sambuc 	*code = m.VBOX_CODE;
152433d6423SLionel Sambuc 
153433d6423SLionel Sambuc   return m.VBOX_RESULT;
154433d6423SLionel Sambuc }
155433d6423SLionel Sambuc 
vbox_set_u32(vbox_param_t * param,u32_t value)156433d6423SLionel Sambuc void vbox_set_u32(vbox_param_t *param, u32_t value)
157433d6423SLionel Sambuc {
158433d6423SLionel Sambuc /* Set the given parameter to a 32-bit value.
159433d6423SLionel Sambuc  */
160433d6423SLionel Sambuc 
161433d6423SLionel Sambuc   param->type = VBOX_TYPE_U32;
162433d6423SLionel Sambuc   param->u32 = value;
163433d6423SLionel Sambuc }
164433d6423SLionel Sambuc 
vbox_set_u64(vbox_param_t * param,u64_t value)165433d6423SLionel Sambuc void vbox_set_u64(vbox_param_t *param, u64_t value)
166433d6423SLionel Sambuc {
167433d6423SLionel Sambuc /* Set the given parameter to a 32-bit value.
168433d6423SLionel Sambuc  */
169433d6423SLionel Sambuc 
170433d6423SLionel Sambuc   param->type = VBOX_TYPE_U64;
171433d6423SLionel Sambuc   param->u64 = value;
172433d6423SLionel Sambuc }
173433d6423SLionel Sambuc 
vbox_set_ptr(vbox_param_t * param,void * ptr,size_t size,unsigned int dir)174433d6423SLionel Sambuc void vbox_set_ptr(vbox_param_t *param, void *ptr, size_t size,
175433d6423SLionel Sambuc   unsigned int dir)
176433d6423SLionel Sambuc {
177433d6423SLionel Sambuc /* Set the given parameter to a grant for the given local pointer.
178433d6423SLionel Sambuc  */
179433d6423SLionel Sambuc   cp_grant_id_t grant = GRANT_INVALID;
180433d6423SLionel Sambuc   int flags;
181433d6423SLionel Sambuc 
182433d6423SLionel Sambuc   flags = 0;
183433d6423SLionel Sambuc   if (dir & VBOX_DIR_IN) flags |= CPF_WRITE;
184433d6423SLionel Sambuc   if (dir & VBOX_DIR_OUT) flags |= CPF_READ;
185433d6423SLionel Sambuc 
186433d6423SLionel Sambuc   if (size > 0) {
187433d6423SLionel Sambuc 	grant = cpf_grant_direct(vbox_endpt, (vir_bytes) ptr, size, flags);
188433d6423SLionel Sambuc 	if (!GRANT_VALID(grant)) {
189433d6423SLionel Sambuc 		param->type = VBOX_TYPE_INVALID;
190433d6423SLionel Sambuc 
191433d6423SLionel Sambuc 		return;
192433d6423SLionel Sambuc 	}
193433d6423SLionel Sambuc   }
194433d6423SLionel Sambuc 
195433d6423SLionel Sambuc   param->type = VBOX_TYPE_PTR;
196433d6423SLionel Sambuc   param->ptr.grant = grant;
197433d6423SLionel Sambuc   param->ptr.off = 0;
198433d6423SLionel Sambuc   param->ptr.size = size;
199433d6423SLionel Sambuc   param->ptr.dir = dir;
200433d6423SLionel Sambuc }
201433d6423SLionel Sambuc 
vbox_set_grant(vbox_param_t * param,endpoint_t endpt,cp_grant_id_t grant,size_t off,size_t size,unsigned int dir)202433d6423SLionel Sambuc void vbox_set_grant(vbox_param_t *param, endpoint_t endpt, cp_grant_id_t grant,
203433d6423SLionel Sambuc   size_t off, size_t size, unsigned int dir)
204433d6423SLionel Sambuc {
205433d6423SLionel Sambuc /* Set the given parameter to an indirect grant for the given grant.
206433d6423SLionel Sambuc  */
207433d6423SLionel Sambuc   cp_grant_id_t indir_grant;
208433d6423SLionel Sambuc 
209433d6423SLionel Sambuc   /* Unfortunately, the current implementation of indirect grants does not
210433d6423SLionel Sambuc    * support making smaller subgrants out of larger original grants. Therefore,
211433d6423SLionel Sambuc    * we are forced to grant more access than we would like.
212433d6423SLionel Sambuc    */
213433d6423SLionel Sambuc   indir_grant = cpf_grant_indirect(vbox_endpt, endpt, grant);
214433d6423SLionel Sambuc   if (!GRANT_VALID(indir_grant)) {
215433d6423SLionel Sambuc 	param->type = VBOX_TYPE_INVALID;
216433d6423SLionel Sambuc 
217433d6423SLionel Sambuc 	return;
218433d6423SLionel Sambuc   }
219433d6423SLionel Sambuc 
220433d6423SLionel Sambuc   param->type = VBOX_TYPE_PTR;
221433d6423SLionel Sambuc   param->ptr.grant = indir_grant;
222433d6423SLionel Sambuc   param->ptr.off = off;
223433d6423SLionel Sambuc   param->ptr.size = size;
224433d6423SLionel Sambuc   param->ptr.dir = dir;
225433d6423SLionel Sambuc }
226433d6423SLionel Sambuc 
vbox_put(vbox_param_t * param,int count)227433d6423SLionel Sambuc void vbox_put(vbox_param_t *param, int count)
228433d6423SLionel Sambuc {
229433d6423SLionel Sambuc /* Free all resources used for the given parameters.
230433d6423SLionel Sambuc  */
231433d6423SLionel Sambuc 
232433d6423SLionel Sambuc   while (count--) {
233433d6423SLionel Sambuc 	if (param->type == VBOX_TYPE_PTR && GRANT_VALID(param->ptr.grant))
234433d6423SLionel Sambuc 		cpf_revoke(param->ptr.grant);
235433d6423SLionel Sambuc 
236433d6423SLionel Sambuc 	param++;
237433d6423SLionel Sambuc   }
238433d6423SLionel Sambuc }
239433d6423SLionel Sambuc 
vbox_get_u32(vbox_param_t * param)240433d6423SLionel Sambuc u32_t vbox_get_u32(vbox_param_t *param)
241433d6423SLionel Sambuc {
242433d6423SLionel Sambuc /* Retrieve the 32-bit value from the given parameter.
243433d6423SLionel Sambuc  */
244433d6423SLionel Sambuc 
245433d6423SLionel Sambuc   assert(param->type == VBOX_TYPE_U32);
246433d6423SLionel Sambuc   return param->u32;
247433d6423SLionel Sambuc }
248433d6423SLionel Sambuc 
vbox_get_u64(vbox_param_t * param)249433d6423SLionel Sambuc u64_t vbox_get_u64(vbox_param_t *param)
250433d6423SLionel Sambuc {
251433d6423SLionel Sambuc /* Retrieve the 64-bit value from the given parameter.
252433d6423SLionel Sambuc  */
253433d6423SLionel Sambuc 
254433d6423SLionel Sambuc   assert(param->type == VBOX_TYPE_U64);
255433d6423SLionel Sambuc   return param->u64;
256433d6423SLionel Sambuc }
257