DrvVD.cpp revision 8083a259c13e6e26e56ca2582edbad4a8cfac25a
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** $Id$ */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @file
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox storage devices:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Media implementation for VBox disk container
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * Copyright (C) 2006-2008 innotek GmbH
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * available from http://www.virtualbox.org. This file is free software;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * you can redistribute it and/or modify it under the terms of the GNU
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * General Public License (GPL) as published by the Free Software
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
a16eb14ad7a4b5ef91ddc22d3e8e92d930f736fcvboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Header files *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define LOG_GROUP LOG_GROUP_DRV_VD
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <VBox/VBoxHDD-new.h>
da957c069c2a3c582fe265ff88170ce4c42b499dvboxsync#include <VBox/pdmdrv.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/alloc.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/assert.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/uuid.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/file.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include <iprt/string.h>
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#include "Builtins.h"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Defined types, constants and macros *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to VDIDISK::IMedia to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIMEDIA_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PVBOXDISK)((uintptr_t)pInterface - RT_OFFSETOF(VBOXDISK, IMedia)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIBASE_2_DRVINS(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** Converts a pointer to PDMDRVINS::IBase to a PVBOXDISK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync#define PDMIBASE_2_VBOXDISK(pInterface) \
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ( PDMINS2DATA(PDMIBASE_2_DRVINS(pInterface), PVBOXDISK) )
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox disk container media main structure, private part.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsynctypedef struct VBOXDISK
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The VBox disk container. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXHDD pDisk;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** The media interface. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDMIMEDIA IMedia;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Pointer to the driver instance. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMDRVINS pDrvIns;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Name of the image format backend. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync char szFormat[16];
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /** Flag whether suspend has changed image open mode to read only. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fTempReadOnly;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync} VBOXDISK, *PVBOXDISK;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Error reporting callback *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync const char *pszFormat, va_list va)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMDRVINS pDrvIns = (PPDMDRVINS)pvUser;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pDrvIns->pDrvHlp->pfnVMSetErrorV(pDrvIns, rc, RT_SRC_POS_ARGS, pszFormat, va);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Media interface methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnRead */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync uint64_t off, void *pvBuf, size_t cbRead)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync off, pvBuf, cbRead));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDRead(pData->pDisk, off, pvBuf, cbRead);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (VBOX_SUCCESS(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log2(("%s: off=%#llx pvBuf=%p cbRead=%d %.*Vhxd\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync off, pvBuf, cbRead, cbRead, pvBuf));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnWrite */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync uint64_t off, const void *pvBuf,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync size_t cbWrite)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync off, pvBuf, cbWrite));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log2(("%s: off=%#llx pvBuf=%p cbWrite=%d %.*Vhxd\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync off, pvBuf, cbWrite, cbWrite, pvBuf));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDWrite(pData->pDisk, off, pvBuf, cbWrite);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnFlush */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDFlush(pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync uint64_t cb = VDGetSize(pData->pDisk, VD_LAST_IMAGE);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return cb;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool f = VDIsReadOnly(pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %d\n", __FUNCTION__, f));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return f;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync PPDMMEDIAGEOMETRY pPCHSGeometry)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (VBOX_FAILURE(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync PCPDMMEDIAGEOMETRY pPCHSGeometry)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDSetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync PPDMMEDIAGEOMETRY pLCHSGeometry)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync if (VBOX_FAILURE(rc))
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync Log(("%s: geometry not available.\n", __FUNCTION__));
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VERR_PDM_GEOMETRY_NOT_SET;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync }
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync PCPDMMEDIAGEOMETRY pLCHSGeometry)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDSetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry);
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDGetUuid(pData->pDisk, 0, pUuid);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc ({%Vuuid})\n", __FUNCTION__, rc, pUuid));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Base interface methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/** @copydoc PDMIBASE::pfnQueryInterface */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync PDMINTERFACE enmInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync switch (enmInterface)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case PDMINTERFACE_BASE:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return &pDrvIns->IBase;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync case PDMINTERFACE_MEDIA:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return &pData->IMedia;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync default:
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return NULL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/*******************************************************************************
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync* Driver methods *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync*******************************************************************************/
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Construct a VBox disk media driver instance.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @returns VBox status.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * If the registration structure is needed, pDrvIns->pDrvReg points to it.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * of the driver instance. It's also found in pDrvIns->pCfgHandle as it's expected
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * to be used frequently in this function.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns,
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync PCFGMNODE pCfgHandle)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VINF_SUCCESS;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync char *pszName; /**< The path of the disk image file. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fReadOnly; /**< True if the media is readonly. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fHonorZeroWrites; /**< True if zero blocks should be written. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Init the static parts.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->pDrvIns = pDrvIns;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->fTempReadOnly = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* IMedia */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnRead = drvvdRead;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnWrite = drvvdWrite;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnFlush = drvvdFlush;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnGetSize = drvvdGetSize;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnIsReadOnly = drvvdIsReadOnly;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync pData->IMedia.pfnGetUuid = drvvdGetUuid;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Validate configuration and find all parent images.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * It's sort of up side down from the image dependency tree.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned iLevel = 0;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCFGMNODE pCurNode = pCfgHandle;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync for (;;)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync bool fValid;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pCurNode == pCfgHandle)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Toplevel configuration contains the format backend name and
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * full image open information. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fValid = CFGMR3AreValuesValid(pCurNode,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "Format\0"
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "Path\0ReadOnly\0HonorZeroWrites\0");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* All other image configurations only contain image name. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fValid = CFGMR3AreValuesValid(pCurNode, "Path\0");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!fValid)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDrvHlpVMSetError(pDrvIns, VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync RT_SRC_POS, N_("DrvVD: Configuration error: keys incorrect at level %d"), iLevel);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PCFGMNODE pParent = CFGMR3GetChild(pCurNode, "Parent");
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!pParent)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCurNode = pParent;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync iLevel++;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Open the images.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (VBOX_SUCCESS(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryString(pCfgHandle, "Format", &pData->szFormat[0],
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync sizeof(pData->szFormat));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Default disk image format is VMDK. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VINF_SUCCESS;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync strncpy(&pData->szFormat[0], "VMDK", sizeof(pData->szFormat));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->szFormat[sizeof(pData->szFormat) - 1] = '\0';
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (VBOX_SUCCESS(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VDCreate(pData->szFormat, drvvdErrorCallback, pDrvIns, &pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* Error message is already set correctly. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"Format\" as string failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync while (pCurNode && VBOX_SUCCESS(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Read the image configuration.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryStringAlloc(pCurNode, "Path", &pszName);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (VBOX_FAILURE(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync VDDestroy(pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"Path\" as string failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (iLevel == 0)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryBool(pCurNode, "ReadOnly", &fReadOnly);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fReadOnly = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else if (VBOX_FAILURE(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync MMR3HeapFree(pszName);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync VDDestroy(pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"ReadOnly\" as boolean failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = CFGMR3QueryBool(pCfgHandle, "HonorZeroWrites", &fHonorZeroWrites);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (rc == VERR_CFGM_VALUE_NOT_FOUND)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fHonorZeroWrites = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else if (VBOX_FAILURE(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync MMR3HeapFree(pszName);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync VDDestroy(pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = PDMDRV_SET_ERROR(pDrvIns, rc,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync N_("DrvVD: Configuration error: Querying \"HonorZeroWrites\" as boolean failed"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fReadOnly = true;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync fHonorZeroWrites = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /*
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Open the image.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned uOpenFlags;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (fReadOnly)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uOpenFlags = VD_OPEN_FLAGS_READONLY;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uOpenFlags = VD_OPEN_FLAGS_NORMAL;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (fHonorZeroWrites)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uOpenFlags |= VD_OPEN_FLAGS_HONOR_ZEROES;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync rc = VDOpen(pData->pDisk, pszName, uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (VBOX_SUCCESS(rc))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync Log(("%s: %d - Opened '%s' in %s mode\n", __FUNCTION__,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync iLevel, pszName,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync VDIsReadOnly(pData->pDisk) ? "read-only" : "read-write"));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync else
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertMsgFailed(("Failed to open image '%s' rc=%Vrc\n", pszName, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync VDDestroy(pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync break;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync MMR3HeapFree(pszName);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* next */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync iLevel--;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pCurNode = CFGMR3GetParent(pCurNode);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync return rc;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Destruct a driver instance.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Most VM resources are freed by the VM. This callback is provided so that any non-VM
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * resources can be freed correctly.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync int rc = VDCloseAll(pData->pDisk);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * When the VM has been suspended we'll change the image mode to read-only
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * so that main and others can read the VDIs. This is important when
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * saving state and so forth.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (!VDIsReadOnly(pData->pDisk))
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned uOpenFlags;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uOpenFlags |= VD_OPEN_FLAGS_READONLY;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->fTempReadOnly = true;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * Before the VM resumes we'll have to undo the read-only mode change
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync * done in drvvdSuspend.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync *
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * @param pDrvIns The driver instance data.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsyncstatic DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync LogFlow(("%s:\n", __FUNCTION__));
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PVBOXDISK pData = PDMINS2DATA(pDrvIns, PVBOXDISK);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync if (pData->fTempReadOnly)
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync {
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync unsigned uOpenFlags;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync uOpenFlags &= ~VD_OPEN_FLAGS_READONLY;
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync AssertRC(rc);
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync pData->fTempReadOnly = false;
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync }
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync}
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync/**
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync * VBox disk container media driver registration record.
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsyncconst PDMDRVREG g_DrvVD =
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync{
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* u32Version */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDM_DRVREG_VERSION,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* szDriverName */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync "DrvVD",
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pszDescription */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync "Generic VBox disk media driver.",
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* fFlags */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* fClass. */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync PDM_DRVREG_CLASS_MEDIA,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* cMaxInstances */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync ~0,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* cbInstance */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync sizeof(VBOXDISK),
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnConstruct */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync drvvdConstruct,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnDestruct */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync drvvdDestruct,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnIOCtl */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NULL,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnPowerOn */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NULL,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnReset */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NULL,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnSuspend */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync drvvdSuspend,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnResume */
8083a259c13e6e26e56ca2582edbad4a8cfac25avboxsync drvvdResume,
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync /* pfnDetach */
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync NULL
a0240ff4f7663045c848fdbc192ea3d4d9f70a11vboxsync};