Changeset 21464 in vbox for trunk/src/VBox/Additions/common/VBoxGuestLib
- Timestamp:
- Jul 10, 2009 2:08:15 AM (16 years ago)
- svn:sync-xref-src-repo-rev:
- 49882
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Additions/common/VBoxGuestLib/HGCMInternal.cpp
r21459 r21464 23 23 #ifdef VBGL_VBOXGUEST 24 24 25 /******************************************************************************* 26 * Header Files * 27 *******************************************************************************/ 25 28 #include "VBGLInternal.h" 29 #include <iprt/alloca.h> 30 #include <iprt/assert.h> 31 #include <iprt/mem.h> 32 #include <iprt/memobj.h> 26 33 #include <iprt/string.h> 27 #include <iprt/assert.h> 28 #include <iprt/alloca.h> 34 35 /******************************************************************************* 36 * Defined Constants And Macros * 37 *******************************************************************************/ 38 /** The max parameter buffer size for a user request. */ 39 #define VBGLR0_MAX_HGCM_USER_PARM _1M 40 /** The max parameter buffer size for a kernel request. */ 41 #define VBGLR0_MAX_HGCM_KERNEL_PARM (16*_1M) 42 #ifdef RT_OS_LINUX 43 /** Linux needs to use bounce buffers since RTR0MemObjLockUser has unwanted 44 * side effects. */ 45 # define USE_BOUNCH_BUFFERS 46 #endif 47 48 29 49 30 50 /* These functions can be only used by VBoxGuest. */ … … 120 140 } 121 141 142 #if 0 /* new code using page list and whatnot. */ 143 144 /** 145 * Lock info structure used by VbglR0HGCMInternalCall and its helpers. 146 */ 147 struct VbglR0ParmInfo 148 { 149 uint32_t cLockBufs; 150 struct 151 { 152 uint32_t iParm; 153 RTR0MEMOBJ hObj; 154 } aLockBufs[10]; 155 }; 156 157 /** 158 * Preprocesses the HGCM call, validating and locking/buffering parameters. 159 * 160 * @returns VBox status code. 161 * 162 * @param pCallInfo The call info. 163 * @param cbCallInfo The size of the call info structure. 164 * @param fIsUser Is it a user request or kernel request. 165 * @param pcbExtra Where to return the extra request space needed for 166 * physical page lists. 167 */ 168 static int vbglR0HGCMInternalPreprocessCall(VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo, 169 bool fIsUser, struct VbglR0ParmInfo *pParmInfo, size_t *pcbExtra) 170 { 171 HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo); 172 uint32_t cParms = pCallInfo->cParms; 173 uint32_t iParm; 174 175 /* 176 * Lock down the any linear buffers so we can get their addresses 177 * and figure out how much extra storage we need for page lists. 178 */ 179 *pcbExtra = 0; 180 pParmInfo->cLockBufs = 0; 181 for (iParm = 0; iParm < cParms; iParm++, pSrcParm++) 182 { 183 switch (pSrcParm->type) 184 { 185 case VMMDevHGCMParmType_32bit: 186 case VMMDevHGCMParmType_64bit: 187 break; 188 189 case VMMDevHGCMParmType_PageList: 190 if (fIsUser) 191 return VERR_INVALID_PARAMETER; 192 if (pSrcParm->u.PageList.size) 193 { 194 HGCMPageListInfo *pPgLst; 195 196 if (pSrcParm->u.Pointer.size > VBGLR0_MAX_HGCM_KERNEL_PARM) 197 return VERR_OUT_OF_RANGE; 198 AssertReturn( pSrcParm->u.PageList.offset >= pCallInfo->cParms * sizeof(HGCMFunctionParameter) 199 && pSrcParm->u.PageList.offset < cbCallInfo - sizeof(HGCMPageListInfo), VERR_INVALID_PARAMETER); 200 pPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + pSrcParm->u.PageList.offset); 201 AssertReturn(RT_OFFSETOF(HGCMPageListInfo, aPages[pPgLst->cPages]) + pSrcParm->u.PageList.offset <= cbCallInfo, VERR_INVALID_PARAMETER); 202 AssertReturn(pPgLst->offFirstPage < PAGE_SIZE, VERR_INVALID_PARAMETER); 203 AssertReturn(pPgLst->flags > VBOX_HGCM_F_PARM_DIRECTION_NONE && pPgLst->flags <= VBOX_HGCM_F_PARM_DIRECTION_BOTH, VERR_INVALID_PARAMETER); 204 205 *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[pPgLst->cPages]); 206 } 207 break; 208 209 case VMMDevHGCMParmType_LinAddr_Locked_In: 210 case VMMDevHGCMParmType_LinAddr_Locked_Out: 211 case VMMDevHGCMParmType_LinAddr_Locked: 212 if (fIsUser) 213 return VERR_INVALID_PARAMETER; 214 if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST()) 215 { 216 if (pSrcParm->u.Pointer.size > VBGLR0_MAX_HGCM_KERNEL_PARM) 217 return VERR_OUT_OF_RANGE; 218 break; 219 } 220 /* fall thru */ 221 222 case VMMDevHGCMParmType_LinAddr_In: 223 case VMMDevHGCMParmType_LinAddr_Out: 224 case VMMDevHGCMParmType_LinAddr: 225 if (pSrcParm->u.Pointer.size > (fIsUser ? VBGLR0_MAX_HGCM_USER_PARM : VBGLR0_MAX_HGCM_KERNEL_PARM)) 226 return VERR_OUT_OF_RANGE; 227 if (pSrcParm->u.Pointer.size != 0) 228 { 229 RTR0MEMOBJ hObj; 230 int rc; 231 232 AssertReturn(pParmInfo->cLockBufs < RT_ELEMENTS(pParmInfo->aLockBufs), VERR_INVALID_PARAMETER); 233 if (!fIsUser) 234 rc = RTR0MemObjLockKernel(&hObj, 235 (void *)pSrcParm->u.Pointer.u.linearAddr, 236 pSrcParm->u.Pointer.size); 237 else 238 { 239 #ifdef USE_BOUNCH_BUFFERS 240 rc = RTR0MemObjAllocPage(&hObj, 241 pSrcParm->u.Pointer.size, 242 false /*fExecutable*/); 243 if ( RT_SUCCESS(rc) 244 && pSrcParm->type != VMMDevHGCMParmType_LinAddr_Out 245 && pSrcParm->type != VMMDevHGCMParmType_LinAddr_Locked_Out) 246 { 247 rc = RTR0MemUserCopyFrom(RTR0MemObjAddress(hObj), 248 pSrcParm->u.Pointer.u.linearAddr, 249 pSrcParm->u.Pointer.size + 2); 250 if (RT_FAILURE(rc)) 251 RTR0MemObjFree(hObj, false /*fFreeMappings*/); 252 } 253 #else 254 rc = RTR0MemObjLockUser(&hObj, 255 (RTR3PTR)pSrcParm->u.Pointer.u.linearAddr, 256 pSrcParm->u.Pointer.size, 257 NIL_RTR0PROCESS); 258 #endif 259 } 260 if (RT_FAILURE(rc)) 261 return rc; 262 263 pParmInfo->aLockBufs[pParmInfo->cLockBufs].iParm = iParm; 264 pParmInfo->aLockBufs[pParmInfo->cLockBufs].hObj = hObj; 265 pParmInfo->cLockBufs++; 266 267 if (VBGLR0_CAN_USE_PHYS_PAGE_LIST()) 268 { 269 size_t cPages = RTR0MemObjSize(hObj); 270 *pcbExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]); 271 } 272 } 273 break; 274 275 default: 276 return VERR_INVALID_PARAMETER; 277 } 278 } 279 280 return VINF_SUCCESS; 281 } 282 283 /** 284 * Translates locked linear address to the normal type. 285 * The locked types are only for the guest side and not handled by the host. 286 * 287 * @returns normal linear address type. 288 * @param enmType The type. 289 */ 290 static HGCMFunctionParameterType vbglR0HGCMInternalConvertLinAddrType(HGCMFunctionParameterType enmType) 291 { 292 switch (enmType) 293 { 294 case VMMDevHGCMParmType_LinAddr_Locked_In: 295 return VMMDevHGCMParmType_LinAddr_In; 296 case VMMDevHGCMParmType_LinAddr_Locked_Out: 297 return VMMDevHGCMParmType_LinAddr_Out; 298 case VMMDevHGCMParmType_LinAddr_Locked: 299 return VMMDevHGCMParmType_LinAddr; 300 default: 301 return enmType; 302 } 303 } 304 305 /** 306 * Translates linear address types to page list direction flags. 307 * 308 * @returns page list flags. 309 * @param enmType The type. 310 */ 311 static uint32_t vbglR0HGCMInternalLinAddrTypeToPageListFlags(HGCMFunctionParameterType enmType) 312 { 313 switch (enmType) 314 { 315 case VMMDevHGCMParmType_LinAddr_In: 316 case VMMDevHGCMParmType_LinAddr_Locked_In: 317 return VBOX_HGCM_F_PARM_DIRECTION_FROM_HOST; 318 319 case VMMDevHGCMParmType_LinAddr_Out: 320 case VMMDevHGCMParmType_LinAddr_Locked_Out: 321 return VBOX_HGCM_F_PARM_DIRECTION_TO_HOST; 322 323 default: AssertFailed(); 324 case VMMDevHGCMParmType_LinAddr: 325 case VMMDevHGCMParmType_LinAddr_Locked: 326 return VBOX_HGCM_F_PARM_DIRECTION_BOTH; 327 } 328 } 329 330 331 /** 332 * Initializes the call request that we're sending to the host. 333 * 334 * @returns VBox status code. 335 * 336 * @param pCallInfo The call info. 337 * @param cbCallInfo The size of the call info structure. 338 * @param fIsUser Is it a user request or kernel request. 339 * @param pcbExtra Where to return the extra request space needed for 340 * physical page lists. 341 */ 342 static void vbglR0HGCMInternalInitCall(VMMDevHGCMCall *pHGCMCall, VBoxGuestHGCMCallInfo const *pCallInfo, uint32_t cbCallInfo, 343 bool fIsUser, struct VbglR0ParmInfo *pParmInfo) 344 { 345 HGCMFunctionParameter const *pSrcParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo); 346 HGCMFunctionParameter *pDstParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall); 347 uint32_t cParms = pCallInfo->cParms; 348 uint32_t offExtra = (uintptr_t)(pDstParm + cParms) - (uintptr_t)pHGCMCall; 349 uint32_t iLockBuf = 0; 350 uint32_t iParm; 351 352 353 /* 354 * The call request headers. 355 */ 356 pHGCMCall->header.fu32Flags = 0; 357 pHGCMCall->header.result = VINF_SUCCESS; 358 359 pHGCMCall->u32ClientID = pCallInfo->u32ClientID; 360 pHGCMCall->u32Function = pCallInfo->u32Function; 361 pHGCMCall->cParms = cParms; 362 363 /* 364 * The parameters. 365 */ 366 for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pSrcParm++, pDstParm++) 367 { 368 switch (pSrcParm->type) 369 { 370 case VMMDevHGCMParmType_32bit: 371 case VMMDevHGCMParmType_64bit: 372 *pDstParm = *pSrcParm; 373 break; 374 375 case VMMDevHGCMParmType_PageList: 376 pDstParm->type = VMMDevHGCMParmType_PageList; 377 pDstParm->u.PageList.size = pSrcParm->u.PageList.size; 378 if (pSrcParm->u.PageList.size) 379 { 380 HGCMPageListInfo const *pSrcPgLst = (HGCMPageListInfo *)((uint8_t *)pCallInfo + pSrcParm->u.PageList.offset); 381 HGCMPageListInfo *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra); 382 uint32_t const cPages = pSrcPgLst->cPages; 383 uint32_t iPage; 384 385 pDstParm->u.PageList.offset = offExtra; 386 pDstPgLst->flags = pSrcPgLst->flags; 387 pDstPgLst->offFirstPage = pSrcPgLst->offFirstPage; 388 pDstPgLst->cPages = cPages; 389 for (iPage = 0; iPage < cPages; iPage++) 390 pDstPgLst->aPages[iPage] = pSrcPgLst->aPages[iPage]; 391 392 offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]); 393 } 394 else 395 pDstParm->u.PageList.offset = 0; 396 break; 397 398 case VMMDevHGCMParmType_LinAddr_Locked_In: 399 case VMMDevHGCMParmType_LinAddr_Locked_Out: 400 case VMMDevHGCMParmType_LinAddr_Locked: 401 if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST()) 402 { 403 *pDstParm = *pSrcParm; 404 break; 405 } 406 /* fall thru */ 407 408 case VMMDevHGCMParmType_LinAddr_In: 409 case VMMDevHGCMParmType_LinAddr_Out: 410 case VMMDevHGCMParmType_LinAddr: 411 if (pSrcParm->u.Pointer.size != 0) 412 { 413 RTR0MEMOBJ hObj = pParmInfo->aLockBufs[iLockBuf].hObj; 414 Assert(iParm == pParmInfo->aLockBufs[iLockBuf].iParm); 415 416 if (VBGLR0_CAN_USE_PHYS_PAGE_LIST()) 417 { 418 HGCMPageListInfo *pDstPgLst = (HGCMPageListInfo *)((uint8_t *)pHGCMCall + offExtra); 419 size_t const cPages = RTR0MemObjSize(hObj) >> PAGE_SHIFT; 420 size_t iPage; 421 422 pDstParm->type = VMMDevHGCMParmType_PageList; 423 pDstParm->u.PageList.size = pSrcParm->u.Pointer.size; 424 pDstParm->u.PageList.offset = offExtra; 425 pDstPgLst->flags = vbglR0HGCMInternalLinAddrTypeToPageListFlags(pSrcParm->type); 426 #ifdef USE_BOUNCH_BUFFERS 427 if (fIsUser) 428 pDstPgLst->offFirstPage = 0; 429 else 430 #endif 431 pDstPgLst->offFirstPage = pSrcParm->u.Pointer.u.linearAddr & PAGE_OFFSET_MASK; 432 pDstPgLst->cPages = cPages; Assert(pDstPgLst->cPages == cPages); 433 for (iPage = 0; iPage < cPages; iPage++) 434 { 435 pDstPgLst->aPages[iPage] = RTR0MemObjGetPagePhysAddr(hObj, iPage); 436 Assert(pDstPgLst->aPages[iPage] != NIL_RTHCPHYS); 437 } 438 439 offExtra += RT_OFFSETOF(HGCMPageListInfo, aPages[cPages]); 440 } 441 else 442 { 443 pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type); 444 pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size; 445 #ifdef USE_BOUNCH_BUFFERS 446 if (fIsUser) 447 pDstParm->u.Pointer.u.linearAddr = (uintptr_t)RTR0MemObjAddress(hObj); 448 else 449 #endif 450 pDstParm->u.Pointer.u.linearAddr = pSrcParm->u.Pointer.u.linearAddr; 451 } 452 iLockBuf++; 453 } 454 else 455 { 456 pDstParm->type = vbglR0HGCMInternalConvertLinAddrType(pSrcParm->type); 457 pDstParm->u.Pointer.size = 0; 458 pDstParm->u.Pointer.u.linearAddr = 0; 459 } 460 break; 461 462 default: 463 AssertFailed(); 464 pDstParm->type = VMMDevHGCMParmType_Invalid; 465 break; 466 } 467 } 468 } 469 470 471 /** 472 * Performs the call and completion wait. 473 * 474 * @returns VBox status code of this operation, not necessarily the call. 475 * 476 * @param pHGCMCall The HGCM call info. 477 * @param pfnAsyncCallback The async callback that will wait for the call 478 * to complete. 479 * @param pvAsyncData Argument for the callback. 480 * @param u32AsyncData Argument for the callback. 481 */ 482 static int vbglR0HGCMInternalDoCall(VMMDevHGCMCall *pHGCMCall, VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) 483 { 484 int rc; 485 486 Log(("calling VbglGRPerform\n")); 487 rc = VbglGRPerform(&pHGCMCall->header.header); 488 Log(("VbglGRPerform rc = %Rrc (header rc=%d)\n", rc, pHGCMCall->header.result)); 489 490 /* 491 * If the call failed, but as a result of the request itself, then pretend 492 * success. Upper layers will interpret the result code in the packet. 493 */ 494 if ( RT_FAILURE(rc) 495 && rc == pHGCMCall->header.result) 496 { 497 Assert(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE); 498 rc = VINF_SUCCESS; 499 } 500 501 /* 502 * Check if host decides to process the request asynchronously, 503 * if so, we wait for it to complete using the caller supplied callback. 504 */ 505 if ( RT_SUCCESS(rc) 506 && rc == VINF_HGCM_ASYNC_EXECUTE) 507 { 508 Log(("Processing HGCM call asynchronously\n")); 509 /** @todo timeout vs. interrupted. */ 510 pfnAsyncCallback(&pHGCMCall->header, pvAsyncData, u32AsyncData); 511 512 /* 513 * If the request isn't completed by the time the callback returns 514 * we will have to try cancel it. 515 */ 516 if (!(pHGCMCall->header.fu32Flags & VBOX_HGCM_REQ_DONE)) 517 { 518 /** @todo use a new request for this! See @bugref{4052}. */ 519 pHGCMCall->header.fu32Flags |= VBOX_HGCM_REQ_CANCELLED; 520 pHGCMCall->header.header.requestType = VMMDevReq_HGCMCancel; 521 VbglGRPerform(&pHGCMCall->header.header); 522 rc = VERR_INTERRUPTED; 523 } 524 } 525 return rc; 526 } 527 528 529 /** 530 * Copies the result of the call back to the caller info structure and user 531 * buffers (if using bounce buffers). 532 * 533 * @returns rc, unless RTR0MemUserCopyTo fails. 534 * @param pCallInfo Call info structure to update. 535 * @param pHGCMCall HGCM call request. 536 * @param pParmInfo Paramter locking/buffering info. 537 * @param fIsUser Is it a user (true) or kernel request. 538 * @param rc The current result code. Passed along to 539 * preserve informational status codes. 540 */ 541 static int vbglR0HGCMInternalCopyBackResult(VBoxGuestHGCMCallInfo *pCallInfo, VMMDevHGCMCall const *pHGCMCall, 542 struct VbglR0ParmInfo *pParmInfo, bool fIsUser, int rc) 543 { 544 HGCMFunctionParameter const *pSrcParm = VMMDEV_HGCM_CALL_PARMS(pHGCMCall); 545 HGCMFunctionParameter *pDstParm = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo); 546 uint32_t cParms = pCallInfo->cParms; 547 #ifdef USE_BOUNCH_BUFFERS 548 uint32_t iLockBuf = 0; 549 #endif 550 uint32_t iParm; 551 552 /* 553 * The call result. 554 */ 555 pCallInfo->result = pHGCMCall->header.result; 556 557 /* 558 * Copy back parameters. 559 */ 560 for (iParm = 0; iParm < pCallInfo->cParms; iParm++, pSrcParm++, pDstParm++) 561 { 562 switch (pDstParm->type) 563 { 564 case VMMDevHGCMParmType_32bit: 565 case VMMDevHGCMParmType_64bit: 566 *pDstParm = *pSrcParm; 567 break; 568 569 case VMMDevHGCMParmType_PageList: 570 pDstParm->u.PageList.size = pSrcParm->u.PageList.size; 571 break; 572 573 case VMMDevHGCMParmType_LinAddr_Locked_In: 574 case VMMDevHGCMParmType_LinAddr_In: 575 #ifdef USE_BOUNCH_BUFFERS 576 if ( fIsUser 577 && iLockBuf < pParmInfo->cLockBufs 578 && iParm == pParmInfo->aLockBufs[iLockBuf].iParm) 579 iLockBuf++; 580 #endif 581 pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size; 582 break; 583 584 case VMMDevHGCMParmType_LinAddr_Locked_Out: 585 case VMMDevHGCMParmType_LinAddr_Locked: 586 if (!VBGLR0_CAN_USE_PHYS_PAGE_LIST()) 587 { 588 pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size; 589 break; 590 } 591 /* fall thru */ 592 593 case VMMDevHGCMParmType_LinAddr_Out: 594 case VMMDevHGCMParmType_LinAddr: 595 { 596 #ifdef USE_BOUNCH_BUFFERS 597 if (fIsUser) 598 { 599 if ( pSrcParm->u.Pointer.size != 0 600 && pDstParm->u.Pointer.size != 0) 601 { 602 Assert(pParmInfo->aLockBufs[iLockBuf].iParm == iParm); 603 int rc2 = RTR0MemUserCopyTo((RTR3PTR)pDstParm->u.Pointer.u.linearAddr, 604 RTR0MemObjAddress(pParmInfo->aLockBufs[iLockBuf].hObj), 605 RT_MIN(pSrcParm->u.Pointer.size, pDstParm->u.Pointer.size)); 606 if (RT_FAILURE(rc2)) 607 return rc2; 608 iLockBuf++; 609 } 610 else if ( iLockBuf < pParmInfo->cLockBufs 611 && iParm == pParmInfo->aLockBufs[iLockBuf].iParm) 612 iLockBuf++; 613 } 614 #endif 615 pDstParm->u.Pointer.size = pSrcParm->u.Pointer.size; 616 break; 617 } 618 619 default: 620 AssertFailed(); 621 rc = VERR_INTERNAL_ERROR_4; 622 break; 623 } 624 } 625 626 #ifdef USE_BOUNCH_BUFFERS 627 Assert(!fIsUser || pParmInfo->cLockBufs == iLockBuf); 628 #endif 629 return rc; 630 } 631 632 DECLR0VBGL(int) VbglR0HGCMInternalCall(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 633 VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) 634 { 635 bool fIsUser = (fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_USER; 636 struct VbglR0ParmInfo ParmInfo; 637 size_t cbExtra; 638 int rc; 639 640 /* 641 * Basic validation. 642 */ 643 AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 644 ("pCallInfo=%p pfnAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags), 645 VERR_INVALID_PARAMETER); 646 AssertReturn( cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo) 647 || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter), 648 VERR_INVALID_PARAMETER); 649 650 Log (("VbglR0HGCMInternalCall: pCallInfo->cParms = %d, pHGCMCall->u32Function = %d, fFlags=%#x\n", 651 pCallInfo->cParms, pCallInfo->u32Function, fFlags)); 652 653 /* 654 * Preprocess the parameters, locking/buffering stuff. 655 */ 656 rc = vbglR0HGCMInternalPreprocessCall(pCallInfo, cbCallInfo, fIsUser, &ParmInfo, &cbExtra); 657 if (RT_SUCCESS(rc)) 658 { 659 /* 660 * Allocate the request buffer and recreate the call request. 661 */ 662 VMMDevHGCMCall *pHGCMCall; 663 rc = VbglGRAlloc((VMMDevRequestHeader **)&pHGCMCall, 664 sizeof(VMMDevHGCMCall) + pCallInfo->cParms * sizeof(HGCMFunctionParameter) + cbExtra, 665 VMMDevReq_HGCMCall); 666 if (RT_SUCCESS(rc)) 667 { 668 vbglR0HGCMInternalInitCall(pHGCMCall, pCallInfo, cbCallInfo, fIsUser, &ParmInfo); 669 670 /* 671 * Perform the call. 672 */ 673 rc = vbglR0HGCMInternalDoCall(pHGCMCall, pfnAsyncCallback, pvAsyncData, u32AsyncData); 674 if (RT_SUCCESS(rc)) 675 { 676 /* 677 * Copy back the result (parameters and buffers that changed). 678 */ 679 rc = vbglR0HGCMInternalCopyBackResult(pCallInfo, pHGCMCall, &ParmInfo, fIsUser, rc); 680 } 681 682 VbglGRFree(&pHGCMCall->header.header); 683 } 684 } 685 686 /* 687 * Copy back buffered data and release buffers & locks. 688 */ 689 if (ParmInfo.cLockBufs) 690 while (ParmInfo.cLockBufs-- > 0) 691 RTR0MemObjFree(ParmInfo.aLockBufs[ParmInfo.cLockBufs].hObj, false /*fFreeMappings*/); 692 693 return rc; 694 } 695 696 697 # if ARCH_BITS == 64 698 DECLR0VBGL(int) VbglR0HGCMInternalCall32(VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, 699 VBGLHGCMCALLBACK *pfnAsyncCallback, void *pvAsyncData, uint32_t u32AsyncData) 700 { 701 VBoxGuestHGCMCallInfo *pCallInfo64; 702 HGCMFunctionParameter *pParm64; 703 HGCMFunctionParameter32 *pParm32; 704 uint32_t cParms; 705 uint32_t iParm; 706 int rc; 707 708 /* 709 * Input validation. 710 */ 711 AssertMsgReturn(!pCallInfo || !pfnAsyncCallback || pCallInfo->cParms > VBOX_HGCM_MAX_PARMS || !(fFlags & ~VBGLR0_HGCMCALL_F_MODE_MASK), 712 ("pCallInfo=%p pAsyncCallback=%p fFlags=%#x\n", pCallInfo, pfnAsyncCallback, fFlags), 713 VERR_INVALID_PARAMETER); 714 AssertReturn( cbCallInfo >= sizeof(VBoxGuestHGCMCallInfo) 715 || cbCallInfo >= pCallInfo->cParms * sizeof(HGCMFunctionParameter32), 716 VERR_INVALID_PARAMETER); 717 AssertReturn((fFlags & VBGLR0_HGCMCALL_F_MODE_MASK) == VBGLR0_HGCMCALL_F_KERNEL, VERR_INVALID_PARAMETER); 718 719 cParms = pCallInfo->cParms; 720 Log(("VbglR0HGCMInternalCall32: cParms=%d, u32Function=%d, fFlags=%#x\n", cParms, pCallInfo->u32Function, fFlags)); 721 722 /* 723 * The simple approach, allocate a temporary request and convert the parameters. 724 */ 725 pCallInfo64 = (VBoxGuestHGCMCallInfo *)RTMemTmpAllocZ(sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter)); 726 if (!pCallInfo64) 727 return VERR_NO_TMP_MEMORY; 728 729 *pCallInfo64 = *pCallInfo; 730 pParm32 = VBOXGUEST_HGCM_CALL_PARMS32(pCallInfo); 731 pParm64 = VBOXGUEST_HGCM_CALL_PARMS(pCallInfo64); 732 for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++) 733 { 734 switch (pParm32->type) 735 { 736 case VMMDevHGCMParmType_32bit: 737 pParm64->type = VMMDevHGCMParmType_32bit; 738 pParm64->u.value32 = pParm32->u.value32; 739 break; 740 741 case VMMDevHGCMParmType_64bit: 742 pParm64->type = VMMDevHGCMParmType_64bit; 743 pParm64->u.value64 = pParm32->u.value64; 744 break; 745 746 case VMMDevHGCMParmType_LinAddr_Out: 747 case VMMDevHGCMParmType_LinAddr: 748 case VMMDevHGCMParmType_LinAddr_In: 749 pParm64->type = pParm32->type; 750 pParm64->u.Pointer.size = pParm32->u.Pointer.size; 751 pParm64->u.Pointer.u.linearAddr = pParm32->u.Pointer.u.linearAddr; 752 break; 753 754 default: 755 rc = VERR_INVALID_PARAMETER; 756 break; 757 } 758 if (RT_FAILURE(rc)) 759 break; 760 } 761 if (RT_SUCCESS(rc)) 762 { 763 rc = VbglR0HGCMInternalCall(pCallInfo64, sizeof(*pCallInfo64) + cParms * sizeof(HGCMFunctionParameter), fFlags, 764 pfnAsyncCallback, pvAsyncData, u32AsyncData); 765 766 /* 767 * Copy back. 768 */ 769 for (iParm = 0; iParm < cParms; iParm++, pParm32++, pParm64++) 770 { 771 switch (pParm32->type) 772 { 773 case VMMDevHGCMParmType_32bit: 774 pParm32->u.value32 = pParm32->u.value32; 775 break; 776 777 case VMMDevHGCMParmType_64bit: 778 pParm32->u.value64 = pParm64->u.value64; 779 break; 780 781 case VMMDevHGCMParmType_LinAddr_Out: 782 case VMMDevHGCMParmType_LinAddr: 783 case VMMDevHGCMParmType_LinAddr_In: 784 pParm32->u.Pointer.size = pParm64->u.Pointer.size; 785 break; 786 787 default: 788 rc = VERR_INTERNAL_ERROR_3; 789 break; 790 } 791 } 792 *pCallInfo = *pCallInfo64; 793 } 794 795 RTMemTmpFree(pCallInfo64); 796 return rc; 797 } 798 # endif /* ARCH_BITS == 64 */ 799 800 # else /* old code: */ 122 801 123 802 /** @todo merge with the one below (use a header file). Too lazy now. */ … … 319 998 return rc; 320 999 } 321 # if ARCH_BITS == 64 1000 1001 # if ARCH_BITS == 64 322 1002 /** @todo merge with the one above (use a header file). Too lazy now. */ 323 1003 DECLR0VBGL(int) VbglR0HGCMInternalCall32 (VBoxGuestHGCMCallInfo *pCallInfo, uint32_t cbCallInfo, uint32_t fFlags, … … 517 1197 return rc; 518 1198 } 519 # endif /* ARCH_BITS == 64 */ 1199 # endif /* ARCH_BITS == 64 */ 1200 1201 # endif /* old code */ 520 1202 521 1203 #endif /* VBGL_VBOXGUEST */
Note:
See TracChangeset
for help on using the changeset viewer.