VirtualBox

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

Last change on this file since 4014 was 4014, checked in by vboxsync, 17 years ago

Use pdmdrv.h and pdmdev.h where appropirate.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 12.9 KB
Line 
1/** @file
2 *
3 * VBox storage devices:
4 * Raw image driver
5 */
6
7/*
8 * Copyright (C) 2006-2007 innotek GmbH
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 as published by the Free Software Foundation,
14 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
15 * distribution. VirtualBox OSE is distributed in the hope that it will
16 * be useful, but WITHOUT ANY WARRANTY of any kind.
17 *
18 * If you received this file as part of a commercial VirtualBox
19 * distribution, then only the terms of your commercial VirtualBox
20 * license agreement apply instead of the previous paragraph.
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) ( PDMINS2DATA(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} DRVRAWIMAGE, *PDRVRAWIMAGE;
68
69
70
71/*******************************************************************************
72* Internal Functions *
73*******************************************************************************/
74static DECLCALLBACK(int) drvRawImageRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead);
75static DECLCALLBACK(int) drvRawImageWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite);
76static DECLCALLBACK(int) drvRawImageFlush(PPDMIMEDIA pInterface);
77static DECLCALLBACK(bool) drvRawImageIsReadOnly(PPDMIMEDIA pInterface);
78static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface);
79static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid);
80static DECLCALLBACK(int) drvRawImageBiosGetGeometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors);
81static DECLCALLBACK(int) drvRawImageBiosSetGeometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors);
82static DECLCALLBACK(int) drvRawImageBiosGetTranslation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation);
83static DECLCALLBACK(int) drvRawImageBiosSetTranslation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation);
84
85static DECLCALLBACK(void *) drvRawImageQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface);
86
87
88
89
90/**
91 * Construct a raw image driver instance.
92 *
93 * @returns VBox status.
94 * @param pDrvIns The driver instance data.
95 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
96 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
97 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
98 * iInstance it's expected to be used a bit in this function.
99 */
100static DECLCALLBACK(int) drvRawImageConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
101{
102 PDRVRAWIMAGE pData = PDMINS2DATA(pDrvIns, PDRVRAWIMAGE);
103
104 /*
105 * Init the static parts.
106 */
107 pData->pDrvIns = pDrvIns;
108 pData->File = NIL_RTFILE;
109 /* IBase */
110 pDrvIns->IBase.pfnQueryInterface = drvRawImageQueryInterface;
111 /* IMedia */
112 pData->IMedia.pfnRead = drvRawImageRead;
113 pData->IMedia.pfnWrite = drvRawImageWrite;
114 pData->IMedia.pfnFlush = drvRawImageFlush;
115 pData->IMedia.pfnGetSize = drvRawImageGetSize;
116 pData->IMedia.pfnGetUuid = drvRawImageGetUuid;
117 pData->IMedia.pfnIsReadOnly = drvRawImageIsReadOnly;
118 pData->IMedia.pfnBiosGetGeometry = drvRawImageBiosGetGeometry;
119 pData->IMedia.pfnBiosSetGeometry = drvRawImageBiosSetGeometry;
120 pData->IMedia.pfnBiosGetTranslation = drvRawImageBiosGetTranslation;
121 pData->IMedia.pfnBiosSetTranslation = drvRawImageBiosSetTranslation;
122
123 /*
124 * Read the configuration.
125 */
126 if (!CFGMR3AreValuesValid(pCfgHandle, "Path\0"))
127 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
128
129 char *pszName;
130 int rc = CFGMR3QueryStringAlloc(pCfgHandle, "Path", &pszName);
131 if (VBOX_FAILURE(rc))
132 {
133 AssertMsgFailed(("Configuration error: query for \"Path\" string return %Vrc.\n", rc));
134 return rc;
135 }
136
137 /*
138 * Open the image.
139 */
140 rc = RTFileOpen(&pData->File, pszName,
141 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
142 if (VBOX_SUCCESS(rc))
143 {
144 LogFlow(("drvRawImageConstruct: Raw image '%s' opened successfully.\n", pszName));
145 pData->pszFilename = pszName;
146 }
147 else
148 {
149 AssertMsgFailed(("Could not open Raw image file %s, rc=%Vrc\n", pszName, rc));
150 MMR3HeapFree(pszName);
151 }
152
153 return rc;
154}
155
156
157/**
158 * Destruct a driver instance.
159 *
160 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
161 * resources can be freed correctly.
162 *
163 * @param pDrvIns The driver instance data.
164 */
165static DECLCALLBACK(void) drvRawImageDestruct(PPDMDRVINS pDrvIns)
166{
167 PDRVRAWIMAGE pData = PDMINS2DATA(pDrvIns, PDRVRAWIMAGE);
168 LogFlow(("drvRawImageDestruct: '%s'\n", pData->pszFilename));
169
170 if (pData->File != NIL_RTFILE)
171 {
172 RTFileClose(pData->File);
173 pData->File = NIL_RTFILE;
174 }
175 if (pData->pszFilename)
176 MMR3HeapFree(pData->pszFilename);
177}
178
179
180/** @copydoc PDMIMEDIA::pfnGetSize */
181static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface)
182{
183 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
184 LogFlow(("drvRawImageGetSize: '%s'\n", pData->pszFilename));
185
186 uint64_t cbFile;
187 int rc = RTFileGetSize(pData->File, &cbFile);
188 if (VBOX_SUCCESS(rc))
189 {
190 LogFlow(("drvRawImageGetSize: returns %lld (%s)\n", cbFile, pData->pszFilename));
191 return cbFile;
192 }
193
194 AssertMsgFailed(("Error querying Raw image file size, rc=%Vrc. (%s)\n", rc, pData->pszFilename));
195 return 0;
196}
197
198
199/** @copydoc PDMIMEDIA::pfnBiosGetGeometry */
200static DECLCALLBACK(int) drvRawImageBiosGetGeometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)
201{
202 return VERR_NOT_IMPLEMENTED;
203}
204
205
206/** @copydoc PDMIMEDIA::pfnBiosSetGeometry */
207static DECLCALLBACK(int) drvRawImageBiosSetGeometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)
208{
209 return VERR_NOT_IMPLEMENTED;
210}
211
212
213/**
214 * Read bits.
215 *
216 * @see PDMIMEDIA::pfnRead for details.
217 */
218static DECLCALLBACK(int) drvRawImageRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
219{
220 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
221 LogFlow(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n", off, pvBuf, cbRead, pData->pszFilename));
222
223 Assert(pData->File);
224 Assert(pvBuf);
225
226 /*
227 * Seek to the position and read.
228 */
229 int rc = RTFileSeek(pData->File, off, RTFILE_SEEK_BEGIN, NULL);
230 if (VBOX_SUCCESS(rc))
231 {
232 rc = RTFileRead(pData->File, pvBuf, cbRead, NULL);
233 if (VBOX_SUCCESS(rc))
234 {
235 Log2(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n"
236 "%16.*Vhxd\n",
237 off, pvBuf, cbRead, pData->pszFilename,
238 cbRead, pvBuf));
239 }
240 else
241 AssertMsgFailed(("RTFileRead(%d, %p, %#x) -> %Vrc (off=%#llx '%s')\n",
242 pData->File, pvBuf, cbRead, rc, off, pData->pszFilename));
243 }
244 else
245 AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Vrc\n", pData->File, off, rc));
246 LogFlow(("drvRawImageRead: returns %Vrc\n", rc));
247 return rc;
248}
249
250
251/** @copydoc PDMIMEDIA::pfnWrite */
252static DECLCALLBACK(int) drvRawImageWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
253{
254 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
255 LogFlow(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n", off, pvBuf, cbWrite, pData->pszFilename));
256
257 Assert(pData->File);
258 Assert(pvBuf);
259
260 /*
261 * Seek to the position and write.
262 */
263 int rc = RTFileSeek(pData->File, off, RTFILE_SEEK_BEGIN, NULL);
264 if (VBOX_SUCCESS(rc))
265 {
266 rc = RTFileWrite(pData->File, pvBuf, cbWrite, NULL);
267 if (VBOX_SUCCESS(rc))
268 {
269 Log2(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n"
270 "%16.*Vhxd\n",
271 off, pvBuf, cbWrite, pData->pszFilename,
272 cbWrite, pvBuf));
273 }
274 else
275 AssertMsgFailed(("RTFileWrite(%d, %p, %#x) -> %Vrc (off=%#llx '%s')\n",
276 pData->File, pvBuf, cbWrite, rc, off, pData->pszFilename));
277 }
278 else
279 AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Vrc\n", pData->File, off, rc));
280 LogFlow(("drvRawImageWrite: returns %Vrc\n", rc));
281 return rc;
282}
283
284
285/** @copydoc PDMIMEDIA::pfnFlush */
286static DECLCALLBACK(int) drvRawImageFlush(PPDMIMEDIA pInterface)
287{
288 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
289 LogFlow(("drvRawImageFlush: (%s)\n", pData->pszFilename));
290
291 Assert(pData->File != NIL_RTFILE);
292 int rc = RTFileFlush(pData->File);
293 LogFlow(("drvRawImageFlush: returns %Vrc\n", rc));
294 return rc;
295}
296
297
298/** @copydoc PDMIMEDIA::pfnGetUuid */
299static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
300{
301 LogFlow(("drvRawImageGetUuid: returns VERR_NOT_IMPLEMENTED\n"));
302 return VERR_NOT_IMPLEMENTED;
303}
304
305
306/** @copydoc PDMIMEDIA::pfnIsReadOnly */
307static DECLCALLBACK(bool) drvRawImageIsReadOnly(PPDMIMEDIA pInterface)
308{
309 return false;
310}
311
312
313/**
314 * Stub - operation not supported.
315 *
316 * @copydoc PDMIMEDIA::pfnBiosGetTranslation
317 */
318static DECLCALLBACK(int) drvRawImageBiosGetTranslation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation)
319{
320 NOREF(pInterface); NOREF(penmTranslation);
321 return VERR_NOT_IMPLEMENTED;
322}
323
324
325/**
326 * Stub - operation not supported.
327 *
328 * @copydoc PDMIMEDIA::pfnBiosSetTranslation
329 */
330static DECLCALLBACK(int) drvRawImageBiosSetTranslation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation)
331{
332 NOREF(pInterface); NOREF(enmTranslation);
333 return VERR_NOT_IMPLEMENTED;
334}
335
336
337/**
338 * Queries an interface to the driver.
339 *
340 * @returns Pointer to interface.
341 * @returns NULL if the interface was not supported by the driver.
342 * @param pInterface Pointer to this interface structure.
343 * @param enmInterface The requested interface identification.
344 * @thread Any thread.
345 */
346static DECLCALLBACK(void *) drvRawImageQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface)
347{
348 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface);
349 PDRVRAWIMAGE pData = PDMINS2DATA(pDrvIns, PDRVRAWIMAGE);
350 switch (enmInterface)
351 {
352 case PDMINTERFACE_BASE:
353 return &pDrvIns->IBase;
354 case PDMINTERFACE_MEDIA:
355 return &pData->IMedia;
356 default:
357 return NULL;
358 }
359}
360
361
362/**
363 * Raw image driver registration record.
364 */
365const PDMDRVREG g_DrvRawImage =
366{
367 /* u32Version */
368 PDM_DRVREG_VERSION,
369 /* szDriverName */
370 "RawImage",
371 /* pszDescription */
372 "Raw image access driver.",
373 /* fFlags */
374 PDM_DRVREG_FLAGS_HOST_BITS_DEFAULT,
375 /* fClass. */
376 PDM_DRVREG_CLASS_MEDIA,
377 /* cMaxInstances */
378 ~0,
379 /* cbInstance */
380 sizeof(DRVRAWIMAGE),
381 /* pfnConstruct */
382 drvRawImageConstruct,
383 /* pfnDestruct */
384 drvRawImageDestruct,
385 /* pfnIOCtl */
386 NULL,
387 /* pfnPowerOn */
388 NULL,
389 /* pfnReset */
390 NULL,
391 /* pfnSuspend */
392 NULL,
393 /* pfnResume */
394 NULL,
395 /* pfnDetach */
396 NULL,
397 /* pfnPowerOff */
398 NULL
399};
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