DrvHostBase.cpp revision 6fc2cd995fdffb6398f9c9c923064b5d8745e611
ae2463725fd7908cb1f99f4a9850776737fb2287vboxsync * DrvHostBase - Host base drive access driver.
* available from http://www.virtualbox.org. This file is free software;
* Clara, CA 95054 USA or visit http://www.sun.com if you need
#ifdef RT_OS_DARWIN
# include <errno.h>
# include <fcntl.h>
# include <errno.h>
# include <stropts.h>
# include <malloc.h>
# define WIN32_NO_STATUS
# include <Windows.h>
# include <dbt.h>
# include <ntstatus.h>
/* from ntdef.h */
/* from ntddk.h */
typedef struct _IO_STATUS_BLOCK {
/* from ntinternals.com */
typedef enum _FS_INFORMATION_CLASS {
typedef struct _FILE_FS_SIZE_INFORMATION {
# include <errno.h>
# include <stdio.h>
#include "DrvHostBase.h"
static DECLCALLBACK(int) drvHostBaseRead(PPDMIBLOCK pInterface, uint64_t off, void *pvBuf, size_t cbRead)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, off, pvBuf, cbRead, pThis->pszDevice));
int rc;
#ifdef RT_OS_DARWIN
SCSI_READ_12, 0,
Log(("%s-%d: drvHostBaseRead: RTFileSeek(%d,%#llx,) -> %Rrc\n", pThis->pDrvIns->pDrvReg->szDriverName,
LogFlow(("%s-%d: drvHostBaseRead: returns %Rrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
static DECLCALLBACK(int) drvHostBaseWrite(PPDMIBLOCK pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, off, pvBuf, cbWrite, pThis->pszDevice));
int rc;
LogFlow(("%s-%d: drvHostBaseWrite: returns %Rrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
int rc;
LogFlow(("%s-%d: drvHostBaseFlush: returns %Rrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
LogFlow(("%s-%d: drvHostBaseGetSize: returns %llu\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, cb));
return cb;
LogFlow(("%s-%d: drvHostBaseGetType: returns %d\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->enmType));
LogFlow(("%s-%d: drvHostBaseGetUuid: returns VINF_SUCCESS *pUuid=%RTuuid\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pUuid));
return VINF_SUCCESS;
#define PDMIBLOCKBIOS_2_DRVHOSTBASE(pInterface) ( (PDRVHOSTBASE((uintptr_t)pInterface - RT_OFFSETOF(DRVHOSTBASE, IBlockBios))) )
static DECLCALLBACK(int) drvHostBaseGetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, rc, pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors));
return rc;
static DECLCALLBACK(int) drvHostBaseSetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors));
return rc;
static DECLCALLBACK(int) drvHostBaseGetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, rc, pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors));
return rc;
static DECLCALLBACK(int) drvHostBaseSetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors));
return rc;
static DECLCALLBACK(int) drvHostBaseMount(PPDMIMOUNT pInterface, const char *pszFilename, const char *pszCoreDriver)
return VERR_PDM_MEDIA_MOUNTED;
return VERR_NOT_SUPPORTED;
return fRc;
LogFlow(("%s-%d: drvHostBaseLock: already locked\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
LogFlow(("%s-%d: drvHostBaseLock: returns %Rrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
LogFlow(("%s-%d: drvHostBaseUnlock: not locked\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
LogFlow(("%s-%d: drvHostBaseUnlock: returns %Rrc\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc));
return rc;
return fRc;
return NULL;
#ifdef RT_OS_DARWIN
# define MY_RUN_LOOP_MODE CFSTR("drvHostBaseDA") /** @todo r=bird: Check if this will cause trouble in the same way that the one in the USB code did. */
CFStringRef BSDNameStrRef = (CFStringRef)IORegistryEntryCreateCFProperty(Child, CFSTR(kIOBSDNameKey), kCFAllocatorDefault, 0);
if (BSDNameStrRef)
AssertFailed();
return rc;
static void drvHostBaseDADoneCallback(DADiskRef DiskRef, DADissenterRef DissenterRef, void *pvContext)
if (!DissenterRef)
*prc = 0;
SCSI_PREVENT_ALLOW_MEDIUM_REMOVAL, 0, 0, 0, false, 0,
return VINF_SUCCESS;
return VERR_DRIVE_LOCKED;
Log(("%s-%d: calling DADiskClaim on '%s'.\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, szName));
DADiskClaim(pThis->pDADisk, kDADiskClaimOptionDefault, NULL, NULL, drvHostBaseDADoneCallback, &rcDA);
&& !rcDA)
Log(("%s-%d: calling DADiskUnmount on '%s'.\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, szName));
&& !rcDA)
Log(("%s-%d: umount => rc32=%d & rcDA=%#x\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc32, rcDA));
Log(("%s-%d: claim => rc32=%d & rcDA=%#x\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, rc32, rcDA));
Log(("%s-%d: failed to open disk '%s'!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, szName));
#ifndef RT_OS_SOLARIS
#ifdef RT_OS_DARWIN
* (This enumeration must be identical to the one performed in DrvHostBase.cpp.)
CFDictionaryRef DevCharRef = (CFDictionaryRef)CFDictionaryGetValue(PropsRef, CFSTR(kIOPropertyDeviceCharacteristicsKey));
if (DevCharRef)
if ( ValueRef
if ( ValueRef
krc = IOCreatePlugInInterfaceForService(DVDService, kIOMMCDeviceUserClientTypeID, kIOCFPlugInInterfaceID,
return rc;
int FileDevice = open(pThis->pszDeviceOpen, (pThis->fReadOnlyConfig ? O_RDONLY : O_RDWR) | O_NONBLOCK);
if (FileDevice < 0)
return VINF_SUCCESS;
rc = RTFileOpen(&FileDevice, pThis->pszDeviceOpen, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
return rc;
if (!rcBSD)
rc = RTFileOpen(&PassthroughDevice, pszPassthroughDevice, RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
if (!rcBSD)
return rc;
static int drvHostBaseOpen(PDRVHOSTBASE pThis, PRTFILE pFileBlockDevice, PRTFILE pFileRawDevice, bool fReadOnly)
return rc;
return rc;
LogFlow(("%s-%d: drvHostBaseReopen: '%s'\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->pszDeviceOpen));
#ifdef RT_OS_SOLARIS
LogFlow(("%s-%d: drvHostBaseReopen: '%s' - retry readonly (%Rrc)\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, pThis->pszDeviceOpen, rc));
#ifdef RT_OS_SOLARIS
return rc;
#ifdef RT_OS_SOLARIS
return VINF_SUCCESS;
} Buf = {0, 0};
SCSI_READ_CAPACITY, 0, 0, 0, 0, 0, 0,
// Buf.cbBlock = 2048;
return rc;
return VINF_SUCCESS;
if (rcNt >= 0)
return VINF_SUCCESS;
switch (rcNt)
return rc;
DECLCALLBACK(int) DRVHostBaseScsiCmd(PDRVHOSTBASE pThis, const uint8_t *pbCmd, size_t cbCmd, PDMBLOCKTXDIR enmTxDir,
Assert(enmTxDir == PDMBLOCKTXDIR_NONE || enmTxDir == PDMBLOCKTXDIR_FROM_DEVICE || enmTxDir == PDMBLOCKTXDIR_TO_DEVICE);
if (pcbBuf)
*pcbBuf = 0;
# ifdef RT_OS_DARWIN
if (!ppScsiTaskI)
return VERR_NO_MEMORY;
irc = (*ppScsiTaskI)->SetScatterGatherEntries(ppScsiTaskI, NULL, 0, 0, kSCSIDataTransfer_NoDataTransfer);
irc = (*ppScsiTaskI)->SetTimeoutDuration(ppScsiTaskI, cTimeoutMillies ? cTimeoutMillies : 30000 /*ms*/);
if (pcbBuf)
&& pbSense)
int rcBSD = 0;
if (!rcBSD)
? cbBuf
: sizeof(struct scsi_inquiry_data);;
if (pcbBuf)
if (!rcBSD)
case CAM_REQ_CMP:
case CAM_SEL_TIMEOUT:
case CAM_CMD_TIMEOUT:
if (pcbBuf)
if (pbSense)
return rc;
return rc;
return rc;
return VINF_SUCCESS;
#ifdef RT_OS_WINDOWS
if (pThis)
PostQuitMessage(0);
switch (wParam)
case DBT_DEVICEARRIVAL:
case DBT_DEVICEREMOVECOMPLETE:
return TRUE;
#ifdef RT_OS_WINDOWS
if (s_hAtomDeviceChange == 0)
HWND hwnd = CreateWindow((LPCTSTR)s_hAtomDeviceChange, "", WS_POPUP, 0, 0, 0, 0, 0, 0, s_classDeviceChange.hInstance, 0);
if (!hwnd)
LogFlow(("%s-%d: drvHostBaseMediaThread: returns VERR_GENERAL_FAILURE\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
return VERR_GENERAL_FAILURE;
LogFlow(("%s-%d: drvHostBaseMediaThread: Created hwndDeviceChange=%p\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, hwnd));
bool fFirst = true;
&& cRetries-- > 0)
if (fFirst)
fFirst = false;
return rc;
LogFlow(("%s-%d: drvHostBaseMediaThread: returns VINF_SUCCESS\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
return VINF_SUCCESS;
LogFlow(("%s-%d: drvHostBaseMediaThread:\n", pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance));
return VINF_SUCCESS;
LogFlow(("%s-%d: drvHostBaseDestruct: iInstance=%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pDrvIns->iInstance));
int rc;
#ifdef RT_OS_WINDOWS
PostMessage(pThis->hwndDeviceChange, WM_CLOSE, 0, 0); /* default win proc will destroy the window */
if (!rc)
#ifdef RT_OS_DARWIN
* (We're currently not unlocking the device after use. See todo in DevATA.cpp.) */
#ifdef RT_OS_WINDOWS
PostMessage(pThis->hwndDeviceChange, WM_CLOSE, 0, 0); /* default win proc will destroy the window */
#ifdef RT_OS_DARWIN
LogFlow(("%s-%d: releasing exclusive scsi access!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
LogFlow(("%s-%d: releasing the MMC object!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
LogFlow(("%s-%d: releasing the DA session!\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
#ifdef RT_OS_SOLARIS
LogFlow(("%s-%d: drvHostBaseDestruct completed\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance));
LogFlow(("%s-%d: DRVHostBaseInitData: iInstance=%d\n", pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pDrvIns->iInstance));
#ifdef RT_OS_DARWIN
#ifdef RT_OS_SOLARIS
return VERR_PDM_MISSING_INTERFACE_ABOVE;
return rc;
return rc;
pThis->fReadOnlyConfig = enmType == PDMBLOCKTYPE_DVD || enmType == PDMBLOCKTYPE_CDROM ? true : false;
return rc;
return rc;
return rc;
char *psz;
return rc;
return rc;
bool fAttachFailError;
fAttachFailError = true;
#ifdef RT_OS_WINDOWS
return VERR_INVALID_PARAMETER;
if (!pszBlockDevName)
return VERR_NO_MEMORY;
return VERR_NO_MEMORY;
return VINF_SUCCESS;
Log(("%s-%d: pszDevice='%s' (%s) cMilliesPoller=%d fReadOnlyConfig=%d fLocked=%d fBIOSVisible=%d Uuid=%RTuuid\n",
pDrvIns->pDrvReg->szDriverName, pDrvIns->iInstance, pThis->pszDevice, pThis->pszDeviceOpen, pThis->cMilliesPoller,
return rc;
#ifdef RT_OS_WINDOWS
case PDMBLOCKTYPE_FLOPPY_360:
case PDMBLOCKTYPE_FLOPPY_720:
case PDMBLOCKTYPE_FLOPPY_1_20:
case PDMBLOCKTYPE_FLOPPY_1_44:
case PDMBLOCKTYPE_FLOPPY_2_88:
return VERR_INVALID_PARAMETER;
case PDMBLOCKTYPE_CDROM:
case PDMBLOCKTYPE_DVD:
return VERR_INVALID_PARAMETER;
case PDMBLOCKTYPE_HARD_DISK:
return VERR_INVALID_PARAMETER;
#if defined(RT_OS_DARWIN)
#ifndef RT_OS_DARWIN
#ifdef RT_OS_SOLARIS
switch (rc)
case VERR_ACCESS_DENIED:
#ifdef RT_OS_LINUX
return rc;
#ifdef RT_OS_WINDOWS
return rc;
#ifndef RT_OS_WINDOWS
return rc;
return rc;
return rc;
#ifdef RT_OS_WINDOWS
return VERR_GENERAL_FAILURE;
return src;
return rc;