[25966] | 1 | /* $Id: DrvMediaISO.cpp 28800 2010-04-27 08:22:32Z vboxsync $ */
|
---|
[1] | 2 | /** @file
|
---|
[25966] | 3 | * VBox storage devices: ISO image media driver
|
---|
[1] | 4 | */
|
---|
| 5 |
|
---|
| 6 | /*
|
---|
[28800] | 7 | * Copyright (C) 2006-2007 Oracle Corporation
|
---|
[1] | 8 | *
|
---|
| 9 | * This file is part of VirtualBox Open Source Edition (OSE), as
|
---|
| 10 | * available from http://www.virtualbox.org. This file is free software;
|
---|
| 11 | * you can redistribute it and/or modify it under the terms of the GNU
|
---|
[5999] | 12 | * General Public License (GPL) as published by the Free Software
|
---|
| 13 | * Foundation, in version 2 as it comes in the "COPYING" file of the
|
---|
| 14 | * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
|
---|
| 15 | * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
|
---|
[1] | 16 | */
|
---|
| 17 |
|
---|
| 18 | /*******************************************************************************
|
---|
| 19 | * Header Files *
|
---|
| 20 | *******************************************************************************/
|
---|
| 21 | #define LOG_GROUP LOG_GROUP_DRV_ISO
|
---|
[4014] | 22 | #include <VBox/pdmdrv.h>
|
---|
[1] | 23 | #include <iprt/assert.h>
|
---|
| 24 | #include <iprt/file.h>
|
---|
[25966] | 25 | #include <iprt/string.h>
|
---|
| 26 | #include <iprt/uuid.h>
|
---|
[1] | 27 |
|
---|
| 28 | #include "Builtins.h"
|
---|
| 29 |
|
---|
[25966] | 30 |
|
---|
[1] | 31 | /*******************************************************************************
|
---|
| 32 | * Defined Constants And Macros *
|
---|
| 33 | *******************************************************************************/
|
---|
| 34 | /** Converts a pointer to MEDIAISO::IMedia to a PRDVMEDIAISO. */
|
---|
| 35 | #define PDMIMEDIA_2_DRVMEDIAISO(pInterface) ( (PDRVMEDIAISO)((uintptr_t)pInterface - RT_OFFSETOF(DRVMEDIAISO, IMedia)) )
|
---|
| 36 |
|
---|
| 37 | /** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
|
---|
| 38 | #define PDMIBASE_2_DRVINS(pInterface) ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
|
---|
| 39 |
|
---|
| 40 | /** Converts a pointer to PDMDRVINS::IBase to a PVBOXHDD. */
|
---|
[11267] | 41 | #define PDMIBASE_2_DRVMEDIAISO(pInterface) ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PDRVMEDIAISO) )
|
---|
[1] | 42 |
|
---|
| 43 |
|
---|
| 44 |
|
---|
| 45 | /*******************************************************************************
|
---|
| 46 | * Structures and Typedefs *
|
---|
| 47 | *******************************************************************************/
|
---|
| 48 | /**
|
---|
| 49 | * Block driver instance data.
|
---|
[25966] | 50 | *
|
---|
| 51 | * @implements PDMIMEDIA
|
---|
[1] | 52 | */
|
---|
| 53 | typedef struct DRVMEDIAISO
|
---|
| 54 | {
|
---|
| 55 | /** The media interface. */
|
---|
| 56 | PDMIMEDIA IMedia;
|
---|
| 57 | /** Pointer to the driver instance. */
|
---|
| 58 | PPDMDRVINS pDrvIns;
|
---|
| 59 | /** Pointer to the filename. (Freed by MM) */
|
---|
| 60 | char *pszFilename;
|
---|
| 61 | /** File handle of the ISO file. */
|
---|
| 62 | RTFILE File;
|
---|
| 63 | } DRVMEDIAISO, *PDRVMEDIAISO;
|
---|
| 64 |
|
---|
| 65 |
|
---|
| 66 |
|
---|
[26001] | 67 | /* -=-=-=-=- PDMIMEDIA -=-=-=-=- */
|
---|
[1] | 68 |
|
---|
| 69 | /** @copydoc PDMIMEDIA::pfnGetSize */
|
---|
| 70 | static DECLCALLBACK(uint64_t) drvMediaISOGetSize(PPDMIMEDIA pInterface)
|
---|
| 71 | {
|
---|
[11269] | 72 | PDRVMEDIAISO pThis = PDMIMEDIA_2_DRVMEDIAISO(pInterface);
|
---|
| 73 | LogFlow(("drvMediaISOGetSize: '%s'\n", pThis->pszFilename));
|
---|
[1] | 74 |
|
---|
| 75 | uint64_t cbFile;
|
---|
[11269] | 76 | int rc = RTFileGetSize(pThis->File, &cbFile);
|
---|
[11266] | 77 | if (RT_SUCCESS(rc))
|
---|
[1] | 78 | {
|
---|
[11269] | 79 | LogFlow(("drvMediaISOGetSize: returns %lld (%s)\n", cbFile, pThis->pszFilename));
|
---|
[1] | 80 | return cbFile;
|
---|
| 81 | }
|
---|
| 82 |
|
---|
[11284] | 83 | AssertMsgFailed(("Error querying ISO file size, rc=%Rrc. (%s)\n", rc, pThis->pszFilename));
|
---|
[1] | 84 | return 0;
|
---|
| 85 | }
|
---|
| 86 |
|
---|
| 87 |
|
---|
[6291] | 88 | /** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
|
---|
| 89 | static DECLCALLBACK(int) drvMediaISOBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
|
---|
[1] | 90 | {
|
---|
| 91 | return VERR_NOT_IMPLEMENTED;
|
---|
| 92 | }
|
---|
| 93 |
|
---|
| 94 |
|
---|
[6291] | 95 | /** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
|
---|
| 96 | static DECLCALLBACK(int) drvMediaISOBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
|
---|
[1] | 97 | {
|
---|
| 98 | return VERR_NOT_IMPLEMENTED;
|
---|
| 99 | }
|
---|
| 100 |
|
---|
| 101 |
|
---|
[6291] | 102 | /** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
|
---|
| 103 | static DECLCALLBACK(int) drvMediaISOBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
|
---|
| 104 | {
|
---|
| 105 | return VERR_NOT_IMPLEMENTED;
|
---|
| 106 | }
|
---|
| 107 |
|
---|
| 108 |
|
---|
| 109 | /** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
|
---|
| 110 | static DECLCALLBACK(int) drvMediaISOBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
|
---|
| 111 | {
|
---|
| 112 | return VERR_NOT_IMPLEMENTED;
|
---|
| 113 | }
|
---|
| 114 |
|
---|
| 115 |
|
---|
[1] | 116 | /**
|
---|
| 117 | * Read bits.
|
---|
| 118 | *
|
---|
| 119 | * @see PDMIMEDIA::pfnRead for details.
|
---|
| 120 | */
|
---|
| 121 | static DECLCALLBACK(int) drvMediaISORead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
|
---|
| 122 | {
|
---|
[11269] | 123 | PDRVMEDIAISO pThis = PDMIMEDIA_2_DRVMEDIAISO(pInterface);
|
---|
| 124 | LogFlow(("drvMediaISORead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n", off, pvBuf, cbRead, pThis->pszFilename));
|
---|
[1] | 125 |
|
---|
[11269] | 126 | Assert(pThis->File);
|
---|
[1] | 127 | Assert(pvBuf);
|
---|
| 128 |
|
---|
| 129 | /*
|
---|
| 130 | * Seek to the position and read.
|
---|
| 131 | */
|
---|
[11269] | 132 | int rc = RTFileSeek(pThis->File, off, RTFILE_SEEK_BEGIN, NULL);
|
---|
[11266] | 133 | if (RT_SUCCESS(rc))
|
---|
[1] | 134 | {
|
---|
[11269] | 135 | rc = RTFileRead(pThis->File, pvBuf, cbRead, NULL);
|
---|
[11266] | 136 | if (RT_SUCCESS(rc))
|
---|
[1] | 137 | {
|
---|
| 138 | Log2(("drvMediaISORead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n"
|
---|
[13840] | 139 | "%16.*Rhxd\n",
|
---|
[11269] | 140 | off, pvBuf, cbRead, pThis->pszFilename,
|
---|
[1] | 141 | cbRead, pvBuf));
|
---|
| 142 | }
|
---|
| 143 | else
|
---|
[11284] | 144 | AssertMsgFailed(("RTFileRead(%d, %p, %#x) -> %Rrc (off=%#llx '%s')\n",
|
---|
[11269] | 145 | pThis->File, pvBuf, cbRead, rc, off, pThis->pszFilename));
|
---|
[1] | 146 | }
|
---|
| 147 | else
|
---|
[11284] | 148 | AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Rrc\n", pThis->File, off, rc));
|
---|
| 149 | LogFlow(("drvMediaISORead: returns %Rrc\n", rc));
|
---|
[1] | 150 | return rc;
|
---|
| 151 | }
|
---|
| 152 |
|
---|
| 153 |
|
---|
| 154 | /** @copydoc PDMIMEDIA::pfnWrite */
|
---|
| 155 | static DECLCALLBACK(int) drvMediaISOWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
|
---|
| 156 | {
|
---|
| 157 | AssertMsgFailed(("Attempt to write to an ISO file!\n"));
|
---|
| 158 | return VERR_NOT_IMPLEMENTED;
|
---|
| 159 | }
|
---|
| 160 |
|
---|
| 161 |
|
---|
| 162 | /** @copydoc PDMIMEDIA::pfnFlush */
|
---|
| 163 | static DECLCALLBACK(int) drvMediaISOFlush(PPDMIMEDIA pInterface)
|
---|
| 164 | {
|
---|
| 165 | /* No buffered data that still needs to be written. */
|
---|
| 166 | return VINF_SUCCESS;
|
---|
| 167 | }
|
---|
| 168 |
|
---|
| 169 |
|
---|
| 170 | /** @copydoc PDMIMEDIA::pfnGetUuid */
|
---|
| 171 | static DECLCALLBACK(int) drvMediaISOGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
|
---|
| 172 | {
|
---|
| 173 | LogFlow(("drvMediaISOGetUuid: returns VERR_NOT_IMPLEMENTED\n"));
|
---|
| 174 | return VERR_NOT_IMPLEMENTED;
|
---|
| 175 | }
|
---|
| 176 |
|
---|
| 177 |
|
---|
| 178 | /** @copydoc PDMIMEDIA::pfnIsReadOnly */
|
---|
| 179 | static DECLCALLBACK(bool) drvMediaISOIsReadOnly(PPDMIMEDIA pInterface)
|
---|
| 180 | {
|
---|
| 181 | return true;
|
---|
| 182 | }
|
---|
| 183 |
|
---|
[26001] | 184 | /* -=-=-=-=- PDMIBASE -=-=-=-=- */
|
---|
[1] | 185 |
|
---|
| 186 | /**
|
---|
[25966] | 187 | * @interface_method_impl{PDMIBASE,pfnQueryInterface}
|
---|
[1] | 188 | */
|
---|
[25966] | 189 | static DECLCALLBACK(void *) drvMediaISOQueryInterface(PPDMIBASE pInterface, const char *pszIID)
|
---|
[1] | 190 | {
|
---|
| 191 | PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
|
---|
[11269] | 192 | PDRVMEDIAISO pThis = PDMINS_2_DATA(pDrvIns, PDRVMEDIAISO);
|
---|
[25985] | 193 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMIBASE, &pDrvIns->IBase);
|
---|
[25974] | 194 | PDMIBASE_RETURN_INTERFACE(pszIID, PDMIMEDIA, &pThis->IMedia);
|
---|
[25966] | 195 | return NULL;
|
---|
[1] | 196 | }
|
---|
| 197 |
|
---|
[26001] | 198 | /* -=-=-=-=- PDMDRVREG -=-=-=-=- */
|
---|
[1] | 199 |
|
---|
| 200 | /**
|
---|
[26001] | 201 | * Destruct a driver instance.
|
---|
| 202 | *
|
---|
| 203 | * Most VM resources are freed by the VM. This callback is provided so that any non-VM
|
---|
| 204 | * resources can be freed correctly.
|
---|
| 205 | *
|
---|
| 206 | * @param pDrvIns The driver instance data.
|
---|
| 207 | */
|
---|
| 208 | static DECLCALLBACK(void) drvMediaISODestruct(PPDMDRVINS pDrvIns)
|
---|
| 209 | {
|
---|
| 210 | PDRVMEDIAISO pThis = PDMINS_2_DATA(pDrvIns, PDRVMEDIAISO);
|
---|
| 211 | LogFlow(("drvMediaISODestruct: '%s'\n", pThis->pszFilename));
|
---|
| 212 | PDMDRV_CHECK_VERSIONS_RETURN_VOID(pDrvIns);
|
---|
| 213 |
|
---|
| 214 | if (pThis->File != NIL_RTFILE)
|
---|
| 215 | {
|
---|
| 216 | RTFileClose(pThis->File);
|
---|
| 217 | pThis->File = NIL_RTFILE;
|
---|
| 218 | }
|
---|
| 219 | if (pThis->pszFilename)
|
---|
| 220 | MMR3HeapFree(pThis->pszFilename);
|
---|
| 221 | }
|
---|
| 222 |
|
---|
| 223 |
|
---|
| 224 | /**
|
---|
| 225 | * Construct a ISO media driver instance.
|
---|
| 226 | *
|
---|
| 227 | * @copydoc FNPDMDRVCONSTRUCT
|
---|
| 228 | */
|
---|
[26173] | 229 | static DECLCALLBACK(int) drvMediaISOConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfg, uint32_t fFlags)
|
---|
[26001] | 230 | {
|
---|
| 231 | PDRVMEDIAISO pThis = PDMINS_2_DATA(pDrvIns, PDRVMEDIAISO);
|
---|
| 232 | PDMDRV_CHECK_VERSIONS_RETURN(pDrvIns);
|
---|
| 233 |
|
---|
| 234 | /*
|
---|
| 235 | * Init the static parts.
|
---|
| 236 | */
|
---|
| 237 | pThis->pDrvIns = pDrvIns;
|
---|
| 238 | pThis->File = NIL_RTFILE;
|
---|
| 239 | /* IBase */
|
---|
| 240 | pDrvIns->IBase.pfnQueryInterface = drvMediaISOQueryInterface;
|
---|
| 241 | /* IMedia */
|
---|
| 242 | pThis->IMedia.pfnRead = drvMediaISORead;
|
---|
| 243 | pThis->IMedia.pfnWrite = drvMediaISOWrite;
|
---|
| 244 | pThis->IMedia.pfnFlush = drvMediaISOFlush;
|
---|
| 245 | pThis->IMedia.pfnGetSize = drvMediaISOGetSize;
|
---|
| 246 | pThis->IMedia.pfnGetUuid = drvMediaISOGetUuid;
|
---|
| 247 | pThis->IMedia.pfnIsReadOnly = drvMediaISOIsReadOnly;
|
---|
| 248 | pThis->IMedia.pfnBiosGetPCHSGeometry = drvMediaISOBiosGetPCHSGeometry;
|
---|
| 249 | pThis->IMedia.pfnBiosSetPCHSGeometry = drvMediaISOBiosSetPCHSGeometry;
|
---|
| 250 | pThis->IMedia.pfnBiosGetLCHSGeometry = drvMediaISOBiosGetLCHSGeometry;
|
---|
| 251 | pThis->IMedia.pfnBiosSetLCHSGeometry = drvMediaISOBiosSetLCHSGeometry;
|
---|
| 252 |
|
---|
| 253 | /*
|
---|
| 254 | * Read the configuration.
|
---|
| 255 | */
|
---|
[26173] | 256 | if (!CFGMR3AreValuesValid(pCfg, "Path\0"))
|
---|
[26001] | 257 | return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
|
---|
| 258 |
|
---|
| 259 | char *pszName;
|
---|
[26173] | 260 | int rc = CFGMR3QueryStringAlloc(pCfg, "Path", &pszName);
|
---|
[26001] | 261 | if (RT_FAILURE(rc))
|
---|
| 262 | return PDMDRV_SET_ERROR(pDrvIns, rc, N_("Failed to query \"Path\" from the config"));
|
---|
| 263 |
|
---|
| 264 | /*
|
---|
| 265 | * Open the image.
|
---|
| 266 | */
|
---|
| 267 | rc = RTFileOpen(&pThis->File, pszName,
|
---|
| 268 | RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE);
|
---|
| 269 | if (RT_SUCCESS(rc))
|
---|
| 270 | {
|
---|
| 271 | LogFlow(("drvMediaISOConstruct: ISO image '%s' opened successfully.\n", pszName));
|
---|
| 272 | pThis->pszFilename = pszName;
|
---|
| 273 | }
|
---|
| 274 | else
|
---|
| 275 | {
|
---|
| 276 | PDMDrvHlpVMSetError(pDrvIns, rc, RT_SRC_POS, N_("Failed to open ISO file \"%s\""), pszName);
|
---|
| 277 | MMR3HeapFree(pszName);
|
---|
| 278 | }
|
---|
| 279 |
|
---|
| 280 | return rc;
|
---|
| 281 | }
|
---|
| 282 |
|
---|
| 283 |
|
---|
| 284 | /**
|
---|
[1] | 285 | * ISO media driver registration record.
|
---|
| 286 | */
|
---|
| 287 | const PDMDRVREG g_DrvMediaISO =
|
---|
| 288 | {
|
---|
| 289 | /* u32Version */
|
---|
| 290 | PDM_DRVREG_VERSION,
|
---|
[26166] | 291 | /* szName */
|
---|
[1] | 292 | "MediaISO",
|
---|
[25893] | 293 | /* szRCMod */
|
---|
| 294 | "",
|
---|
| 295 | /* szR0Mod */
|
---|
| 296 | "",
|
---|
[1] | 297 | /* pszDescription */
|
---|
| 298 | "ISO media access driver.",
|
---|
| 299 | /* fFlags */
|
---|
| 300 | PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
|
---|
| 301 | /* fClass. */
|
---|
| 302 | PDM_DRVREG_CLASS_MEDIA,
|
---|
| 303 | /* cMaxInstances */
|
---|
| 304 | ~0,
|
---|
| 305 | /* cbInstance */
|
---|
| 306 | sizeof(DRVMEDIAISO),
|
---|
| 307 | /* pfnConstruct */
|
---|
| 308 | drvMediaISOConstruct,
|
---|
| 309 | /* pfnDestruct */
|
---|
| 310 | drvMediaISODestruct,
|
---|
[25893] | 311 | /* pfnRelocate */
|
---|
| 312 | NULL,
|
---|
[1] | 313 | /* pfnIOCtl */
|
---|
| 314 | NULL,
|
---|
| 315 | /* pfnPowerOn */
|
---|
| 316 | NULL,
|
---|
| 317 | /* pfnReset */
|
---|
| 318 | NULL,
|
---|
| 319 | /* pfnSuspend */
|
---|
| 320 | NULL,
|
---|
| 321 | /* pfnResume */
|
---|
| 322 | NULL,
|
---|
[22277] | 323 | /* pfnAttach */
|
---|
| 324 | NULL,
|
---|
[1] | 325 | /* pfnDetach */
|
---|
[25893] | 326 | NULL,
|
---|
[22277] | 327 | /* pfnPowerOff */
|
---|
[25893] | 328 | NULL,
|
---|
[22277] | 329 | /* pfnSoftReset */
|
---|
[1] | 330 | NULL,
|
---|
[22277] | 331 | /* u32EndVersion */
|
---|
| 332 | PDM_DRVREG_VERSION
|
---|
[1] | 333 | };
|
---|
[22277] | 334 |
|
---|