Correcting the usage of a variable when calling register_disk()
[vdi_driver.git] / src / VDICore.h
blobff03a4ff501ff3cd5bae46c64c3cc03173c2b118
1 /** $Id: VDICore.h 25896 2007-11-01 16:13:17Z frank $ */
2 /** @file
3 * Virtual Disk Image (VDI), Core Code Header (internal).
4 */
6 /*
7 * Copyright (C) 2006-2007 innotek GmbH
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
12 * General Public License as published by the Free Software Foundation,
13 * in version 2 as it comes in the "COPYING" file of the VirtualBox OSE
14 * distribution. VirtualBox OSE is distributed in the hope that it will
15 * be useful, but WITHOUT ANY WARRANTY of any kind.
18 #ifndef __VDICore_h__
21 /*******************************************************************************
22 * Header Files *
23 *******************************************************************************/
24 #include <stdint.h>
25 #include <cstring>
26 #include "types.h"
27 #include "cdefs.h"
28 #include "func_defines.h"
29 #include "const_defines.h"
30 #include "VBoxHDD.h"
33 /*******************************************************************************
34 * Constants And Macros, Structures and Typedefs *
35 *******************************************************************************/
37 /** The Sector size.
38 * Currently we support only 512 bytes sectors.
40 #define VDI_GEOMETRY_SECTOR_SIZE (512)
41 /** 512 = 2^^9 */
42 #define VDI_GEOMETRY_SECTOR_SHIFT (9)
44 /**
45 * Harddisk geometry.
47 #pragma pack(1)
48 typedef struct VDIDISKGEOMETRY
50 /** Cylinders. */
51 uint32_t cCylinders;
52 /** Heads. */
53 uint32_t cHeads;
54 /** Sectors per track. */
55 uint32_t cSectors;
56 /** Sector size. (bytes per sector) */
57 uint32_t cbSector;
58 } VDIDISKGEOMETRY, *PVDIDISKGEOMETRY;
59 #pragma pack()
61 /** Image signature. */
62 #define VDI_IMAGE_SIGNATURE (0xbeda107f)
64 /**
65 * Pre-Header to be stored in image file - used for version control.
67 #pragma pack(1)
68 typedef struct VDIPREHEADER
70 /** Just text info about image type, for eyes only. */
71 char szFileInfo[64];
72 /** The image signature (VDI_IMAGE_SIGNATURE). */
73 uint32_t u32Signature;
74 /** The image version (VDI_IMAGE_VERSION). */
75 uint32_t u32Version;
76 } VDIPREHEADER, *PVDIPREHEADER;
77 #pragma pack()
79 /**
80 * Size of szComment field of HDD image header.
82 #define VDI_IMAGE_COMMENT_SIZE 256
84 /**
85 * Header to be stored in image file, VDI_IMAGE_VERSION_MAJOR = 0.
86 * Prepended by VDIPREHEADER.
88 #pragma pack(1)
89 typedef struct VDIHEADER0
91 /** The image type (VDI_IMAGE_TYPE_*). */
92 uint32_t u32Type;
93 /** Image flags (VDI_IMAGE_FLAGS_*). */
94 uint32_t fFlags;
95 /** Image comment. (UTF-8) */
96 char szComment[VDI_IMAGE_COMMENT_SIZE];
97 /** Image geometry. */
98 VDIDISKGEOMETRY Geometry;
99 /** Size of disk (in bytes). */
100 uint64_t cbDisk;
101 /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) */
102 uint32_t cbBlock;
103 /** Number of blocks. */
104 uint32_t cBlocks;
105 /** Number of allocated blocks. */
106 uint32_t cBlocksAllocated;
107 /** UUID of image. */
108 RTUUID uuidCreate;
109 /** UUID of image's last modification. */
110 RTUUID uuidModify;
111 /** Only for secondary images - UUID of primary image. */
112 RTUUID uuidLinkage;
113 } VDIHEADER0, *PVDIHEADER0;
114 #pragma pack()
117 * Header to be stored in image file, VDI_IMAGE_VERSION_MAJOR = 1.
118 * Prepended by VDIPREHEADER.
120 #pragma pack(1)
121 typedef struct VDIHEADER1
123 /** Size of this structure in bytes. */
124 uint32_t cbHeader;
125 /** The image type (VDI_IMAGE_TYPE_*). */
126 uint32_t u32Type;
127 /** Image flags (VDI_IMAGE_FLAGS_*). */
128 uint32_t fFlags;
129 /** Image comment. (UTF-8) */
130 char szComment[VDI_IMAGE_COMMENT_SIZE];
131 /** Offset of Blocks array from the begining of image file.
132 * Should be sector-aligned for HDD access optimization. */
133 uint32_t offBlocks;
134 /** Offset of image data from the begining of image file.
135 * Should be sector-aligned for HDD access optimization. */
136 uint32_t offData;
137 /** Image geometry. */
138 VDIDISKGEOMETRY Geometry;
139 /** BIOS HDD translation mode, see PDMBIOSTRANSLATION. */
140 uint32_t u32Translation;
141 /** Size of disk (in bytes). */
142 uint64_t cbDisk;
143 /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) Should be a power of 2! */
144 uint32_t cbBlock;
145 /** Size of additional service information of every data block.
146 * Prepended before block data. May be 0.
147 * Should be a power of 2 and sector-aligned for optimization reasons. */
148 uint32_t cbBlockExtra;
149 /** Number of blocks. */
150 uint32_t cBlocks;
151 /** Number of allocated blocks. */
152 uint32_t cBlocksAllocated;
153 /** UUID of image. */
154 RTUUID uuidCreate;
155 /** UUID of image's last modification. */
156 RTUUID uuidModify;
157 /** Only for secondary images - UUID of previous image. */
158 RTUUID uuidLinkage;
159 /** Only for secondary images - UUID of previous image's last modification. */
160 RTUUID uuidParentModify;
161 } VDIHEADER1, *PVDIHEADER1;
162 #pragma pack()
165 * Header structure for all versions.
167 typedef struct VDIHEADER
169 unsigned uVersion;
170 union
172 VDIHEADER0 v0;
173 VDIHEADER1 v1;
174 } u;
175 } VDIHEADER, *PVDIHEADER;
177 /** Block 'pointer'. */
178 typedef uint32_t VDIIMAGEBLOCKPOINTER;
179 /** Pointer to a block 'pointer'. */
180 typedef VDIIMAGEBLOCKPOINTER *PVDIIMAGEBLOCKPOINTER;
183 * Block marked as free is not allocated in image file, read from this
184 * block may returns any random data.
186 #define VDI_IMAGE_BLOCK_FREE ((VDIIMAGEBLOCKPOINTER)~0)
189 * Block marked as zero is not allocated in image file, read from this
190 * block returns zeroes.
192 #define VDI_IMAGE_BLOCK_ZERO ((VDIIMAGEBLOCKPOINTER)~1)
195 * Block 'pointer' >= VDI_IMAGE_BLOCK_UNALLOCATED indicates block is not
196 * allocated in image file.
198 #define VDI_IMAGE_BLOCK_UNALLOCATED (VDI_IMAGE_BLOCK_ZERO)
199 #define IS_VDI_IMAGE_BLOCK_ALLOCATED(bp) (bp < VDI_IMAGE_BLOCK_UNALLOCATED)
201 #define GET_MAJOR_HEADER_VERSION(ph) (VDI_GET_VERSION_MAJOR((ph)->uVersion))
202 #define GET_MINOR_HEADER_VERSION(ph) (VDI_GET_VERSION_MINOR((ph)->uVersion))
205 /*******************************************************************************
206 * Internal Functions for header access *
207 *******************************************************************************/
208 DECLINLINE(VDIIMAGETYPE) getImageType(PVDIHEADER ph)
210 switch (GET_MAJOR_HEADER_VERSION(ph))
212 case 0: return (VDIIMAGETYPE)ph->u.v0.u32Type;
213 case 1: return (VDIIMAGETYPE)ph->u.v1.u32Type;
215 AssertFailed();
216 return (VDIIMAGETYPE)0;
219 DECLINLINE(unsigned) getImageFlags(PVDIHEADER ph)
221 switch (GET_MAJOR_HEADER_VERSION(ph))
223 case 0: return ph->u.v0.fFlags;
224 case 1: return ph->u.v1.fFlags;
226 AssertFailed();
227 return 0;
230 DECLINLINE(char *) getImageComment(PVDIHEADER ph)
232 switch (GET_MAJOR_HEADER_VERSION(ph))
234 case 0: return &ph->u.v0.szComment[0];
235 case 1: return &ph->u.v1.szComment[0];
237 AssertFailed();
238 return NULL;
241 DECLINLINE(unsigned) getImageBlocksOffset(PVDIHEADER ph)
243 switch (GET_MAJOR_HEADER_VERSION(ph))
245 case 0: return (sizeof(VDIPREHEADER) + sizeof(VDIHEADER0));
246 case 1: return ph->u.v1.offBlocks;
248 AssertFailed();
249 return 0;
252 DECLINLINE(unsigned) getImageDataOffset(PVDIHEADER ph)
254 switch (GET_MAJOR_HEADER_VERSION(ph))
256 case 0: return sizeof(VDIPREHEADER) + sizeof(VDIHEADER0) + \
257 (ph->u.v0.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER));
258 case 1: return ph->u.v1.offData;
260 AssertFailed();
261 return 0;
264 DECLINLINE(PVDIDISKGEOMETRY) getImageGeometry(PVDIHEADER ph)
266 switch (GET_MAJOR_HEADER_VERSION(ph))
268 case 0: return &ph->u.v0.Geometry;
269 case 1: return &ph->u.v1.Geometry;
271 AssertFailed();
272 return NULL;
275 DECLINLINE(PDMBIOSTRANSLATION) getImageTranslation(PVDIHEADER ph)
277 switch (GET_MAJOR_HEADER_VERSION(ph))
279 case 0: return PDMBIOSTRANSLATION_AUTO;
280 case 1: return (PDMBIOSTRANSLATION)ph->u.v1.u32Translation;
282 AssertFailed();
283 return PDMBIOSTRANSLATION_NONE;
286 DECLINLINE(void) setImageTranslation(PVDIHEADER ph, PDMBIOSTRANSLATION enmTranslation)
288 switch (GET_MAJOR_HEADER_VERSION(ph))
290 case 0: return;
291 case 1: ph->u.v1.u32Translation = (uint32_t)enmTranslation; return;
293 AssertFailed();
296 DECLINLINE(uint64_t) getImageDiskSize(PVDIHEADER ph)
298 switch (GET_MAJOR_HEADER_VERSION(ph))
300 case 0: return ph->u.v0.cbDisk;
301 case 1: return ph->u.v1.cbDisk;
303 AssertFailed();
304 return 0;
307 DECLINLINE(unsigned) getImageBlockSize(PVDIHEADER ph)
309 switch (GET_MAJOR_HEADER_VERSION(ph))
311 case 0: return ph->u.v0.cbBlock;
312 case 1: return ph->u.v1.cbBlock;
314 AssertFailed();
315 return 0;
318 DECLINLINE(unsigned) getImageExtraBlockSize(PVDIHEADER ph)
320 switch (GET_MAJOR_HEADER_VERSION(ph))
322 case 0: return 0;
323 case 1: return ph->u.v1.cbBlockExtra;
325 AssertFailed();
326 return 0;
329 DECLINLINE(unsigned) getImageBlocks(PVDIHEADER ph)
331 switch (GET_MAJOR_HEADER_VERSION(ph))
333 case 0: return ph->u.v0.cBlocks;
334 case 1: return ph->u.v1.cBlocks;
336 AssertFailed();
337 return 0;
340 DECLINLINE(unsigned) getImageBlocksAllocated(PVDIHEADER ph)
342 switch (GET_MAJOR_HEADER_VERSION(ph))
344 case 0: return ph->u.v0.cBlocksAllocated;
345 case 1: return ph->u.v1.cBlocksAllocated;
347 AssertFailed();
348 return 0;
351 DECLINLINE(void) setImageBlocksAllocated(PVDIHEADER ph, unsigned cBlocks)
353 switch (GET_MAJOR_HEADER_VERSION(ph))
355 case 0: ph->u.v0.cBlocksAllocated = cBlocks; return;
356 case 1: ph->u.v1.cBlocksAllocated = cBlocks; return;
358 AssertFailed();
361 DECLINLINE(PRTUUID) getImageCreationUUID(PVDIHEADER ph)
363 switch (GET_MAJOR_HEADER_VERSION(ph))
365 case 0: return &ph->u.v0.uuidCreate;
366 case 1: return &ph->u.v1.uuidCreate;
368 AssertFailed();
369 return NULL;
372 DECLINLINE(PRTUUID) getImageModificationUUID(PVDIHEADER ph)
374 switch (GET_MAJOR_HEADER_VERSION(ph))
376 case 0: return &ph->u.v0.uuidModify;
377 case 1: return &ph->u.v1.uuidModify;
379 AssertFailed();
380 return NULL;
383 DECLINLINE(PRTUUID) getImageParentUUID(PVDIHEADER ph)
385 switch (GET_MAJOR_HEADER_VERSION(ph))
387 case 0: return &ph->u.v0.uuidLinkage;
388 case 1: return &ph->u.v1.uuidLinkage;
390 AssertFailed();
391 return NULL;
394 DECLINLINE(PRTUUID) getImageParentModificationUUID(PVDIHEADER ph)
396 switch (GET_MAJOR_HEADER_VERSION(ph))
398 case 1: return &ph->u.v1.uuidParentModify;
400 AssertFailed();
401 return NULL;
405 * Default image block size, may be changed by setBlockSize/getBlockSize.
407 * Note: for speed reasons block size should be a power of 2 !
409 #define VDI_IMAGE_DEFAULT_BLOCK_SIZE _1M
412 * fModified bit flags.
414 #define VDI_IMAGE_MODIFIED_FLAG RT_BIT(0)
415 #define VDI_IMAGE_MODIFIED_FIRST RT_BIT(1)
416 #define VDI_IMAGE_MODIFIED_DISABLE_UUID_UPDATE RT_BIT(2)
419 * Image structure
421 typedef struct VDIIMAGEDESC
423 /** Link to parent image descriptor, if any. */
424 struct VDIIMAGEDESC *pPrev;
425 /** Link to child image descriptor, if any. */
426 struct VDIIMAGEDESC *pNext;
427 /** File handle. */
428 RTFILE File;
429 /** True if the image is operating in readonly mode. */
430 bool fReadOnly;
431 /** Image open flags, VDI_OPEN_FLAGS_*. */
432 unsigned fOpen;
433 /** Image pre-header. */
434 VDIPREHEADER PreHeader;
435 /** Image header. */
436 VDIHEADER Header;
437 /** Pointer to a block array. */
438 PVDIIMAGEBLOCKPOINTER paBlocks;
439 /** fFlags copy from image header, for speed optimization. */
440 unsigned fFlags;
441 /** Start offset of block array in image file, here for speed optimization. */
442 unsigned offStartBlocks;
443 /** Start offset of data in image file, here for speed optimization. */
444 unsigned offStartData;
445 /** Block mask for getting the offset into a block from a byte hdd offset. */
446 unsigned uBlockMask;
447 /** Block shift value for converting byte hdd offset into paBlock index. */
448 unsigned uShiftOffset2Index;
449 /** Block shift value for converting block index into offset in image. */
450 unsigned uShiftIndex2Offset;
451 /** Offset of data from the beginning of block. */
452 unsigned offStartBlockData;
453 /** Image is modified flags (VDI_IMAGE_MODIFIED*). */
454 unsigned fModified;
455 /** Container filename. (UTF-8)
456 * @todo Make this variable length to save a bunch of bytes. (low prio) */
457 char szFilename[RTPATH_MAX];
458 } VDIIMAGEDESC, *PVDIIMAGEDESC;
461 * Default work buffer size, may be changed by setBufferSize() method.
463 * For best speed performance it must be equal to image block size.
465 #define VDIDISK_DEFAULT_BUFFER_SIZE (VDI_IMAGE_DEFAULT_BLOCK_SIZE)
467 /** VDIDISK Signature. */
468 #define VDIDISK_SIGNATURE (0xbedafeda)
471 * VBox HDD Container main structure, private part.
473 struct VDIDISK
475 /** Structure signature (VDIDISK_SIGNATURE). */
476 uint32_t u32Signature;
478 /** Number of opened images. */
479 unsigned cImages;
481 /** Base image. */
482 PVDIIMAGEDESC pBase;
484 /** Last opened image in the chain.
485 * The same as pBase if only one image is used or the last opened diff image. */
486 PVDIIMAGEDESC pLast;
488 /** Default block size for newly created images. */
489 unsigned cbBlock;
491 /** Working buffer size, allocated only while committing data,
492 * copying block from primary image to secondary and saving previously
493 * zero block. Buffer deallocated after operation complete.
494 * @remark For best performance buffer size must be equal to image's
495 * block size, however it may be decreased for memory saving.
497 unsigned cbBuf;
499 /** Flag whether zero writes should be handled normally or optimized
500 * away if possible. */
501 bool fHonorZeroWrites;
503 /** The media interface. */
504 PDMIMEDIA IMedia;
505 /** Pointer to the driver instance. */
506 PPDMDRVINS pDrvIns;
509 * VBox VDI disk Container main structure.
511 /* Forward declaration, VDIDISK structure is visible only inside VDI module. */
512 //struct VDIDISK;
513 typedef struct VDIDISK VDIDISK;
514 typedef VDIDISK *PVDIDISK;
517 /*******************************************************************************
518 * Internal Functions *
519 *******************************************************************************/
520 __BEGIN_DECLS
522 void vdiInitVDIDisk(PVDIDISK pDisk);
523 void vdiFlushImage(PVDIIMAGEDESC pImage);
524 int vdiChangeImageMode(PVDIIMAGEDESC pImage, bool fReadOnly);
526 __END_DECLS
528 #endif