Ejemplo n.º 1
0
/* 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;
}