DrvVD.cpp revision cba6719bd64ec749967bbe931230452664109857
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/* $Id$ */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @file
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * DrvVD - Generic VBox disk media driver.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu */
f94c602698937f2fc025056c894e5a769f39d8fejj
f94c602698937f2fc025056c894e5a769f39d8fejj/*
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Copyright (C) 2006-2008 Sun Microsystems, Inc.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * This file is part of VirtualBox Open Source Edition (OSE), as
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * available from http://www.virtualbox.org. This file is free software;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * you can redistribute it and/or modify it under the terms of the GNU
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * General Public License (GPL) as published by the Free Software
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Foundation, in version 2 as it comes in the "COPYING" file of the
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Clara, CA 95054 USA or visit http://www.sun.com if you need
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * additional information or have any questions.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
c85864d8472aaccb47ceb468ebd9b3a85b66d161Krishna Elango
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* Header files *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#define LOG_GROUP LOG_GROUP_DRV_VD
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <VBox/VBoxHDD.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <VBox/pdmdrv.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <VBox/pdmasynccompletion.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <iprt/alloc.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <iprt/assert.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <iprt/uuid.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <iprt/file.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <iprt/string.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <iprt/cache.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <iprt/tcp.h>
70025d765b044c6d8594bb965a2247a61e991a99johnny#include <iprt/semaphore.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#ifdef VBOX_WITH_INIP
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/* All lwip header files are not C++ safe. So hack around this. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchuRT_C_DECLS_BEGIN
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <lwip/inet.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <lwip/tcp.h>
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include <lwip/sockets.h>
92e1ac0d7d0f8596dfc8b9e1302e1100e5b35efajjRT_C_DECLS_END
92e1ac0d7d0f8596dfc8b9e1302e1100e5b35efajj#endif /* VBOX_WITH_INIP */
92e1ac0d7d0f8596dfc8b9e1302e1100e5b35efajj
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#include "Builtins.h"
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#ifdef VBOX_WITH_INIP
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/* Small hack to get at lwIP initialized status */
f8d2de6bd2421da1926f3daa456d161670decdf7jchuextern bool DevINIPConfigured(void);
269473047d747f7815af570197e4ef7322d3632cEvan Yan#endif /* VBOX_WITH_INIP */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*******************************************************************************
269473047d747f7815af570197e4ef7322d3632cEvan Yan* Defined types, constants and macros *
269473047d747f7815af570197e4ef7322d3632cEvan Yan*******************************************************************************/
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/** Converts a pointer to VDIDISK::IMedia to a PVBOXDISK. */
269473047d747f7815af570197e4ef7322d3632cEvan Yan#define PDMIMEDIA_2_VBOXDISK(pInterface) \
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
70025d765b044c6d8594bb965a2247a61e991a99johnny/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
70025d765b044c6d8594bb965a2247a61e991a99johnny#define PDMIBASE_2_DRVINS(pInterface) \
70025d765b044c6d8594bb965a2247a61e991a99johnny ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
70025d765b044c6d8594bb965a2247a61e991a99johnny#define PDMIBASE_2_VBOXDISK(pInterface) \
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
269473047d747f7815af570197e4ef7322d3632cEvan Yan/** Converts a pointer to VBOXDISK::IMediaAsync to a PVBOXDISK. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#define PDMIMEDIAASYNC_2_VBOXDISK(pInterface) \
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMediaAsync)) )
c85864d8472aaccb47ceb468ebd9b3a85b66d161Krishna Elango
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/**
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * VBox disk container, image information, private part.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchutypedef struct VBOXIMAGE
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae{
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae /** Pointer to next image. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu struct VBOXIMAGE *pNext;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Pointer to list of VD interfaces. Per-image. */
3221df98598173bea3b143712532cdd09f4fbd0fKrishna Elango PVDINTERFACE pVDIfsImage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Common structure for the configuration information interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu VDINTERFACE VDIConfig;
70025d765b044c6d8594bb965a2247a61e991a99johnny} VBOXIMAGE, *PVBOXIMAGE;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/**
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Storage backend data.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu */
f8d2de6bd2421da1926f3daa456d161670decdf7jchutypedef struct DRVVDSTORAGEBACKEND
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** PDM async completion end point. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMASYNCCOMPLETIONENDPOINT pEndpoint;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The template. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMASYNCCOMPLETIONTEMPLATE pTemplate;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Event semaphore for synchronous operations. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTSEMEVENT EventSem;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether a synchronous operation is currently pending. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu volatile bool fSyncIoPending;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback routine */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PFNVDCOMPLETED pfnCompleted;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu} DRVVDSTORAGEBACKEND, *PDRVVDSTORAGEBACKEND;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/**
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * VBox disk container media main structure, private part.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu */
f8d2de6bd2421da1926f3daa456d161670decdf7jchutypedef struct VBOXDISK
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The VBox disk container. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXHDD pDisk;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The media interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMIMEDIA IMedia;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Pointer to the driver instance. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMDRVINS pDrvIns;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether suspend has changed image open mode to read only. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu bool fTempReadOnly;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether to use the runtime (true) or startup error facility. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu bool fErrorUseRuntime;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Pointer to list of VD interfaces. Per-disk. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVDINTERFACE pVDIfsDisk;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Common structure for the supported error interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu VDINTERFACE VDIError;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for error interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu VDINTERFACEERROR VDIErrorCallbacks;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Common structure for the supported TCP network stack interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu VDINTERFACE VDITcpNet;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for TCP network stack interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu VDINTERFACETCPNET VDITcpNetCallbacks;
337fc9e235877b459e389f54daf9833bbc645439anish /** Common structure for the supported async I/O interface. */
337fc9e235877b459e389f54daf9833bbc645439anish VDINTERFACE VDIAsyncIO;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for async I/O interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu VDINTERFACEASYNCIO VDIAsyncIOCallbacks;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Callback table for the configuration information interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu VDINTERFACECONFIG VDIConfigCallbacks;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** Flag whether opened disk suppports async I/O operations. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu bool fAsyncIOSupported;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The async media interface. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMIMEDIAASYNC IMediaAsync;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** The async media port interface above. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMIMEDIAASYNCPORT pDrvMediaAsyncPort;
70025d765b044c6d8594bb965a2247a61e991a99johnny /** Pointer to the list of data we need to keep per image. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXIMAGE pImages;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu} VBOXDISK, *PVBOXDISK;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* Error reporting callback *
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram*******************************************************************************/
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu const char *pszFormat, va_list va)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMDRVINS pDrvIns = (PPDMDRVINS)pvUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (pThis->fErrorUseRuntime)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* We must not pass VMSETRTERR_FLAGS_FATAL as it could lead to a
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * deadlock: We are probably executed in a thread context != EMT
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * and the EM thread would wait until every thread is suspended
0114761d17f41c0b83189e4bf95e6b789e7ba99eAlan Adamson, SD OSSD * but we would wait for the EM thread ... */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pDrvIns->pDrvHlp->pfnVMSetRuntimeErrorV(pDrvIns, /* fFlags=*/ 0, "DrvVD", pszFormat, va);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu else
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pDrvIns->pDrvHlp->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram/**
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram * Internal: allocate new image descriptor and put it in the list
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram */
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuramstatic PVBOXIMAGE drvvdNewImage(PVBOXDISK pThis)
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram{
95ad88f0c773d4a7dbe017b66e02eb6e9a0511c6raghuram AssertPtr(pThis);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXIMAGE pImage = (PVBOXIMAGE)RTMemAllocZ(sizeof(VBOXIMAGE));
0114761d17f41c0b83189e4bf95e6b789e7ba99eAlan Adamson, SD OSSD if (pImage)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pImage->pVDIfsImage = NULL;
70025d765b044c6d8594bb965a2247a61e991a99johnny PVBOXIMAGE *pp = &pThis->pImages;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu while (*pp != NULL)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pp = &(*pp)->pNext;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu *pp = pImage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pImage->pNext = NULL;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return pImage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
70025d765b044c6d8594bb965a2247a61e991a99johnny/**
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Internal: free the list of images descriptors.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic void drvvdFreeImages(PVBOXDISK pThis)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu while (pThis->pImages != NULL)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXIMAGE p = pThis->pImages;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->pImages = pThis->pImages->pNext;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTMemFree(p);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* VD Async I/O interface implementation *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(void) drvvdAsyncTaskCompleted(PPDMDRVINS pDrvIns, void *pvTemplateUser, void *pvUser)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pvTemplateUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = VINF_VD_ASYNC_IO_FINISHED;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu void *pvCallerUser = NULL;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (pStorageBackend->fSyncIoPending)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pStorageBackend->fSyncIoPending;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTSemEventSignal(pStorageBackend->EventSem);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu else if (pStorageBackend->pfnCompleted)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = pStorageBackend->pfnCompleted(pvUser, &pvCallerUser);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu else
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pvCallerUser = pvUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (rc == VINF_VD_ASYNC_IO_FINISHED)
70025d765b044c6d8594bb965a2247a61e991a99johnny {
70025d765b044c6d8594bb965a2247a61e991a99johnny rc = pThis->pDrvMediaAsyncPort->pfnTransferCompleteNotify(pThis->pDrvMediaAsyncPort, pvCallerUser);
70025d765b044c6d8594bb965a2247a61e991a99johnny AssertRC(rc);
70025d765b044c6d8594bb965a2247a61e991a99johnny }
c85864d8472aaccb47ceb468ebd9b3a85b66d161Krishna Elango else
c85864d8472aaccb47ceb468ebd9b3a85b66d161Krishna Elango AssertMsg(rc == VERR_VD_ASYNC_IO_IN_PROGRESS, ("Invalid return code from disk backend rc=%Rrc\n", rc));
c85864d8472aaccb47ceb468ebd9b3a85b66d161Krishna Elango}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOOpen(void *pvUser, const char *pszLocation, bool fReadonly,
70025d765b044c6d8594bb965a2247a61e991a99johnny PFNVDCOMPLETED pfnCompleted, void **ppStorage)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)RTMemAllocZ(sizeof(DRVVDSTORAGEBACKEND));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = VINF_SUCCESS;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (pStorageBackend)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pStorageBackend->fSyncIoPending = false;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pStorageBackend->pfnCompleted = pfnCompleted;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = RTSemEventCreate(&pStorageBackend->EventSem);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (RT_SUCCESS(rc))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = PDMDrvHlpPDMAsyncCompletionTemplateCreate(pDrvVD->pDrvIns, &pStorageBackend->pTemplate,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu drvvdAsyncTaskCompleted, pStorageBackend, "AsyncTaskCompleted");
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (RT_SUCCESS(rc))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
70025d765b044c6d8594bb965a2247a61e991a99johnny rc = PDMR3AsyncCompletionEpCreateForFile(&pStorageBackend->pEndpoint, pszLocation,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu fReadonly
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ? PDMACEP_FILE_FLAGS_READ_ONLY | PDMACEP_FILE_FLAGS_CACHING
f8d2de6bd2421da1926f3daa456d161670decdf7jchu : PDMACEP_FILE_FLAGS_CACHING,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pStorageBackend->pTemplate);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (RT_SUCCESS(rc))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu *ppStorage = pStorageBackend;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VINF_SUCCESS;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTSemEventDestroy(pStorageBackend->EventSem);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTMemFree(pStorageBackend);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu else
f94c602698937f2fc025056c894e5a769f39d8fejj rc = VERR_NO_MEMORY;
f94c602698937f2fc025056c894e5a769f39d8fejj
f94c602698937f2fc025056c894e5a769f39d8fejj return rc;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
70025d765b044c6d8594bb965a2247a61e991a99johnny
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOClose(void *pvUser, void *pStorage)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMR3AsyncCompletionEpClose(pStorageBackend->pEndpoint);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDMR3AsyncCompletionTemplateDestroy(pStorageBackend->pTemplate);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTSemEventDestroy(pStorageBackend->EventSem);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTMemFree(pStorageBackend);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VINF_SUCCESS;;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOGetSize(void *pvUser, void *pStorage, uint64_t *pcbSize)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return PDMR3AsyncCompletionEpGetSize(pStorageBackend->pEndpoint, pcbSize);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOReadSync(void *pvUser, void *pStorage, uint64_t uOffset,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu size_t cbRead, void *pvBuf, size_t *pcbRead)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
70025d765b044c6d8594bb965a2247a61e991a99johnny PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
70025d765b044c6d8594bb965a2247a61e991a99johnny PDMDATASEG DataSeg;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMASYNCCOMPLETIONTASK pTask;
70025d765b044c6d8594bb965a2247a61e991a99johnny
f8d2de6bd2421da1926f3daa456d161670decdf7jchu Assert(!pStorageBackend->fSyncIoPending);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pStorageBackend->fSyncIoPending = true;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu DataSeg.cbSeg = cbRead;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu DataSeg.pvSeg = pvBuf;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbRead, NULL, &pTask);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (RT_FAILURE(rc))
70025d765b044c6d8594bb965a2247a61e991a99johnny return rc;
70025d765b044c6d8594bb965a2247a61e991a99johnny
f94c602698937f2fc025056c894e5a769f39d8fejj /* Wait */
70025d765b044c6d8594bb965a2247a61e991a99johnny rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
70025d765b044c6d8594bb965a2247a61e991a99johnny AssertRC(rc);
269473047d747f7815af570197e4ef7322d3632cEvan Yan
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (pcbRead)
70025d765b044c6d8594bb965a2247a61e991a99johnny *pcbRead = cbRead;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return VINF_SUCCESS;
70025d765b044c6d8594bb965a2247a61e991a99johnny}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
70025d765b044c6d8594bb965a2247a61e991a99johnnystatic DECLCALLBACK(int) drvvdAsyncIOWriteSync(void *pvUser, void *pStorage, uint64_t uOffset,
70025d765b044c6d8594bb965a2247a61e991a99johnny size_t cbWrite, const void *pvBuf, size_t *pcbWritten)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
70025d765b044c6d8594bb965a2247a61e991a99johnny PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
70025d765b044c6d8594bb965a2247a61e991a99johnny PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
70025d765b044c6d8594bb965a2247a61e991a99johnny PDMDATASEG DataSeg;
70025d765b044c6d8594bb965a2247a61e991a99johnny PPDMASYNCCOMPLETIONTASK pTask;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny Assert(!pStorageBackend->fSyncIoPending);
70025d765b044c6d8594bb965a2247a61e991a99johnny pStorageBackend->fSyncIoPending = true;
70025d765b044c6d8594bb965a2247a61e991a99johnny DataSeg.cbSeg = cbWrite;
70025d765b044c6d8594bb965a2247a61e991a99johnny DataSeg.pvSeg = (void *)pvBuf;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, &DataSeg, 1, cbWrite, NULL, &pTask);
70025d765b044c6d8594bb965a2247a61e991a99johnny if (RT_FAILURE(rc))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return rc;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Wait */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu AssertRC(rc);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
70025d765b044c6d8594bb965a2247a61e991a99johnny if (pcbWritten)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu *pcbWritten = cbWrite;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny return VINF_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdAsyncIOFlushSync(void *pvUser, void *pStorage)
70025d765b044c6d8594bb965a2247a61e991a99johnny{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMASYNCCOMPLETIONTASK pTask;
70025d765b044c6d8594bb965a2247a61e991a99johnny
70025d765b044c6d8594bb965a2247a61e991a99johnny Assert(!pStorageBackend->fSyncIoPending);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pStorageBackend->fSyncIoPending = true;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
70025d765b044c6d8594bb965a2247a61e991a99johnny int rc = PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, NULL, &pTask);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (RT_FAILURE(rc))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return rc;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Wait */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = RTSemEventWait(pStorageBackend->EventSem, RT_INDEFINITE_WAIT);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu AssertRC(rc);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
269473047d747f7815af570197e4ef7322d3632cEvan Yan return VINF_SUCCESS;
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdAsyncIOReadAsync(void *pvUser, void *pStorage, uint64_t uOffset,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PCPDMDATASEG paSegments, size_t cSegments,
269473047d747f7815af570197e4ef7322d3632cEvan Yan size_t cbRead, void *pvCompletion,
269473047d747f7815af570197e4ef7322d3632cEvan Yan void **ppTask)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
269473047d747f7815af570197e4ef7322d3632cEvan Yan PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return PDMR3AsyncCompletionEpRead(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbRead,
269473047d747f7815af570197e4ef7322d3632cEvan Yan pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdAsyncIOWriteAsync(void *pvUser, void *pStorage, uint64_t uOffset,
269473047d747f7815af570197e4ef7322d3632cEvan Yan PCPDMDATASEG paSegments, size_t cSegments,
269473047d747f7815af570197e4ef7322d3632cEvan Yan size_t cbWrite, void *pvCompletion,
269473047d747f7815af570197e4ef7322d3632cEvan Yan void **ppTask)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
269473047d747f7815af570197e4ef7322d3632cEvan Yan PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return PDMR3AsyncCompletionEpWrite(pStorageBackend->pEndpoint, uOffset, paSegments, cSegments, cbWrite,
269473047d747f7815af570197e4ef7322d3632cEvan Yan pvCompletion, (PPPDMASYNCCOMPLETIONTASK)ppTask);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdAsyncIOFlushAsync(void *pvUser, void *pStorage,
269473047d747f7815af570197e4ef7322d3632cEvan Yan void *pvCompletion, void **ppTask)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pDrvVD = (PVBOXDISK)pvUser;
269473047d747f7815af570197e4ef7322d3632cEvan Yan PDRVVDSTORAGEBACKEND pStorageBackend = (PDRVVDSTORAGEBACKEND)pStorage;
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan return PDMR3AsyncCompletionEpFlush(pStorageBackend->pEndpoint, pvCompletion,
269473047d747f7815af570197e4ef7322d3632cEvan Yan (PPPDMASYNCCOMPLETIONTASK)ppTask);
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan#endif /* VBOX_WITH_PDM_ASYNC_COMPLETION */
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/*******************************************************************************
269473047d747f7815af570197e4ef7322d3632cEvan Yan* VD Configuration interface implementation *
269473047d747f7815af570197e4ef7322d3632cEvan Yan*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic bool drvvdCfgAreKeysValid(void *pvUser, const char *pszzValid)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return CFGMR3AreValuesValid((PCFGMNODE)pvUser, pszzValid);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic int drvvdCfgQuerySize(void *pvUser, const char *pszName, size_t *pcb)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return CFGMR3QuerySize((PCFGMNODE)pvUser, pszName, pcb);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic int drvvdCfgQuery(void *pvUser, const char *pszName, char *pszString, size_t cchString)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return CFGMR3QueryString((PCFGMNODE)pvUser, pszName, pszString, cchString);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#ifdef VBOX_WITH_INIP
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
337fc9e235877b459e389f54daf9833bbc645439anish* VD TCP network stack interface implementation - INIP case *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
337fc9e235877b459e389f54daf9833bbc645439anish/** @copydoc VDINTERFACETCPNET::pfnClientConnect */
337fc9e235877b459e389f54daf9833bbc645439anishstatic DECLCALLBACK(int) drvvdINIPClientConnect(const char *pszAddress, uint32_t uPort, PRTSOCKET pSock)
337fc9e235877b459e389f54daf9833bbc645439anish{
337fc9e235877b459e389f54daf9833bbc645439anish int rc = VINF_SUCCESS;
337fc9e235877b459e389f54daf9833bbc645439anish /* First check whether lwIP is set up in this VM instance. */
337fc9e235877b459e389f54daf9833bbc645439anish if (!DevINIPConfigured())
337fc9e235877b459e389f54daf9833bbc645439anish {
337fc9e235877b459e389f54daf9833bbc645439anish LogRelFunc(("no IP stack\n"));
337fc9e235877b459e389f54daf9833bbc645439anish return VERR_NET_HOST_UNREACHABLE;
337fc9e235877b459e389f54daf9833bbc645439anish }
337fc9e235877b459e389f54daf9833bbc645439anish /* Resolve hostname. As there is no standard resolver for lwIP yet,
337fc9e235877b459e389f54daf9833bbc645439anish * just accept numeric IP addresses for now. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu struct in_addr ip;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (!lwip_inet_aton(pszAddress, &ip))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogRelFunc(("cannot resolve IP %s\n", pszAddress));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_NET_HOST_UNREACHABLE;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Create socket and connect. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RTSOCKET Sock = lwip_socket(PF_INET, SOCK_STREAM, 0);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (Sock != -1)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu struct sockaddr_in InAddr = {0};
f8d2de6bd2421da1926f3daa456d161670decdf7jchu InAddr.sin_family = AF_INET;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu InAddr.sin_port = htons(uPort);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu InAddr.sin_addr = ip;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (!lwip_connect(Sock, (struct sockaddr *)&InAddr, sizeof(InAddr)))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu *pSock = Sock;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VINF_SUCCESS;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu lwip_close(Sock);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu else
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = VERR_NET_CONNECTION_REFUSED; /* @todo real solution needed */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return rc;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnClientClose */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPClientClose(RTSOCKET Sock)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu lwip_close(Sock);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return VINF_SUCCESS; /** @todo real solution needed */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnSelectOne */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPSelectOne(RTSOCKET Sock, unsigned cMillies)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu fd_set fdsetR;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu FD_ZERO(&fdsetR);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu FD_SET(Sock, &fdsetR);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fd_set fdsetE = fdsetR;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (cMillies == RT_INDEFINITE_WAIT)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, NULL);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet else
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet struct timeval timeout;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu timeout.tv_sec = cMillies / 1000;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu timeout.tv_usec = (cMillies % 1000) * 1000;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = lwip_select(Sock + 1, &fdsetR, NULL, &fdsetE, &timeout);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (rc > 0)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VINF_SUCCESS;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (rc == 0)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_TIMEOUT;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnRead */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPRead(RTSOCKET Sock, void *pvBuffer, size_t cbBuffer, size_t *pcbRead)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Do params checking */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (!pvBuffer || !cbBuffer)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu AssertMsgFailed(("Invalid params\n"));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_INVALID_PARAMETER;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /*
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * Read loop.
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * If pcbRead is NULL we have to fill the entire buffer!
f8d2de6bd2421da1926f3daa456d161670decdf7jchu */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu size_t cbRead = 0;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu size_t cbToRead = cbBuffer;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu for (;;)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** @todo this clipping here is just in case (the send function
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * needed it, so I added it here, too). Didn't investigate if this
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * really has issues. Better be safe than sorry. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ssize_t cbBytesRead = lwip_recv(Sock, (char *)pvBuffer + cbRead,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RT_MIN(cbToRead, 32768), 0);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (cbBytesRead < 0)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (cbBytesRead == 0 && errno)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VERR_NET_CONNECTION_REFUSED; /** @todo real solution */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (pcbRead)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* return partial data */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu *pcbRead = cbBytesRead;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu break;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* read more? */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu cbRead += cbBytesRead;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (cbRead == cbBuffer)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu break;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
eae2e508a8e70b1ec407b10bd068c080651bbe5ckrishnae /* next */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu cbToRead = cbBuffer - cbRead;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VINF_SUCCESS;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnWrite */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPWrite(RTSOCKET Sock, const void *pvBuffer, size_t cbBuffer)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu do
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /** @todo lwip send only supports up to 65535 bytes in a single
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * send (stupid limitation buried in the code), so make sure we
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * don't get any wraparounds. This should be moved to DevINIP
f8d2de6bd2421da1926f3daa456d161670decdf7jchu * stack interface once that's implemented. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu ssize_t cbWritten = lwip_send(Sock, (void *)pvBuffer,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu RT_MIN(cbBuffer, 32768), 0);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (cbWritten < 0)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return VERR_NET_CONNECTION_REFUSED; /** @todo real solution needed */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet AssertMsg(cbBuffer >= (size_t)cbWritten, ("Wrote more than we requested!!! cbWritten=%d cbBuffer=%d\n",
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet cbWritten, cbBuffer));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet cbBuffer -= cbWritten;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pvBuffer = (const char *)pvBuffer + cbWritten;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet } while (cbBuffer);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VINF_SUCCESS;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc VDINTERFACETCPNET::pfnFlush */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdINIPFlush(RTSOCKET Sock)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int fFlag = 1;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet lwip_setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet (const char *)&fFlag, sizeof(fFlag));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet fFlag = 0;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet lwip_setsockopt(Sock, IPPROTO_TCP, TCP_NODELAY,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu (const char *)&fFlag, sizeof(fFlag));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return VINF_SUCCESS;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu#endif /* VBOX_WITH_INIP */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/*******************************************************************************
f8d2de6bd2421da1926f3daa456d161670decdf7jchu* Media interface methods *
f8d2de6bd2421da1926f3daa456d161670decdf7jchu*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnRead */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu uint64_t off, void *pvBuf, size_t cbRead)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu off, pvBuf, cbRead));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = VDRead(pThis->pDisk, off, pvBuf, cbRead);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu if (RT_SUCCESS(rc))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Rhxd\n", __FUNCTION__,
665a7fca9fb82b4c029eb6763aefcc9bc563a486govinda off, pvBuf, cbRead, cbRead, pvBuf));
665a7fca9fb82b4c029eb6763aefcc9bc563a486govinda LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
665a7fca9fb82b4c029eb6763aefcc9bc563a486govinda return rc;
665a7fca9fb82b4c029eb6763aefcc9bc563a486govinda}
665a7fca9fb82b4c029eb6763aefcc9bc563a486govinda
665a7fca9fb82b4c029eb6763aefcc9bc563a486govinda/** @copydoc PDMIMEDIA::pfnWrite */
665a7fca9fb82b4c029eb6763aefcc9bc563a486govindastatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
269473047d747f7815af570197e4ef7322d3632cEvan Yan uint64_t off, const void *pvBuf,
269473047d747f7815af570197e4ef7322d3632cEvan Yan size_t cbWrite)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
269473047d747f7815af570197e4ef7322d3632cEvan Yan off, pvBuf, cbWrite));
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
269473047d747f7815af570197e4ef7322d3632cEvan Yan Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Rhxd\n", __FUNCTION__,
269473047d747f7815af570197e4ef7322d3632cEvan Yan off, pvBuf, cbWrite, cbWrite, pvBuf));
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rc = VDWrite(pThis->pDisk, off, pvBuf, cbWrite);
269473047d747f7815af570197e4ef7322d3632cEvan Yan LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
269473047d747f7815af570197e4ef7322d3632cEvan Yan return rc;
269473047d747f7815af570197e4ef7322d3632cEvan Yan}
269473047d747f7815af570197e4ef7322d3632cEvan Yan
269473047d747f7815af570197e4ef7322d3632cEvan Yan/** @copydoc PDMIMEDIA::pfnFlush */
269473047d747f7815af570197e4ef7322d3632cEvan Yanstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
269473047d747f7815af570197e4ef7322d3632cEvan Yan{
269473047d747f7815af570197e4ef7322d3632cEvan Yan LogFlow(("%s:\n", __FUNCTION__));
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
269473047d747f7815af570197e4ef7322d3632cEvan Yan int rc = VDFlush(pThis->pDisk);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return rc;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnGetSize */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s:\n", __FUNCTION__));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu uint64_t cb = VDGetSize(pThis->pDisk, VD_LAST_IMAGE);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return cb;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnIsReadOnly */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s:\n", __FUNCTION__));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu bool f = VDIsReadOnly(pThis->pDisk);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: returns %d\n", __FUNCTION__, f));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return f;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PPDMMEDIAGEOMETRY pPCHSGeometry)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s:\n", __FUNCTION__));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDGetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (RT_FAILURE(rc))
f8d2de6bd2421da1926f3daa456d161670decdf7jchu {
f8d2de6bd2421da1926f3daa456d161670decdf7jchu Log(("%s: geometry not available.\n", __FUNCTION__));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc = VERR_PDM_GEOMETRY_NOT_SET;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu }
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu return rc;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu}
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PCPDMMEDIAGEOMETRY pPCHSGeometry)
c85864d8472aaccb47ceb468ebd9b3a85b66d161Krishna Elango{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
269473047d747f7815af570197e4ef7322d3632cEvan Yan PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = VDSetPCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
bf8fc2340620695a402331e5da7c7db43264174det if (rc == VERR_VD_GEOMETRY_NOT_SET)
bf8fc2340620695a402331e5da7c7db43264174det rc = VERR_PDM_GEOMETRY_NOT_SET;
bf8fc2340620695a402331e5da7c7db43264174det LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
bf8fc2340620695a402331e5da7c7db43264174det return rc;
bf8fc2340620695a402331e5da7c7db43264174det}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PPDMMEDIAGEOMETRY pLCHSGeometry)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s:\n", __FUNCTION__));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDGetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (RT_FAILURE(rc))
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet Log(("%s: geometry not available.\n", __FUNCTION__));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rc = VERR_PDM_GEOMETRY_NOT_SET;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %Rrc (CHS=%d/%d/%d)\n", __FUNCTION__,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return rc;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCPDMMEDIAGEOMETRY pLCHSGeometry)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDSetLCHSGeometry(pThis->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet if (rc == VERR_VD_GEOMETRY_NOT_SET)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet rc = VERR_PDM_GEOMETRY_NOT_SET;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return rc;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/** @copydoc PDMIMEDIA::pfnGetUuid */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s:\n", __FUNCTION__));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIA_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDGetUuid(pThis->pDisk, 0, pUuid);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %Rrc ({%RTuuid})\n", __FUNCTION__, rc, pUuid));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return rc;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Async Media interface methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdStartRead(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PPDMDATASEG paSeg, unsigned cSeg,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet size_t cbRead, void *pvUser)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbRead=%d\n pvUser=%#p", __FUNCTION__,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uOffset, paSeg, cSeg, cbRead, pvUser));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VDAsyncRead(pThis->pDisk, uOffset, cbRead, paSeg, cSeg, pvUser);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return rc;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdStartWrite(PPDMIMEDIAASYNC pInterface, uint64_t uOffset,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PPDMDATASEG paSeg, unsigned cSeg,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet size_t cbWrite, void *pvUser)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
f8d2de6bd2421da1926f3daa456d161670decdf7jchu LogFlow(("%s: uOffset=%#llx paSeg=%#p cSeg=%u cbWrite=%d\n pvUser=%#p", __FUNCTION__,
f8d2de6bd2421da1926f3daa456d161670decdf7jchu uOffset, paSeg, cSeg, cbWrite, pvUser));
f8d2de6bd2421da1926f3daa456d161670decdf7jchu PVBOXDISK pThis = PDMIMEDIAASYNC_2_VBOXDISK(pInterface);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu int rc = VDAsyncWrite(pThis->pDisk, uOffset, cbWrite, paSeg, cSeg, pvUser);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return rc;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Async transport port interface methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdTasksCompleteNotify(PPDMDRVINS pDrvIns, void *pvUser)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return VERR_NOT_IMPLEMENTED;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Base interface methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu/** @copydoc PDMIBASE::pfnQueryInterface */
f8d2de6bd2421da1926f3daa456d161670decdf7jchustatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PDMINTERFACE enmInterface)
f8d2de6bd2421da1926f3daa456d161670decdf7jchu{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet switch (enmInterface)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet {
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case PDMINTERFACE_BASE:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return &pDrvIns->IBase;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case PDMINTERFACE_MEDIA:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return &pThis->IMedia;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet case PDMINTERFACE_MEDIA_ASYNC:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return pThis->fAsyncIOSupported ? &pThis->IMediaAsync : NULL;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet default:
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet return NULL;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet }
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet}
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/*******************************************************************************
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet* Driver methods *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet*******************************************************************************/
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet/**
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Construct a VBox disk media driver instance.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet *
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * @copydoc FNPDMDRVCONSTRUCT
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreetstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PCFGMNODE pCfgHandle,
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet uint32_t fFlags)
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet{
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet LogFlow(("%s:\n", __FUNCTION__));
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet int rc = VINF_SUCCESS;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char *pszName = NULL; /**< The path of the disk image file. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet char *pszFormat = NULL; /**< The format backed to use for this image. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet bool fReadOnly; /**< True if the media is readonly. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet bool fHonorZeroWrites; /**< True if zero blocks should be written. */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /*
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet * Init the static parts.
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->pDrvIns = pDrvIns;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->fTempReadOnly = false;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->pDisk = NULL;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->fAsyncIOSupported = false;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet /* IMedia */
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->IMedia.pfnRead = drvvdRead;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->IMedia.pfnWrite = drvvdWrite;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMedia.pfnFlush = drvvdFlush;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMedia.pfnGetSize = drvvdGetSize;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMedia.pfnIsReadOnly = drvvdIsReadOnly;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
00d0963faf2e861a4aef6b1bf28f99a5b2b20755dilpreet pThis->IMedia.pfnGetUuid = drvvdGetUuid;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* IMediaAsync */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMediaAsync.pfnStartRead = drvvdStartRead;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->IMediaAsync.pfnStartWrite = drvvdStartWrite;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu /* Initialize supported VD interfaces. */
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->pVDIfsDisk = NULL;
f8d2de6bd2421da1926f3daa456d161670decdf7jchu
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->VDIErrorCallbacks.cbSize = sizeof(VDINTERFACEERROR);
f8d2de6bd2421da1926f3daa456d161670decdf7jchu pThis->VDIErrorCallbacks.enmInterface = VDINTERFACETYPE_ERROR;
pThis->VDIErrorCallbacks.pfnError = drvvdErrorCallback;
pThis->VDIErrorCallbacks.pfnMessage = NULL;
rc = VDInterfaceAdd(&pThis->VDIError, "DrvVD_VDIError", VDINTERFACETYPE_ERROR,
&pThis->VDIErrorCallbacks, pDrvIns, &pThis->pVDIfsDisk);
AssertRC(rc);
#ifdef VBOX_WITH_PDM_ASYNC_COMPLETION
pThis->VDIAsyncIOCallbacks.cbSize = sizeof(VDINTERFACEASYNCIO);
pThis->VDIAsyncIOCallbacks.enmInterface = VDINTERFACETYPE_ASYNCIO;
pThis->VDIAsyncIOCallbacks.pfnOpen = drvvdAsyncIOOpen;
pThis->VDIAsyncIOCallbacks.pfnClose = drvvdAsyncIOClose;
pThis->VDIAsyncIOCallbacks.pfnGetSize = drvvdAsyncIOGetSize;
pThis->VDIAsyncIOCallbacks.pfnReadSync = drvvdAsyncIOReadSync;
pThis->VDIAsyncIOCallbacks.pfnWriteSync = drvvdAsyncIOWriteSync;
pThis->VDIAsyncIOCallbacks.pfnFlushSync = drvvdAsyncIOFlushSync;
pThis->VDIAsyncIOCallbacks.pfnReadAsync = drvvdAsyncIOReadAsync;
pThis->VDIAsyncIOCallbacks.pfnWriteAsync = drvvdAsyncIOWriteAsync;
pThis->VDIAsyncIOCallbacks.pfnFlushAsync = drvvdAsyncIOFlushAsync;
rc = VDInterfaceAdd(&pThis->VDIAsyncIO, "DrvVD_AsyncIO", VDINTERFACETYPE_ASYNCIO,
&pThis->VDIAsyncIOCallbacks, pThis, &pThis->pVDIfsDisk);
AssertRC(rc);
#endif
/* This is just prepared here, the actual interface is per-image, so it's
* added later. No need to have separate callback tables. */
pThis->VDIConfigCallbacks.cbSize = sizeof(VDINTERFACECONFIG);
pThis->VDIConfigCallbacks.enmInterface = VDINTERFACETYPE_CONFIG;
pThis->VDIConfigCallbacks.pfnAreKeysValid = drvvdCfgAreKeysValid;
pThis->VDIConfigCallbacks.pfnQuerySize = drvvdCfgQuerySize;
pThis->VDIConfigCallbacks.pfnQuery = drvvdCfgQuery;
/* List of images is empty now. */
pThis->pImages = NULL;
/* Try to attach async media port interface above.*/
pThis->pDrvMediaAsyncPort = (PPDMIMEDIAASYNCPORT)pDrvIns->pUpBase->pfnQueryInterface(pDrvIns->pUpBase, PDMINTERFACE_MEDIA_ASYNC_PORT);
/*
* Attach the async transport driver below if the device above us implements the
* async interface.
*/
if (pThis->pDrvMediaAsyncPort)
{
/* Try to attach the driver. */
PPDMIBASE pBase;
rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
if (rc == VERR_PDM_NO_ATTACHED_DRIVER)
{
/*
* Though the device supports async I/O there is no transport driver
* which processes async requests.
* Revert to non async I/O.
*/
rc = VINF_SUCCESS;
pThis->pDrvMediaAsyncPort = NULL;
pThis->fAsyncIOSupported = false;
}
else if (RT_FAILURE(rc))
{
AssertMsgFailed(("Failed to attach async transport driver below rc=%Rrc\n", rc));
}
else
{
/*
* The device supports async I/O and we successfully attached the transport driver.
* Indicate that async I/O is supported for now as we check if the image backend supports
* it later.
*/
pThis->fAsyncIOSupported = true;
/** @todo: Use PDM async completion manager */
}
}
/*
* Validate configuration and find all parent images.
* It's sort of up side down from the image dependency tree.
*/
bool fHostIP = false;
unsigned iLevel = 0;
PCFGMNODE pCurNode = pCfgHandle;
for (;;)
{
bool fValid;
if (pCurNode == pCfgHandle)
{
/* Toplevel configuration additionally contains the global image
* open flags. Some might be converted to per-image flags later. */
fValid = CFGMR3AreValuesValid(pCurNode,
"Format\0Path\0"
"ReadOnly\0HonorZeroWrites\0"
"HostIPStack\0");
}
else
{
/* All other image configurations only contain image name and
* the format information. */
fValid = CFGMR3AreValuesValid(pCurNode, "Format\0Path\0");
}
if (!fValid)
{
rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
RT_SRC_POS, N_("DrvVD: Configuration error: keys incorrect at level %d"), iLevel);
break;
}
if (pCurNode == pCfgHandle)
{
rc = CFGMR3QueryBool(pCurNode, "HostIPStack", &fHostIP);
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
{
fHostIP = true;
rc = VINF_SUCCESS;
}
else if (RT_FAILURE(rc))
{
rc = PDMDRV_SET_ERROR(pDrvIns, rc,
N_("DrvVD: Configuration error: Querying \"HostIPStack\" as boolean failed"));
break;
}
rc = CFGMR3QueryBool(pCurNode, "HonorZeroWrites", &fHonorZeroWrites);
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
{
fHonorZeroWrites = false;
rc = VINF_SUCCESS;
}
else if (RT_FAILURE(rc))
{
rc = PDMDRV_SET_ERROR(pDrvIns, rc,
N_("DrvVD: Configuration error: Querying \"HonorZeroWrites\" as boolean failed"));
break;
}
rc = CFGMR3QueryBool(pCurNode, "ReadOnly", &fReadOnly);
if (rc == VERR_CFGM_VALUE_NOT_FOUND)
{
fReadOnly = false;
rc = VINF_SUCCESS;
}
else if (RT_FAILURE(rc))
{
rc = PDMDRV_SET_ERROR(pDrvIns, rc,
N_("DrvVD: Configuration error: Querying \"ReadOnly\" as boolean failed"));
break;
}
}
PCFGMNODE pParent = CFGMR3GetChild(pCurNode, "Parent");
if (!pParent)
break;
pCurNode = pParent;
iLevel++;
}
/*
* Open the images.
*/
if (RT_SUCCESS(rc))
{
/* First of all figure out what kind of TCP networking stack interface
* to use. This is done unconditionally, as backends which don't need
* it will just ignore it. */
if (fHostIP)
{
pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET);
pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET;
pThis->VDITcpNetCallbacks.pfnClientConnect = RTTcpClientConnect;
pThis->VDITcpNetCallbacks.pfnClientClose = RTTcpClientClose;
pThis->VDITcpNetCallbacks.pfnSelectOne = RTTcpSelectOne;
pThis->VDITcpNetCallbacks.pfnRead = RTTcpRead;
pThis->VDITcpNetCallbacks.pfnWrite = RTTcpWrite;
pThis->VDITcpNetCallbacks.pfnFlush = RTTcpFlush;
}
else
{
#ifndef VBOX_WITH_INIP
rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
RT_SRC_POS, N_("DrvVD: Configuration error: TCP over Internal Networking not compiled in"));
#else /* VBOX_WITH_INIP */
pThis->VDITcpNetCallbacks.cbSize = sizeof(VDINTERFACETCPNET);
pThis->VDITcpNetCallbacks.enmInterface = VDINTERFACETYPE_TCPNET;
pThis->VDITcpNetCallbacks.pfnClientConnect = drvvdINIPClientConnect;
pThis->VDITcpNetCallbacks.pfnClientClose = drvvdINIPClientClose;
pThis->VDITcpNetCallbacks.pfnSelectOne = drvvdINIPSelectOne;
pThis->VDITcpNetCallbacks.pfnRead = drvvdINIPRead;
pThis->VDITcpNetCallbacks.pfnWrite = drvvdINIPWrite;
pThis->VDITcpNetCallbacks.pfnFlush = drvvdINIPFlush;
#endif /* VBOX_WITH_INIP */
}
if (RT_SUCCESS(rc))
{
rc = VDInterfaceAdd(&pThis->VDITcpNet, "DrvVD_INIP",
VDINTERFACETYPE_TCPNET,
&pThis->VDITcpNetCallbacks, NULL,
&pThis->pVDIfsDisk);
}
if (RT_SUCCESS(rc))
{
rc = VDCreate(pThis->pVDIfsDisk, &pThis->pDisk);
/* Error message is already set correctly. */
}
}
while (pCurNode && RT_SUCCESS(rc))
{
/* Allocate per-image data. */
PVBOXIMAGE pImage = drvvdNewImage(pThis);
if (!pImage)
{
rc = VERR_NO_MEMORY;
break;
}
/*
* Read the image configuration.
*/
rc = CFGMR3QueryStringAlloc(pCurNode, "Path", &pszName);
if (RT_FAILURE(rc))
{
rc = PDMDRV_SET_ERROR(pDrvIns, rc,
N_("DrvVD: Configuration error: Querying \"Path\" as string failed"));
break;
}
rc = CFGMR3QueryStringAlloc(pCurNode, "Format", &pszFormat);
if (RT_FAILURE(rc))
{
rc = PDMDRV_SET_ERROR(pDrvIns, rc,
N_("DrvVD: Configuration error: Querying \"Format\" as string failed"));
break;
}
PCFGMNODE pCfg = CFGMR3GetChild(pCurNode, "VDConfig");
rc = VDInterfaceAdd(&pImage->VDIConfig, "DrvVD_Config", VDINTERFACETYPE_CONFIG,
&pThis->VDIConfigCallbacks, pCfg, &pImage->pVDIfsImage);
AssertRC(rc);
/*
* Open the image.
*/
unsigned uOpenFlags;
if (fReadOnly || iLevel != 0)
uOpenFlags = VD_OPEN_FLAGS_READONLY;
else
uOpenFlags = VD_OPEN_FLAGS_NORMAL;
if (fHonorZeroWrites)
uOpenFlags |= VD_OPEN_FLAGS_HONOR_ZEROES;
if (pThis->pDrvMediaAsyncPort)
uOpenFlags |= VD_OPEN_FLAGS_ASYNC_IO;
/* Try to open backend in asyc I/O mode first. */
rc = VDOpen(pThis->pDisk, pszFormat, pszName, uOpenFlags, pImage->pVDIfsImage);
if (rc == VERR_NOT_SUPPORTED)
{
/* Seems async I/O is not supported by the backend, open in normal mode. */
uOpenFlags &= ~VD_OPEN_FLAGS_ASYNC_IO;
rc = VDOpen(pThis->pDisk, pszFormat, pszName, uOpenFlags, pImage->pVDIfsImage);
}
if (RT_SUCCESS(rc))
{
Log(("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__,
iLevel, pszName,
VDIsReadOnly(pThis->pDisk) ? "read-only" : "read-write"));
if ( VDIsReadOnly(pThis->pDisk)
&& !fReadOnly
&& iLevel == 0)
{
rc = PDMDrvHlpVMSetError(pDrvIns, VERR_VD_IMAGE_READ_ONLY, RT_SRC_POS,
N_("Failed to open image '%s' for writing due to wrong "
"permissions"), pszName);
break;
}
}
else
{
rc = PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
N_("Failed to open image '%s' in %s mode rc=%Rrc"), pszName,
(uOpenFlags & VD_OPEN_FLAGS_READONLY) ? "readonly" : "read-write", rc);
break;
}
MMR3HeapFree(pszName);
pszName = NULL;
MMR3HeapFree(pszFormat);
pszFormat = NULL;
/* next */
iLevel--;
pCurNode = CFGMR3GetParent(pCurNode);
}
if (RT_FAILURE(rc))
{
if (VALID_PTR(pThis->pDisk))
{
VDDestroy(pThis->pDisk);
pThis->pDisk = NULL;
}
drvvdFreeImages(pThis);
if (VALID_PTR(pszName))
MMR3HeapFree(pszName);
if (VALID_PTR(pszFormat))
MMR3HeapFree(pszFormat);
return rc;
}
else
{
/*
* Check if every opened image supports async I/O.
* If not we revert to non async I/O.
*/
if (pThis->fAsyncIOSupported)
{
for (unsigned i = 0; i < VDGetCount(pThis->pDisk); i++)
{
VDBACKENDINFO vdBackendInfo;
rc = VDBackendInfoSingle(pThis->pDisk, i, &vdBackendInfo);
AssertRC(rc);
if (vdBackendInfo.uBackendCaps & VD_CAP_ASYNC)
{
/*
* Backend indicates support for at least some files.
* Check if current file is supported with async I/O)
*/
rc = VDImageIsAsyncIOSupported(pThis->pDisk, i, &pThis->fAsyncIOSupported);
AssertRC(rc);
/*
* Check if current image is supported.
* If not we can stop checking because
* at least one does not support it.
*/
if (!pThis->fAsyncIOSupported)
break;
}
else
{
pThis->fAsyncIOSupported = false;
break;
}
}
}
/* Switch to runtime error facility. */
pThis->fErrorUseRuntime = true;
}
LogFlow(("%s: returns %Rrc\n", __FUNCTION__, rc));
return rc;
}
/**
* Destruct a driver instance.
*
* Most VM resources are freed by the VM. This callback is provided so that any non-VM
* resources can be freed correctly.
*
* @param pDrvIns The driver instance data.
*/
static DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns)
{
PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
LogFlow(("%s:\n", __FUNCTION__));
drvvdFreeImages(pThis);
}
/**
* When the VM has been suspended we'll change the image mode to read-only
* so that main and others can read the VDIs. This is important when
* saving state and so forth.
*
* @param pDrvIns The driver instance data.
*/
static DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
{
LogFlow(("%s:\n", __FUNCTION__));
PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
if (!VDIsReadOnly(pThis->pDisk))
{
unsigned uOpenFlags;
int rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
AssertRC(rc);
uOpenFlags |= VD_OPEN_FLAGS_READONLY;
rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
AssertRC(rc);
pThis->fTempReadOnly = true;
}
}
/**
* Before the VM resumes we'll have to undo the read-only mode change
* done in drvvdSuspend.
*
* @param pDrvIns The driver instance data.
*/
static DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
{
LogFlow(("%s:\n", __FUNCTION__));
PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
if (pThis->fTempReadOnly)
{
unsigned uOpenFlags;
int rc = VDGetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, &uOpenFlags);
AssertRC(rc);
uOpenFlags &= ~VD_OPEN_FLAGS_READONLY;
rc = VDSetOpenFlags(pThis->pDisk, VD_LAST_IMAGE, uOpenFlags);
AssertRC(rc);
pThis->fTempReadOnly = false;
}
}
static DECLCALLBACK(void) drvvdPowerOff(PPDMDRVINS pDrvIns)
{
LogFlow(("%s:\n", __FUNCTION__));
PVBOXDISK pThis = PDMINS_2_DATA(pDrvIns, PVBOXDISK);
/*
* We must close the disk here to ensure that
* the backend closes all files before the
* async transport driver is destructed.
*/
int rc = VDCloseAll(pThis->pDisk);
AssertRC(rc);
}
/**
* VBox disk container media driver registration record.
*/
const PDMDRVREG g_DrvVD =
{
/* u32Version */
PDM_DRVREG_VERSION,
/* szDriverName */
"VD",
/* pszDescription */
"Generic VBox disk media driver.",
/* fFlags */
PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
/* fClass. */
PDM_DRVREG_CLASS_MEDIA,
/* cMaxInstances */
~0,
/* cbInstance */
sizeof(VBOXDISK),
/* pfnConstruct */
drvvdConstruct,
/* pfnDestruct */
drvvdDestruct,
/* pfnIOCtl */
NULL,
/* pfnPowerOn */
NULL,
/* pfnReset */
NULL,
/* pfnSuspend */
drvvdSuspend,
/* pfnResume */
drvvdResume,
/* pfnAttach */
NULL,
/* pfnDetach */
NULL,
/* pfnPowerOff */
drvvdPowerOff,
/* pfnSoftReset */
NULL,
/* u32EndVersion */
PDM_DRVREG_VERSION
};