VirtualBox

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

Last change on this file since 2558 was 1, checked in by vboxsync, 55 years ago

import

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 13.0 KB
Line 
1/** @file
2 *
3 * VBox storage devices:
4 * Raw image driver
5 */
6
7/*
8 * Copyright (C) 2006 InnoTek Systemberatung 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/pdm.h>
29#include <VBox/cfgm.h>
30#include <VBox/mm.h>
31#include <VBox/err.h>
32
33#include <VBox/log.h>
34#include <iprt/assert.h>
35#include <iprt/file.h>
36#include <iprt/string.h>
37
38#include "Builtins.h"
39
40
41/*******************************************************************************
42* Defined Constants And Macros *
43*******************************************************************************/
44
45/** Converts a pointer to RAWIMAGE::IMedia to a PRDVRAWIMAGE. */
46#define PDMIMEDIA_2_DRVRAWIMAGE(pInterface) ( (PDRVRAWIMAGE)((uintptr_t)pInterface - RT_OFFSETOF(DRVRAWIMAGE, IMedia)) )
47
48/** Converts a pointer to PDMDRVINS::IBase to a PPDMDRVINS. */
49#define PDMIBASE_2_DRVINS(pInterface) ( (PPDMDRVINS)((uintptr_t)pInterface - RT_OFFSETOF(PDMDRVINS, IBase)) )
50
51/** Converts a pointer to PDMDRVINS::IBase to a PVBOXHDD. */
52#define PDMIBASE_2_DRVRAWIMAGE(pInterface) ( PDMINS2DATA(PDMIBASE_2_DRVINS(pInterface), PDRVRAWIMAGE) )
53
54
55
56/*******************************************************************************
57* Structures and Typedefs *
58*******************************************************************************/
59/**
60 * Block driver instance data.
61 */
62typedef struct DRVRAWIMAGE
63{
64 /** The media interface. */
65 PDMIMEDIA IMedia;
66 /** Pointer to the driver instance. */
67 PPDMDRVINS pDrvIns;
68 /** Pointer to the filename. (Freed by MM) */
69 char *pszFilename;
70 /** File handle of the raw image file. */
71 RTFILE File;
72} DRVRAWIMAGE, *PDRVRAWIMAGE;
73
74
75
76/*******************************************************************************
77* Internal Functions *
78*******************************************************************************/
79static DECLCALLBACK(int) drvRawImageRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead);
80static DECLCALLBACK(int) drvRawImageWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite);
81static DECLCALLBACK(int) drvRawImageFlush(PPDMIMEDIA pInterface);
82static DECLCALLBACK(bool) drvRawImageIsReadOnly(PPDMIMEDIA pInterface);
83static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface);
84static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid);
85static DECLCALLBACK(int) drvRawImageBiosGetGeometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors);
86static DECLCALLBACK(int) drvRawImageBiosSetGeometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors);
87static DECLCALLBACK(int) drvRawImageBiosGetTranslation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation);
88static DECLCALLBACK(int) drvRawImageBiosSetTranslation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation);
89
90static DECLCALLBACK(void *) drvRawImageQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface);
91
92
93
94
95/**
96 * Construct a raw image driver instance.
97 *
98 * @returns VBox status.
99 * @param pDrvIns The driver instance data.
100 * If the registration structure is needed, pDrvIns->pDrvReg points to it.
101 * @param pCfgHandle Configuration node handle for the driver. Use this to obtain the configuration
102 * of the driver instance. It's also found in pDrvIns->pCfgHandle, but like
103 * iInstance it's expected to be used a bit in this function.
104 */
105static DECLCALLBACK(int) drvRawImageConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle)
106{
107 PDRVRAWIMAGE pData = PDMINS2DATA(pDrvIns, PDRVRAWIMAGE);
108
109 /*
110 * Init the static parts.
111 */
112 pData->pDrvIns = pDrvIns;
113 pData->File = NIL_RTFILE;
114 /* IBase */
115 pDrvIns->IBase.pfnQueryInterface = drvRawImageQueryInterface;
116 /* IMedia */
117 pData->IMedia.pfnRead = drvRawImageRead;
118 pData->IMedia.pfnWrite = drvRawImageWrite;
119 pData->IMedia.pfnFlush = drvRawImageFlush;
120 pData->IMedia.pfnGetSize = drvRawImageGetSize;
121 pData->IMedia.pfnGetUuid = drvRawImageGetUuid;
122 pData->IMedia.pfnIsReadOnly = drvRawImageIsReadOnly;
123 pData->IMedia.pfnBiosGetGeometry = drvRawImageBiosGetGeometry;
124 pData->IMedia.pfnBiosSetGeometry = drvRawImageBiosSetGeometry;
125 pData->IMedia.pfnBiosGetTranslation = drvRawImageBiosGetTranslation;
126 pData->IMedia.pfnBiosSetTranslation = drvRawImageBiosSetTranslation;
127
128 /*
129 * Read the configuration.
130 */
131 if (!CFGMR3AreValuesValid(pCfgHandle, "Path\0"))
132 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES;
133
134 char *pszName;
135 int rc = CFGMR3QueryStringAlloc(pCfgHandle, "Path", &pszName);
136 if (VBOX_FAILURE(rc))
137 {
138 AssertMsgFailed(("Configuration error: query for \"Path\" string return %Vrc.\n", rc));
139 return rc;
140 }
141
142 /*
143 * Open the image.
144 */
145 rc = RTFileOpen(&pData->File, pszName,
146 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_NONE);
147 if (VBOX_SUCCESS(rc))
148 {
149 LogFlow(("drvRawImageConstruct: Raw image '%s' opened successfully.\n", pszName));
150 pData->pszFilename = pszName;
151 }
152 else
153 {
154 AssertMsgFailed(("Could not open Raw image file %s, rc=%Vrc\n", pszName, rc));
155 MMR3HeapFree(pszName);
156 }
157
158 return rc;
159}
160
161
162/**
163 * Destruct a driver instance.
164 *
165 * Most VM resources are freed by the VM. This callback is provided so that any non-VM
166 * resources can be freed correctly.
167 *
168 * @param pDrvIns The driver instance data.
169 */
170static DECLCALLBACK(void) drvRawImageDestruct(PPDMDRVINS pDrvIns)
171{
172 PDRVRAWIMAGE pData = PDMINS2DATA(pDrvIns, PDRVRAWIMAGE);
173 LogFlow(("drvRawImageDestruct: '%s'\n", pData->pszFilename));
174
175 if (pData->File != NIL_RTFILE)
176 {
177 RTFileClose(pData->File);
178 pData->File = NIL_RTFILE;
179 }
180 if (pData->pszFilename)
181 MMR3HeapFree(pData->pszFilename);
182}
183
184
185/** @copydoc PDMIMEDIA::pfnGetSize */
186static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface)
187{
188 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
189 LogFlow(("drvRawImageGetSize: '%s'\n", pData->pszFilename));
190
191 uint64_t cbFile;
192 int rc = RTFileGetSize(pData->File, &cbFile);
193 if (VBOX_SUCCESS(rc))
194 {
195 LogFlow(("drvRawImageGetSize: returns %lld (%s)\n", cbFile, pData->pszFilename));
196 return cbFile;
197 }
198
199 AssertMsgFailed(("Error querying Raw image file size, rc=%Vrc. (%s)\n", rc, pData->pszFilename));
200 return 0;
201}
202
203
204/** @copydoc PDMIMEDIA::pfnBiosGetGeometry */
205static DECLCALLBACK(int) drvRawImageBiosGetGeometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)
206{
207 return VERR_NOT_IMPLEMENTED;
208}
209
210
211/** @copydoc PDMIMEDIA::pfnBiosSetGeometry */
212static DECLCALLBACK(int) drvRawImageBiosSetGeometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)
213{
214 return VERR_NOT_IMPLEMENTED;
215}
216
217
218/**
219 * Read bits.
220 *
221 * @see PDMIMEDIA::pfnRead for details.
222 */
223static DECLCALLBACK(int) drvRawImageRead(PPDMIMEDIA pInterface, uint64_t off, void *pvBuf, size_t cbRead)
224{
225 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
226 LogFlow(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n", off, pvBuf, cbRead, pData->pszFilename));
227
228 Assert(pData->File);
229 Assert(pvBuf);
230
231 /*
232 * Seek to the position and read.
233 */
234 int rc = RTFileSeek(pData->File, off, RTFILE_SEEK_BEGIN, NULL);
235 if (VBOX_SUCCESS(rc))
236 {
237 rc = RTFileRead(pData->File, pvBuf, cbRead, NULL);
238 if (VBOX_SUCCESS(rc))
239 {
240 Log2(("drvRawImageRead: off=%#llx pvBuf=%p cbRead=%#x (%s)\n"
241 "%16.*Vhxd\n",
242 off, pvBuf, cbRead, pData->pszFilename,
243 cbRead, pvBuf));
244 }
245 else
246 AssertMsgFailed(("RTFileRead(%d, %p, %#x) -> %Vrc (off=%#llx '%s')\n",
247 pData->File, pvBuf, cbRead, rc, off, pData->pszFilename));
248 }
249 else
250 AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Vrc\n", pData->File, off, rc));
251 LogFlow(("drvRawImageRead: returns %Vrc\n", rc));
252 return rc;
253}
254
255
256/** @copydoc PDMIMEDIA::pfnWrite */
257static DECLCALLBACK(int) drvRawImageWrite(PPDMIMEDIA pInterface, uint64_t off, const void *pvBuf, size_t cbWrite)
258{
259 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
260 LogFlow(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n", off, pvBuf, cbWrite, pData->pszFilename));
261
262 Assert(pData->File);
263 Assert(pvBuf);
264
265 /*
266 * Seek to the position and write.
267 */
268 int rc = RTFileSeek(pData->File, off, RTFILE_SEEK_BEGIN, NULL);
269 if (VBOX_SUCCESS(rc))
270 {
271 rc = RTFileWrite(pData->File, pvBuf, cbWrite, NULL);
272 if (VBOX_SUCCESS(rc))
273 {
274 Log2(("drvRawImageWrite: off=%#llx pvBuf=%p cbWrite=%#x (%s)\n"
275 "%16.*Vhxd\n",
276 off, pvBuf, cbWrite, pData->pszFilename,
277 cbWrite, pvBuf));
278 }
279 else
280 AssertMsgFailed(("RTFileWrite(%d, %p, %#x) -> %Vrc (off=%#llx '%s')\n",
281 pData->File, pvBuf, cbWrite, rc, off, pData->pszFilename));
282 }
283 else
284 AssertMsgFailed(("RTFileSeek(%d,%#llx,) -> %Vrc\n", pData->File, off, rc));
285 LogFlow(("drvRawImageWrite: returns %Vrc\n", rc));
286 return rc;
287}
288
289
290/** @copydoc PDMIMEDIA::pfnFlush */
291static DECLCALLBACK(int) drvRawImageFlush(PPDMIMEDIA pInterface)
292{
293 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface);
294 LogFlow(("drvRawImageFlush: (%s)\n", pData->pszFilename));
295
296 Assert(pData->File != NIL_RTFILE);
297 int rc = RTFileFlush(pData->File);
298 LogFlow(("drvRawImageFlush: returns %Vrc\n", rc));
299 return rc;
300}
301
302
303/** @copydoc PDMIMEDIA::pfnGetUuid */
304static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)
305{
306 LogFlow(("drvRawImageGetUuid: returns VERR_NOT_IMPLEMENTED\n"));
307 return VERR_NOT_IMPLEMENTED;
308}
309
310
311/** @copydoc PDMIMEDIA::pfnIsReadOnly */
312static DECLCALLBACK(bool) drvRawImageIsReadOnly(PPDMIMEDIA pInterface)
313{
314 return false;
315}
316
317
318/**
319 * Stub - operation not supported.
320 *
321 * @copydoc PDMIMEDIA::pfnBiosGetTranslation
322 */
323static DECLCALLBACK(int) drvRawImageBiosGetTranslation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation)
324{
325 NOREF(pInterface); NOREF(penmTranslation);
326 return VERR_NOT_IMPLEMENTED;
327}
328
329
330/**
331 * Stub - operation not supported.
332 *
333 * @copydoc PDMIMEDIA::pfnBiosSetTranslation
334 */
335static DECLCALLBACK(int) drvRawImageBiosSetTranslation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation)
336{
337 NOREF(pInterface); NOREF(enmTranslation);
338 return VERR_NOT_IMPLEMENTED;
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 pData = PDMINS2DATA(pDrvIns, PDRVRAWIMAGE);
355 switch (enmInterface)
356 {
357 case PDMINTERFACE_BASE:
358 return &pDrvIns->IBase;
359 case PDMINTERFACE_MEDIA:
360 return &pData->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