1 // SPDX-License-Identifier: MIT
3 * Wrapper functions for the shfl host calls.
5 * Copyright (C) 2006-2018 Oracle Corporation
9 #include <linux/slab.h>
10 #include <linux/vbox_err.h>
11 #include <linux/vbox_utils.h>
14 #define SHFL_REQUEST \
15 (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \
16 VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN)
18 static u32 vboxsf_client_id
;
20 int vboxsf_connect(void)
23 struct vmmdev_hgcm_service_location loc
;
26 loc
.type
= VMMDEV_HGCM_LOC_LOCALHOST_EXISTING
;
27 strcpy(loc
.u
.localhost
.service_name
, "VBoxSharedFolders");
29 gdev
= vbg_get_gdev();
31 return -ENODEV
; /* No guest-device */
33 err
= vbg_hgcm_connect(gdev
, SHFL_REQUEST
, &loc
,
34 &vboxsf_client_id
, &vbox_status
);
37 return err
? err
: vbg_status_code_to_errno(vbox_status
);
40 void vboxsf_disconnect(void)
45 gdev
= vbg_get_gdev();
47 return; /* guest-device is gone, already disconnected */
49 vbg_hgcm_disconnect(gdev
, SHFL_REQUEST
, vboxsf_client_id
, &vbox_status
);
53 static int vboxsf_call(u32 function
, void *parms
, u32 parm_count
, int *status
)
58 gdev
= vbg_get_gdev();
60 return -ESHUTDOWN
; /* guest-dev removed underneath us */
62 err
= vbg_hgcm_call(gdev
, SHFL_REQUEST
, vboxsf_client_id
, function
,
63 U32_MAX
, parms
, parm_count
, &vbox_status
);
70 *status
= vbox_status
;
72 return vbg_status_code_to_errno(vbox_status
);
75 int vboxsf_map_folder(struct shfl_string
*folder_name
, u32
*root
)
77 struct shfl_map_folder parms
;
80 parms
.path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL
;
81 parms
.path
.u
.pointer
.size
= shfl_string_buf_size(folder_name
);
82 parms
.path
.u
.pointer
.u
.linear_addr
= (uintptr_t)folder_name
;
84 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
85 parms
.root
.u
.value32
= 0;
87 parms
.delimiter
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
88 parms
.delimiter
.u
.value32
= '/';
90 parms
.case_sensitive
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
91 parms
.case_sensitive
.u
.value32
= 1;
93 err
= vboxsf_call(SHFL_FN_MAP_FOLDER
, &parms
, SHFL_CPARMS_MAP_FOLDER
,
95 if (err
== -ENOSYS
&& status
== VERR_NOT_IMPLEMENTED
)
96 vbg_err("%s: Error host is too old\n", __func__
);
98 *root
= parms
.root
.u
.value32
;
102 int vboxsf_unmap_folder(u32 root
)
104 struct shfl_unmap_folder parms
;
106 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
107 parms
.root
.u
.value32
= root
;
109 return vboxsf_call(SHFL_FN_UNMAP_FOLDER
, &parms
,
110 SHFL_CPARMS_UNMAP_FOLDER
, NULL
);
114 * vboxsf_create - Create a new file or folder
115 * @root: Root of the shared folder in which to create the file
116 * @parsed_path: The path of the file or folder relative to the shared folder
117 * @param: create_parms Parameters for file/folder creation.
119 * Create a new file or folder or open an existing one in a shared folder.
120 * Note this function always returns 0 / success unless an exceptional condition
121 * occurs - out of memory, invalid arguments, etc. If the file or folder could
122 * not be opened or created, create_parms->handle will be set to
123 * SHFL_HANDLE_NIL on return. In this case the value in create_parms->result
124 * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result
125 * is also set on success as additional information.
128 * 0 or negative errno value.
130 int vboxsf_create(u32 root
, struct shfl_string
*parsed_path
,
131 struct shfl_createparms
*create_parms
)
133 struct shfl_create parms
;
135 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
136 parms
.root
.u
.value32
= root
;
138 parms
.path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL
;
139 parms
.path
.u
.pointer
.size
= shfl_string_buf_size(parsed_path
);
140 parms
.path
.u
.pointer
.u
.linear_addr
= (uintptr_t)parsed_path
;
142 parms
.parms
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL
;
143 parms
.parms
.u
.pointer
.size
= sizeof(struct shfl_createparms
);
144 parms
.parms
.u
.pointer
.u
.linear_addr
= (uintptr_t)create_parms
;
146 return vboxsf_call(SHFL_FN_CREATE
, &parms
, SHFL_CPARMS_CREATE
, NULL
);
149 int vboxsf_close(u32 root
, u64 handle
)
151 struct shfl_close parms
;
153 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
154 parms
.root
.u
.value32
= root
;
156 parms
.handle
.type
= VMMDEV_HGCM_PARM_TYPE_64BIT
;
157 parms
.handle
.u
.value64
= handle
;
159 return vboxsf_call(SHFL_FN_CLOSE
, &parms
, SHFL_CPARMS_CLOSE
, NULL
);
162 int vboxsf_remove(u32 root
, struct shfl_string
*parsed_path
, u32 flags
)
164 struct shfl_remove parms
;
166 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
167 parms
.root
.u
.value32
= root
;
169 parms
.path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
170 parms
.path
.u
.pointer
.size
= shfl_string_buf_size(parsed_path
);
171 parms
.path
.u
.pointer
.u
.linear_addr
= (uintptr_t)parsed_path
;
173 parms
.flags
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
174 parms
.flags
.u
.value32
= flags
;
176 return vboxsf_call(SHFL_FN_REMOVE
, &parms
, SHFL_CPARMS_REMOVE
, NULL
);
179 int vboxsf_rename(u32 root
, struct shfl_string
*src_path
,
180 struct shfl_string
*dest_path
, u32 flags
)
182 struct shfl_rename parms
;
184 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
185 parms
.root
.u
.value32
= root
;
187 parms
.src
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
188 parms
.src
.u
.pointer
.size
= shfl_string_buf_size(src_path
);
189 parms
.src
.u
.pointer
.u
.linear_addr
= (uintptr_t)src_path
;
191 parms
.dest
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
192 parms
.dest
.u
.pointer
.size
= shfl_string_buf_size(dest_path
);
193 parms
.dest
.u
.pointer
.u
.linear_addr
= (uintptr_t)dest_path
;
195 parms
.flags
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
196 parms
.flags
.u
.value32
= flags
;
198 return vboxsf_call(SHFL_FN_RENAME
, &parms
, SHFL_CPARMS_RENAME
, NULL
);
201 int vboxsf_read(u32 root
, u64 handle
, u64 offset
, u32
*buf_len
, u8
*buf
)
203 struct shfl_read parms
;
206 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
207 parms
.root
.u
.value32
= root
;
209 parms
.handle
.type
= VMMDEV_HGCM_PARM_TYPE_64BIT
;
210 parms
.handle
.u
.value64
= handle
;
211 parms
.offset
.type
= VMMDEV_HGCM_PARM_TYPE_64BIT
;
212 parms
.offset
.u
.value64
= offset
;
213 parms
.cb
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
214 parms
.cb
.u
.value32
= *buf_len
;
215 parms
.buffer
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT
;
216 parms
.buffer
.u
.pointer
.size
= *buf_len
;
217 parms
.buffer
.u
.pointer
.u
.linear_addr
= (uintptr_t)buf
;
219 err
= vboxsf_call(SHFL_FN_READ
, &parms
, SHFL_CPARMS_READ
, NULL
);
221 *buf_len
= parms
.cb
.u
.value32
;
225 int vboxsf_write(u32 root
, u64 handle
, u64 offset
, u32
*buf_len
, u8
*buf
)
227 struct shfl_write parms
;
230 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
231 parms
.root
.u
.value32
= root
;
233 parms
.handle
.type
= VMMDEV_HGCM_PARM_TYPE_64BIT
;
234 parms
.handle
.u
.value64
= handle
;
235 parms
.offset
.type
= VMMDEV_HGCM_PARM_TYPE_64BIT
;
236 parms
.offset
.u
.value64
= offset
;
237 parms
.cb
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
238 parms
.cb
.u
.value32
= *buf_len
;
239 parms
.buffer
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
240 parms
.buffer
.u
.pointer
.size
= *buf_len
;
241 parms
.buffer
.u
.pointer
.u
.linear_addr
= (uintptr_t)buf
;
243 err
= vboxsf_call(SHFL_FN_WRITE
, &parms
, SHFL_CPARMS_WRITE
, NULL
);
245 *buf_len
= parms
.cb
.u
.value32
;
249 /* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */
250 int vboxsf_dirinfo(u32 root
, u64 handle
,
251 struct shfl_string
*parsed_path
, u32 flags
, u32 index
,
252 u32
*buf_len
, struct shfl_dirinfo
*buf
, u32
*file_count
)
254 struct shfl_list parms
;
257 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
258 parms
.root
.u
.value32
= root
;
260 parms
.handle
.type
= VMMDEV_HGCM_PARM_TYPE_64BIT
;
261 parms
.handle
.u
.value64
= handle
;
262 parms
.flags
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
263 parms
.flags
.u
.value32
= flags
;
264 parms
.cb
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
265 parms
.cb
.u
.value32
= *buf_len
;
267 parms
.path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
268 parms
.path
.u
.pointer
.size
= shfl_string_buf_size(parsed_path
);
269 parms
.path
.u
.pointer
.u
.linear_addr
= (uintptr_t)parsed_path
;
271 parms
.path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_IN
;
272 parms
.path
.u
.pointer
.size
= 0;
273 parms
.path
.u
.pointer
.u
.linear_addr
= 0;
276 parms
.buffer
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT
;
277 parms
.buffer
.u
.pointer
.size
= *buf_len
;
278 parms
.buffer
.u
.pointer
.u
.linear_addr
= (uintptr_t)buf
;
280 parms
.resume_point
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
281 parms
.resume_point
.u
.value32
= index
;
282 parms
.file_count
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
283 parms
.file_count
.u
.value32
= 0; /* out parameter only */
285 err
= vboxsf_call(SHFL_FN_LIST
, &parms
, SHFL_CPARMS_LIST
, &status
);
286 if (err
== -ENODATA
&& status
== VERR_NO_MORE_FILES
)
289 *buf_len
= parms
.cb
.u
.value32
;
290 *file_count
= parms
.file_count
.u
.value32
;
294 int vboxsf_fsinfo(u32 root
, u64 handle
, u32 flags
,
295 u32
*buf_len
, void *buf
)
297 struct shfl_information parms
;
300 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
301 parms
.root
.u
.value32
= root
;
303 parms
.handle
.type
= VMMDEV_HGCM_PARM_TYPE_64BIT
;
304 parms
.handle
.u
.value64
= handle
;
305 parms
.flags
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
306 parms
.flags
.u
.value32
= flags
;
307 parms
.cb
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
308 parms
.cb
.u
.value32
= *buf_len
;
309 parms
.info
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL
;
310 parms
.info
.u
.pointer
.size
= *buf_len
;
311 parms
.info
.u
.pointer
.u
.linear_addr
= (uintptr_t)buf
;
313 err
= vboxsf_call(SHFL_FN_INFORMATION
, &parms
, SHFL_CPARMS_INFORMATION
,
316 *buf_len
= parms
.cb
.u
.value32
;
320 int vboxsf_readlink(u32 root
, struct shfl_string
*parsed_path
,
321 u32 buf_len
, u8
*buf
)
323 struct shfl_readLink parms
;
325 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
326 parms
.root
.u
.value32
= root
;
328 parms
.path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
329 parms
.path
.u
.pointer
.size
= shfl_string_buf_size(parsed_path
);
330 parms
.path
.u
.pointer
.u
.linear_addr
= (uintptr_t)parsed_path
;
332 parms
.buffer
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT
;
333 parms
.buffer
.u
.pointer
.size
= buf_len
;
334 parms
.buffer
.u
.pointer
.u
.linear_addr
= (uintptr_t)buf
;
336 return vboxsf_call(SHFL_FN_READLINK
, &parms
, SHFL_CPARMS_READLINK
,
340 int vboxsf_symlink(u32 root
, struct shfl_string
*new_path
,
341 struct shfl_string
*old_path
, struct shfl_fsobjinfo
*buf
)
343 struct shfl_symlink parms
;
345 parms
.root
.type
= VMMDEV_HGCM_PARM_TYPE_32BIT
;
346 parms
.root
.u
.value32
= root
;
348 parms
.new_path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
349 parms
.new_path
.u
.pointer
.size
= shfl_string_buf_size(new_path
);
350 parms
.new_path
.u
.pointer
.u
.linear_addr
= (uintptr_t)new_path
;
352 parms
.old_path
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN
;
353 parms
.old_path
.u
.pointer
.size
= shfl_string_buf_size(old_path
);
354 parms
.old_path
.u
.pointer
.u
.linear_addr
= (uintptr_t)old_path
;
356 parms
.info
.type
= VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT
;
357 parms
.info
.u
.pointer
.size
= sizeof(struct shfl_fsobjinfo
);
358 parms
.info
.u
.pointer
.u
.linear_addr
= (uintptr_t)buf
;
360 return vboxsf_call(SHFL_FN_SYMLINK
, &parms
, SHFL_CPARMS_SYMLINK
, NULL
);
363 int vboxsf_set_utf8(void)
365 return vboxsf_call(SHFL_FN_SET_UTF8
, NULL
, 0, NULL
);
368 int vboxsf_set_symlinks(void)
370 return vboxsf_call(SHFL_FN_SET_SYMLINKS
, NULL
, 0, NULL
);