/* $Id$ */
/** @file
* VBox Host Guest Shared Memory Interface (HGSMI) - Functions common to both host and guest.
*/
/*
* Copyright (C) 2006-2015 Oracle Corporation
*
* This file is part of VirtualBox Open Source Edition (OSE), as
* available from http://www.virtualbox.org. This file is free software;
* General Public License (GPL) as published by the Free Software
* Foundation, in version 2 as it comes in the "COPYING" file of the
* VirtualBox OSE distribution. VirtualBox OSE is distributed in the
* hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
*/
/* Channel flags. */
/* Assertions for situations which could happen and normally must be processed properly
* but must be investigated during development: guest misbehaving, etc.
*/
#ifdef HGSMI_STRICT
#else
#define HGSMI_STRICT_ASSERT_FAILED() do {} while (0)
#endif /* !HGSMI_STRICT */
/* One-at-a-Time Hash from
*
* ub4 one_at_a_time(char *key, ub4 len)
* {
* ub4 hash, i;
* for (hash=0, i=0; i<len; ++i)
* {
* hash += key[i];
* hash += (hash << 10);
* hash ^= (hash >> 6);
* }
* hash += (hash << 3);
* hash ^= (hash >> 11);
* hash += (hash << 15);
* return hash;
* }
*/
{
return 0;
}
const void *pvData,
{
while (cbData--)
{
}
return hash;
}
{
return hash;
}
const HGSMIBUFFERHEADER *pHeader,
const HGSMIBUFFERTAIL *pTail)
{
return hgsmiHashEnd (u32Checksum);
}
{
if ( !pArea
|| !pHeader)
{
return HGSMIOFFSET_VOID;
}
/* Buffer must be within the area:
* * header data size do not exceed the maximum data size;
* * buffer address is greater than the area base address;
* * buffer address is lower than the maximum allowed for the given data size.
*/
if ( u32DataSize > cbMaximumDataSize
{
return HGSMIOFFSET_VOID;
}
pTail->u32Reserved = 0;
return offBuffer;
}
{
if ( !pArea /* Check that the area: */
|| offBase > UINT32_C(0xFFFFFFFF) - cbArea /* Area within the 32 bit space: offBase + cbMem <= 0xFFFFFFFF */
)
{
return VERR_INVALID_PARAMETER;
}
return VINF_SUCCESS;
}
{
if (pArea)
{
}
}
/* Initialize the memory buffer including its checksum.
* No changes alloed to the header and the tail after that.
*/
{
if (cbBuffer < HGSMIBufferMinimumSize ())
{
return HGSMIOFFSET_VOID;
}
return hgsmiBufferInitializeSingle (pArea, pHeader, cbBuffer - HGSMIBufferMinimumSize (), u8Channel, u16ChannelInfo);
}
{
}
void *pvBase,
{
if ( !pHeap
|| !pvBase)
{
return VERR_INVALID_PARAMETER;
}
if (RT_SUCCESS (rc))
{
if (u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
{
}
else if (u32HeapType == HGSMI_HEAP_TYPE_POINTER)
{
}
else
{
/* HGSMI_HEAP_TYPE_MA does not need the relocation. */
}
if (RT_SUCCESS(rc))
{
}
else
{
}
}
return rc;
}
void *pvBase,
{
if (RT_SUCCESS (rc))
{
if (RT_SUCCESS(rc))
{
}
else
{
}
}
return rc;
}
void *pvBase,
{
if ( !pHeap
|| !pvBase)
{
return VERR_INVALID_PARAMETER;
}
if (RT_SUCCESS (rc))
{
if (u32HeapType == HGSMI_HEAP_TYPE_MA)
{
}
else if (u32HeapType == HGSMI_HEAP_TYPE_POINTER)
{
}
else if (u32HeapType == HGSMI_HEAP_TYPE_OFFSET)
{
}
else
{
}
if (RT_SUCCESS (rc))
{
}
else
{
}
}
return rc;
}
{
if (pHeap)
{
{
}
}
}
{
if (!pHeader)
return NULL;
return HGSMIBufferData (pHeader);
}
void *pvData)
{
return offBuffer;
}
void *pvData)
{
if ( pvData
{
}
}
{
{
}
{
}
{
}
if (pvBuf)
{
}
return pvBuf;
}
void *pvBuf)
{
{
}
{
}
{
}
}
typedef struct HGSMIBUFFERCONTEXT
{
/* Verify that the given offBuffer points to a valid buffer, which is within the area.
*/
{
LogFlowFunc(("buffer 0x%x, area %p %x [0x%x;0x%x]\n",
{
LogFunc(("offset 0x%x is outside the area [0x%x;0x%x]!!!\n",
}
else
{
/* 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",
{
/* At least both header and tail structures are in the area. Check the checksum. */
LogFlowFunc(("checksum check: u32Checksum = 0x%x pTail->u32Checksum = 0x%x\n",
{
/* Success. */
}
else
{
LogFunc(("invalid checksum 0x%x, expected 0x%x!!!\n",
}
}
else
{
LogFunc(("invalid data size 0x%x, maximum is 0x%x!!!\n",
}
}
return rc;
}
/* A wrapper to safely call the handler.
*/
const HGSMIBUFFERCONTEXT *pBufferContext)
{
int rc;
if ( pHandler
&& pHandler->pfnHandler)
{
}
else
{
/* It is a NOOP case here. */
rc = VINF_SUCCESS;
}
return rc;
}
/** Helper to convert HGSMI channel index to the channel structure pointer.
*
* @returns Pointer to the channel data.
* @param pChannelInfo The channel pool.
* @param u8Channel The channel index.
*/
{
{
return pChannel;
}
return NULL;
}
/** 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.
*/
{
/* Guest has prepared a command description at 'offBuffer'. */
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.
*/
if (pChannel)
{
}
else
{
}
}
return rc;
}
/** 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.
*/
const char *pszName,
void *pvChannelHandler)
{
/* Check whether the channel is already registered. */
if (pChannel)
{
return VERR_ALREADY_EXISTS;
}
/* Channel is not yet registered. */
return VINF_SUCCESS;
}