DrvDiskIntegrity.cpp revision bf27591c0d413dd4d7ba41cf89f117171968d462
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/* $Id$ */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @file
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * VBox storage devices: Disk integrity check.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/*
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Copyright (C) 2006-2010 Sun Microsystems, Inc.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * This file is part of VirtualBox Open Source Edition (OSE), as
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * available from http://www.virtualbox.org. This file is free software;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * you can redistribute it and/or modify it under the terms of the GNU
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * General Public License (GPL) as published by the Free Software
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Foundation, in version 2 as it comes in the "COPYING" file of the
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Clara, CA 95054 USA or visit http://www.sun.com if you need
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * additional information or have any questions.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/*******************************************************************************
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync* Header Files *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync*******************************************************************************/
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#define LOG_GROUP LOG_GROUP_DRV_DISK_INTEGRITY
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <VBox/pdmdrv.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/assert.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/string.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/uuid.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/avl.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include <iprt/mem.h>
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync#include <iprt/message.h>
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#include "Builtins.h"
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/*******************************************************************************
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync* Structures and Typedefs *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync*******************************************************************************/
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync/**
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync * I/O log entry.
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsynctypedef struct IOLOGENT
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync{
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Start offset */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync uint64_t off;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Write size */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync size_t cbWrite;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Number of references to this entry. */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync unsigned cRefs;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync} IOLOGENT, *PIOLOGENT;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Disk segment.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsynctypedef struct DRVDISKSEGMENT
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** AVL core. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync AVLRFOFFNODECORE Core;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Size of the segment */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbSeg;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Data for this segment */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync uint8_t *pbSeg;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Numbner of entries in the I/O array. */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync unsigned cIoLogEntries;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /** Array of I/O log references. */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync PIOLOGENT apIoLog[1];
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync} DRVDISKSEGMENT, *PDRVDISKSEGMENT;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Disk integrity driver instance data.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @implements PDMIMEDIA
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsynctypedef struct DRVDISKINTEGRITY
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Pointer driver instance. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMDRVINS pDrvIns;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Pointer to the media driver below us.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * This is NULL if the media is not mounted. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMIMEDIA pDrvMedia;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Our media interface */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMIMEDIA IMedia;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** AVL tree containing the disk blocks to check. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PAVLRFOFFTREE pTreeSegments;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync} DRVDISKINTEGRITY, *PDRVDISKINTEGRITY;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/* -=-=-=-=- IMedia -=-=-=-=- */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** Makes a PDRVDISKINTEGRITY out of a PPDMIMEDIA. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync#define PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface) ( (PDRVDISKINTEGRITY)((uintptr_t)pInterface - RT_OFFSETOF(DRVDISKINTEGRITY, IMedia)) )
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/*******************************************************************************
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync* Media interface methods *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync*******************************************************************************/
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnRead */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintRead(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync uint64_t off, void *pvBuf, size_t cbRead)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync int rc = pThis->pDrvMedia->pfnRead(pThis->pDrvMedia, off, pvBuf, cbRead);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (RT_FAILURE(rc))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(off % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(cbRead % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Compare read data */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbLeft = cbRead;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTFOFF offCurr = (RTFOFF)off;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync uint8_t *pbBuf = (uint8_t *)pvBuf;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync while (cbLeft)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbRange = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync bool fCmp = false;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync unsigned offSeg = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Get next segment */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* No data in the tree for this read. Assume everything is ok. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbRange = cbLeft;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else if (offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbRange = cbLeft;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbRange = pSeg->Core.Key - offCurr;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync fCmp = true;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync offSeg = offCurr - pSeg->Core.Key;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if ( fCmp
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync && memcmp(pbBuf, pSeg->pbSeg + offSeg, cbRange))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync unsigned offWrong = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync for (offWrong = 0; offWrong < cbRange; offWrong++)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (pbBuf[offWrong] != pSeg->pbSeg[offSeg + offWrong])
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync {
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /* Corrupted disk, print I/O log entry of the last write which accessed this range. */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync uint32_t cSector = (offSeg + offWrong) / 512;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync AssertMsg(cSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync RTMsgError("Corrupted disk at offset %llu (%u bytes in the current read buffer)!\n",
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync offCurr + offWrong, offWrong);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync RTMsgError("Last write to this sector started at offset %llu with %u bytes (%u references to this log entry)\n",
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->apIoLog[cSector]->off,
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->apIoLog[cSector]->cbWrite,
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->apIoLog[cSector]->cRefs);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync RTAssertDebugBreak();
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync offCurr += cbRange;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbLeft -= cbRange;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pbBuf += cbRange;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnWrite */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintWrite(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync uint64_t off, const void *pvBuf,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbWrite)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync int rc = pThis->pDrvMedia->pfnWrite(pThis->pDrvMedia, off, pvBuf, cbWrite);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (RT_FAILURE(rc))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Update the segments */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbLeft = cbWrite;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTFOFF offCurr = (RTFOFF)off;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync uint8_t *pbBuf = (uint8_t *)pvBuf;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync PIOLOGENT pIoLogEnt = (PIOLOGENT)RTMemAllocZ(sizeof(IOLOGENT));
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync if (!pIoLogEnt)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync return VERR_NO_MEMORY;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->off = off;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->cbWrite = cbWrite;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->cRefs = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync while (cbLeft)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetRangeGet(pThis->pTreeSegments, offCurr);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync size_t cbRange = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync bool fSet = false;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync unsigned offSeg = 0;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Get next segment */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pSeg = (PDRVDISKSEGMENT)RTAvlrFileOffsetGetBestFit(pThis->pTreeSegments, offCurr, true);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if ( !pSeg
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync || offCurr + (RTFOFF)cbLeft <= pSeg->Core.Key)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbRange = cbLeft;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbRange = pSeg->Core.Key - offCurr;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(cbRange % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* Create new segment */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg = (PDRVDISKSEGMENT)RTMemAllocZ(RT_OFFSETOF(DRVDISKSEGMENT, apIoLog[cbRange / 512]));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (pSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->Core.Key = offCurr;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->Core.KeyLast = offCurr + (RTFOFF)cbRange - 1;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->cbSeg = cbRange;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->pbSeg = (uint8_t *)RTMemAllocZ(cbRange);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->cIoLogEntries = cbRange / 512;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pSeg->pbSeg)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pSeg);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync bool fInserted = RTAvlrFileOffsetInsert(pThis->pTreeSegments, &pSeg->Core);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync AssertMsg(fInserted, ("Bug!\n"));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync fSet = true;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync else
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync fSet = true;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync offSeg = offCurr - pSeg->Core.Key;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync cbRange = RT_MIN(cbLeft, (size_t)(pSeg->Core.KeyLast + 1 - offCurr));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (fSet)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync AssertPtr(pSeg);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync memcpy(pSeg->pbSeg + offSeg, pbBuf, cbRange);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync /* Update the I/O log pointers */
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(offSeg % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync Assert(cbRange % 512 == 0);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync while (offSeg < cbRange)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync {
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync uint32_t uSector = offSeg / 512;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync PIOLOGENT pIoLogOld = NULL;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync AssertMsg(uSector < pSeg->cIoLogEntries, ("Internal bug!\n"));
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogOld = pSeg->apIoLog[uSector];
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync if (pIoLogOld)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync {
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogOld->cRefs--;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync if (!pIoLogOld->cRefs)
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync RTMemFree(pIoLogOld);
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync }
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pSeg->apIoLog[uSector] = pIoLogEnt;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync pIoLogEnt->cRefs++;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync offSeg += 512;
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync offCurr += cbRange;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync cbLeft -= cbRange;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pbBuf += cbRange;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnFlush */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintFlush(PPDMIMEDIA pInterface)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnFlush(pThis->pDrvMedia);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnGetSize */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(uint64_t) drvdiskintGetSize(PPDMIMEDIA pInterface)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnGetSize(pThis->pDrvMedia);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnIsReadOnly */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(bool) drvdiskintIsReadOnly(PPDMIMEDIA pInterface)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnIsReadOnly(pThis->pDrvMedia);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetPCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMMEDIAGEOMETRY pPCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosGetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosSetPCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PCPDMMEDIAGEOMETRY pPCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosSetPCHSGeometry(pThis->pDrvMedia, pPCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosGetLCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMMEDIAGEOMETRY pLCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosGetLCHSGeometry(pThis->pDrvMedia, pLCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintBiosSetLCHSGeometry(PPDMIMEDIA pInterface,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PCPDMMEDIAGEOMETRY pLCHSGeometry)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnBiosSetLCHSGeometry(pThis->pDrvMedia, pLCHSGeometry);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/** @copydoc PDMIMEDIA::pfnGetUuid */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMIMEDIA_2_DRVDISKINTEGRITY(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return pThis->pDrvMedia->pfnGetUuid(pThis->pDrvMedia, pUuid);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/* -=-=-=-=- IBase -=-=-=-=- */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @interface_method_impl{PDMIBASE,pfnQueryInterface}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(void *) drvdiskintQueryInterface(PPDMIBASE pInterface, const char *pszIID)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMDRVINS pDrvIns = PDMIBASE_2_PDMDRV(pInterface);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return NULL;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/* -=-=-=-=- driver interface -=-=-=-=- */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic int drvdiskintTreeDestroy(PAVLRFOFFNODECORE pNode, void *pvUser)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKSEGMENT pSeg = (PDRVDISKSEGMENT)pNode;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pSeg->pbSeg);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pSeg);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return VINF_SUCCESS;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @copydoc FNPDMDRVDESTRUCT
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(void) drvdiskintDestruct(PPDMDRVINS pDrvIns)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (pThis->pTreeSegments)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync {
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTAvlrFileOffsetDestroy(pThis->pTreeSegments, drvdiskintTreeDestroy, NULL);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync RTMemFree(pThis->pTreeSegments);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync }
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Construct a disk integrity driver instance.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync *
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * @copydoc FNPDMDRVCONSTRUCT
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncstatic DECLCALLBACK(int) drvdiskintConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDRVDISKINTEGRITY pThis = PDMINS_2_DATA(pDrvIns, PDRVDISKINTEGRITY);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync LogFlow(("drvdiskintConstruct: iInstance=%d\n", pDrvIns->iInstance));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /*
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Validate configuration.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!CFGMR3AreValuesValid(pCfg, ""))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /*
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Initialize most of the data members.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->pDrvIns = pDrvIns;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* IBase. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pDrvIns->IBase.pfnQueryInterface = drvdiskintQueryInterface;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* IMedia */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnRead = drvdiskintRead;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnWrite = drvdiskintWrite;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnFlush = drvdiskintFlush;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnGetSize = drvdiskintGetSize;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnIsReadOnly = drvdiskintIsReadOnly;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosGetPCHSGeometry = drvdiskintBiosGetPCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosSetPCHSGeometry = drvdiskintBiosSetPCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosGetLCHSGeometry = drvdiskintBiosGetLCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnBiosSetLCHSGeometry = drvdiskintBiosSetLCHSGeometry;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->IMedia.pfnGetUuid = drvdiskintGetUuid;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /*
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Try attach driver below and query it's media interface.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PPDMIBASE pBase;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync int rc = PDMDrvHlpAttach(pDrvIns, fFlags, &pBase);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (RT_FAILURE(rc))
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync N_("Failed to attach driver below us! %Rrf"), rc);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->pDrvMedia = PDMIBASE_QUERY_INTERFACE(pBase, PDMIMEDIA);
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pThis->pDrvMedia)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync return PDMDRV_SET_ERROR(pDrvIns, VERR_PDM_MISSING_INTERFACE_BELOW,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync N_("No media or async media interface below"));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /** Create the AVL tree. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync pThis->pTreeSegments = (PAVLRFOFFTREE)RTMemAllocZ(sizeof(AVLRFOFFTREE));
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync if (!pThis->pTreeSegments)
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync rc = VERR_NO_MEMORY;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
bf27591c0d413dd4d7ba41cf89f117171968d462vboxsync return rc;
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync}
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync/**
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync * Block driver registration record.
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsyncconst PDMDRVREG g_DrvDiskIntegrity =
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync{
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* u32Version */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_VERSION,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* szName */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "DiskIntegrity",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* szRCMod */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* szR0Mod */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pszDescription */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync "Disk integrity driver.",
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* fFlags */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* fClass. */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_CLASS_BLOCK,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* cMaxInstances */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync ~0,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* cbInstance */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync sizeof(DRVDISKINTEGRITY),
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnConstruct */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync drvdiskintConstruct,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnDestruct */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync drvdiskintDestruct,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnRelocate */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnIOCtl */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnPowerOn */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnReset */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnSuspend */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnResume */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnAttach */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnDetach */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnPowerOff */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* pfnSoftReset */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync NULL,
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync /* u32EndVersion */
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync PDM_DRVREG_VERSION
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync};
fb7b8c126ea3bc0adf9dd2b2b6a43870ee41853avboxsync