VirtualBox

Ignore:
Timestamp:
Mar 22, 2007 8:45:59 AM (18 years ago)
Author:
vboxsync
Message:

Added an HGCM call ioctl to the Linux Additions kernel module. The code path is not yet tested and not yet used.

Location:
trunk/src/VBox/Additions/linux/module
Files:
2 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Additions/linux/module/vboxmod.c

    r1067 r1619  
    244244            VbglGRFree(reqFull);
    245245            break;
     246        }
     247
     248        case IOCTL_VBOXGUEST_HGCM_CALL:
     249        {
     250            VBoxGuestHGCMCallInfo callHeader, *hgcmR3, *hgcmR0;
     251            uint8_t *pu8PointerData;
     252            size_t cbPointerData = 0, offPointerData = 0;
     253            int i, rc;
     254
     255            compiler_assert(_IOC_SIZE(IOCTL_VBOXGUEST_HGCM_CALL) == sizeof(VBoxGuestHGCMCallInfo));
     256            if (copy_from_user(&callHeader, (void*)arg, _IOC_SIZE(cmd)))
     257            {
     258                elog("IOCTL_VBOXGUEST_HGCM_CALL: copy_from_user failed!\n");
     259                return -EFAULT;
     260            }
     261            hgcmR3 = kmalloc(sizeof(*hgcmR3) + callHeader.cParms * sizeof(HGCMFunctionParameter),
     262                               GFP_KERNEL);
     263            if (!hgcmR3)
     264            {
     265                elog("IOCTL_VBOXGUEST_HGCM_CALL: cannot allocate memory!\n");
     266                return -ENOMEM;
     267            }
     268            if (copy_from_user(hgcmR3, (void*)arg,
     269                               sizeof(*hgcmR3) +   callHeader.cParms
     270                                                 * sizeof(HGCMFunctionParameter)))
     271            {
     272                elog("IOCTL_VBOXGUEST_HGCM_CALL: copy_from_user failed!\n");
     273                kfree(hgcmR3);
     274                return -EFAULT;
     275            }
     276            hgcmR0 = kmalloc(sizeof(*hgcmR0) + callHeader.cParms * sizeof(HGCMFunctionParameter),
     277                               GFP_KERNEL);
     278            if (!hgcmR0)
     279            {
     280                elog("IOCTL_VBOXGUEST_HGCM_CALL: cannot allocate memory!\n");
     281                kfree(hgcmR3);
     282                return -ENOMEM;
     283            }
     284            hgcmR0->u32ClientID = callHeader.u32ClientID;
     285            hgcmR0->u32Function = callHeader.u32Function;
     286            hgcmR0->cParms = callHeader.cParms;
     287            /* Calculate the total size of pointer space.  Will normally be for a single pointer */
     288            for (i = 0; i < callHeader.cParms; ++i)
     289            {
     290                switch (VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type)
     291                {
     292                case VMMDevHGCMParmType_32bit:
     293                case VMMDevHGCMParmType_64bit:
     294                    break;
     295                case VMMDevHGCMParmType_LinAddr:
     296                case VMMDevHGCMParmType_LinAddr_In:
     297                case VMMDevHGCMParmType_LinAddr_Out:
     298                    cbPointerData += VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.size;
     299                    break;
     300                default:
     301                    elog("IOCTL_VBOXGUEST_HGCM_CALL: unsupported or unknown parameter type\n");
     302                    kfree(hgcmR3);
     303                    kfree(hgcmR0);
     304                    return -EINVAL;
     305                }
     306            }
     307            pu8PointerData = kmalloc (cbPointerData, GFP_KERNEL);
     308            /* Reconstruct the pointer parameter data in kernel space */
     309            if (pu8PointerData == NULL)
     310            {
     311                elog("IOCTL_VBOXGUEST_HGCM_CALL: out of memory allocating %d bytes for pointer data\n",
     312                       cbPointerData);
     313                kfree(hgcmR3);
     314                kfree(hgcmR0);
     315                return -ENOMEM;
     316            }
     317            for (i = 0; i < callHeader.cParms; ++i)
     318            {
     319                VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].type
     320                    = VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type;
     321                if (   (VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type == VMMDevHGCMParmType_LinAddr)
     322                    || (VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type
     323                            == VMMDevHGCMParmType_LinAddr_In))
     324                {
     325                    /* We are sending data to the host or sending and reading. */
     326                    if (copy_from_user(&pu8PointerData[offPointerData],
     327                                       VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.u.linearAddr,
     328                                       VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.size))
     329                    {
     330                        elog("IOCTL_VBOXGUEST_HGCM_CALL: copy_from_user failed!\n");
     331                        rc = -EFAULT;
     332                        goto hgcm_exit;
     333                    }
     334                    VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.Pointer.u.linearAddr
     335                        = &pu8PointerData[offPointerData];
     336                    VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.Pointer.size
     337                        = VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.size;
     338                    offPointerData += VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.size;
     339                }
     340                else if (VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type
     341                             == VMMDevHGCMParmType_LinAddr_Out)
     342                {
     343                    /* We are reading data from the host */
     344                    VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.Pointer.u.linearAddr
     345                        = &pu8PointerData[offPointerData];
     346                    VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.Pointer.size
     347                        = VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.size;
     348                    offPointerData += VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.size;
     349                }
     350                else
     351                {
     352                    /* If it is not a pointer, then it is a 32bit or 64bit value */
     353                    VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.value64
     354                        = VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.value64;
     355                }
     356            }
     357            /* Internal VBoxGuest IOCTL interface */
     358            rc = vboxadd_cmc_call(vboxDev, IOCTL_VBOXGUEST_HGCM_CALL, hgcmR0);
     359            if (rc != VINF_SUCCESS)
     360            {
     361                elog("IOCTL_VBOXGUEST_HGCM_CALL: internal ioctl call failed, rc=%d\n", rc);
     362                /** @todo We need a function to convert VBox error codes back to Linux. */
     363                rc = -EINVAL;
     364                goto hgcm_exit;
     365            }
     366            for (i = 0; i < callHeader.cParms; ++i)
     367            {
     368                if (   (VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type == VMMDevHGCMParmType_LinAddr)
     369                    || (VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type
     370                            == VMMDevHGCMParmType_LinAddr_Out))
     371                {
     372                    /* We are sending data to the host or sending and reading. */
     373                    if (copy_to_user(VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.u.linearAddr,
     374                                     VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.Pointer.u.linearAddr,
     375                                     VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.Pointer.size))
     376                    {
     377                        elog("IOCTL_VBOXGUEST_HGCM_CALL: copy_to_user failed!\n");
     378                        rc = -EFAULT;
     379                        goto hgcm_exit;
     380                    }
     381                    VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.Pointer.size
     382                        = VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.Pointer.size;
     383                }
     384                else if (VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].type
     385                             != VMMDevHGCMParmType_LinAddr_Out)
     386                {
     387                    /* If it is not a pointer, then it is a 32bit or 64bit value */
     388                    VBOXGUEST_HGCM_CALL_PARMS(hgcmR3)[i].u.value64
     389                        = VBOXGUEST_HGCM_CALL_PARMS(hgcmR0)[i].u.value64;
     390                }
     391            }
     392            hgcmR3->result = hgcmR0->result;
     393            if (copy_to_user((void*)arg, hgcmR3,
     394                             sizeof(*hgcmR3) + callHeader.cParms * sizeof(HGCMFunctionParameter)))
     395            {
     396                elog("IOCTL_VBOXGUEST_HGCM_CALL: copy_to_user failed!\n");
     397                rc = -EFAULT;
     398                goto hgcm_exit;
     399            }
     400        hgcm_exit:
     401            kfree(hgcmR3);
     402            kfree(hgcmR0);
     403            kfree(pu8PointerData);
     404            return rc;
    246405        }
    247406
  • trunk/src/VBox/Additions/linux/module/vboxmod.h

    r1 r1619  
    6767if (n >= vboxadd_verbosity) printk (KERN_DEBUG "vboxadd: " __VA_ARGS__)
    6868
     69#define compiler_assert(val) \
     70do { \
     71switch(0) { \
     72case 0: \
     73case (val): \
     74default: \
     75break; \
     76} \
     77} while(0);
     78
    6979extern int vboxadd_cmc_init (void);
    7080extern void vboxadd_cmc_fini (void);
Note: See TracChangeset for help on using the changeset viewer.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette