VirtualBox

source: vbox/trunk/src/VBox/Storage/VDICore.h@ 38469

Last change on this file since 38469 was 38469, checked in by vboxsync, 14 years ago

VD: Interface cleanup. Merge the two involved structures (generic interface descriptor and callback table) into one, remove the duplicated interface wrappers in the backends and move the interface definitions into separate headers separating public and private interfaces.

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 16.6 KB
Line 
1/* $Id: VDICore.h 38469 2011-08-16 10:34:32Z vboxsync $ */
2/** @file
3 * Virtual Disk Image (VDI), Core Code Header (internal).
4 */
5
6/*
7 * Copyright (C) 2006-2010 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.215389.xyz. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
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.
16 */
17
18#ifndef ___VDICore_h___
19
20
21/*******************************************************************************
22* Header Files *
23*******************************************************************************/
24#include <VBox/vd.h>
25#include <VBox/err.h>
26
27#include <VBox/log.h>
28#include <iprt/alloc.h>
29#include <iprt/assert.h>
30#include <iprt/uuid.h>
31#include <iprt/string.h>
32#include <iprt/asm.h>
33
34
35/*******************************************************************************
36* Constants And Macros, Structures and Typedefs *
37*******************************************************************************/
38
39/** Image info, not handled anyhow.
40 * Must be less than 64 bytes in length, including the trailing 0.
41 */
42#define VDI_IMAGE_FILE_INFO "<<< Oracle VM VirtualBox Disk Image >>>\n"
43
44/** The Sector size.
45 * Currently we support only 512 bytes sectors.
46 */
47#define VDI_GEOMETRY_SECTOR_SIZE (512)
48/** 512 = 2^^9 */
49#define VDI_GEOMETRY_SECTOR_SHIFT (9)
50
51/**
52 * Harddisk geometry.
53 */
54#pragma pack(1)
55typedef struct VDIDISKGEOMETRY
56{
57 /** Cylinders. */
58 uint32_t cCylinders;
59 /** Heads. */
60 uint32_t cHeads;
61 /** Sectors per track. */
62 uint32_t cSectors;
63 /** Sector size. (bytes per sector) */
64 uint32_t cbSector;
65} VDIDISKGEOMETRY, *PVDIDISKGEOMETRY;
66#pragma pack()
67
68/** Image signature. */
69#define VDI_IMAGE_SIGNATURE (0xbeda107f)
70
71/**
72 * Pre-Header to be stored in image file - used for version control.
73 */
74#pragma pack(1)
75typedef struct VDIPREHEADER
76{
77 /** Just text info about image type, for eyes only. */
78 char szFileInfo[64];
79 /** The image signature (VDI_IMAGE_SIGNATURE). */
80 uint32_t u32Signature;
81 /** The image version (VDI_IMAGE_VERSION). */
82 uint32_t u32Version;
83} VDIPREHEADER, *PVDIPREHEADER;
84#pragma pack()
85
86/**
87 * Size of szComment field of HDD image header.
88 */
89#define VDI_IMAGE_COMMENT_SIZE 256
90
91/**
92 * Header to be stored in image file, VDI_IMAGE_VERSION_MAJOR = 0.
93 * Prepended by VDIPREHEADER.
94 */
95#pragma pack(1)
96typedef struct VDIHEADER0
97{
98 /** The image type (VDI_IMAGE_TYPE_*). */
99 uint32_t u32Type;
100 /** Image flags (VDI_IMAGE_FLAGS_*). */
101 uint32_t fFlags;
102 /** Image comment. (UTF-8) */
103 char szComment[VDI_IMAGE_COMMENT_SIZE];
104 /** Legacy image geometry (previous code stored PCHS there). */
105 VDIDISKGEOMETRY LegacyGeometry;
106 /** Size of disk (in bytes). */
107 uint64_t cbDisk;
108 /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) */
109 uint32_t cbBlock;
110 /** Number of blocks. */
111 uint32_t cBlocks;
112 /** Number of allocated blocks. */
113 uint32_t cBlocksAllocated;
114 /** UUID of image. */
115 RTUUID uuidCreate;
116 /** UUID of image's last modification. */
117 RTUUID uuidModify;
118 /** Only for secondary images - UUID of primary image. */
119 RTUUID uuidLinkage;
120} VDIHEADER0, *PVDIHEADER0;
121#pragma pack()
122
123/**
124 * Header to be stored in image file, VDI_IMAGE_VERSION_MAJOR = 1,
125 * VDI_IMAGE_VERSION_MINOR = 1. Prepended by VDIPREHEADER.
126 */
127#pragma pack(1)
128typedef struct VDIHEADER1
129{
130 /** Size of this structure in bytes. */
131 uint32_t cbHeader;
132 /** The image type (VDI_IMAGE_TYPE_*). */
133 uint32_t u32Type;
134 /** Image flags (VDI_IMAGE_FLAGS_*). */
135 uint32_t fFlags;
136 /** Image comment. (UTF-8) */
137 char szComment[VDI_IMAGE_COMMENT_SIZE];
138 /** Offset of Blocks array from the beginning of image file.
139 * Should be sector-aligned for HDD access optimization. */
140 uint32_t offBlocks;
141 /** Offset of image data from the beginning of image file.
142 * Should be sector-aligned for HDD access optimization. */
143 uint32_t offData;
144 /** Legacy image geometry (previous code stored PCHS there). */
145 VDIDISKGEOMETRY LegacyGeometry;
146 /** Was BIOS HDD translation mode, now unused. */
147 uint32_t u32Dummy;
148 /** Size of disk (in bytes). */
149 uint64_t cbDisk;
150 /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) Should be a power of 2! */
151 uint32_t cbBlock;
152 /** Size of additional service information of every data block.
153 * Prepended before block data. May be 0.
154 * Should be a power of 2 and sector-aligned for optimization reasons. */
155 uint32_t cbBlockExtra;
156 /** Number of blocks. */
157 uint32_t cBlocks;
158 /** Number of allocated blocks. */
159 uint32_t cBlocksAllocated;
160 /** UUID of image. */
161 RTUUID uuidCreate;
162 /** UUID of image's last modification. */
163 RTUUID uuidModify;
164 /** Only for secondary images - UUID of previous image. */
165 RTUUID uuidLinkage;
166 /** Only for secondary images - UUID of previous image's last modification. */
167 RTUUID uuidParentModify;
168} VDIHEADER1, *PVDIHEADER1;
169#pragma pack()
170
171/**
172 * Header to be stored in image file, VDI_IMAGE_VERSION_MAJOR = 1,
173 * VDI_IMAGE_VERSION_MINOR = 1, the slightly changed variant necessary as the
174 * old released code doesn't support changing the minor version at all.
175 */
176#pragma pack(1)
177typedef struct VDIHEADER1PLUS
178{
179 /** Size of this structure in bytes. */
180 uint32_t cbHeader;
181 /** The image type (VDI_IMAGE_TYPE_*). */
182 uint32_t u32Type;
183 /** Image flags (VDI_IMAGE_FLAGS_*). */
184 uint32_t fFlags;
185 /** Image comment. (UTF-8) */
186 char szComment[VDI_IMAGE_COMMENT_SIZE];
187 /** Offset of blocks array from the beginning of image file.
188 * Should be sector-aligned for HDD access optimization. */
189 uint32_t offBlocks;
190 /** Offset of image data from the beginning of image file.
191 * Should be sector-aligned for HDD access optimization. */
192 uint32_t offData;
193 /** Legacy image geometry (previous code stored PCHS there). */
194 VDIDISKGEOMETRY LegacyGeometry;
195 /** Was BIOS HDD translation mode, now unused. */
196 uint32_t u32Dummy;
197 /** Size of disk (in bytes). */
198 uint64_t cbDisk;
199 /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) Should be a power of 2! */
200 uint32_t cbBlock;
201 /** Size of additional service information of every data block.
202 * Prepended before block data. May be 0.
203 * Should be a power of 2 and sector-aligned for optimization reasons. */
204 uint32_t cbBlockExtra;
205 /** Number of blocks. */
206 uint32_t cBlocks;
207 /** Number of allocated blocks. */
208 uint32_t cBlocksAllocated;
209 /** UUID of image. */
210 RTUUID uuidCreate;
211 /** UUID of image's last modification. */
212 RTUUID uuidModify;
213 /** Only for secondary images - UUID of previous image. */
214 RTUUID uuidLinkage;
215 /** Only for secondary images - UUID of previous image's last modification. */
216 RTUUID uuidParentModify;
217 /** LCHS image geometry (new field in VDI1.2 version. */
218 VDIDISKGEOMETRY LCHSGeometry;
219} VDIHEADER1PLUS, *PVDIHEADER1PLUS;
220#pragma pack()
221
222/**
223 * Header structure for all versions.
224 */
225typedef struct VDIHEADER
226{
227 unsigned uVersion;
228 union
229 {
230 VDIHEADER0 v0;
231 VDIHEADER1 v1;
232 VDIHEADER1PLUS v1plus;
233 } u;
234} VDIHEADER, *PVDIHEADER;
235
236/**
237 * File alignment boundary for both the block array and data area. Should be
238 * at least the size of a physical sector on disk for performance reasons.
239 * With the growing market share of disks with 4K sectors this needs to be
240 * bumped, and maybe again later. */
241#define VDI_DATA_ALIGN _4K
242
243/** Block 'pointer'. */
244typedef uint32_t VDIIMAGEBLOCKPOINTER;
245/** Pointer to a block 'pointer'. */
246typedef VDIIMAGEBLOCKPOINTER *PVDIIMAGEBLOCKPOINTER;
247
248/**
249 * Block marked as free is not allocated in image file, read from this
250 * block may returns any random data.
251 */
252#define VDI_IMAGE_BLOCK_FREE ((VDIIMAGEBLOCKPOINTER)~0)
253
254/**
255 * Block marked as zero is not allocated in image file, read from this
256 * block returns zeroes.
257 */
258#define VDI_IMAGE_BLOCK_ZERO ((VDIIMAGEBLOCKPOINTER)~1)
259
260/**
261 * Block 'pointer' >= VDI_IMAGE_BLOCK_UNALLOCATED indicates block is not
262 * allocated in image file.
263 */
264#define VDI_IMAGE_BLOCK_UNALLOCATED (VDI_IMAGE_BLOCK_ZERO)
265#define IS_VDI_IMAGE_BLOCK_ALLOCATED(bp) (bp < VDI_IMAGE_BLOCK_UNALLOCATED)
266
267#define GET_MAJOR_HEADER_VERSION(ph) (VDI_GET_VERSION_MAJOR((ph)->uVersion))
268#define GET_MINOR_HEADER_VERSION(ph) (VDI_GET_VERSION_MINOR((ph)->uVersion))
269
270/** @name VDI image types
271 * @{ */
272typedef enum VDIIMAGETYPE
273{
274 /** Normal dynamically growing base image file. */
275 VDI_IMAGE_TYPE_NORMAL = 1,
276 /** Preallocated base image file of a fixed size. */
277 VDI_IMAGE_TYPE_FIXED,
278 /** Dynamically growing image file for undo/commit changes support. */
279 VDI_IMAGE_TYPE_UNDO,
280 /** Dynamically growing image file for differencing support. */
281 VDI_IMAGE_TYPE_DIFF,
282
283 /** First valid image type value. */
284 VDI_IMAGE_TYPE_FIRST = VDI_IMAGE_TYPE_NORMAL,
285 /** Last valid image type value. */
286 VDI_IMAGE_TYPE_LAST = VDI_IMAGE_TYPE_DIFF
287} VDIIMAGETYPE;
288/** Pointer to VDI image type. */
289typedef VDIIMAGETYPE *PVDIIMAGETYPE;
290/** @} */
291
292/*******************************************************************************
293* Internal Functions for header access *
294*******************************************************************************/
295DECLINLINE(VDIIMAGETYPE) getImageType(PVDIHEADER ph)
296{
297 switch (GET_MAJOR_HEADER_VERSION(ph))
298 {
299 case 0: return (VDIIMAGETYPE)ph->u.v0.u32Type;
300 case 1: return (VDIIMAGETYPE)ph->u.v1.u32Type;
301 }
302 AssertFailed();
303 return (VDIIMAGETYPE)0;
304}
305
306DECLINLINE(unsigned) getImageFlags(PVDIHEADER ph)
307{
308 switch (GET_MAJOR_HEADER_VERSION(ph))
309 {
310 case 0:
311 /* VDI image flag conversion to VD image flags. */
312 return ph->u.v0.fFlags << 8;
313 case 1:
314 /* VDI image flag conversion to VD image flags. */
315 return ph->u.v1.fFlags << 8;
316 }
317 AssertFailed();
318 return 0;
319}
320
321DECLINLINE(char *) getImageComment(PVDIHEADER ph)
322{
323 switch (GET_MAJOR_HEADER_VERSION(ph))
324 {
325 case 0: return &ph->u.v0.szComment[0];
326 case 1: return &ph->u.v1.szComment[0];
327 }
328 AssertFailed();
329 return NULL;
330}
331
332DECLINLINE(unsigned) getImageBlocksOffset(PVDIHEADER ph)
333{
334 switch (GET_MAJOR_HEADER_VERSION(ph))
335 {
336 case 0: return (sizeof(VDIPREHEADER) + sizeof(VDIHEADER0));
337 case 1: return ph->u.v1.offBlocks;
338 }
339 AssertFailed();
340 return 0;
341}
342
343DECLINLINE(uint32_t) getImageDataOffset(PVDIHEADER ph)
344{
345 switch (GET_MAJOR_HEADER_VERSION(ph))
346 {
347 case 0: return sizeof(VDIPREHEADER) + sizeof(VDIHEADER0) + \
348 (ph->u.v0.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER));
349 case 1: return ph->u.v1.offData;
350 }
351 AssertFailed();
352 return 0;
353}
354
355DECLINLINE(void) setImageDataOffset(PVDIHEADER ph, uint32_t offData)
356{
357 switch (GET_MAJOR_HEADER_VERSION(ph))
358 {
359 case 0: return;
360 case 1: ph->u.v1.offData = offData; return;
361 }
362 AssertFailed();
363}
364
365DECLINLINE(PVDIDISKGEOMETRY) getImageLCHSGeometry(PVDIHEADER ph)
366{
367 switch (GET_MAJOR_HEADER_VERSION(ph))
368 {
369 case 0: return NULL;
370 case 1:
371 switch (GET_MINOR_HEADER_VERSION(ph))
372 {
373 case 1:
374 if (ph->u.v1.cbHeader < sizeof(ph->u.v1plus))
375 return NULL;
376 else
377 return &ph->u.v1plus.LCHSGeometry;
378 }
379 }
380 AssertFailed();
381 return NULL;
382}
383
384DECLINLINE(uint64_t) getImageDiskSize(PVDIHEADER ph)
385{
386 switch (GET_MAJOR_HEADER_VERSION(ph))
387 {
388 case 0: return ph->u.v0.cbDisk;
389 case 1: return ph->u.v1.cbDisk;
390 }
391 AssertFailed();
392 return 0;
393}
394
395DECLINLINE(void) setImageDiskSize(PVDIHEADER ph, uint64_t cbDisk)
396{
397 switch (GET_MAJOR_HEADER_VERSION(ph))
398 {
399 case 0: ph->u.v0.cbDisk = cbDisk; return;
400 case 1: ph->u.v1.cbDisk = cbDisk; return;
401 }
402 AssertFailed();
403}
404
405DECLINLINE(unsigned) getImageBlockSize(PVDIHEADER ph)
406{
407 switch (GET_MAJOR_HEADER_VERSION(ph))
408 {
409 case 0: return ph->u.v0.cbBlock;
410 case 1: return ph->u.v1.cbBlock;
411 }
412 AssertFailed();
413 return 0;
414}
415
416DECLINLINE(unsigned) getImageExtraBlockSize(PVDIHEADER ph)
417{
418 switch (GET_MAJOR_HEADER_VERSION(ph))
419 {
420 case 0: return 0;
421 case 1: return ph->u.v1.cbBlockExtra;
422 }
423 AssertFailed();
424 return 0;
425}
426
427DECLINLINE(unsigned) getImageBlocks(PVDIHEADER ph)
428{
429 switch (GET_MAJOR_HEADER_VERSION(ph))
430 {
431 case 0: return ph->u.v0.cBlocks;
432 case 1: return ph->u.v1.cBlocks;
433 }
434 AssertFailed();
435 return 0;
436}
437
438DECLINLINE(void) setImageBlocks(PVDIHEADER ph, unsigned cBlocks)
439{
440 switch (GET_MAJOR_HEADER_VERSION(ph))
441 {
442 case 0: ph->u.v0.cBlocks = cBlocks; return;
443 case 1: ph->u.v1.cBlocks = cBlocks; return;
444 }
445 AssertFailed();
446}
447
448
449DECLINLINE(unsigned) getImageBlocksAllocated(PVDIHEADER ph)
450{
451 switch (GET_MAJOR_HEADER_VERSION(ph))
452 {
453 case 0: return ph->u.v0.cBlocksAllocated;
454 case 1: return ph->u.v1.cBlocksAllocated;
455 }
456 AssertFailed();
457 return 0;
458}
459
460DECLINLINE(void) setImageBlocksAllocated(PVDIHEADER ph, unsigned cBlocks)
461{
462 switch (GET_MAJOR_HEADER_VERSION(ph))
463 {
464 case 0: ph->u.v0.cBlocksAllocated = cBlocks; return;
465 case 1: ph->u.v1.cBlocksAllocated = cBlocks; return;
466 }
467 AssertFailed();
468}
469
470DECLINLINE(PRTUUID) getImageCreationUUID(PVDIHEADER ph)
471{
472 switch (GET_MAJOR_HEADER_VERSION(ph))
473 {
474 case 0: return &ph->u.v0.uuidCreate;
475 case 1: return &ph->u.v1.uuidCreate;
476 }
477 AssertFailed();
478 return NULL;
479}
480
481DECLINLINE(PRTUUID) getImageModificationUUID(PVDIHEADER ph)
482{
483 switch (GET_MAJOR_HEADER_VERSION(ph))
484 {
485 case 0: return &ph->u.v0.uuidModify;
486 case 1: return &ph->u.v1.uuidModify;
487 }
488 AssertFailed();
489 return NULL;
490}
491
492DECLINLINE(PRTUUID) getImageParentUUID(PVDIHEADER ph)
493{
494 switch (GET_MAJOR_HEADER_VERSION(ph))
495 {
496 case 0: return &ph->u.v0.uuidLinkage;
497 case 1: return &ph->u.v1.uuidLinkage;
498 }
499 AssertFailed();
500 return NULL;
501}
502
503DECLINLINE(PRTUUID) getImageParentModificationUUID(PVDIHEADER ph)
504{
505 switch (GET_MAJOR_HEADER_VERSION(ph))
506 {
507 case 1: return &ph->u.v1.uuidParentModify;
508 }
509 AssertFailed();
510 return NULL;
511}
512
513/**
514 * Image structure
515 */
516typedef struct VDIIMAGEDESC
517{
518 /** Opaque storage handle. */
519 PVDIOSTORAGE pStorage;
520 /** Image open flags, VD_OPEN_FLAGS_*. */
521 unsigned uOpenFlags;
522 /** Image pre-header. */
523 VDIPREHEADER PreHeader;
524 /** Image header. */
525 VDIHEADER Header;
526 /** Pointer to a block array. */
527 PVDIIMAGEBLOCKPOINTER paBlocks;
528 /** fFlags copy from image header, for speed optimization. */
529 unsigned uImageFlags;
530 /** Start offset of block array in image file, here for speed optimization. */
531 unsigned offStartBlocks;
532 /** Start offset of data in image file, here for speed optimization. */
533 unsigned offStartData;
534 /** Block mask for getting the offset into a block from a byte hdd offset. */
535 unsigned uBlockMask;
536 /** Block shift value for converting byte hdd offset into paBlock index. */
537 unsigned uShiftOffset2Index;
538 /** Offset of data from the beginning of block. */
539 unsigned offStartBlockData;
540 /** Total size of image block (including the extra data). */
541 unsigned cbTotalBlockData;
542 /** Container filename. (UTF-8) */
543 const char *pszFilename;
544 /** Physical geometry of this image (never actually stored). */
545 VDGEOMETRY PCHSGeometry;
546 /** Pointer to the per-disk VD interface list. */
547 PVDINTERFACE pVDIfsDisk;
548 /** Pointer to the per-image VD interface list. */
549 PVDINTERFACE pVDIfsImage;
550 /** Error interface. */
551 PVDINTERFACEERROR pIfError;
552 /** I/O interface. */
553 PVDINTERFACEIOINT pIfIo;
554} VDIIMAGEDESC, *PVDIIMAGEDESC;
555
556#endif
557
Note: See TracBrowser for help on using the repository browser.

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