Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: MIT
0002 /*
0003  * Wrapper functions for the shfl host calls.
0004  *
0005  * Copyright (C) 2006-2018 Oracle Corporation
0006  */
0007 
0008 #include <linux/mm.h>
0009 #include <linux/slab.h>
0010 #include <linux/vbox_err.h>
0011 #include <linux/vbox_utils.h>
0012 #include "vfsmod.h"
0013 
0014 #define SHFL_REQUEST \
0015     (VMMDEV_REQUESTOR_KERNEL | VMMDEV_REQUESTOR_USR_DRV_OTHER | \
0016      VMMDEV_REQUESTOR_CON_DONT_KNOW | VMMDEV_REQUESTOR_TRUST_NOT_GIVEN)
0017 
0018 static u32 vboxsf_client_id;
0019 
0020 int vboxsf_connect(void)
0021 {
0022     struct vbg_dev *gdev;
0023     struct vmmdev_hgcm_service_location loc;
0024     int err, vbox_status;
0025 
0026     loc.type = VMMDEV_HGCM_LOC_LOCALHOST_EXISTING;
0027     strcpy(loc.u.localhost.service_name, "VBoxSharedFolders");
0028 
0029     gdev = vbg_get_gdev();
0030     if (IS_ERR(gdev))
0031         return -ENODEV; /* No guest-device */
0032 
0033     err = vbg_hgcm_connect(gdev, SHFL_REQUEST, &loc,
0034                    &vboxsf_client_id, &vbox_status);
0035     vbg_put_gdev(gdev);
0036 
0037     return err ? err : vbg_status_code_to_errno(vbox_status);
0038 }
0039 
0040 void vboxsf_disconnect(void)
0041 {
0042     struct vbg_dev *gdev;
0043     int vbox_status;
0044 
0045     gdev = vbg_get_gdev();
0046     if (IS_ERR(gdev))
0047         return;   /* guest-device is gone, already disconnected */
0048 
0049     vbg_hgcm_disconnect(gdev, SHFL_REQUEST, vboxsf_client_id, &vbox_status);
0050     vbg_put_gdev(gdev);
0051 }
0052 
0053 static int vboxsf_call(u32 function, void *parms, u32 parm_count, int *status)
0054 {
0055     struct vbg_dev *gdev;
0056     int err, vbox_status;
0057 
0058     gdev = vbg_get_gdev();
0059     if (IS_ERR(gdev))
0060         return -ESHUTDOWN; /* guest-dev removed underneath us */
0061 
0062     err = vbg_hgcm_call(gdev, SHFL_REQUEST, vboxsf_client_id, function,
0063                 U32_MAX, parms, parm_count, &vbox_status);
0064     vbg_put_gdev(gdev);
0065 
0066     if (err < 0)
0067         return err;
0068 
0069     if (status)
0070         *status = vbox_status;
0071 
0072     return vbg_status_code_to_errno(vbox_status);
0073 }
0074 
0075 int vboxsf_map_folder(struct shfl_string *folder_name, u32 *root)
0076 {
0077     struct shfl_map_folder parms;
0078     int err, status;
0079 
0080     parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0081     parms.path.u.pointer.size = shfl_string_buf_size(folder_name);
0082     parms.path.u.pointer.u.linear_addr = (uintptr_t)folder_name;
0083 
0084     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0085     parms.root.u.value32 = 0;
0086 
0087     parms.delimiter.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0088     parms.delimiter.u.value32 = '/';
0089 
0090     parms.case_sensitive.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0091     parms.case_sensitive.u.value32 = 1;
0092 
0093     err = vboxsf_call(SHFL_FN_MAP_FOLDER, &parms, SHFL_CPARMS_MAP_FOLDER,
0094               &status);
0095     if (err == -ENOSYS && status == VERR_NOT_IMPLEMENTED)
0096         vbg_err("%s: Error host is too old\n", __func__);
0097 
0098     *root = parms.root.u.value32;
0099     return err;
0100 }
0101 
0102 int vboxsf_unmap_folder(u32 root)
0103 {
0104     struct shfl_unmap_folder parms;
0105 
0106     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0107     parms.root.u.value32 = root;
0108 
0109     return vboxsf_call(SHFL_FN_UNMAP_FOLDER, &parms,
0110                SHFL_CPARMS_UNMAP_FOLDER, NULL);
0111 }
0112 
0113 /**
0114  * vboxsf_create - Create a new file or folder
0115  * @root:         Root of the shared folder in which to create the file
0116  * @parsed_path:  The path of the file or folder relative to the shared folder
0117  * @param:        create_parms Parameters for file/folder creation.
0118  *
0119  * Create a new file or folder or open an existing one in a shared folder.
0120  * Note this function always returns 0 / success unless an exceptional condition
0121  * occurs - out of memory, invalid arguments, etc. If the file or folder could
0122  * not be opened or created, create_parms->handle will be set to
0123  * SHFL_HANDLE_NIL on return.  In this case the value in create_parms->result
0124  * provides information as to why (e.g. SHFL_FILE_EXISTS), create_parms->result
0125  * is also set on success as additional information.
0126  *
0127  * Returns:
0128  * 0 or negative errno value.
0129  */
0130 int vboxsf_create(u32 root, struct shfl_string *parsed_path,
0131           struct shfl_createparms *create_parms)
0132 {
0133     struct shfl_create parms;
0134 
0135     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0136     parms.root.u.value32 = root;
0137 
0138     parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0139     parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0140     parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0141 
0142     parms.parms.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0143     parms.parms.u.pointer.size = sizeof(struct shfl_createparms);
0144     parms.parms.u.pointer.u.linear_addr = (uintptr_t)create_parms;
0145 
0146     return vboxsf_call(SHFL_FN_CREATE, &parms, SHFL_CPARMS_CREATE, NULL);
0147 }
0148 
0149 int vboxsf_close(u32 root, u64 handle)
0150 {
0151     struct shfl_close parms;
0152 
0153     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0154     parms.root.u.value32 = root;
0155 
0156     parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0157     parms.handle.u.value64 = handle;
0158 
0159     return vboxsf_call(SHFL_FN_CLOSE, &parms, SHFL_CPARMS_CLOSE, NULL);
0160 }
0161 
0162 int vboxsf_remove(u32 root, struct shfl_string *parsed_path, u32 flags)
0163 {
0164     struct shfl_remove parms;
0165 
0166     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0167     parms.root.u.value32 = root;
0168 
0169     parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0170     parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0171     parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0172 
0173     parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0174     parms.flags.u.value32 = flags;
0175 
0176     return vboxsf_call(SHFL_FN_REMOVE, &parms, SHFL_CPARMS_REMOVE, NULL);
0177 }
0178 
0179 int vboxsf_rename(u32 root, struct shfl_string *src_path,
0180           struct shfl_string *dest_path, u32 flags)
0181 {
0182     struct shfl_rename parms;
0183 
0184     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0185     parms.root.u.value32 = root;
0186 
0187     parms.src.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0188     parms.src.u.pointer.size = shfl_string_buf_size(src_path);
0189     parms.src.u.pointer.u.linear_addr = (uintptr_t)src_path;
0190 
0191     parms.dest.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0192     parms.dest.u.pointer.size = shfl_string_buf_size(dest_path);
0193     parms.dest.u.pointer.u.linear_addr = (uintptr_t)dest_path;
0194 
0195     parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0196     parms.flags.u.value32 = flags;
0197 
0198     return vboxsf_call(SHFL_FN_RENAME, &parms, SHFL_CPARMS_RENAME, NULL);
0199 }
0200 
0201 int vboxsf_read(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf)
0202 {
0203     struct shfl_read parms;
0204     int err;
0205 
0206     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0207     parms.root.u.value32 = root;
0208 
0209     parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0210     parms.handle.u.value64 = handle;
0211     parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0212     parms.offset.u.value64 = offset;
0213     parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0214     parms.cb.u.value32 = *buf_len;
0215     parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0216     parms.buffer.u.pointer.size = *buf_len;
0217     parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0218 
0219     err = vboxsf_call(SHFL_FN_READ, &parms, SHFL_CPARMS_READ, NULL);
0220 
0221     *buf_len = parms.cb.u.value32;
0222     return err;
0223 }
0224 
0225 int vboxsf_write(u32 root, u64 handle, u64 offset, u32 *buf_len, u8 *buf)
0226 {
0227     struct shfl_write parms;
0228     int err;
0229 
0230     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0231     parms.root.u.value32 = root;
0232 
0233     parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0234     parms.handle.u.value64 = handle;
0235     parms.offset.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0236     parms.offset.u.value64 = offset;
0237     parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0238     parms.cb.u.value32 = *buf_len;
0239     parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0240     parms.buffer.u.pointer.size = *buf_len;
0241     parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0242 
0243     err = vboxsf_call(SHFL_FN_WRITE, &parms, SHFL_CPARMS_WRITE, NULL);
0244 
0245     *buf_len = parms.cb.u.value32;
0246     return err;
0247 }
0248 
0249 /* Returns 0 on success, 1 on end-of-dir, negative errno otherwise */
0250 int vboxsf_dirinfo(u32 root, u64 handle,
0251            struct shfl_string *parsed_path, u32 flags, u32 index,
0252            u32 *buf_len, struct shfl_dirinfo *buf, u32 *file_count)
0253 {
0254     struct shfl_list parms;
0255     int err, status;
0256 
0257     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0258     parms.root.u.value32 = root;
0259 
0260     parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0261     parms.handle.u.value64 = handle;
0262     parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0263     parms.flags.u.value32 = flags;
0264     parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0265     parms.cb.u.value32 = *buf_len;
0266     if (parsed_path) {
0267         parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0268         parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0269         parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0270     } else {
0271         parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_IN;
0272         parms.path.u.pointer.size = 0;
0273         parms.path.u.pointer.u.linear_addr = 0;
0274     }
0275 
0276     parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0277     parms.buffer.u.pointer.size = *buf_len;
0278     parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0279 
0280     parms.resume_point.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0281     parms.resume_point.u.value32 = index;
0282     parms.file_count.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0283     parms.file_count.u.value32 = 0; /* out parameter only */
0284 
0285     err = vboxsf_call(SHFL_FN_LIST, &parms, SHFL_CPARMS_LIST, &status);
0286     if (err == -ENODATA && status == VERR_NO_MORE_FILES)
0287         err = 1;
0288 
0289     *buf_len = parms.cb.u.value32;
0290     *file_count = parms.file_count.u.value32;
0291     return err;
0292 }
0293 
0294 int vboxsf_fsinfo(u32 root, u64 handle, u32 flags,
0295           u32 *buf_len, void *buf)
0296 {
0297     struct shfl_information parms;
0298     int err;
0299 
0300     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0301     parms.root.u.value32 = root;
0302 
0303     parms.handle.type = VMMDEV_HGCM_PARM_TYPE_64BIT;
0304     parms.handle.u.value64 = handle;
0305     parms.flags.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0306     parms.flags.u.value32 = flags;
0307     parms.cb.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0308     parms.cb.u.value32 = *buf_len;
0309     parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL;
0310     parms.info.u.pointer.size = *buf_len;
0311     parms.info.u.pointer.u.linear_addr = (uintptr_t)buf;
0312 
0313     err = vboxsf_call(SHFL_FN_INFORMATION, &parms, SHFL_CPARMS_INFORMATION,
0314               NULL);
0315 
0316     *buf_len = parms.cb.u.value32;
0317     return err;
0318 }
0319 
0320 int vboxsf_readlink(u32 root, struct shfl_string *parsed_path,
0321             u32 buf_len, u8 *buf)
0322 {
0323     struct shfl_readLink parms;
0324 
0325     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0326     parms.root.u.value32 = root;
0327 
0328     parms.path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0329     parms.path.u.pointer.size = shfl_string_buf_size(parsed_path);
0330     parms.path.u.pointer.u.linear_addr = (uintptr_t)parsed_path;
0331 
0332     parms.buffer.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0333     parms.buffer.u.pointer.size = buf_len;
0334     parms.buffer.u.pointer.u.linear_addr = (uintptr_t)buf;
0335 
0336     return vboxsf_call(SHFL_FN_READLINK, &parms, SHFL_CPARMS_READLINK,
0337                NULL);
0338 }
0339 
0340 int vboxsf_symlink(u32 root, struct shfl_string *new_path,
0341            struct shfl_string *old_path, struct shfl_fsobjinfo *buf)
0342 {
0343     struct shfl_symlink parms;
0344 
0345     parms.root.type = VMMDEV_HGCM_PARM_TYPE_32BIT;
0346     parms.root.u.value32 = root;
0347 
0348     parms.new_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0349     parms.new_path.u.pointer.size = shfl_string_buf_size(new_path);
0350     parms.new_path.u.pointer.u.linear_addr = (uintptr_t)new_path;
0351 
0352     parms.old_path.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_IN;
0353     parms.old_path.u.pointer.size = shfl_string_buf_size(old_path);
0354     parms.old_path.u.pointer.u.linear_addr = (uintptr_t)old_path;
0355 
0356     parms.info.type = VMMDEV_HGCM_PARM_TYPE_LINADDR_KERNEL_OUT;
0357     parms.info.u.pointer.size = sizeof(struct shfl_fsobjinfo);
0358     parms.info.u.pointer.u.linear_addr = (uintptr_t)buf;
0359 
0360     return vboxsf_call(SHFL_FN_SYMLINK, &parms, SHFL_CPARMS_SYMLINK, NULL);
0361 }
0362 
0363 int vboxsf_set_utf8(void)
0364 {
0365     return vboxsf_call(SHFL_FN_SET_UTF8, NULL, 0, NULL);
0366 }
0367 
0368 int vboxsf_set_symlinks(void)
0369 {
0370     return vboxsf_call(SHFL_FN_SET_SYMLINKS, NULL, 0, NULL);
0371 }