/* Verify that the given offBuffer points to a valid buffer, which is within the area. */ static const HGSMIBUFFERHEADER *hgsmiVerifyBuffer (const HGSMIAREA *pArea, HGSMIOFFSET offBuffer) { AssertPtr(pArea); LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n", offBuffer, pArea->pu8Base, pArea->cbArea, pArea->offBase, pArea->offLast)); if ( offBuffer < pArea->offBase || offBuffer > pArea->offLast) { LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n", offBuffer, pArea->offBase, pArea->offLast)); HGSMI_STRICT_ASSERT_FAILED(); return NULL; } const HGSMIBUFFERHEADER *pHeader = HGSMIOffsetToPointer (pArea, offBuffer); /* Quick check of the data size, it should be less than the maximum * data size for the buffer at this offset. */ LogFlowFunc(("datasize check: pHeader->u32DataSize = 0x%x pArea->offLast - offBuffer = 0x%x\n", pHeader->u32DataSize, pArea->offLast - offBuffer)); if (pHeader->u32DataSize <= pArea->offLast - offBuffer) { HGSMIBUFFERTAIL *pTail = HGSMIBufferTail (pHeader); /* At least both pHeader and pTail structures are in the area. Check the checksum. */ uint32_t u32Checksum = HGSMIChecksum (offBuffer, pHeader, pTail); LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n", u32Checksum, pTail->u32Checksum)); if (u32Checksum == pTail->u32Checksum) { LogFlowFunc(("returning %p\n", pHeader)); return pHeader; } else { LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n", u32Checksum, pTail->u32Checksum)); HGSMI_STRICT_ASSERT_FAILED(); } } else { LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n", pHeader->u32DataSize, pArea->offLast - offBuffer)); HGSMI_STRICT_ASSERT_FAILED(); } LogFlowFunc(("returning NULL\n")); return NULL; }
/** Register a new HGSMI channel by index. * * @returns VBox status. * @param pChannelInfo The channel pool managed by the caller. * @param u8Channel Index of the channel. * @param pszName Name of the channel (optional, allocated by the caller). * @param pfnChannelHandler The channel callback. * @param pvChannelHandler The callback pointer. */ int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo, uint8_t u8Channel, const char *pszName, PFNHGSMICHANNELHANDLER pfnChannelHandler, void *pvChannelHandler) { /* Check whether the channel is already registered. */ HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, u8Channel); if (pChannel) { HGSMI_STRICT_ASSERT_FAILED(); return VERR_ALREADY_EXISTS; } /* Channel is not yet registered. */ pChannel = &pChannelInfo->Channels[u8Channel]; pChannel->u8Flags = HGSMI_CH_F_REGISTERED; pChannel->u8Channel = u8Channel; pChannel->handler.pfnHandler = pfnChannelHandler; pChannel->handler.pvHandler = pvChannelHandler; pChannel->pszName = pszName; return VINF_SUCCESS; }
/** Process a guest buffer. * * @returns VBox status. * @param pArea Area which supposed to contain the buffer. * @param pChannelInfo The channel pool. * @param offBuffer The buffer location in the area. */ int HGSMIBufferProcess(const HGSMIAREA *pArea, HGSMICHANNELINFO *pChannelInfo, HGSMIOFFSET offBuffer) { LogFlowFunc(("pArea %p, offBuffer 0x%x\n", pArea, offBuffer)); AssertPtrReturn(pArea, VERR_INVALID_PARAMETER); AssertPtrReturn(pChannelInfo, VERR_INVALID_PARAMETER); /* Guest has prepared a command description at 'offBuffer'. */ HGSMIBUFFERCONTEXT bufferContext; int rc = hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext); if (RT_SUCCESS(rc)) { /* Pass the command to the appropriate handler registered with this instance. * Start with the handler list head, which is the preallocated HGSMI setup channel. */ const HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, bufferContext.pHeader->u8Channel); if (pChannel) { const HGSMICHANNELHANDLER *pHandler = &pChannel->handler; if (pHandler->pfnHandler) { pHandler->pfnHandler(pHandler->pvHandler, bufferContext.pHeader->u16ChannelInfo, bufferContext.pvData, bufferContext.cbData); } HGSMI_STRICT_ASSERT(RT_SUCCESS(hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext))); } else { rc = VERR_INVALID_FUNCTION; HGSMI_STRICT_ASSERT_FAILED(); } } return rc; }
/** Verify that the given offBuffer points to a valid buffer, which is within the area. * * @returns VBox status and the buffer information in pBufferContext. * @param pArea Area which supposed to contain the buffer. * @param offBuffer The buffer location in the area. * @param pBufferContext Where to write information about the buffer. */ static int hgsmiVerifyBuffer(const HGSMIAREA *pArea, HGSMIOFFSET offBuffer, HGSMIBUFFERCONTEXT *pBufferContext) { LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n", offBuffer, pArea->pu8Base, pArea->cbArea, pArea->offBase, pArea->offLast)); int rc = VINF_SUCCESS; if ( offBuffer < pArea->offBase || offBuffer > pArea->offLast) { LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n", offBuffer, pArea->offBase, pArea->offLast)); rc = VERR_INVALID_PARAMETER; HGSMI_STRICT_ASSERT_FAILED(); } else { void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer); HGSMIBUFFERHEADER header = *HGSMIBufferHeaderFromPtr(pvBuffer); /* Quick check of the data size, it should be less than the maximum * data size for the buffer at this offset. */ LogFlowFunc(("datasize check: header.u32DataSize = 0x%x pArea->offLast - offBuffer = 0x%x\n", header.u32DataSize, pArea->offLast - offBuffer)); if (header.u32DataSize <= pArea->offLast - offBuffer) { HGSMIBUFFERTAIL tail = *HGSMIBufferTailFromPtr(pvBuffer, header.u32DataSize); /* At least both header and tail structures are in the area. Check the checksum. */ uint32_t u32Checksum = HGSMIChecksum(offBuffer, &header, &tail); LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n", u32Checksum, tail.u32Checksum)); if (u32Checksum == tail.u32Checksum) { /* Success. */ pBufferContext->pHeader = HGSMIBufferHeaderFromPtr(pvBuffer); pBufferContext->pvData = HGSMIBufferDataFromPtr(pvBuffer); pBufferContext->cbData = header.u32DataSize; } else { LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n", u32Checksum, tail.u32Checksum)); rc = VERR_INVALID_STATE; HGSMI_STRICT_ASSERT_FAILED(); } } else { LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n", header.u32DataSize, pArea->offLast - offBuffer)); rc = VERR_TOO_MUCH_DATA; HGSMI_STRICT_ASSERT_FAILED(); } } return rc; }