[3626] | 1 | /* $Id: SUPDrv-freebsd.c 99739 2023-05-11 01:01:08Z vboxsync $ */
|
---|
| 2 | /** @file
|
---|
[10662] | 3 | * VBoxDrv - The VirtualBox Support Driver - FreeBSD specifics.
|
---|
[3626] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
| 7 | * Copyright (c) 2007 knut st. osmundsen <bird-src-spam@anduin.net>
|
---|
| 8 | *
|
---|
| 9 | * Permission is hereby granted, free of charge, to any person
|
---|
| 10 | * obtaining a copy of this software and associated documentation
|
---|
| 11 | * files (the "Software"), to deal in the Software without
|
---|
| 12 | * restriction, including without limitation the rights to use,
|
---|
| 13 | * copy, modify, merge, publish, distribute, sublicense, and/or sell
|
---|
| 14 | * copies of the Software, and to permit persons to whom the
|
---|
| 15 | * Software is furnished to do so, subject to the following
|
---|
| 16 | * conditions:
|
---|
| 17 | *
|
---|
| 18 | * The above copyright notice and this permission notice shall be
|
---|
| 19 | * included in all copies or substantial portions of the Software.
|
---|
| 20 | *
|
---|
| 21 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
---|
| 22 | * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
|
---|
| 23 | * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
---|
| 24 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
|
---|
| 25 | * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
---|
| 26 | * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
---|
| 27 | * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
|
---|
| 28 | * OTHER DEALINGS IN THE SOFTWARE.
|
---|
| 29 | */
|
---|
| 30 |
|
---|
[57358] | 31 |
|
---|
| 32 | /*********************************************************************************************************************************
|
---|
| 33 | * Header Files *
|
---|
| 34 | *********************************************************************************************************************************/
|
---|
[10662] | 35 | #define LOG_GROUP LOG_GROUP_SUP_DRV
|
---|
[3626] | 36 | /* Deal with conflicts first. */
|
---|
| 37 | #include <sys/param.h>
|
---|
| 38 | #undef PVM
|
---|
| 39 | #include <sys/types.h>
|
---|
| 40 | #include <sys/module.h>
|
---|
| 41 | #include <sys/systm.h>
|
---|
| 42 | #include <sys/errno.h>
|
---|
| 43 | #include <sys/kernel.h>
|
---|
[4988] | 44 | #include <sys/fcntl.h>
|
---|
[3626] | 45 | #include <sys/conf.h>
|
---|
| 46 | #include <sys/uio.h>
|
---|
[91785] | 47 | #include <vm/pmap.h> /* for pmap_map() */
|
---|
[3626] | 48 |
|
---|
[10263] | 49 | #include "../SUPDrvInternal.h"
|
---|
[3626] | 50 | #include <VBox/version.h>
|
---|
| 51 | #include <iprt/initterm.h>
|
---|
| 52 | #include <iprt/string.h>
|
---|
| 53 | #include <iprt/spinlock.h>
|
---|
| 54 | #include <iprt/process.h>
|
---|
| 55 | #include <iprt/assert.h>
|
---|
[19343] | 56 | #include <iprt/uuid.h>
|
---|
[10662] | 57 | #include <VBox/log.h>
|
---|
[4988] | 58 | #include <iprt/alloc.h>
|
---|
| 59 | #include <iprt/err.h>
|
---|
[29501] | 60 | #include <iprt/asm.h>
|
---|
[3626] | 61 |
|
---|
[19343] | 62 | #ifdef VBOX_WITH_HARDENING
|
---|
| 63 | # define VBOXDRV_PERM 0600
|
---|
| 64 | #else
|
---|
| 65 | # define VBOXDRV_PERM 0666
|
---|
| 66 | #endif
|
---|
[3626] | 67 |
|
---|
[57358] | 68 |
|
---|
| 69 | /*********************************************************************************************************************************
|
---|
| 70 | * Internal Functions *
|
---|
| 71 | *********************************************************************************************************************************/
|
---|
[3626] | 72 | static int VBoxDrvFreeBSDModuleEvent(struct module *pMod, int enmEventType, void *pvArg);
|
---|
| 73 | static int VBoxDrvFreeBSDLoad(void);
|
---|
| 74 | static int VBoxDrvFreeBSDUnload(void);
|
---|
[4988] | 75 |
|
---|
[44182] | 76 | static d_open_t VBoxDrvFreeBSDOpenUsr;
|
---|
| 77 | static d_open_t VBoxDrvFreeBSDOpenSys;
|
---|
[59217] | 78 | static void vboxdrvFreeBSDDtr(void *pvData);
|
---|
[3626] | 79 | static d_ioctl_t VBoxDrvFreeBSDIOCtl;
|
---|
[4988] | 80 | static int VBoxDrvFreeBSDIOCtlSlow(PSUPDRVSESSION pSession, u_long ulCmd, caddr_t pvData, struct thread *pTd);
|
---|
[3626] | 81 |
|
---|
| 82 |
|
---|
[57358] | 83 | /*********************************************************************************************************************************
|
---|
| 84 | * Global Variables *
|
---|
| 85 | *********************************************************************************************************************************/
|
---|
[3626] | 86 | /**
|
---|
| 87 | * Module info structure used by the kernel.
|
---|
| 88 | */
|
---|
[4988] | 89 | static moduledata_t g_VBoxDrvFreeBSDModule =
|
---|
[3626] | 90 | {
|
---|
| 91 | "vboxdrv",
|
---|
| 92 | VBoxDrvFreeBSDModuleEvent,
|
---|
| 93 | NULL
|
---|
| 94 | };
|
---|
| 95 |
|
---|
| 96 | /** Declare the module as a pseudo device. */
|
---|
[4988] | 97 | DECLARE_MODULE(vboxdrv, g_VBoxDrvFreeBSDModule, SI_SUB_PSEUDO, SI_ORDER_ANY);
|
---|
[25258] | 98 | MODULE_VERSION(vboxdrv, 1);
|
---|
[3626] | 99 |
|
---|
| 100 | /**
|
---|
| 101 | * The /dev/vboxdrv character device entry points.
|
---|
| 102 | */
|
---|
[44182] | 103 | static struct cdevsw g_VBoxDrvFreeBSDChrDevSwSys =
|
---|
[3626] | 104 | {
|
---|
| 105 | .d_version = D_VERSION,
|
---|
[44182] | 106 | .d_open = VBoxDrvFreeBSDOpenSys,
|
---|
[3626] | 107 | .d_ioctl = VBoxDrvFreeBSDIOCtl,
|
---|
| 108 | .d_name = "vboxdrv"
|
---|
| 109 | };
|
---|
[44182] | 110 | /** The /dev/vboxdrv character device. */
|
---|
| 111 | static struct cdev *g_pVBoxDrvFreeBSDChrDevSys;
|
---|
[3626] | 112 |
|
---|
[44182] | 113 | /**
|
---|
| 114 | * The /dev/vboxdrvu character device entry points.
|
---|
| 115 | */
|
---|
| 116 | static struct cdevsw g_VBoxDrvFreeBSDChrDevSwUsr =
|
---|
| 117 | {
|
---|
| 118 | .d_version = D_VERSION,
|
---|
| 119 | .d_open = VBoxDrvFreeBSDOpenUsr,
|
---|
| 120 | .d_ioctl = VBoxDrvFreeBSDIOCtl,
|
---|
| 121 | .d_name = "vboxdrvu"
|
---|
| 122 | };
|
---|
| 123 | /** The /dev/vboxdrvu character device. */
|
---|
| 124 | static struct cdev *g_pVBoxDrvFreeBSDChrDevUsr;
|
---|
| 125 |
|
---|
[18968] | 126 | /** Reference counter. */
|
---|
| 127 | static volatile uint32_t g_cUsers;
|
---|
[3626] | 128 |
|
---|
| 129 | /** The device extention. */
|
---|
[4988] | 130 | static SUPDRVDEVEXT g_VBoxDrvFreeBSDDevExt;
|
---|
[3626] | 131 |
|
---|
| 132 | /**
|
---|
| 133 | * Module event handler.
|
---|
| 134 | *
|
---|
| 135 | * @param pMod The module structure.
|
---|
| 136 | * @param enmEventType The event type (modeventtype_t).
|
---|
| 137 | * @param pvArg Module argument. NULL.
|
---|
| 138 | *
|
---|
| 139 | * @return 0 on success, errno.h status code on failure.
|
---|
| 140 | */
|
---|
| 141 | static int VBoxDrvFreeBSDModuleEvent(struct module *pMod, int enmEventType, void *pvArg)
|
---|
| 142 | {
|
---|
| 143 | int rc;
|
---|
| 144 | switch (enmEventType)
|
---|
| 145 | {
|
---|
| 146 | case MOD_LOAD:
|
---|
| 147 | rc = VBoxDrvFreeBSDLoad();
|
---|
| 148 | break;
|
---|
| 149 |
|
---|
| 150 | case MOD_UNLOAD:
|
---|
[22678] | 151 | mtx_unlock(&Giant);
|
---|
[3626] | 152 | rc = VBoxDrvFreeBSDUnload();
|
---|
[22678] | 153 | mtx_lock(&Giant);
|
---|
[3626] | 154 | break;
|
---|
| 155 |
|
---|
| 156 | case MOD_SHUTDOWN:
|
---|
| 157 | case MOD_QUIESCE:
|
---|
| 158 | default:
|
---|
| 159 | return EOPNOTSUPP;
|
---|
| 160 | }
|
---|
| 161 |
|
---|
| 162 | if (RT_SUCCESS(rc))
|
---|
| 163 | return 0;
|
---|
[4988] | 164 | return RTErrConvertToErrno(rc);
|
---|
[3626] | 165 | }
|
---|
| 166 |
|
---|
| 167 |
|
---|
| 168 | static int VBoxDrvFreeBSDLoad(void)
|
---|
| 169 | {
|
---|
[18968] | 170 | g_cUsers = 0;
|
---|
[18915] | 171 |
|
---|
[3626] | 172 | /*
|
---|
| 173 | * Initialize the runtime.
|
---|
| 174 | */
|
---|
[3677] | 175 | int rc = RTR0Init(0);
|
---|
[3626] | 176 | if (RT_SUCCESS(rc))
|
---|
| 177 | {
|
---|
[25465] | 178 | Log(("VBoxDrvFreeBSDLoad:\n"));
|
---|
| 179 |
|
---|
[3626] | 180 | /*
|
---|
| 181 | * Initialize the device extension.
|
---|
| 182 | */
|
---|
[25484] | 183 | rc = supdrvInitDevExt(&g_VBoxDrvFreeBSDDevExt, sizeof(SUPDRVSESSION));
|
---|
[3626] | 184 | if (RT_SUCCESS(rc))
|
---|
| 185 | {
|
---|
| 186 | /*
|
---|
[44182] | 187 | * Configure character devices. Add symbolic links for compatibility.
|
---|
[3626] | 188 | */
|
---|
[44182] | 189 | g_pVBoxDrvFreeBSDChrDevSys = make_dev(&g_VBoxDrvFreeBSDChrDevSwSys, 0, UID_ROOT, GID_WHEEL, VBOXDRV_PERM, "vboxdrv");
|
---|
| 190 | g_pVBoxDrvFreeBSDChrDevUsr = make_dev(&g_VBoxDrvFreeBSDChrDevSwUsr, 1, UID_ROOT, GID_WHEEL, 0666, "vboxdrvu");
|
---|
[39521] | 191 | return VINF_SUCCESS;
|
---|
[3626] | 192 | }
|
---|
[44182] | 193 |
|
---|
| 194 | printf("vboxdrv: supdrvInitDevExt failed, rc=%d\n", rc);
|
---|
[3677] | 195 | RTR0Term();
|
---|
[3626] | 196 | }
|
---|
| 197 | else
|
---|
| 198 | printf("vboxdrv: RTR0Init failed, rc=%d\n", rc);
|
---|
| 199 | return rc;
|
---|
| 200 | }
|
---|
| 201 |
|
---|
| 202 | static int VBoxDrvFreeBSDUnload(void)
|
---|
| 203 | {
|
---|
[25465] | 204 | Log(("VBoxDrvFreeBSDUnload:\n"));
|
---|
[3626] | 205 |
|
---|
[18968] | 206 | if (g_cUsers > 0)
|
---|
[39522] | 207 | return VERR_RESOURCE_BUSY;
|
---|
[3626] | 208 |
|
---|
| 209 | /*
|
---|
| 210 | * Reserve what we did in VBoxDrvFreeBSDInit.
|
---|
| 211 | */
|
---|
[44182] | 212 | destroy_dev(g_pVBoxDrvFreeBSDChrDevUsr);
|
---|
| 213 | destroy_dev(g_pVBoxDrvFreeBSDChrDevSys);
|
---|
[3626] | 214 |
|
---|
[4988] | 215 | supdrvDeleteDevExt(&g_VBoxDrvFreeBSDDevExt);
|
---|
[3626] | 216 |
|
---|
[43435] | 217 | RTR0TermForced();
|
---|
[3626] | 218 |
|
---|
[4988] | 219 | memset(&g_VBoxDrvFreeBSDDevExt, 0, sizeof(g_VBoxDrvFreeBSDDevExt));
|
---|
[3626] | 220 | return VINF_SUCCESS;
|
---|
| 221 | }
|
---|
| 222 |
|
---|
| 223 |
|
---|
[4988] | 224 | /**
|
---|
| 225 | *
|
---|
| 226 | * @returns 0 on success, errno on failure.
|
---|
| 227 | * EBUSY if the device is used by someone else.
|
---|
[58340] | 228 | * @param pDev The device node.
|
---|
| 229 | * @param fOpen The open flags.
|
---|
| 230 | * @param iDevType Some device type thing we don't use.
|
---|
| 231 | * @param pTd The thread.
|
---|
| 232 | * @param fUnrestricted Set if opening /dev/vboxdrv, clear if /dev/vboxdrvu.
|
---|
[4988] | 233 | */
|
---|
[58340] | 234 | static int vboxdrvFreeBSDOpenCommon(struct cdev *pDev, int fOpen, int iDevType, struct thread *pTd, bool fUnrestricted)
|
---|
[3626] | 235 | {
|
---|
[4988] | 236 | PSUPDRVSESSION pSession;
|
---|
| 237 | int rc;
|
---|
| 238 |
|
---|
| 239 | /*
|
---|
| 240 | * Let's be a bit picky about the flags...
|
---|
| 241 | */
|
---|
[44182] | 242 | if (fOpen != (FREAD | FWRITE /*=O_RDWR*/))
|
---|
[4988] | 243 | {
|
---|
[25465] | 244 | Log(("VBoxDrvFreeBSDOpen: fOpen=%#x expected %#x\n", fOpen, O_RDWR));
|
---|
[4988] | 245 | return EINVAL;
|
---|
| 246 | }
|
---|
| 247 |
|
---|
| 248 | /*
|
---|
| 249 | * Create a new session.
|
---|
| 250 | */
|
---|
[44182] | 251 | rc = supdrvCreateSession(&g_VBoxDrvFreeBSDDevExt, true /* fUser */, fUnrestricted, &pSession);
|
---|
[4988] | 252 | if (RT_SUCCESS(rc))
|
---|
| 253 | {
|
---|
[11725] | 254 | /** @todo get (r)uid and (r)gid.
|
---|
[10377] | 255 | pSession->Uid = stuff;
|
---|
| 256 | pSession->Gid = stuff; */
|
---|
[58340] | 257 | rc = devfs_set_cdevpriv(pSession, vboxdrvFreeBSDDtr); Assert(rc == 0);
|
---|
[39521] | 258 | Log(("VBoxDrvFreeBSDOpen: pSession=%p\n", pSession));
|
---|
| 259 | ASMAtomicIncU32(&g_cUsers);
|
---|
| 260 | return 0;
|
---|
[4988] | 261 | }
|
---|
| 262 |
|
---|
| 263 | return RTErrConvertToErrno(rc);
|
---|
[3626] | 264 | }
|
---|
| 265 |
|
---|
[4016] | 266 |
|
---|
[44182] | 267 | /** For vboxdrv. */
|
---|
[58340] | 268 | static int VBoxDrvFreeBSDOpenSys(struct cdev *pDev, int fOpen, int iDevType, struct thread *pTd)
|
---|
[44182] | 269 | {
|
---|
[58340] | 270 | return vboxdrvFreeBSDOpenCommon(pDev, fOpen, iDevType, pTd, true);
|
---|
[44182] | 271 | }
|
---|
| 272 |
|
---|
| 273 |
|
---|
| 274 | /** For vboxdrvu. */
|
---|
[58340] | 275 | static int VBoxDrvFreeBSDOpenUsr(struct cdev *pDev, int fOpen, int iDevType, struct thread *pTd)
|
---|
[44182] | 276 | {
|
---|
[58340] | 277 | return vboxdrvFreeBSDOpenCommon(pDev, fOpen, iDevType, pTd, false);
|
---|
[44182] | 278 | }
|
---|
| 279 |
|
---|
| 280 |
|
---|
[4988] | 281 | /**
|
---|
[58340] | 282 | * Close a file device previously opened by VBoxDrvFreeBSDOpen.
|
---|
[4988] | 283 | *
|
---|
[58340] | 284 | * @param pvData The session being closed.
|
---|
[4988] | 285 | */
|
---|
[58340] | 286 | static void vboxdrvFreeBSDDtr(void *pvData)
|
---|
[3626] | 287 | {
|
---|
[58340] | 288 | PSUPDRVSESSION pSession = pvData;
|
---|
| 289 | Log(("vboxdrvFreeBSDDtr: pSession=%p\n", pSession));
|
---|
[4988] | 290 |
|
---|
| 291 | /*
|
---|
[39521] | 292 | * Close the session.
|
---|
[4988] | 293 | */
|
---|
[49718] | 294 | supdrvSessionRelease(pSession);
|
---|
[39521] | 295 | ASMAtomicDecU32(&g_cUsers);
|
---|
[3626] | 296 | }
|
---|
| 297 |
|
---|
| 298 |
|
---|
| 299 | /**
|
---|
[4988] | 300 | * I/O control request.
|
---|
[3626] | 301 | *
|
---|
[4988] | 302 | * @returns depends...
|
---|
| 303 | * @param pDev The device.
|
---|
| 304 | * @param ulCmd The command.
|
---|
| 305 | * @param pvData Pointer to the data.
|
---|
| 306 | * @param fFile The file descriptor flags.
|
---|
| 307 | * @param pTd The calling thread.
|
---|
[3626] | 308 | */
|
---|
[4988] | 309 | static int VBoxDrvFreeBSDIOCtl(struct cdev *pDev, u_long ulCmd, caddr_t pvData, int fFile, struct thread *pTd)
|
---|
[3626] | 310 | {
|
---|
[39521] | 311 | PSUPDRVSESSION pSession;
|
---|
| 312 | devfs_get_cdevpriv((void **)&pSession);
|
---|
[4988] | 313 |
|
---|
| 314 | /*
|
---|
| 315 | * Deal with the fast ioctl path first.
|
---|
| 316 | */
|
---|
[71198] | 317 | AssertCompile((SUP_IOCTL_FAST_DO_FIRST & 0xff) == (SUP_IOCTL_FLAG | 64));
|
---|
[77107] | 318 | if ( (uintptr_t)(ulCmd - SUP_IOCTL_FAST_DO_FIRST) < (uintptr_t)32
|
---|
[71198] | 319 | && pSession->fUnrestricted)
|
---|
| 320 | return supdrvIOCtlFast(ulCmd - SUP_IOCTL_FAST_DO_FIRST, *(uint32_t *)pvData, &g_VBoxDrvFreeBSDDevExt, pSession);
|
---|
[4988] | 321 |
|
---|
| 322 | return VBoxDrvFreeBSDIOCtlSlow(pSession, ulCmd, pvData, pTd);
|
---|
| 323 | }
|
---|
| 324 |
|
---|
| 325 |
|
---|
| 326 | /**
|
---|
| 327 | * Deal with the 'slow' I/O control requests.
|
---|
| 328 | *
|
---|
| 329 | * @returns 0 on success, appropriate errno on failure.
|
---|
| 330 | * @param pSession The session.
|
---|
| 331 | * @param ulCmd The command.
|
---|
| 332 | * @param pvData The request data.
|
---|
| 333 | * @param pTd The calling thread.
|
---|
| 334 | */
|
---|
| 335 | static int VBoxDrvFreeBSDIOCtlSlow(PSUPDRVSESSION pSession, u_long ulCmd, caddr_t pvData, struct thread *pTd)
|
---|
| 336 | {
|
---|
| 337 | PSUPREQHDR pHdr;
|
---|
| 338 | uint32_t cbReq = IOCPARM_LEN(ulCmd);
|
---|
| 339 | void *pvUser = NULL;
|
---|
| 340 |
|
---|
| 341 | /*
|
---|
| 342 | * Buffered request?
|
---|
| 343 | */
|
---|
| 344 | if ((IOC_DIRMASK & ulCmd) == IOC_INOUT)
|
---|
[3626] | 345 | {
|
---|
[4988] | 346 | pHdr = (PSUPREQHDR)pvData;
|
---|
| 347 | if (RT_UNLIKELY(cbReq < sizeof(*pHdr)))
|
---|
| 348 | {
|
---|
| 349 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: cbReq=%#x < %#x; ulCmd=%#lx\n", cbReq, (int)sizeof(*pHdr), ulCmd));
|
---|
| 350 | return EINVAL;
|
---|
| 351 | }
|
---|
| 352 | if (RT_UNLIKELY((pHdr->fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))
|
---|
| 353 | {
|
---|
| 354 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: bad magic fFlags=%#x; ulCmd=%#lx\n", pHdr->fFlags, ulCmd));
|
---|
| 355 | return EINVAL;
|
---|
| 356 | }
|
---|
| 357 | if (RT_UNLIKELY( RT_MAX(pHdr->cbIn, pHdr->cbOut) != cbReq
|
---|
| 358 | || pHdr->cbIn < sizeof(*pHdr)
|
---|
| 359 | || pHdr->cbOut < sizeof(*pHdr)))
|
---|
| 360 | {
|
---|
| 361 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: max(%#x,%#x) != %#x; ulCmd=%#lx\n", pHdr->cbIn, pHdr->cbOut, cbReq, ulCmd));
|
---|
| 362 | return EINVAL;
|
---|
| 363 | }
|
---|
[3626] | 364 | }
|
---|
[4988] | 365 | /*
|
---|
| 366 | * Big unbuffered request?
|
---|
| 367 | */
|
---|
| 368 | else if ((IOC_DIRMASK & ulCmd) == IOC_VOID && !cbReq)
|
---|
| 369 | {
|
---|
| 370 | /*
|
---|
| 371 | * Read the header, validate it and figure out how much that needs to be buffered.
|
---|
| 372 | */
|
---|
| 373 | SUPREQHDR Hdr;
|
---|
| 374 | pvUser = *(void **)pvData;
|
---|
| 375 | int rc = copyin(pvUser, &Hdr, sizeof(Hdr));
|
---|
| 376 | if (RT_UNLIKELY(rc))
|
---|
| 377 | {
|
---|
| 378 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyin(%p,Hdr,) -> %#x; ulCmd=%#lx\n", pvUser, rc, ulCmd));
|
---|
| 379 | return rc;
|
---|
| 380 | }
|
---|
| 381 | if (RT_UNLIKELY((Hdr.fFlags & SUPREQHDR_FLAGS_MAGIC_MASK) != SUPREQHDR_FLAGS_MAGIC))
|
---|
| 382 | {
|
---|
| 383 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: bad magic fFlags=%#x; ulCmd=%#lx\n", Hdr.fFlags, ulCmd));
|
---|
| 384 | return EINVAL;
|
---|
| 385 | }
|
---|
| 386 | cbReq = RT_MAX(Hdr.cbIn, Hdr.cbOut);
|
---|
| 387 | if (RT_UNLIKELY( Hdr.cbIn < sizeof(Hdr)
|
---|
| 388 | || Hdr.cbOut < sizeof(Hdr)
|
---|
| 389 | || cbReq > _1M*16))
|
---|
| 390 | {
|
---|
| 391 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: max(%#x,%#x); ulCmd=%#lx\n", Hdr.cbIn, Hdr.cbOut, ulCmd));
|
---|
| 392 | return EINVAL;
|
---|
| 393 | }
|
---|
[3626] | 394 |
|
---|
[4988] | 395 | /*
|
---|
| 396 | * Allocate buffer and copy in the data.
|
---|
| 397 | */
|
---|
| 398 | pHdr = (PSUPREQHDR)RTMemTmpAlloc(cbReq);
|
---|
| 399 | if (RT_UNLIKELY(!pHdr))
|
---|
| 400 | {
|
---|
| 401 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: failed to allocate buffer of %d bytes; ulCmd=%#lx\n", cbReq, ulCmd));
|
---|
| 402 | return ENOMEM;
|
---|
| 403 | }
|
---|
| 404 | rc = copyin(pvUser, pHdr, Hdr.cbIn);
|
---|
| 405 | if (RT_UNLIKELY(rc))
|
---|
| 406 | {
|
---|
| 407 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyin(%p,%p,%#x) -> %#x; ulCmd=%#lx\n",
|
---|
| 408 | pvUser, pHdr, Hdr.cbIn, rc, ulCmd));
|
---|
| 409 | RTMemTmpFree(pHdr);
|
---|
| 410 | return rc;
|
---|
| 411 | }
|
---|
[52575] | 412 | if (Hdr.cbIn < cbReq)
|
---|
[52576] | 413 | RT_BZERO((uint8_t *)pHdr + Hdr.cbIn, cbReq - Hdr.cbIn);
|
---|
[4988] | 414 | }
|
---|
| 415 | else
|
---|
| 416 | {
|
---|
[25465] | 417 | Log(("VBoxDrvFreeBSDIOCtlSlow: huh? cbReq=%#x ulCmd=%#lx\n", cbReq, ulCmd));
|
---|
[4988] | 418 | return EINVAL;
|
---|
| 419 | }
|
---|
| 420 |
|
---|
| 421 | /*
|
---|
| 422 | * Process the IOCtl.
|
---|
| 423 | */
|
---|
[52575] | 424 | int rc = supdrvIOCtl(ulCmd, &g_VBoxDrvFreeBSDDevExt, pSession, pHdr, cbReq);
|
---|
[4988] | 425 | if (RT_LIKELY(!rc))
|
---|
| 426 | {
|
---|
| 427 | /*
|
---|
| 428 | * If unbuffered, copy back the result before returning.
|
---|
| 429 | */
|
---|
| 430 | if (pvUser)
|
---|
| 431 | {
|
---|
| 432 | uint32_t cbOut = pHdr->cbOut;
|
---|
| 433 | if (cbOut > cbReq)
|
---|
| 434 | {
|
---|
| 435 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: too much output! %#x > %#x; uCmd=%#lx!\n", cbOut, cbReq, ulCmd));
|
---|
| 436 | cbOut = cbReq;
|
---|
| 437 | }
|
---|
| 438 | rc = copyout(pHdr, pvUser, cbOut);
|
---|
| 439 | if (RT_UNLIKELY(rc))
|
---|
| 440 | OSDBGPRINT(("VBoxDrvFreeBSDIOCtlSlow: copyout(%p,%p,%#x) -> %d; uCmd=%#lx!\n", pHdr, pvUser, cbOut, rc, ulCmd));
|
---|
| 441 |
|
---|
[25465] | 442 | Log(("VBoxDrvFreeBSDIOCtlSlow: returns %d / %d ulCmd=%lx\n", 0, pHdr->rc, ulCmd));
|
---|
[18915] | 443 |
|
---|
[4988] | 444 | /* cleanup */
|
---|
| 445 | RTMemTmpFree(pHdr);
|
---|
| 446 | }
|
---|
| 447 | }
|
---|
| 448 | else
|
---|
| 449 | {
|
---|
| 450 | /*
|
---|
| 451 | * The request failed, just clean up.
|
---|
| 452 | */
|
---|
| 453 | if (pvUser)
|
---|
| 454 | RTMemTmpFree(pHdr);
|
---|
| 455 |
|
---|
[25465] | 456 | Log(("VBoxDrvFreeBSDIOCtlSlow: ulCmd=%lx pData=%p failed, rc=%d\n", ulCmd, pvData, rc));
|
---|
[4988] | 457 | rc = EINVAL;
|
---|
| 458 | }
|
---|
| 459 |
|
---|
| 460 | return rc;
|
---|
[3626] | 461 | }
|
---|
| 462 |
|
---|
[4016] | 463 |
|
---|
[10263] | 464 | /**
|
---|
| 465 | * The SUPDRV IDC entry point.
|
---|
| 466 | *
|
---|
| 467 | * @returns VBox status code, see supdrvIDC.
|
---|
[58340] | 468 | * @param uReq The request code.
|
---|
[10263] | 469 | * @param pReq The request.
|
---|
| 470 | */
|
---|
| 471 | int VBOXCALL SUPDrvFreeBSDIDC(uint32_t uReq, PSUPDRVIDCREQHDR pReq)
|
---|
| 472 | {
|
---|
| 473 | PSUPDRVSESSION pSession;
|
---|
[4988] | 474 |
|
---|
[10263] | 475 | /*
|
---|
| 476 | * Some quick validations.
|
---|
| 477 | */
|
---|
[90780] | 478 | if (RT_UNLIKELY(!RT_VALID_PTR(pReq)))
|
---|
[10263] | 479 | return VERR_INVALID_POINTER;
|
---|
| 480 |
|
---|
| 481 | pSession = pReq->pSession;
|
---|
| 482 | if (pSession)
|
---|
| 483 | {
|
---|
[90780] | 484 | if (RT_UNLIKELY(!RT_VALID_PTR(pReq->pSession)))
|
---|
[10263] | 485 | return VERR_INVALID_PARAMETER;
|
---|
[19343] | 486 | if (RT_UNLIKELY(pSession->pDevExt != &g_VBoxDrvFreeBSDDevExt))
|
---|
[10263] | 487 | return VERR_INVALID_PARAMETER;
|
---|
| 488 | }
|
---|
| 489 | else if (RT_UNLIKELY(uReq != SUPDRV_IDC_REQ_CONNECT))
|
---|
| 490 | return VERR_INVALID_PARAMETER;
|
---|
| 491 |
|
---|
| 492 | /*
|
---|
| 493 | * Do the job.
|
---|
| 494 | */
|
---|
[19343] | 495 | return supdrvIDC(uReq, &g_VBoxDrvFreeBSDDevExt, pSession, pReq);
|
---|
[10263] | 496 | }
|
---|
| 497 |
|
---|
| 498 |
|
---|
[51770] | 499 | void VBOXCALL supdrvOSCleanupSession(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession)
|
---|
| 500 | {
|
---|
| 501 | NOREF(pDevExt);
|
---|
| 502 | NOREF(pSession);
|
---|
| 503 | }
|
---|
| 504 |
|
---|
| 505 |
|
---|
| 506 | void VBOXCALL supdrvOSSessionHashTabInserted(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
|
---|
| 507 | {
|
---|
| 508 | NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
|
---|
| 509 | }
|
---|
| 510 |
|
---|
| 511 |
|
---|
| 512 | void VBOXCALL supdrvOSSessionHashTabRemoved(PSUPDRVDEVEXT pDevExt, PSUPDRVSESSION pSession, void *pvUser)
|
---|
| 513 | {
|
---|
| 514 | NOREF(pDevExt); NOREF(pSession); NOREF(pvUser);
|
---|
| 515 | }
|
---|
| 516 |
|
---|
| 517 |
|
---|
[4016] | 518 | void VBOXCALL supdrvOSObjInitCreator(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession)
|
---|
| 519 | {
|
---|
| 520 | NOREF(pObj);
|
---|
| 521 | NOREF(pSession);
|
---|
| 522 | }
|
---|
| 523 |
|
---|
| 524 |
|
---|
| 525 | bool VBOXCALL supdrvOSObjCanAccess(PSUPDRVOBJ pObj, PSUPDRVSESSION pSession, const char *pszObjName, int *prc)
|
---|
| 526 | {
|
---|
| 527 | NOREF(pObj);
|
---|
| 528 | NOREF(pSession);
|
---|
| 529 | NOREF(pszObjName);
|
---|
| 530 | NOREF(prc);
|
---|
| 531 | return false;
|
---|
| 532 | }
|
---|
| 533 |
|
---|
[9477] | 534 |
|
---|
[9470] | 535 | bool VBOXCALL supdrvOSGetForcedAsyncTscMode(PSUPDRVDEVEXT pDevExt)
|
---|
| 536 | {
|
---|
| 537 | return false;
|
---|
| 538 | }
|
---|
[4016] | 539 |
|
---|
[9470] | 540 |
|
---|
[54581] | 541 | bool VBOXCALL supdrvOSAreCpusOfflinedOnSuspend(void)
|
---|
| 542 | {
|
---|
| 543 | /** @todo verify this. */
|
---|
| 544 | return false;
|
---|
| 545 | }
|
---|
| 546 |
|
---|
| 547 |
|
---|
[53396] | 548 | bool VBOXCALL supdrvOSAreTscDeltasInSync(void)
|
---|
| 549 | {
|
---|
| 550 | return false;
|
---|
| 551 | }
|
---|
| 552 |
|
---|
| 553 |
|
---|
[25258] | 554 | int VBOXCALL supdrvOSLdrOpen(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
|
---|
| 555 | {
|
---|
| 556 | NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
|
---|
| 557 | return VERR_NOT_SUPPORTED;
|
---|
| 558 | }
|
---|
| 559 |
|
---|
| 560 |
|
---|
[75003] | 561 | int VBOXCALL supdrvOSLdrValidatePointer(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, void *pv,
|
---|
| 562 | const uint8_t *pbImageBits, const char *pszSymbol)
|
---|
[25258] | 563 | {
|
---|
[75003] | 564 | NOREF(pDevExt); NOREF(pImage); NOREF(pv); NOREF(pbImageBits); NOREF(pszSymbol);
|
---|
[25258] | 565 | return VERR_NOT_SUPPORTED;
|
---|
| 566 | }
|
---|
| 567 |
|
---|
| 568 |
|
---|
[37249] | 569 | int VBOXCALL supdrvOSLdrLoad(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const uint8_t *pbImageBits, PSUPLDRLOAD pReq)
|
---|
[25258] | 570 | {
|
---|
[37249] | 571 | NOREF(pDevExt); NOREF(pImage); NOREF(pbImageBits); NOREF(pReq);
|
---|
[25258] | 572 | return VERR_NOT_SUPPORTED;
|
---|
| 573 | }
|
---|
| 574 |
|
---|
| 575 |
|
---|
| 576 | void VBOXCALL supdrvOSLdrUnload(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
|
---|
| 577 | {
|
---|
| 578 | NOREF(pDevExt); NOREF(pImage);
|
---|
| 579 | }
|
---|
| 580 |
|
---|
| 581 |
|
---|
[58872] | 582 | void VBOXCALL supdrvOSLdrNotifyOpened(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage, const char *pszFilename)
|
---|
| 583 | {
|
---|
| 584 | NOREF(pDevExt); NOREF(pImage); NOREF(pszFilename);
|
---|
| 585 | }
|
---|
| 586 |
|
---|
| 587 |
|
---|
| 588 | void VBOXCALL supdrvOSLdrNotifyUnloaded(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
|
---|
| 589 | {
|
---|
| 590 | NOREF(pDevExt); NOREF(pImage);
|
---|
| 591 | }
|
---|
| 592 |
|
---|
| 593 |
|
---|
[75282] | 594 | int VBOXCALL supdrvOSLdrQuerySymbol(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage,
|
---|
| 595 | const char *pszSymbol, size_t cchSymbol, void **ppvSymbol)
|
---|
| 596 | {
|
---|
| 597 | RT_NOREF(pDevExt, pImage, pszSymbol, cchSymbol, ppvSymbol);
|
---|
| 598 | return VERR_WRONG_ORDER;
|
---|
| 599 | }
|
---|
| 600 |
|
---|
| 601 |
|
---|
[87700] | 602 | void VBOXCALL supdrvOSLdrRetainWrapperModule(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
|
---|
| 603 | {
|
---|
| 604 | RT_NOREF(pDevExt, pImage);
|
---|
| 605 | AssertFailed();
|
---|
| 606 | }
|
---|
| 607 |
|
---|
| 608 |
|
---|
| 609 | void VBOXCALL supdrvOSLdrReleaseWrapperModule(PSUPDRVDEVEXT pDevExt, PSUPDRVLDRIMAGE pImage)
|
---|
| 610 | {
|
---|
| 611 | RT_NOREF(pDevExt, pImage);
|
---|
| 612 | AssertFailed();
|
---|
| 613 | }
|
---|
| 614 |
|
---|
[49634] | 615 | #ifdef SUPDRV_WITH_MSR_PROBER
|
---|
| 616 |
|
---|
| 617 | int VBOXCALL supdrvOSMsrProberRead(uint32_t uMsr, RTCPUID idCpu, uint64_t *puValue)
|
---|
| 618 | {
|
---|
| 619 | NOREF(uMsr); NOREF(idCpu); NOREF(puValue);
|
---|
| 620 | return VERR_NOT_SUPPORTED;
|
---|
| 621 | }
|
---|
| 622 |
|
---|
| 623 |
|
---|
| 624 | int VBOXCALL supdrvOSMsrProberWrite(uint32_t uMsr, RTCPUID idCpu, uint64_t uValue)
|
---|
| 625 | {
|
---|
| 626 | NOREF(uMsr); NOREF(idCpu); NOREF(uValue);
|
---|
| 627 | return VERR_NOT_SUPPORTED;
|
---|
| 628 | }
|
---|
| 629 |
|
---|
| 630 |
|
---|
| 631 | int VBOXCALL supdrvOSMsrProberModify(RTCPUID idCpu, PSUPMSRPROBER pReq)
|
---|
| 632 | {
|
---|
| 633 | NOREF(idCpu); NOREF(pReq);
|
---|
| 634 | return VERR_NOT_SUPPORTED;
|
---|
| 635 | }
|
---|
| 636 |
|
---|
| 637 | #endif /* SUPDRV_WITH_MSR_PROBER */
|
---|
| 638 |
|
---|
| 639 |
|
---|
[91785] | 640 | #if defined(RT_ARCH_AMD64) || defined(RT_ARCH_ARM64)
|
---|
| 641 | SUPR0DECL(int) SUPR0HCPhysToVirt(RTHCPHYS HCPhys, void **ppv)
|
---|
| 642 | {
|
---|
| 643 | AssertReturn(!(HCPhys & PAGE_OFFSET_MASK), VERR_INVALID_POINTER);
|
---|
| 644 | AssertReturn(HCPhys != NIL_RTHCPHYS, VERR_INVALID_POINTER);
|
---|
| 645 | *ppv = (void *)(uintptr_t)pmap_map(NULL, HCPhys, (HCPhys | PAGE_OFFSET_MASK) + 1, VM_PROT_WRITE | VM_PROT_READ);
|
---|
| 646 | return VINF_SUCCESS;
|
---|
| 647 | }
|
---|
| 648 | #endif
|
---|
| 649 |
|
---|
| 650 |
|
---|
[91789] | 651 | SUPR0DECL(int) SUPR0PrintfV(const char *pszFormat, va_list va)
|
---|
[4016] | 652 | {
|
---|
| 653 | char szMsg[256];
|
---|
[91789] | 654 | RTStrPrintfV(szMsg, sizeof(szMsg), pszFormat, va);
|
---|
| 655 | szMsg[sizeof(szMsg) - 1] = '\0';
|
---|
[4016] | 656 |
|
---|
| 657 | printf("%s", szMsg);
|
---|
[91789] | 658 | return 0;
|
---|
[4016] | 659 | }
|
---|
| 660 |
|
---|
[52192] | 661 |
|
---|
| 662 | SUPR0DECL(uint32_t) SUPR0GetKernelFeatures(void)
|
---|
| 663 | {
|
---|
| 664 | return 0;
|
---|
| 665 | }
|
---|
| 666 |
|
---|
[95087] | 667 |
|
---|
| 668 | SUPR0DECL(bool) SUPR0FpuBegin(bool fCtxHook)
|
---|
| 669 | {
|
---|
| 670 | RT_NOREF(fCtxHook);
|
---|
| 671 | return false;
|
---|
| 672 | }
|
---|
| 673 |
|
---|
| 674 |
|
---|
| 675 | SUPR0DECL(void) SUPR0FpuEnd(bool fCtxHook)
|
---|
| 676 | {
|
---|
| 677 | RT_NOREF(fCtxHook);
|
---|
| 678 | }
|
---|
| 679 |
|
---|