87902654924b5893d165c3f31f1d8a50f87205b4vboxsync/* $Id$ */
9bee881471745317e907eefbacf9ef344c74c899vboxsync/** @file
87902654924b5893d165c3f31f1d8a50f87205b4vboxsync * VBox Host Guest Shared Memory Interface (HGSMI) - Functions common to both host and guest.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync/*
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * Copyright (C) 2006-2015 Oracle Corporation
9bee881471745317e907eefbacf9ef344c74c899vboxsync *
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * available from http://www.virtualbox.org. This file is free software;
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * you can redistribute it and/or modify it under the terms of the GNU
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * General Public License (GPL) as published by the Free Software
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
cf5f6bf2704d4fff443139e10bccc6a0a7fa4b85vboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
9bee881471745317e907eefbacf9ef344c74c899vboxsync
87902654924b5893d165c3f31f1d8a50f87205b4vboxsync#define LOG_DISABLED /* Maybe we can enabled it all the time now? */
87902654924b5893d165c3f31f1d8a50f87205b4vboxsync#define LOG_GROUP LOG_GROUP_HGSMI
9bee881471745317e907eefbacf9ef344c74c899vboxsync#include <iprt/heap.h>
9bee881471745317e907eefbacf9ef344c74c899vboxsync#include <iprt/string.h>
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync#include <VBox/HGSMI/HGSMI.h>
87902654924b5893d165c3f31f1d8a50f87205b4vboxsync#include <VBox/log.h>
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync/* Channel flags. */
9bee881471745317e907eefbacf9ef344c74c899vboxsync#define HGSMI_CH_F_REGISTERED 0x01
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync/* Assertions for situations which could happen and normally must be processed properly
9bee881471745317e907eefbacf9ef344c74c899vboxsync * but must be investigated during development: guest misbehaving, etc.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
9bee881471745317e907eefbacf9ef344c74c899vboxsync#ifdef HGSMI_STRICT
9bee881471745317e907eefbacf9ef344c74c899vboxsync#define HGSMI_STRICT_ASSERT_FAILED() AssertFailed()
9bee881471745317e907eefbacf9ef344c74c899vboxsync#define HGSMI_STRICT_ASSERT(expr) Assert(expr)
9bee881471745317e907eefbacf9ef344c74c899vboxsync#else
9bee881471745317e907eefbacf9ef344c74c899vboxsync#define HGSMI_STRICT_ASSERT_FAILED() do {} while (0)
9bee881471745317e907eefbacf9ef344c74c899vboxsync#define HGSMI_STRICT_ASSERT(expr) do {} while (0)
9bee881471745317e907eefbacf9ef344c74c899vboxsync#endif /* !HGSMI_STRICT */
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync/* One-at-a-Time Hash from
9bee881471745317e907eefbacf9ef344c74c899vboxsync * http://www.burtleburtle.net/bob/hash/doobs.html
9bee881471745317e907eefbacf9ef344c74c899vboxsync *
9bee881471745317e907eefbacf9ef344c74c899vboxsync * ub4 one_at_a_time(char *key, ub4 len)
9bee881471745317e907eefbacf9ef344c74c899vboxsync * {
9bee881471745317e907eefbacf9ef344c74c899vboxsync * ub4 hash, i;
9bee881471745317e907eefbacf9ef344c74c899vboxsync * for (hash=0, i=0; i<len; ++i)
9bee881471745317e907eefbacf9ef344c74c899vboxsync * {
9bee881471745317e907eefbacf9ef344c74c899vboxsync * hash += key[i];
9bee881471745317e907eefbacf9ef344c74c899vboxsync * hash += (hash << 10);
9bee881471745317e907eefbacf9ef344c74c899vboxsync * hash ^= (hash >> 6);
9bee881471745317e907eefbacf9ef344c74c899vboxsync * }
9bee881471745317e907eefbacf9ef344c74c899vboxsync * hash += (hash << 3);
9bee881471745317e907eefbacf9ef344c74c899vboxsync * hash ^= (hash >> 11);
9bee881471745317e907eefbacf9ef344c74c899vboxsync * hash += (hash << 15);
9bee881471745317e907eefbacf9ef344c74c899vboxsync * return hash;
9bee881471745317e907eefbacf9ef344c74c899vboxsync * }
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncstatic uint32_t hgsmiHashBegin (void)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync return 0;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncstatic uint32_t hgsmiHashProcess (uint32_t hash,
9bee881471745317e907eefbacf9ef344c74c899vboxsync const void *pvData,
9bee881471745317e907eefbacf9ef344c74c899vboxsync size_t cbData)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync const uint8_t *pu8Data = (const uint8_t *)pvData;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync while (cbData--)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync hash += *pu8Data++;
9bee881471745317e907eefbacf9ef344c74c899vboxsync hash += (hash << 10);
9bee881471745317e907eefbacf9ef344c74c899vboxsync hash ^= (hash >> 6);
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return hash;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncstatic uint32_t hgsmiHashEnd (uint32_t hash)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync hash += (hash << 3);
9bee881471745317e907eefbacf9ef344c74c899vboxsync hash ^= (hash >> 11);
9bee881471745317e907eefbacf9ef344c74c899vboxsync hash += (hash << 15);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return hash;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncuint32_t HGSMIChecksum (HGSMIOFFSET offBuffer,
9bee881471745317e907eefbacf9ef344c74c899vboxsync const HGSMIBUFFERHEADER *pHeader,
9bee881471745317e907eefbacf9ef344c74c899vboxsync const HGSMIBUFFERTAIL *pTail)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint32_t u32Checksum = hgsmiHashBegin ();
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync u32Checksum = hgsmiHashProcess (u32Checksum, &offBuffer, sizeof (offBuffer));
9bee881471745317e907eefbacf9ef344c74c899vboxsync u32Checksum = hgsmiHashProcess (u32Checksum, pHeader, sizeof (HGSMIBUFFERHEADER));
9bee881471745317e907eefbacf9ef344c74c899vboxsync u32Checksum = hgsmiHashProcess (u32Checksum, pTail, RT_OFFSETOF(HGSMIBUFFERTAIL, u32Checksum));
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return hgsmiHashEnd (u32Checksum);
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncstatic HGSMIOFFSET hgsmiBufferInitializeSingle (const HGSMIAREA *pArea,
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIBUFFERHEADER *pHeader,
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint32_t u32DataSize,
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint8_t u8Channel,
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint16_t u16ChannelInfo)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync if ( !pArea
9bee881471745317e907eefbacf9ef344c74c899vboxsync || !pHeader)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync return HGSMIOFFSET_VOID;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync /* Buffer must be within the area:
9bee881471745317e907eefbacf9ef344c74c899vboxsync * * header data size do not exceed the maximum data size;
9bee881471745317e907eefbacf9ef344c74c899vboxsync * * buffer address is greater than the area base address;
9bee881471745317e907eefbacf9ef344c74c899vboxsync * * buffer address is lower than the maximum allowed for the given data size.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMISIZE cbMaximumDataSize = pArea->offLast - pArea->offBase;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync if ( u32DataSize > cbMaximumDataSize
9bee881471745317e907eefbacf9ef344c74c899vboxsync || (uint8_t *)pHeader < pArea->pu8Base
9bee881471745317e907eefbacf9ef344c74c899vboxsync || (uint8_t *)pHeader > pArea->pu8Base + cbMaximumDataSize - u32DataSize)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync return HGSMIOFFSET_VOID;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIOFFSET offBuffer = HGSMIPointerToOffset (pArea, pHeader);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync pHeader->u8Flags = HGSMI_BUFFER_HEADER_F_SEQ_SINGLE;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pHeader->u32DataSize = u32DataSize;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pHeader->u8Channel = u8Channel;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pHeader->u16ChannelInfo = u16ChannelInfo;
9bee881471745317e907eefbacf9ef344c74c899vboxsync memset (pHeader->u.au8Union, 0, sizeof (pHeader->u.au8Union));
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIBUFFERTAIL *pTail = HGSMIBufferTail (pHeader);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync pTail->u32Reserved = 0;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pTail->u32Checksum = HGSMIChecksum (offBuffer, pHeader, pTail);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return offBuffer;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncint HGSMIAreaInitialize (HGSMIAREA *pArea, void *pvBase, HGSMISIZE cbArea, HGSMIOFFSET offBase)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint8_t *pu8Base = (uint8_t *)pvBase;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync if ( !pArea /* Check that the area: */
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync || cbArea < HGSMIBufferMinimumSize () /* Large enough. */
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync || pu8Base + cbArea < pu8Base /* No address space wrap. */
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync || offBase > UINT32_C(0xFFFFFFFF) - cbArea /* Area within the 32 bit space: offBase + cbMem <= 0xFFFFFFFF */
9bee881471745317e907eefbacf9ef344c74c899vboxsync )
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync return VERR_INVALID_PARAMETER;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync pArea->pu8Base = pu8Base;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pArea->offBase = offBase;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pArea->offLast = cbArea - HGSMIBufferMinimumSize () + offBase;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pArea->cbArea = cbArea;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return VINF_SUCCESS;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncvoid HGSMIAreaClear (HGSMIAREA *pArea)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (pArea)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync memset (pArea, 0, sizeof (HGSMIAREA));
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync/* Initialize the memory buffer including its checksum.
9bee881471745317e907eefbacf9ef344c74c899vboxsync * No changes alloed to the header and the tail after that.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
9bee881471745317e907eefbacf9ef344c74c899vboxsyncHGSMIOFFSET HGSMIBufferInitializeSingle (const HGSMIAREA *pArea,
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIBUFFERHEADER *pHeader,
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMISIZE cbBuffer,
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint8_t u8Channel,
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint16_t u16ChannelInfo)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (cbBuffer < HGSMIBufferMinimumSize ())
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync return HGSMIOFFSET_VOID;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return hgsmiBufferInitializeSingle (pArea, pHeader, cbBuffer - HGSMIBufferMinimumSize (), u8Channel, u16ChannelInfo);
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
32b1164f35483be483177be7b5235002a4a5afbevboxsyncvoid HGSMIHeapSetupUninitialized(HGSMIHEAP *pHeap)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
32b1164f35483be483177be7b5235002a4a5afbevboxsync RT_ZERO(*pHeap);
32b1164f35483be483177be7b5235002a4a5afbevboxsync pHeap->u32HeapType = HGSMI_HEAP_TYPE_NULL;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncint HGSMIHeapRelocate (HGSMIHEAP *pHeap,
32b1164f35483be483177be7b5235002a4a5afbevboxsync uint32_t u32HeapType,
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync void *pvBase,
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync uint32_t offHeapHandle,
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync uintptr_t offDelta,
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync HGSMISIZE cbArea,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync HGSMIOFFSET offBase)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync if ( !pHeap
9bee881471745317e907eefbacf9ef344c74c899vboxsync || !pvBase)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync return VERR_INVALID_PARAMETER;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync int rc = HGSMIAreaInitialize (&pHeap->area, pvBase, cbArea, offBase);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (RT_SUCCESS (rc))
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync if (u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync pHeap->u.hOff = (RTHEAPOFFSET)((uint8_t *)pvBase + offHeapHandle);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else if (u32HeapType == HGSMI_HEAP_TYPE_POINTER)
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync {
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync pHeap->u.hPtr = (RTHEAPSIMPLE)((uint8_t *)pvBase + offHeapHandle);
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync rc = RTHeapSimpleRelocate (pHeap->u.hPtr, offDelta); AssertRC(rc);
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync /* HGSMI_HEAP_TYPE_MA does not need the relocation. */
32b1164f35483be483177be7b5235002a4a5afbevboxsync rc = VERR_NOT_SUPPORTED;
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync
32b1164f35483be483177be7b5235002a4a5afbevboxsync if (RT_SUCCESS(rc))
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync pHeap->cRefs = 0;
32b1164f35483be483177be7b5235002a4a5afbevboxsync pHeap->u32HeapType = u32HeapType;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync else
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIAreaClear (&pHeap->area);
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return rc;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsyncint HGSMIHeapRestoreMA(HGSMIHEAP *pHeap,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync void *pvBase,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync HGSMISIZE cbArea,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync HGSMIOFFSET offBase,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync uint32_t cBlocks,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync HGSMIOFFSET *paDescriptors,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync HGSMISIZE cbMaxBlock,
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync HGSMIENV *pEnv)
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync{
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync int rc = HGSMIAreaInitialize(&pHeap->area, pvBase, cbArea, offBase);
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync if (RT_SUCCESS (rc))
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync {
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync rc = HGSMIMAInit(&pHeap->u.ma, &pHeap->area, paDescriptors, cBlocks, cbMaxBlock, pEnv);
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync if (RT_SUCCESS(rc))
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync {
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync pHeap->cRefs = 0;
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync pHeap->u32HeapType = HGSMI_HEAP_TYPE_MA;
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync }
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync else
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync {
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync HGSMIAreaClear(&pHeap->area);
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync }
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync }
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync return rc;
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync}
8b2529a5ddb7e6170c5ab2399a8fc4ef102f8e3dvboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncint HGSMIHeapSetup (HGSMIHEAP *pHeap,
32b1164f35483be483177be7b5235002a4a5afbevboxsync uint32_t u32HeapType,
9bee881471745317e907eefbacf9ef344c74c899vboxsync void *pvBase,
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMISIZE cbArea,
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync HGSMIOFFSET offBase,
32b1164f35483be483177be7b5235002a4a5afbevboxsync const HGSMIENV *pEnv)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync if ( !pHeap
9bee881471745317e907eefbacf9ef344c74c899vboxsync || !pvBase)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync return VERR_INVALID_PARAMETER;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync int rc = HGSMIAreaInitialize (&pHeap->area, pvBase, cbArea, offBase);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (RT_SUCCESS (rc))
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync if (u32HeapType == HGSMI_HEAP_TYPE_MA)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync rc = HGSMIMAInit(&pHeap->u.ma, &pHeap->area, NULL, 0, 0, pEnv);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else if (u32HeapType == HGSMI_HEAP_TYPE_POINTER)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync rc = RTHeapSimpleInit (&pHeap->u.hPtr, pvBase, cbArea);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else if (u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
8f1c8e96fab0c5f5a8dcabeb4e20a56a8b4cea18vboxsync rc = RTHeapOffsetInit (&pHeap->u.hOff, pvBase, cbArea);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync rc = VERR_NOT_SUPPORTED;
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (RT_SUCCESS (rc))
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync pHeap->cRefs = 0;
32b1164f35483be483177be7b5235002a4a5afbevboxsync pHeap->u32HeapType = u32HeapType;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync else
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIAreaClear (&pHeap->area);
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return rc;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncvoid HGSMIHeapDestroy (HGSMIHEAP *pHeap)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (pHeap)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_MA)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync HGSMIMAUninit(&pHeap->u.ma);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
e6b70a63c722fdf132fdf96257aa00a1e0e37e3dvboxsync Assert(!pHeap->cRefs);
32b1164f35483be483177be7b5235002a4a5afbevboxsync HGSMIHeapSetupUninitialized(pHeap);
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncvoid *HGSMIHeapAlloc (HGSMIHEAP *pHeap,
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMISIZE cbData,
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint8_t u8Channel,
9bee881471745317e907eefbacf9ef344c74c899vboxsync uint16_t u16ChannelInfo)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
32b1164f35483be483177be7b5235002a4a5afbevboxsync HGSMISIZE cbAlloc = HGSMIBufferRequiredSize (cbData);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIHeapBufferAlloc (pHeap, cbAlloc);
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (!pHeader)
9bee881471745317e907eefbacf9ef344c74c899vboxsync return NULL;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync hgsmiBufferInitializeSingle (&pHeap->area, pHeader, cbData, u8Channel, u16ChannelInfo);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return HGSMIBufferData (pHeader);
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncHGSMIOFFSET HGSMIHeapBufferOffset (HGSMIHEAP *pHeap,
9bee881471745317e907eefbacf9ef344c74c899vboxsync void *pvData)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData (pvData);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIOFFSET offBuffer = HGSMIPointerToOffset (&pHeap->area, pHeader);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return offBuffer;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsyncvoid HGSMIHeapFree (HGSMIHEAP *pHeap,
9bee881471745317e907eefbacf9ef344c74c899vboxsync void *pvData)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync if ( pvData
32b1164f35483be483177be7b5235002a4a5afbevboxsync && pHeap->u32HeapType != HGSMI_HEAP_TYPE_NULL)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData (pvData);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync HGSMIHeapBufferFree (pHeap, pHeader);
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsyncvoid* HGSMIHeapBufferAlloc (HGSMIHEAP *pHeap, HGSMISIZE cbBuffer)
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync{
32b1164f35483be483177be7b5235002a4a5afbevboxsync void* pvBuf = NULL;
32b1164f35483be483177be7b5235002a4a5afbevboxsync if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_MA)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync pvBuf = HGSMIMAAlloc(&pHeap->u.ma, cbBuffer);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_POINTER)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync pvBuf = RTHeapSimpleAlloc (pHeap->u.hPtr, cbBuffer, 0);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync pvBuf = RTHeapOffsetAlloc (pHeap->u.hOff, cbBuffer, 0);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync
32b1164f35483be483177be7b5235002a4a5afbevboxsync if (pvBuf)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync ++pHeap->cRefs;
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync return pvBuf;
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync}
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsyncvoid HGSMIHeapBufferFree(HGSMIHEAP *pHeap,
32b1164f35483be483177be7b5235002a4a5afbevboxsync void *pvBuf)
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync{
32b1164f35483be483177be7b5235002a4a5afbevboxsync if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_MA)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
32b1164f35483be483177be7b5235002a4a5afbevboxsync HGSMIMAFree(&pHeap->u.ma, pvBuf);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_POINTER)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync RTHeapSimpleFree (pHeap->u.hPtr, pvBuf);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
32b1164f35483be483177be7b5235002a4a5afbevboxsync else if (pHeap->u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
32b1164f35483be483177be7b5235002a4a5afbevboxsync {
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync RTHeapOffsetFree (pHeap->u.hOff, pvBuf);
32b1164f35483be483177be7b5235002a4a5afbevboxsync }
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync --pHeap->cRefs;
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync}
d0a71f63bd810b54e0359223fe53b07730154dc5vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsynctypedef struct HGSMIBUFFERCONTEXT
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync{
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync const HGSMIBUFFERHEADER *pHeader; /* The original buffer header. */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync void *pvData; /* Payload data in the buffer./ */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync uint32_t cbData; /* Size of data */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync} HGSMIBUFFERCONTEXT;
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync/* Verify that the given offBuffer points to a valid buffer, which is within the area.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsyncstatic int hgsmiVerifyBuffer(const HGSMIAREA *pArea,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMIOFFSET offBuffer,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMIBUFFERCONTEXT *pBufferContext)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n",
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync offBuffer, pArea->pu8Base, pArea->cbArea, pArea->offBase, pArea->offLast));
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync int rc = VINF_SUCCESS;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync if ( offBuffer < pArea->offBase
9bee881471745317e907eefbacf9ef344c74c899vboxsync || offBuffer > pArea->offLast)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n",
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync offBuffer, pArea->offBase, pArea->offLast));
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync rc = VERR_INVALID_PARAMETER;
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMI_STRICT_ASSERT_FAILED();
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync else
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMIBUFFERHEADER header = *HGSMIBufferHeaderFromPtr(pvBuffer);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync /* Quick check of the data size, it should be less than the maximum
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * data size for the buffer at this offset.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync LogFlowFunc(("datasize check: header.u32DataSize = 0x%x pArea->offLast - offBuffer = 0x%x\n",
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync header.u32DataSize, pArea->offLast - offBuffer));
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync if (header.u32DataSize <= pArea->offLast - offBuffer)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMIBUFFERTAIL tail = *HGSMIBufferTailFromPtr(pvBuffer, header.u32DataSize);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync /* At least both header and tail structures are in the area. Check the checksum. */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync uint32_t u32Checksum = HGSMIChecksum(offBuffer, &header, &tail);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n",
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync u32Checksum, pTail->u32Checksum));
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync if (u32Checksum == tail.u32Checksum)
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync /* Success. */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pBufferContext->pHeader = HGSMIBufferHeaderFromPtr(pvBuffer);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pBufferContext->pvData = HGSMIBufferDataFromPtr(pvBuffer);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pBufferContext->cbData = header.u32DataSize;
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync }
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync else
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n",
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync u32Checksum, pTail->u32Checksum));
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync rc = VERR_INVALID_STATE;
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMI_STRICT_ASSERT_FAILED();
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync else
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n",
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync header.u32DataSize, pArea->offLast - offBuffer));
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync rc = VERR_TOO_MUCH_DATA;
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMI_STRICT_ASSERT_FAILED();
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync return rc;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync/* A wrapper to safely call the handler.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsyncstatic int hgsmiChannelHandlerCall(const HGSMICHANNELHANDLER *pHandler,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync const HGSMIBUFFERCONTEXT *pBufferContext)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync LogFlowFunc(("pHandler %p\n", pHandler));
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync int rc;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync if ( pHandler
9bee881471745317e907eefbacf9ef344c74c899vboxsync && pHandler->pfnHandler)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync rc = pHandler->pfnHandler(pHandler->pvHandler, pBufferContext->pHeader->u16ChannelInfo,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pBufferContext->pvData, pBufferContext->cbData);
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync else
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync /* It is a NOOP case here. */
9bee881471745317e907eefbacf9ef344c74c899vboxsync rc = VINF_SUCCESS;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync LogFlowFunc(("leave rc = %Rrc\n", rc));
9bee881471745317e907eefbacf9ef344c74c899vboxsync return rc;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync/** Helper to convert HGSMI channel index to the channel structure pointer.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync *
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @returns Pointer to the channel data.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param pChannelInfo The channel pool.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param u8Channel The channel index.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsyncHGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync uint8_t u8Channel)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync AssertCompile(RT_ELEMENTS(pChannelInfo->Channels) >= 0x100);
9bee881471745317e907eefbacf9ef344c74c899vboxsync HGSMICHANNEL *pChannel = &pChannelInfo->Channels[u8Channel];
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (pChannel->u8Flags & HGSMI_CH_F_REGISTERED)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync return pChannel;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return NULL;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync/** Process a guest buffer.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync *
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @returns VBox status.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param pArea Area which supposed to contain the buffer.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param pChannelInfo The channel pool.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param offBuffer The buffer location in the area.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsyncint HGSMIBufferProcess(HGSMIAREA *pArea,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMICHANNELINFO *pChannelInfo,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMIOFFSET offBuffer)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync LogFlowFunc(("pArea %p, offBuffer 0x%x\n", pArea, offBuffer));
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync AssertPtrReturn(pArea, VERR_INVALID_PARAMETER);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync AssertPtrReturn(pChannelInfo, VERR_INVALID_PARAMETER);
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync /* Guest has prepared a command description at 'offBuffer'. */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMIBUFFERCONTEXT bufferContext;
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync int rc = hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync if (RT_SUCCESS(rc))
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
9bee881471745317e907eefbacf9ef344c74c899vboxsync /* Pass the command to the appropriate handler registered with this instance.
9bee881471745317e907eefbacf9ef344c74c899vboxsync * Start with the handler list head, which is the preallocated HGSMI setup channel.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, bufferContext.pHeader->u8Channel);
9bee881471745317e907eefbacf9ef344c74c899vboxsync if (pChannel)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync rc = hgsmiChannelHandlerCall(&pChannel->handler, &bufferContext);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMI_STRICT_ASSERT(RT_SUCCESS(hgsmiVerifyBuffer(pArea, offBuffer, &bufferContext)));
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync else
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
df277f214bcaae98f80456ec998330eaa7460ecavboxsync rc = VERR_INVALID_FUNCTION;
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMI_STRICT_ASSERT_FAILED();
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return rc;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync/** Register a new HGSMI channel by index.
9bee881471745317e907eefbacf9ef344c74c899vboxsync *
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @returns VBox status.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param pChannelInfo The channel pool managed by the caller.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param u8Channel Index of the channel.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param pszName Name of the channel (optional, allocated by the caller).
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param pfnChannelHandler The channel callback.
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync * @param pvChannelHandler The callback pointer.
9bee881471745317e907eefbacf9ef344c74c899vboxsync */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsyncint HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync uint8_t u8Channel,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync const char *pszName,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync PFNHGSMICHANNELHANDLER pfnChannelHandler,
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync void *pvChannelHandler)
9bee881471745317e907eefbacf9ef344c74c899vboxsync{
9bee881471745317e907eefbacf9ef344c74c899vboxsync /* Check whether the channel is already registered. */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMICHANNEL *pChannel = HGSMIChannelFindById(pChannelInfo, u8Channel);
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync if (pChannel)
9bee881471745317e907eefbacf9ef344c74c899vboxsync {
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync HGSMI_STRICT_ASSERT_FAILED();
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync return VERR_ALREADY_EXISTS;
9bee881471745317e907eefbacf9ef344c74c899vboxsync }
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync /* Channel is not yet registered. */
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pChannel = &pChannelInfo->Channels[u8Channel];
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pChannel->u8Flags = HGSMI_CH_F_REGISTERED;
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pChannel->u8Channel = u8Channel;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync pChannel->handler.pfnHandler = pfnChannelHandler;
9bee881471745317e907eefbacf9ef344c74c899vboxsync pChannel->handler.pvHandler = pvChannelHandler;
9bee881471745317e907eefbacf9ef344c74c899vboxsync
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync pChannel->pszName = pszName;
dfc68b62b28c82701524c03873d326a99ebaa6cfvboxsync
9bee881471745317e907eefbacf9ef344c74c899vboxsync return VINF_SUCCESS;
9bee881471745317e907eefbacf9ef344c74c899vboxsync}