VirtualBox

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

最後變更 在這個檔案從6198是 5999,由 vboxsync 提交於 17 年 前

The Giant CDDL Dual-License Header Change.

  • 屬性 svn:eol-style 設為 native
  • 屬性 svn:keywords 設為 Author Date Id Revision
檔案大小: 15.2 KB
 
1/** $Id: VDICore.h 5999 2007-12-07 15:05:06Z vboxsync $ */
2/** @file
3 * Virtual Disk Image (VDI), Core Code Header (internal).
4 */
5
6/*
7 * Copyright (C) 2006-2007 innotek GmbH
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.alldomusa.eu.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 (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/VBoxHDD.h>
25#include <VBox/pdm.h>
26#include <VBox/mm.h>
27#include <VBox/err.h>
28
29#include <VBox/log.h>
30#include <iprt/alloc.h>
31#include <iprt/assert.h>
32#include <iprt/uuid.h>
33#include <iprt/file.h>
34#include <iprt/string.h>
35#include <iprt/asm.h>
36
37
38/*******************************************************************************
39* Constants And Macros, Structures and Typedefs *
40*******************************************************************************/
41
42/** Image info, not handled anyhow.
43 * Must be less than 64 bytes in length, including the trailing 0.
44 */
45#define VDI_IMAGE_FILE_INFO "<<< innotek VirtualBox Disk Image >>>\n"
46
47/** The Sector size.
48 * Currently we support only 512 bytes sectors.
49 */
50#define VDI_GEOMETRY_SECTOR_SIZE (512)
51/** 512 = 2^^9 */
52#define VDI_GEOMETRY_SECTOR_SHIFT (9)
53
54/**
55 * Harddisk geometry.
56 */
57#pragma pack(1)
58typedef struct VDIDISKGEOMETRY
59{
60 /** Cylinders. */
61 uint32_t cCylinders;
62 /** Heads. */
63 uint32_t cHeads;
64 /** Sectors per track. */
65 uint32_t cSectors;
66 /** Sector size. (bytes per sector) */
67 uint32_t cbSector;
68} VDIDISKGEOMETRY, *PVDIDISKGEOMETRY;
69#pragma pack()
70
71/** Image signature. */
72#define VDI_IMAGE_SIGNATURE (0xbeda107f)
73
74/**
75 * Pre-Header to be stored in image file - used for version control.
76 */
77#pragma pack(1)
78typedef struct VDIPREHEADER
79{
80 /** Just text info about image type, for eyes only. */
81 char szFileInfo[64];
82 /** The image signature (VDI_IMAGE_SIGNATURE). */
83 uint32_t u32Signature;
84 /** The image version (VDI_IMAGE_VERSION). */
85 uint32_t u32Version;
86} VDIPREHEADER, *PVDIPREHEADER;
87#pragma pack()
88
89/**
90 * Size of szComment field of HDD image header.
91 */
92#define VDI_IMAGE_COMMENT_SIZE 256
93
94/**
95 * Header to be stored in image file, VDI_IMAGE_VERSION_MAJOR = 0.
96 * Prepended by VDIPREHEADER.
97 */
98#pragma pack(1)
99typedef struct VDIHEADER0
100{
101 /** The image type (VDI_IMAGE_TYPE_*). */
102 uint32_t u32Type;
103 /** Image flags (VDI_IMAGE_FLAGS_*). */
104 uint32_t fFlags;
105 /** Image comment. (UTF-8) */
106 char szComment[VDI_IMAGE_COMMENT_SIZE];
107 /** Image geometry. */
108 VDIDISKGEOMETRY Geometry;
109 /** Size of disk (in bytes). */
110 uint64_t cbDisk;
111 /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) */
112 uint32_t cbBlock;
113 /** Number of blocks. */
114 uint32_t cBlocks;
115 /** Number of allocated blocks. */
116 uint32_t cBlocksAllocated;
117 /** UUID of image. */
118 RTUUID uuidCreate;
119 /** UUID of image's last modification. */
120 RTUUID uuidModify;
121 /** Only for secondary images - UUID of primary image. */
122 RTUUID uuidLinkage;
123} VDIHEADER0, *PVDIHEADER0;
124#pragma pack()
125
126/**
127 * Header to be stored in image file, VDI_IMAGE_VERSION_MAJOR = 1.
128 * Prepended by VDIPREHEADER.
129 */
130#pragma pack(1)
131typedef struct VDIHEADER1
132{
133 /** Size of this structure in bytes. */
134 uint32_t cbHeader;
135 /** The image type (VDI_IMAGE_TYPE_*). */
136 uint32_t u32Type;
137 /** Image flags (VDI_IMAGE_FLAGS_*). */
138 uint32_t fFlags;
139 /** Image comment. (UTF-8) */
140 char szComment[VDI_IMAGE_COMMENT_SIZE];
141 /** Offset of Blocks array from the begining of image file.
142 * Should be sector-aligned for HDD access optimization. */
143 uint32_t offBlocks;
144 /** Offset of image data from the begining of image file.
145 * Should be sector-aligned for HDD access optimization. */
146 uint32_t offData;
147 /** Image geometry. */
148 VDIDISKGEOMETRY Geometry;
149 /** BIOS HDD translation mode, see PDMBIOSTRANSLATION. */
150 uint32_t u32Translation;
151 /** Size of disk (in bytes). */
152 uint64_t cbDisk;
153 /** Block size. (For instance VDI_IMAGE_BLOCK_SIZE.) Should be a power of 2! */
154 uint32_t cbBlock;
155 /** Size of additional service information of every data block.
156 * Prepended before block data. May be 0.
157 * Should be a power of 2 and sector-aligned for optimization reasons. */
158 uint32_t cbBlockExtra;
159 /** Number of blocks. */
160 uint32_t cBlocks;
161 /** Number of allocated blocks. */
162 uint32_t cBlocksAllocated;
163 /** UUID of image. */
164 RTUUID uuidCreate;
165 /** UUID of image's last modification. */
166 RTUUID uuidModify;
167 /** Only for secondary images - UUID of previous image. */
168 RTUUID uuidLinkage;
169 /** Only for secondary images - UUID of previous image's last modification. */
170 RTUUID uuidParentModify;
171} VDIHEADER1, *PVDIHEADER1;
172#pragma pack()
173
174/**
175 * Header structure for all versions.
176 */
177typedef struct VDIHEADER
178{
179 unsigned uVersion;
180 union
181 {
182 VDIHEADER0 v0;
183 VDIHEADER1 v1;
184 } u;
185} VDIHEADER, *PVDIHEADER;
186
187/** Block 'pointer'. */
188typedef uint32_t VDIIMAGEBLOCKPOINTER;
189/** Pointer to a block 'pointer'. */
190typedef VDIIMAGEBLOCKPOINTER *PVDIIMAGEBLOCKPOINTER;
191
192/**
193 * Block marked as free is not allocated in image file, read from this
194 * block may returns any random data.
195 */
196#define VDI_IMAGE_BLOCK_FREE ((VDIIMAGEBLOCKPOINTER)~0)
197
198/**
199 * Block marked as zero is not allocated in image file, read from this
200 * block returns zeroes.
201 */
202#define VDI_IMAGE_BLOCK_ZERO ((VDIIMAGEBLOCKPOINTER)~1)
203
204/**
205 * Block 'pointer' >= VDI_IMAGE_BLOCK_UNALLOCATED indicates block is not
206 * allocated in image file.
207 */
208#define VDI_IMAGE_BLOCK_UNALLOCATED (VDI_IMAGE_BLOCK_ZERO)
209#define IS_VDI_IMAGE_BLOCK_ALLOCATED(bp) (bp < VDI_IMAGE_BLOCK_UNALLOCATED)
210
211#define GET_MAJOR_HEADER_VERSION(ph) (VDI_GET_VERSION_MAJOR((ph)->uVersion))
212#define GET_MINOR_HEADER_VERSION(ph) (VDI_GET_VERSION_MINOR((ph)->uVersion))
213
214
215/*******************************************************************************
216* Internal Functions for header access *
217*******************************************************************************/
218DECLINLINE(VDIIMAGETYPE) getImageType(PVDIHEADER ph)
219{
220 switch (GET_MAJOR_HEADER_VERSION(ph))
221 {
222 case 0: return (VDIIMAGETYPE)ph->u.v0.u32Type;
223 case 1: return (VDIIMAGETYPE)ph->u.v1.u32Type;
224 }
225 AssertFailed();
226 return (VDIIMAGETYPE)0;
227}
228
229DECLINLINE(unsigned) getImageFlags(PVDIHEADER ph)
230{
231 switch (GET_MAJOR_HEADER_VERSION(ph))
232 {
233 case 0: return ph->u.v0.fFlags;
234 case 1: return ph->u.v1.fFlags;
235 }
236 AssertFailed();
237 return 0;
238}
239
240DECLINLINE(char *) getImageComment(PVDIHEADER ph)
241{
242 switch (GET_MAJOR_HEADER_VERSION(ph))
243 {
244 case 0: return &ph->u.v0.szComment[0];
245 case 1: return &ph->u.v1.szComment[0];
246 }
247 AssertFailed();
248 return NULL;
249}
250
251DECLINLINE(unsigned) getImageBlocksOffset(PVDIHEADER ph)
252{
253 switch (GET_MAJOR_HEADER_VERSION(ph))
254 {
255 case 0: return (sizeof(VDIPREHEADER) + sizeof(VDIHEADER0));
256 case 1: return ph->u.v1.offBlocks;
257 }
258 AssertFailed();
259 return 0;
260}
261
262DECLINLINE(unsigned) getImageDataOffset(PVDIHEADER ph)
263{
264 switch (GET_MAJOR_HEADER_VERSION(ph))
265 {
266 case 0: return sizeof(VDIPREHEADER) + sizeof(VDIHEADER0) + \
267 (ph->u.v0.cBlocks * sizeof(VDIIMAGEBLOCKPOINTER));
268 case 1: return ph->u.v1.offData;
269 }
270 AssertFailed();
271 return 0;
272}
273
274DECLINLINE(PVDIDISKGEOMETRY) getImageGeometry(PVDIHEADER ph)
275{
276 switch (GET_MAJOR_HEADER_VERSION(ph))
277 {
278 case 0: return &ph->u.v0.Geometry;
279 case 1: return &ph->u.v1.Geometry;
280 }
281 AssertFailed();
282 return NULL;
283}
284
285DECLINLINE(PDMBIOSTRANSLATION) getImageTranslation(PVDIHEADER ph)
286{
287 switch (GET_MAJOR_HEADER_VERSION(ph))
288 {
289 case 0: return PDMBIOSTRANSLATION_AUTO;
290 case 1: return (PDMBIOSTRANSLATION)ph->u.v1.u32Translation;
291 }
292 AssertFailed();
293 return PDMBIOSTRANSLATION_NONE;
294}
295
296DECLINLINE(void) setImageTranslation(PVDIHEADER ph, PDMBIOSTRANSLATION enmTranslation)
297{
298 switch (GET_MAJOR_HEADER_VERSION(ph))
299 {
300 case 0: return;
301 case 1: ph->u.v1.u32Translation = (uint32_t)enmTranslation; return;
302 }
303 AssertFailed();
304}
305
306DECLINLINE(uint64_t) getImageDiskSize(PVDIHEADER ph)
307{
308 switch (GET_MAJOR_HEADER_VERSION(ph))
309 {
310 case 0: return ph->u.v0.cbDisk;
311 case 1: return ph->u.v1.cbDisk;
312 }
313 AssertFailed();
314 return 0;
315}
316
317DECLINLINE(unsigned) getImageBlockSize(PVDIHEADER ph)
318{
319 switch (GET_MAJOR_HEADER_VERSION(ph))
320 {
321 case 0: return ph->u.v0.cbBlock;
322 case 1: return ph->u.v1.cbBlock;
323 }
324 AssertFailed();
325 return 0;
326}
327
328DECLINLINE(unsigned) getImageExtraBlockSize(PVDIHEADER ph)
329{
330 switch (GET_MAJOR_HEADER_VERSION(ph))
331 {
332 case 0: return 0;
333 case 1: return ph->u.v1.cbBlockExtra;
334 }
335 AssertFailed();
336 return 0;
337}
338
339DECLINLINE(unsigned) getImageBlocks(PVDIHEADER ph)
340{
341 switch (GET_MAJOR_HEADER_VERSION(ph))
342 {
343 case 0: return ph->u.v0.cBlocks;
344 case 1: return ph->u.v1.cBlocks;
345 }
346 AssertFailed();
347 return 0;
348}
349
350DECLINLINE(unsigned) getImageBlocksAllocated(PVDIHEADER ph)
351{
352 switch (GET_MAJOR_HEADER_VERSION(ph))
353 {
354 case 0: return ph->u.v0.cBlocksAllocated;
355 case 1: return ph->u.v1.cBlocksAllocated;
356 }
357 AssertFailed();
358 return 0;
359}
360
361DECLINLINE(void) setImageBlocksAllocated(PVDIHEADER ph, unsigned cBlocks)
362{
363 switch (GET_MAJOR_HEADER_VERSION(ph))
364 {
365 case 0: ph->u.v0.cBlocksAllocated = cBlocks; return;
366 case 1: ph->u.v1.cBlocksAllocated = cBlocks; return;
367 }
368 AssertFailed();
369}
370
371DECLINLINE(PRTUUID) getImageCreationUUID(PVDIHEADER ph)
372{
373 switch (GET_MAJOR_HEADER_VERSION(ph))
374 {
375 case 0: return &ph->u.v0.uuidCreate;
376 case 1: return &ph->u.v1.uuidCreate;
377 }
378 AssertFailed();
379 return NULL;
380}
381
382DECLINLINE(PRTUUID) getImageModificationUUID(PVDIHEADER ph)
383{
384 switch (GET_MAJOR_HEADER_VERSION(ph))
385 {
386 case 0: return &ph->u.v0.uuidModify;
387 case 1: return &ph->u.v1.uuidModify;
388 }
389 AssertFailed();
390 return NULL;
391}
392
393DECLINLINE(PRTUUID) getImageParentUUID(PVDIHEADER ph)
394{
395 switch (GET_MAJOR_HEADER_VERSION(ph))
396 {
397 case 0: return &ph->u.v0.uuidLinkage;
398 case 1: return &ph->u.v1.uuidLinkage;
399 }
400 AssertFailed();
401 return NULL;
402}
403
404DECLINLINE(PRTUUID) getImageParentModificationUUID(PVDIHEADER ph)
405{
406 switch (GET_MAJOR_HEADER_VERSION(ph))
407 {
408 case 1: return &ph->u.v1.uuidParentModify;
409 }
410 AssertFailed();
411 return NULL;
412}
413
414/**
415 * Default image block size, may be changed by setBlockSize/getBlockSize.
416 *
417 * Note: for speed reasons block size should be a power of 2 !
418 */
419#define VDI_IMAGE_DEFAULT_BLOCK_SIZE _1M
420
421/**
422 * fModified bit flags.
423 */
424#define VDI_IMAGE_MODIFIED_FLAG RT_BIT(0)
425#define VDI_IMAGE_MODIFIED_FIRST RT_BIT(1)
426#define VDI_IMAGE_MODIFIED_DISABLE_UUID_UPDATE RT_BIT(2)
427
428/**
429 * Image structure
430 */
431typedef struct VDIIMAGEDESC
432{
433 /** Link to parent image descriptor, if any. */
434 struct VDIIMAGEDESC *pPrev;
435 /** Link to child image descriptor, if any. */
436 struct VDIIMAGEDESC *pNext;
437 /** File handle. */
438 RTFILE File;
439 /** True if the image is operating in readonly mode. */
440 bool fReadOnly;
441 /** Image open flags, VDI_OPEN_FLAGS_*. */
442 unsigned fOpen;
443 /** Image pre-header. */
444 VDIPREHEADER PreHeader;
445 /** Image header. */
446 VDIHEADER Header;
447 /** Pointer to a block array. */
448 PVDIIMAGEBLOCKPOINTER paBlocks;
449 /** fFlags copy from image header, for speed optimization. */
450 unsigned fFlags;
451 /** Start offset of block array in image file, here for speed optimization. */
452 unsigned offStartBlocks;
453 /** Start offset of data in image file, here for speed optimization. */
454 unsigned offStartData;
455 /** Block mask for getting the offset into a block from a byte hdd offset. */
456 unsigned uBlockMask;
457 /** Block shift value for converting byte hdd offset into paBlock index. */
458 unsigned uShiftOffset2Index;
459 /** Block shift value for converting block index into offset in image. */
460 unsigned uShiftIndex2Offset;
461 /** Offset of data from the beginning of block. */
462 unsigned offStartBlockData;
463 /** Image is modified flags (VDI_IMAGE_MODIFIED*). */
464 unsigned fModified;
465 /** Container filename. (UTF-8)
466 * @todo Make this variable length to save a bunch of bytes. (low prio) */
467 char szFilename[RTPATH_MAX];
468} VDIIMAGEDESC, *PVDIIMAGEDESC;
469
470/**
471 * Default work buffer size, may be changed by setBufferSize() method.
472 *
473 * For best speed performance it must be equal to image block size.
474 */
475#define VDIDISK_DEFAULT_BUFFER_SIZE (VDI_IMAGE_DEFAULT_BLOCK_SIZE)
476
477/** VDIDISK Signature. */
478#define VDIDISK_SIGNATURE (0xbedafeda)
479
480/**
481 * VBox HDD Container main structure, private part.
482 */
483struct VDIDISK
484{
485 /** Structure signature (VDIDISK_SIGNATURE). */
486 uint32_t u32Signature;
487
488 /** Number of opened images. */
489 unsigned cImages;
490
491 /** Base image. */
492 PVDIIMAGEDESC pBase;
493
494 /** Last opened image in the chain.
495 * The same as pBase if only one image is used or the last opened diff image. */
496 PVDIIMAGEDESC pLast;
497
498 /** Default block size for newly created images. */
499 unsigned cbBlock;
500
501 /** Working buffer size, allocated only while committing data,
502 * copying block from primary image to secondary and saving previously
503 * zero block. Buffer deallocated after operation complete.
504 * @remark For best performance buffer size must be equal to image's
505 * block size, however it may be decreased for memory saving.
506 */
507 unsigned cbBuf;
508
509 /** Flag whether zero writes should be handled normally or optimized
510 * away if possible. */
511 bool fHonorZeroWrites;
512
513 /** The media interface. */
514 PDMIMEDIA IMedia;
515 /** Pointer to the driver instance. */
516 PPDMDRVINS pDrvIns;
517};
518
519
520/*******************************************************************************
521* Internal Functions *
522*******************************************************************************/
523__BEGIN_DECLS
524
525VBOXDDU_DECL(void) vdiInitVDIDisk(PVDIDISK pDisk);
526VBOXDDU_DECL(void) vdiFlushImage(PVDIIMAGEDESC pImage);
527VBOXDDU_DECL(int) vdiChangeImageMode(PVDIIMAGEDESC pImage, bool fReadOnly);
528
529__END_DECLS
530
531#endif
注意: 瀏覽 TracBrowser 來幫助您使用儲存庫瀏覽器

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