Changeset 55342 in vbox for trunk/src/VBox/GuestHost/HGSMI
- Timestamp:
- Apr 20, 2015 2:19:53 PM (10 years ago)
- svn:sync-xref-src-repo-rev:
- 99671
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/GuestHost/HGSMI/HGSMICommon.cpp
r50518 r55342 5 5 6 6 /* 7 * Copyright (C) 2006-201 4Oracle Corporation7 * Copyright (C) 2006-2015 Oracle Corporation 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 413 413 } 414 414 415 typedef struct HGSMIBUFFERCONTEXT 416 { 417 const HGSMIBUFFERHEADER *pHeader; /* The original buffer header. */ 418 void *pvData; /* Payload data in the buffer./ */ 419 uint32_t cbData; /* Size of data */ 420 } HGSMIBUFFERCONTEXT; 421 415 422 /* Verify that the given offBuffer points to a valid buffer, which is within the area. 416 423 */ 417 static const HGSMIBUFFERHEADER *hgsmiVerifyBuffer (const HGSMIAREA *pArea, 418 HGSMIOFFSET offBuffer) 419 { 420 AssertPtr(pArea); 421 422 LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n", offBuffer, pArea->pu8Base, pArea->cbArea, pArea->offBase, pArea->offLast)); 424 static int hgsmiVerifyBuffer(const HGSMIAREA *pArea, 425 HGSMIOFFSET offBuffer, 426 HGSMIBUFFERCONTEXT *pBufferContext) 427 { 428 LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n", 429 offBuffer, pArea->pu8Base, pArea->cbArea, pArea->offBase, pArea->offLast)); 430 431 int rc = VINF_SUCCESS; 423 432 424 433 if ( offBuffer < pArea->offBase 425 434 || offBuffer > pArea->offLast) 426 435 { 427 LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n", offBuffer, pArea->offBase, pArea->offLast)); 436 LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n", 437 offBuffer, pArea->offBase, pArea->offLast)); 438 rc = VERR_INVALID_PARAMETER; 428 439 HGSMI_STRICT_ASSERT_FAILED(); 429 return NULL; 430 } 431 432 const HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIOffsetToPointer (pArea, offBuffer); 433 434 /* Quick check of the data size, it should be less than the maximum 435 * data size for the buffer at this offset. 436 */ 437 LogFlowFunc(("datasize check: pHeader->u32DataSize = 0x%x pArea->offLast - offBuffer = 0x%x\n", pHeader->u32DataSize, pArea->offLast - offBuffer)); 438 if (pHeader->u32DataSize <= pArea->offLast - offBuffer) 439 { 440 HGSMIBUFFERTAIL *pTail = HGSMIBufferTail (pHeader); 441 442 /* At least both pHeader and pTail structures are in the area. Check the checksum. */ 443 uint32_t u32Checksum = HGSMIChecksum (offBuffer, pHeader, pTail); 444 445 LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n", u32Checksum, pTail->u32Checksum)); 446 if (u32Checksum == pTail->u32Checksum) 447 { 448 LogFlowFunc(("returning %p\n", pHeader)); 449 return pHeader; 440 } 441 else 442 { 443 void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer); 444 HGSMIBUFFERHEADER header = *HGSMIBufferHeaderFromPtr(pvBuffer); 445 446 /* Quick check of the data size, it should be less than the maximum 447 * data size for the buffer at this offset. 448 */ 449 LogFlowFunc(("datasize check: header.u32DataSize = 0x%x pArea->offLast - offBuffer = 0x%x\n", 450 header.u32DataSize, pArea->offLast - offBuffer)); 451 452 if (header.u32DataSize <= pArea->offLast - offBuffer) 453 { 454 HGSMIBUFFERTAIL tail = *HGSMIBufferTailFromPtr(pvBuffer, header.u32DataSize); 455 456 /* At least both header and tail structures are in the area. Check the checksum. */ 457 uint32_t u32Checksum = HGSMIChecksum(offBuffer, &header, &tail); 458 LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n", 459 u32Checksum, pTail->u32Checksum)); 460 if (u32Checksum == tail.u32Checksum) 461 { 462 /* Success. */ 463 pBufferContext->pHeader = HGSMIBufferHeaderFromPtr(pvBuffer); 464 pBufferContext->pvData = HGSMIBufferDataFromPtr(pvBuffer); 465 pBufferContext->cbData = header.u32DataSize; 466 } 467 else 468 { 469 LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n", 470 u32Checksum, pTail->u32Checksum)); 471 rc = VERR_INVALID_STATE; 472 HGSMI_STRICT_ASSERT_FAILED(); 473 } 450 474 } 451 475 else 452 476 { 453 LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n", u32Checksum, pTail->u32Checksum)); 477 LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n", 478 header.u32DataSize, pArea->offLast - offBuffer)); 479 rc = VERR_TOO_MUCH_DATA; 454 480 HGSMI_STRICT_ASSERT_FAILED(); 455 481 } 456 482 } 457 else 458 { 459 LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n", pHeader->u32DataSize, pArea->offLast - offBuffer)); 460 HGSMI_STRICT_ASSERT_FAILED(); 461 } 462 463 LogFlowFunc(("returning NULL\n")); 464 return NULL; 483 484 return rc; 465 485 } 466 486 467 487 /* A wrapper to safely call the handler. 468 488 */ 469 int HGSMIChannelHandlerCall(const HGSMICHANNELHANDLER *pHandler,470 const HGSMIBUFFERHEADER *pHeader)471 { 472 LogFlowFunc(("pHandler %p , pHeader %p\n", pHandler, pHeader));489 static int hgsmiChannelHandlerCall(const HGSMICHANNELHANDLER *pHandler, 490 const HGSMIBUFFERCONTEXT *pBufferContext) 491 { 492 LogFlowFunc(("pHandler %p\n", pHandler)); 473 493 474 494 int rc; 475 476 Assert(pHandler && pHandler->pfnHandler);477 495 478 496 if ( pHandler 479 497 && pHandler->pfnHandler) 480 498 { 481 void *pvBuffer = HGSMIBufferData (pHeader); 482 HGSMISIZE cbBuffer = pHeader->u32DataSize; 483 484 rc = pHandler->pfnHandler (pHandler->pvHandler, pHeader->u16ChannelInfo, pvBuffer, cbBuffer); 499 rc = pHandler->pfnHandler(pHandler->pvHandler, pBufferContext->pHeader->u16ChannelInfo, 500 pBufferContext->pvData, pBufferContext->cbData); 485 501 } 486 502 else … … 491 507 492 508 LogFlowFunc(("leave rc = %Rrc\n", rc)); 493 494 509 return rc; 495 510 } 496 511 497 /* 498 * Process a guest buffer. 499 * @thread EMT 500 */ 501 static int hgsmiBufferProcess (const HGSMICHANNEL *pChannel, 502 const HGSMIBUFFERHEADER *pHeader) 503 { 504 LogFlowFunc(("pChannel %p, pHeader %p\n", pChannel, pHeader)); 505 506 int rc = HGSMIChannelHandlerCall (&pChannel->handler, 507 pHeader); 508 509 return rc; 510 } 511 512 HGSMICHANNEL *HGSMIChannelFindById (HGSMICHANNELINFO * pChannelInfo, 513 uint8_t u8Channel) 514 { 512 /** Helper to convert HGSMI channel index to the channel structure pointer. 513 * 514 * @returns Pointer to the channel data. 515 * @param pChannelInfo The channel pool. 516 * @param u8Channel The channel index. 517 */ 518 HGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo, 519 uint8_t u8Channel) 520 { 521 AssertCompile(RT_ELEMENTS(pChannelInfo->Channels) >= 0x100); 515 522 HGSMICHANNEL *pChannel = &pChannelInfo->Channels[u8Channel]; 516 523 … … 523 530 } 524 531 525 int HGSMIBufferProcess (HGSMIAREA *pArea, 526 HGSMICHANNELINFO * pChannelInfo, 527 HGSMIOFFSET offBuffer) 532 /** Process a guest buffer. 533 * 534 * @returns VBox status. 535 * @param pArea Area which supposed to contain the buffer. 536 * @param pChannelInfo The channel pool. 537 * @param offBuffer The buffer location in the area. 538 */ 539 int HGSMIBufferProcess(HGSMIAREA *pArea, 540 HGSMICHANNELINFO *pChannelInfo, 541 HGSMIOFFSET offBuffer) 528 542 { 529 543 LogFlowFunc(("pArea %p, offBuffer 0x%x\n", pArea, offBuffer)); 530 544 531 AssertPtr(pArea); 532 AssertPtr(pChannelInfo); 533 534 int rc = VERR_GENERAL_FAILURE; 535 536 // VM_ASSERT_EMT(pIns->pVM); 545 AssertPtrReturn(pArea, VERR_INVALID_PARAMETER); 546 AssertPtrReturn(pChannelInfo, VERR_INVALID_PARAMETER); 537 547 538 548 /* Guest has prepared a command description at 'offBuffer'. */ 539 const HGSMIBUFFERHEADER *pHeader = hgsmiVerifyBuffer (pArea, offBuffer);540 Assert(pHeader);541 if ( pHeader)549 HGSMIBUFFERCONTEXT bufferContext; 550 int rc = hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext); 551 if (RT_SUCCESS(rc)) 542 552 { 543 553 /* Pass the command to the appropriate handler registered with this instance. 544 554 * Start with the handler list head, which is the preallocated HGSMI setup channel. 545 555 */ 546 HGSMICHANNEL *pChannel = HGSMIChannelFindById (pChannelInfo, pHeader->u8Channel); 547 Assert(pChannel); 556 HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, bufferContext.pHeader->u8Channel); 548 557 if (pChannel) 549 558 { 550 hgsmiBufferProcess (pChannel, pHeader); 551 HGSMI_STRICT_ASSERT(hgsmiVerifyBuffer (pArea, offBuffer) != NULL); 552 rc = VINF_SUCCESS; 559 rc = hgsmiChannelHandlerCall(&pChannel->handler, &bufferContext); 560 HGSMI_STRICT_ASSERT(RT_SUCCESS(hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext))); 553 561 } 554 562 else 555 563 { 556 564 rc = VERR_INVALID_FUNCTION; 557 } 558 } 559 else 560 { 561 rc = VERR_INVALID_HANDLE; 562 // LogRel(("HGSMI[%s]: ignored invalid guest buffer 0x%08X!!!\n", pIns->pszName, offBuffer)); 563 } 565 HGSMI_STRICT_ASSERT_FAILED(); 566 } 567 } 568 564 569 return rc; 565 570 } 566 571 567 /* Register a new VBVAchannel by index.572 /** Register a new HGSMI channel by index. 568 573 * 569 */ 570 int HGSMIChannelRegister (HGSMICHANNELINFO * pChannelInfo, 571 uint8_t u8Channel, 572 const char *pszName, 573 PFNHGSMICHANNELHANDLER pfnChannelHandler, 574 void *pvChannelHandler, 575 HGSMICHANNELHANDLER *pOldHandler) 576 { 577 AssertPtrReturn(pOldHandler, VERR_INVALID_PARAMETER); 578 574 * @returns VBox status. 575 * @param pChannelInfo The channel pool managed by the caller. 576 * @param u8Channel Index of the channel. 577 * @param pszName Name of the channel (optional, allocated by the caller). 578 * @param pfnChannelHandler The channel callback. 579 * @param pvChannelHandler The callback pointer. 580 */ 581 int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo, 582 uint8_t u8Channel, 583 const char *pszName, 584 PFNHGSMICHANNELHANDLER pfnChannelHandler, 585 void *pvChannelHandler) 586 { 579 587 /* Check whether the channel is already registered. */ 580 HGSMICHANNEL *pChannel = HGSMIChannelFindById (pChannelInfo, u8Channel); 581 582 if (!pChannel) 583 { 584 /* Channel is not yet registered. */ 585 pChannel = &pChannelInfo->Channels[u8Channel]; 586 587 pChannel->u8Flags = HGSMI_CH_F_REGISTERED; 588 pChannel->u8Channel = u8Channel; 589 590 pChannel->handler.pfnHandler = NULL; 591 pChannel->handler.pvHandler = NULL; 592 593 pChannel->pszName = pszName; 594 } 595 596 *pOldHandler = pChannel->handler; 588 HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, u8Channel); 589 if (pChannel) 590 { 591 HGSMI_STRICT_ASSERT_FAILED(); 592 return VERR_ALREADY_EXISTS; 593 } 594 595 /* Channel is not yet registered. */ 596 pChannel = &pChannelInfo->Channels[u8Channel]; 597 598 pChannel->u8Flags = HGSMI_CH_F_REGISTERED; 599 pChannel->u8Channel = u8Channel; 597 600 598 601 pChannel->handler.pfnHandler = pfnChannelHandler; 599 602 pChannel->handler.pvHandler = pvChannelHandler; 600 603 604 pChannel->pszName = pszName; 605 601 606 return VINF_SUCCESS; 602 607 } 603
Note:
See TracChangeset
for help on using the changeset viewer.