VirtualBox

source: vbox/trunk/src/VBox/Devices/Storage/DrvRawImage.cpp@ 13384

Last change on this file since 13384 was 11284, checked in by vboxsync, 16 years ago

Devices: %Vrc -> %Rrc (just preferred, not mandatory (yet))

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.3 KB
Line 
1/** @file
2 *
3 * VBox storage devices:
4 * Raw image driver
5 */
6
7/*
8 * Copyright (C) 2006-2007 Sun Microsystems, Inc.
9 *
10 * This file is part of VirtualBox Open Source Edition (OSE), as
11 * available from http://www.virtualbox.org. This file is free software;
12 * you can redistribute it and/or modify it under the terms of the GNU
13 * General Public License (GPL) as published by the Free Software
14 * Foundation, in version 2 as it comes in the "COPYING" file of the
15 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
16 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa
19 * Clara, CA 95054 USA or visit http://www.sun.com if you need
20 * additional information or have any questions.
21 */
22
23
24/*******************************************************************************
25* Header Files *
26*******************************************************************************/
27#define LOG_GROUP LOG_GROUP_DRV_RAW_IMAGE
28#include <VBox/pdmdrv.h>
29#include <iprt/assert.h>
30#include <iprt/file.h>
31#include <iprt/string.h>
32
33#include "Builtins.h"
34
35
36/*******************************************************************************
37* Defined Constants And Macros *
38*******************************************************************************/
39
40/** Converts a pointer to RAWIMAGE::IMedia to a PRDVRAWIMAGE. */
41#define PDMIMEDIA_2_DRVRAWIMAGE(pInterface) ( (PDRVRAWIMAGE)((uintptr_t)pInterface - RT_OFFSETOF(DRVRAWIMAGE, IMedia)) )
42
43/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
44#define PDMIBASE_2_DRVINS(pInterface) ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
45
46/** Converts a pointer to PDMDRVINS::IBase to a PVBOXHDD. */
47#define PDMIBASE_2_DRVRAWIMAGE(pInterface) ( PDMINS_2_DATA(PDMIBASE_2_DRVINS(pInterface), PDRVRAWIMAGE) )
48
49
50
51/*******************************************************************************
52* Structures and Typedefs *
53*******************************************************************************/
54/**
55 * Block driver instance data.
56 */
57typedef struct DRVRAWIMAGE
58{
59 /** The media interface. */
60 PDMIMEDIA IMedia;
61 /** Pointer to the driver instance. */
62 PPDMDRVINS pDrvIns;
63 /** Pointer to the filename. (Freed by MM) */
64 char *pszFilename;
65 /** File handle of the raw image file. */
66 RTFILE File;
67 /** True if the image is operating in readonly mode. */
68 bool fReadOnly;
69} DRVRAWIMAGE, *PDRVRAWIMAGE;
70
71
72
73/*******************************************************************************
74* Internal Functions *
75*******************************************************************************/
76static DECLCALLBACK(int) drvRawImageRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead);
77static DECLCALLBACK(int) drvRawImageWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite);
78static DECLCALLBACK(int) drvRawImageFlush(PPDMIMEDIA pInterface);
79static DECLCALLBACK(bool) drvRawImageIsReadOnly(PPDMIMEDIA pInterface);
80static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface);
81static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid);
82static DECLCALLBACK(int) drvRawImageBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry);
83static DECLCALLBACK(int) drvRawImageBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry);
84static DECLCALLBACK(int) drvRawImageBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry);
85static DECLCALLBACK(int) drvRawImageBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry);
86
87static DECLCALLBACK(void *) drvRawImageQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface);
88
89
90
91
92/**
93 * Construct a raw image driver instance.
94 *
95 * @returns VBox status.
96 * @param pDrvIns The driver instance data.
97 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
98 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
99 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
100 * iInstance it's expected to be used a bit in this function.
101 */
102static DECLCALLBACK(int) drvRawImageConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
103{
104 PDRVRAWIMAGE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWIMAGE);
105
106 /*
107 * Init the static parts.
108 */
109 pThis->pDrvIns = pDrvIns;
110 pThis->File = NIL_RTFILE;
111 /* IBase */
112 pDrvIns->IBase.pfnQueryInterface = drvRawImageQueryInterface;
113 /* IMedia */
114 pThis->IMedia.pfnRead = drvRawImageRead;
115 pThis->IMedia.pfnWrite = drvRawImageWrite;
116 pThis->IMedia.pfnFlush = drvRawImageFlush;
117 pThis->IMedia.pfnGetSize = drvRawImageGetSize;
118 pThis->IMedia.pfnGetUuid = drvRawImageGetUuid;
119 pThis->IMedia.pfnIsReadOnly = drvRawImageIsReadOnly;
120 pThis->IMedia.pfnBiosGetPCHSGeometry = drvRawImageBiosGetPCHSGeometry;
121 pThis->IMedia.pfnBiosSetPCHSGeometry = drvRawImageBiosSetPCHSGeometry;
122 pThis->IMedia.pfnBiosGetLCHSGeometry = drvRawImageBiosGetLCHSGeometry;
123 pThis->IMedia.pfnBiosSetLCHSGeometry = drvRawImageBiosSetLCHSGeometry;
124
125 /*
126 * Read the configuration.
127 */
128 if (!CFGMR3AreValuesValid(pCfgHandle, "Path\0"))
129 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
130
131 char *pszName;
132 int rc = CFGMR3QueryStringAlloc(pCfgHandle, "Path", &pszName);
133 if (RT_FAILURE(rc))
134 {
135 AssertMsgFailed(("Configuration error: query for \"Path\" string return %Rrc.\n", rc));
136 return rc;
137 }
138
139 /*
140 * Open the image.
141 */
142 rc = RTFileOpen(&pThis->File, pszName,
143 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
144 if (RT_SUCCESS(rc))
145 {
146 LogFlow(("drvRawImageConstruct: Raw image '%s' opened successfully.\n", pszName));
147 pThis->pszFilename = pszName;
148 pThis->fReadOnly = false;
149 }
150 else
151 {
152 rc = RTFileOpen(&pThis->File, pszName,
153 RTFILE_O_READ | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
154 if (RT_SUCCESS(rc))
155 {
156 LogFlow(("drvRawImageConstruct: Raw image '%s' opened successfully.\n", pszName));
157 pThis->pszFilename = pszName;
158 pThis->fReadOnly = true;
159 }
160 else
161 {
162 AssertMsgFailed(("Could not open Raw image file %s, rc=%Rrc\n", pszName, rc));
163 MMR3HeapFree(pszName);
164 }
165 }
166
167 return rc;
168}
169
170
171/**
172 * Destruct a driver instance.
173 *
174 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
175 * resources can be freed correctly.
176 *
177 * @param pDrvIns The driver instance data.
178 */
179static DECLCALLBACK(void) drvRawImageDestruct(PPDMDRVINS pDrvIns)
180{
181 PDRVRAWIMAGE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWIMAGE);
182 LogFlow(("drvRawImageDestruct: '%s'\n", pThis->pszFilename));
183
184 if (pThis->File != NIL_RTFILE)
185 {
186 RTFileClose(pThis->File);
187 pThis->File = NIL_RTFILE;
188 }
189 if (pThis->pszFilename)
190 MMR3HeapFree(pThis->pszFilename);
191}
192
193
194/** @copydoc PDMIMEDIA::pfnGetSize */
195static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface)
196{
197 PDRVRAWIMAGE pThis = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
198 LogFlow(("drvRawImageGetSize: '%s'\n", pThis->pszFilename));
199
200 uint64_t cbFile;
201 int rc = RTFileGetSize(pThis->File, &cbFile);
202 if (RT_SUCCESS(rc))
203 {
204 LogFlow(("drvRawImageGetSize: returns %lld (%s)\n", cbFile, pThis->pszFilename));
205 return cbFile;
206 }
207
208 AssertMsgFailed(("Error querying Raw image file size, rc=%Rrc. (%s)\n", rc, pThis->pszFilename));
209 return 0;
210}
211
212
213/** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */
214static DECLCALLBACK(int) drvRawImageBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)
215{
216 return VERR_NOT_IMPLEMENTED;
217}
218
219
220/** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */
221static DECLCALLBACK(int) drvRawImageBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)
222{
223 return VERR_NOT_IMPLEMENTED;
224}
225
226
227/** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */
228static DECLCALLBACK(int) drvRawImageBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)
229{
230 return VERR_NOT_IMPLEMENTED;
231}
232
233
234/** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */
235static DECLCALLBACK(int) drvRawImageBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)
236{
237 return VERR_NOT_IMPLEMENTED;
238}
239
240
241/**
242 * Read bits.
243 *
244 * @see PDMIMEDIA::pfnRead for details.
245 */
246static DECLCALLBACK(int) drvRawImageRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
247{
248 PDRVRAWIMAGE pThis = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
249 LogFlow(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n", off, pvBuf, cbRead, pThis->pszFilename));
250
251 Assert(pThis->File);
252 Assert(pvBuf);
253
254 /*
255 * Seek to the position and read.
256 */
257 int rc = RTFileSeek(pThis->File, off, RTFILE_SEEK_BEGIN, NULL);
258 if (RT_SUCCESS(rc))
259 {
260 rc = RTFileRead(pThis->File, pvBuf, cbRead, NULL);
261 if (RT_SUCCESS(rc))
262 {
263 Log2(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n"
264 "%16.*Vhxd\n",
265 off, pvBuf, cbRead, pThis->pszFilename,
266 cbRead, pvBuf));
267 }
268 else
269 AssertMsgFailed(("RTFileRead(%d, %p, %#x) -> %Rrc (off=%#llx '%s')\n",
270 pThis->File, pvBuf, cbRead, rc, off, pThis->pszFilename));
271 }
272 else
273 AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Rrc\n", pThis->File, off, rc));
274 LogFlow(("drvRawImageRead: returns %Rrc\n", rc));
275 return rc;
276}
277
278
279/** @copydoc PDMIMEDIA::pfnWrite */
280static DECLCALLBACK(int) drvRawImageWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
281{
282 PDRVRAWIMAGE pThis = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
283 LogFlow(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n", off, pvBuf, cbWrite, pThis->pszFilename));
284
285 Assert(pThis->File);
286 Assert(pvBuf);
287
288 /*
289 * Seek to the position and write.
290 */
291 int rc = RTFileSeek(pThis->File, off, RTFILE_SEEK_BEGIN, NULL);
292 if (RT_SUCCESS(rc))
293 {
294 rc = RTFileWrite(pThis->File, pvBuf, cbWrite, NULL);
295 if (RT_SUCCESS(rc))
296 {
297 Log2(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n"
298 "%16.*Vhxd\n",
299 off, pvBuf, cbWrite, pThis->pszFilename,
300 cbWrite, pvBuf));
301 }
302 else
303 AssertMsgFailed(("RTFileWrite(%d, %p, %#x) -> %Rrc (off=%#llx '%s')\n",
304 pThis->File, pvBuf, cbWrite, rc, off, pThis->pszFilename));
305 }
306 else
307 AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Rrc\n", pThis->File, off, rc));
308 LogFlow(("drvRawImageWrite: returns %Rrc\n", rc));
309 return rc;
310}
311
312
313/** @copydoc PDMIMEDIA::pfnFlush */
314static DECLCALLBACK(int) drvRawImageFlush(PPDMIMEDIA pInterface)
315{
316 PDRVRAWIMAGE pThis = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
317 LogFlow(("drvRawImageFlush: (%s)\n", pThis->pszFilename));
318
319 Assert(pThis->File != NIL_RTFILE);
320 int rc = RTFileFlush(pThis->File);
321 LogFlow(("drvRawImageFlush: returns %Rrc\n", rc));
322 return rc;
323}
324
325
326/** @copydoc PDMIMEDIA::pfnGetUuid */
327static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
328{
329 LogFlow(("drvRawImageGetUuid: returns VERR_NOT_IMPLEMENTED\n"));
330 return VERR_NOT_IMPLEMENTED;
331}
332
333
334/** @copydoc PDMIMEDIA::pfnIsReadOnly */
335static DECLCALLBACK(bool) drvRawImageIsReadOnly(PPDMIMEDIA pInterface)
336{
337 PDRVRAWIMAGE pThis = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
338 return pThis->fReadOnly;
339}
340
341
342/**
343 * Queries an interface to the driver.
344 *
345 * @returns Pointer to interface.
346 * @returns NULL if the interface was not supported by the driver.
347 * @param pInterface Pointer to this interface structure.
348 * @param enmInterface The requested interface identification.
349 * @thread Any thread.
350 */
351static DECLCALLBACK(void *) drvRawImageQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
352{
353 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
354 PDRVRAWIMAGE pThis = PDMINS_2_DATA(pDrvIns, PDRVRAWIMAGE);
355 switch (enmInterface)
356 {
357 case PDMINTERFACE_BASE:
358 return &pDrvIns->IBase;
359 case PDMINTERFACE_MEDIA:
360 return &pThis->IMedia;
361 default:
362 return NULL;
363 }
364}
365
366
367/**
368 * Raw image driver registration record.
369 */
370const PDMDRVREG g_DrvRawImage =
371{
372 /* u32Version */
373 PDM_DRVREG_VERSION,
374 /* szDriverName */
375 "RawImage",
376 /* pszDescription */
377 "Raw image access driver.",
378 /* fFlags */
379 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
380 /* fClass. */
381 PDM_DRVREG_CLASS_MEDIA,
382 /* cMaxInstances */
383 ~0,
384 /* cbInstance */
385 sizeof(DRVRAWIMAGE),
386 /* pfnConstruct */
387 drvRawImageConstruct,
388 /* pfnDestruct */
389 drvRawImageDestruct,
390 /* pfnIOCtl */
391 NULL,
392 /* pfnPowerOn */
393 NULL,
394 /* pfnReset */
395 NULL,
396 /* pfnSuspend */
397 NULL,
398 /* pfnResume */
399 NULL,
400 /* pfnDetach */
401 NULL,
402 /* pfnPowerOff */
403 NULL
404};
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette