/** @file | |
* | |
* VBox Host Guest Shared Memory Interface (HGSMI). | |
* Host/Guest shared part. | |
*/ | |
/* | |
* 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; | |
* you can redistribute it and/or modify it under the terms of the GNU | |
* 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. | |
* | |
* The contents of this file may alternatively be used under the terms | |
* of the Common Development and Distribution License Version 1.0 | |
* (CDDL) only, as it comes in the "COPYING.CDDL" file of the | |
* VirtualBox OSE distribution, in which case the provisions of the | |
* CDDL are applicable instead of those of the GPL. | |
* | |
* You may elect to license modified versions of this file under the | |
* terms and conditions of either the GPL or the CDDL or both. | |
*/ | |
#ifndef ___VBox_HGSMI_HGSMI_h | |
#define ___VBox_HGSMI_HGSMI_h | |
#include <iprt/assert.h> | |
#include <iprt/types.h> | |
#include <VBox/HGSMI/HGSMIDefs.h> | |
#include <VBox/HGSMI/HGSMIChannels.h> | |
#include <VBox/HGSMI/HGSMIMemAlloc.h> | |
/* | |
* Basic mechanism for the HGSMI is to prepare and pass data buffer to the host and the guest. | |
* Data inside these buffers are opaque for the HGSMI and are interpreted by higher levels. | |
* | |
* Every shared memory buffer passed between the guest/host has the following structure: | |
* | |
* HGSMIBUFFERHEADER header; | |
* uint8_t data[header.u32BufferSize]; | |
* HGSMIBUFFERTAIL tail; | |
* | |
* Note: Offset of the 'header' in the memory is used for virtual hardware IO. | |
* | |
* Buffers are verifyed using the offset and the content of the header and the tail, | |
* which are constant during a call. | |
* | |
* Invalid buffers are ignored. | |
* | |
* Actual 'data' is not verifyed, as it is expected that the data can be changed by the | |
* called function. | |
* | |
* Since only the offset of the buffer is passed in a IO operation, the header and tail | |
* must contain: | |
* * size of data in this buffer; | |
* * checksum for buffer verification. | |
* | |
* For segmented transfers: | |
* * the sequence identifier; | |
* * offset of the current segment in the sequence; | |
* * total bytes in the transfer. | |
* | |
* Additionally contains: | |
* * the channel ID; | |
* * the channel information. | |
*/ | |
typedef struct HGSMIHEAP | |
{ | |
HGSMIAREA area; /* Description. */ | |
HGSMIMADATA ma; /* Memory allocator */ | |
} HGSMIHEAP; | |
/* The size of the array of channels. Array indexes are uint8_t. Note: the value must not be changed. */ | |
#define HGSMI_NUMBER_OF_CHANNELS 0x100 | |
/* Channel handler called when the guest submits a buffer. */ | |
typedef DECLCALLBACK(int) FNHGSMICHANNELHANDLER(void *pvHandler, uint16_t u16ChannelInfo, void *pvBuffer, HGSMISIZE cbBuffer); | |
typedef FNHGSMICHANNELHANDLER *PFNHGSMICHANNELHANDLER; | |
/* Information about a handler: pfn + context. */ | |
typedef struct _HGSMICHANNELHANDLER | |
{ | |
PFNHGSMICHANNELHANDLER pfnHandler; | |
void *pvHandler; | |
} HGSMICHANNELHANDLER; | |
/* Channel description. */ | |
typedef struct _HGSMICHANNEL | |
{ | |
HGSMICHANNELHANDLER handler; /* The channel handler. */ | |
const char *pszName; /* NULL for hardcoded channels or RTStrDup'ed name. */ | |
uint8_t u8Channel; /* The channel id, equal to the channel index in the array. */ | |
uint8_t u8Flags; /* HGSMI_CH_F_* */ | |
} HGSMICHANNEL; | |
typedef struct _HGSMICHANNELINFO | |
{ | |
HGSMICHANNEL Channels[HGSMI_NUMBER_OF_CHANNELS]; /* Channel handlers indexed by the channel id. | |
* The array is accessed under the instance lock. | |
*/ | |
} HGSMICHANNELINFO; | |
RT_C_DECLS_BEGIN | |
DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromPtr(void *pvBuffer) | |
{ | |
return (HGSMIBUFFERHEADER *)pvBuffer; | |
} | |
DECLINLINE(uint8_t *) HGSMIBufferDataFromPtr(void *pvBuffer) | |
{ | |
return (uint8_t *)pvBuffer + sizeof(HGSMIBUFFERHEADER); | |
} | |
DECLINLINE(HGSMIBUFFERTAIL *) HGSMIBufferTailFromPtr(void *pvBuffer, | |
uint32_t u32DataSize) | |
{ | |
return (HGSMIBUFFERTAIL *)(HGSMIBufferDataFromPtr(pvBuffer) + u32DataSize); | |
} | |
DECLINLINE(HGSMISIZE) HGSMIBufferMinimumSize(void) | |
{ | |
return sizeof(HGSMIBUFFERHEADER) + sizeof(HGSMIBUFFERTAIL); | |
} | |
DECLINLINE(HGSMIBUFFERHEADER *) HGSMIBufferHeaderFromData(const void *pvData) | |
{ | |
return (HGSMIBUFFERHEADER *)((uint8_t *)pvData - sizeof(HGSMIBUFFERHEADER)); | |
} | |
DECLINLINE(HGSMISIZE) HGSMIBufferRequiredSize(uint32_t u32DataSize) | |
{ | |
return HGSMIBufferMinimumSize() + u32DataSize; | |
} | |
DECLINLINE(HGSMIOFFSET) HGSMIPointerToOffset(const HGSMIAREA *pArea, | |
const void *pv) | |
{ | |
return pArea->offBase + (HGSMIOFFSET)((uint8_t *)pv - pArea->pu8Base); | |
} | |
DECLINLINE(void *) HGSMIOffsetToPointer(const HGSMIAREA *pArea, | |
HGSMIOFFSET offBuffer) | |
{ | |
return pArea->pu8Base + (offBuffer - pArea->offBase); | |
} | |
DECLINLINE(uint8_t *) HGSMIBufferDataFromOffset(const HGSMIAREA *pArea, | |
HGSMIOFFSET offBuffer) | |
{ | |
void *pvBuffer = HGSMIOffsetToPointer(pArea, offBuffer); | |
return HGSMIBufferDataFromPtr(pvBuffer); | |
} | |
DECLINLINE(HGSMIOFFSET) HGSMIBufferOffsetFromData(const HGSMIAREA *pArea, | |
void *pvData) | |
{ | |
HGSMIBUFFERHEADER *pHeader = HGSMIBufferHeaderFromData(pvData); | |
return HGSMIPointerToOffset(pArea, pHeader); | |
} | |
DECLINLINE(uint8_t *) HGSMIBufferDataAndChInfoFromOffset(const HGSMIAREA *pArea, | |
HGSMIOFFSET offBuffer, | |
uint16_t *pu16ChannelInfo) | |
{ | |
HGSMIBUFFERHEADER *pHeader = (HGSMIBUFFERHEADER *)HGSMIOffsetToPointer(pArea, offBuffer); | |
*pu16ChannelInfo = pHeader->u16ChannelInfo; | |
return HGSMIBufferDataFromPtr(pHeader); | |
} | |
uint32_t HGSMIChecksum(HGSMIOFFSET offBuffer, | |
const HGSMIBUFFERHEADER *pHeader, | |
const HGSMIBUFFERTAIL *pTail); | |
int HGSMIAreaInitialize(HGSMIAREA *pArea, | |
void *pvBase, | |
HGSMISIZE cbArea, | |
HGSMIOFFSET offBase); | |
void HGSMIAreaClear(HGSMIAREA *pArea); | |
DECLINLINE(bool) HGSMIAreaContainsOffset(const HGSMIAREA *pArea, HGSMIOFFSET off) | |
{ | |
return off >= pArea->offBase && off - pArea->offBase < pArea->cbArea; | |
} | |
DECLINLINE(bool) HGSMIAreaContainsPointer(const HGSMIAREA *pArea, const void *pv) | |
{ | |
return (uintptr_t)pv >= (uintptr_t)pArea->pu8Base && (uintptr_t)pv - (uintptr_t)pArea->pu8Base < pArea->cbArea; | |
} | |
HGSMIOFFSET HGSMIBufferInitializeSingle(const HGSMIAREA *pArea, | |
HGSMIBUFFERHEADER *pHeader, | |
HGSMISIZE cbBuffer, | |
uint8_t u8Channel, | |
uint16_t u16ChannelInfo); | |
int HGSMIHeapSetup(HGSMIHEAP *pHeap, | |
void *pvBase, | |
HGSMISIZE cbArea, | |
HGSMIOFFSET offBase, | |
const HGSMIENV *pEnv); | |
void HGSMIHeapDestroy(HGSMIHEAP *pHeap); | |
void *HGSMIHeapBufferAlloc(HGSMIHEAP *pHeap, | |
HGSMISIZE cbBuffer); | |
void HGSMIHeapBufferFree(HGSMIHEAP *pHeap, | |
void *pvBuf); | |
void *HGSMIHeapAlloc(HGSMIHEAP *pHeap, | |
HGSMISIZE cbData, | |
uint8_t u8Channel, | |
uint16_t u16ChannelInfo); | |
void HGSMIHeapFree(HGSMIHEAP *pHeap, | |
void *pvData); | |
DECLINLINE(const HGSMIAREA *) HGSMIHeapArea(HGSMIHEAP *pHeap) | |
{ | |
return &pHeap->area; | |
} | |
DECLINLINE(HGSMIOFFSET) HGSMIHeapOffset(HGSMIHEAP *pHeap) | |
{ | |
return HGSMIHeapArea(pHeap)->offBase; | |
} | |
DECLINLINE(HGSMISIZE) HGSMIHeapSize(HGSMIHEAP *pHeap) | |
{ | |
return HGSMIHeapArea(pHeap)->cbArea; | |
} | |
DECLINLINE(HGSMIOFFSET) HGSMIHeapBufferOffset(HGSMIHEAP *pHeap, | |
void *pvData) | |
{ | |
return HGSMIBufferOffsetFromData(HGSMIHeapArea(pHeap), pvData); | |
} | |
HGSMICHANNEL *HGSMIChannelFindById(HGSMICHANNELINFO *pChannelInfo, | |
uint8_t u8Channel); | |
int HGSMIChannelRegister(HGSMICHANNELINFO *pChannelInfo, | |
uint8_t u8Channel, | |
const char *pszName, | |
PFNHGSMICHANNELHANDLER pfnChannelHandler, | |
void *pvChannelHandler); | |
int HGSMIBufferProcess(const HGSMIAREA *pArea, | |
HGSMICHANNELINFO *pChannelInfo, | |
HGSMIOFFSET offBuffer); | |
RT_C_DECLS_END | |
#endif /* !___VBox_HGSMI_HGSMI_h */ | |