Changeset 6291 in vbox
- Timestamp:
- Jan 9, 2008 10:57:05 AM (17 years ago)
- svn:sync-xref-src-repo-rev:
- 27155
- Location:
- trunk
- Files:
-
- 2 deleted
- 25 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/VBox/VBoxHDD-new.h
r5999 r6291 5 5 6 6 /* 7 * Copyright (C) 2006-200 7innotek GmbH7 * Copyright (C) 2006-2008 innotek GmbH 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 56 56 /** Get VDI minor version from combined version. */ 57 57 #define VDI_GET_VERSION_MINOR(uVer) ((uVer) & 0xffff) 58 59 /** Placeholder for specifying the last opened image. */ 60 #define VD_LAST_IMAGE 0xffffffffU 58 61 59 62 /** @name VBox HDD container image types … … 97 100 /** Mask of valid image flags for VDI. */ 98 101 #define VD_VDI_IMAGE_FLAGS_MASK (VD_IMAGE_FLAGS_NONE | VD_VDI_IMAGE_FLAGS_ZERO_EXPAND) 102 103 /** Mask of all valid image flags for all formats. */ 104 #define VD_IMAGE_FLAGS_MASK (VD_VMDK_IMAGE_FLAGS_MASK | VD_VDI_IMAGE_FLAGS_MASK) 99 105 100 106 /** Default image flags. */ … … 132 138 typedef struct VBOXHDDRAW 133 139 { 140 /** Signature for structure. Must be 'R', 'A', 'W', '\0'. Actually a trick 141 * to make logging of the comment string produce sensible results. */ 142 char szSignature[4]; 134 143 /** Flag whether access to full disk should be given (ignoring the 135 144 * partition information below). */ … … 189 198 190 199 /** 191 * Allocates and initializes an empty VBoxHDD container.200 * Allocates and initializes an empty HDD container. 192 201 * No image files are opened. 193 202 * … … 196 205 * @param pfnError Callback for setting extended error information. 197 206 * @param pvErrorUser Opaque parameter for pfnError. 198 * @param ppDisk Where to store the reference to the VBox HDD container. 199 */ 200 VBOXDDU_DECL(int) VDCreate(const char *pszBackend, PFNVDERROR pfnError, void *pvErrorUser, PVBOXHDD *ppDisk); 201 202 /** 203 * Destroys the VBox HDD container. 207 * @param ppDisk Where to store the reference to HDD container. 208 */ 209 VBOXDDU_DECL(int) VDCreate(const char *pszBackend, PFNVDERROR pfnError, 210 void *pvErrorUser, PVBOXHDD *ppDisk); 211 212 /** 213 * Destroys HDD container. 204 214 * If container has opened image files they will be closed. 205 215 * 206 * @param pDisk Pointer to VBoxHDD container.216 * @param pDisk Pointer to HDD container. 207 217 */ 208 218 VBOXDDU_DECL(void) VDDestroy(PVBOXHDD pDisk); 209 219 210 220 /** 211 * Try to get the backend name which can use this image. 221 * Try to get the backend name which can use this image. 212 222 * 213 223 * @returns VBox status code. … … 221 231 * Opens an image file. 222 232 * 223 * The first opened image file in aHDD container must have a base image type,233 * The first opened image file in HDD container must have a base image type, 224 234 * others (next opened images) must be differencing or undo images. 225 235 * Linkage is checked for differencing image to be consistent with the previously opened image. … … 232 242 * 233 243 * @returns VBox status code. 234 * @param pDisk Pointer to VBoxHDD container.244 * @param pDisk Pointer to HDD container. 235 245 * @param pszFilename Name of the image file to open. 236 246 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. 237 247 */ 238 VBOXDDU_DECL(int) VDOpen(PVBOXHDD pDisk, const char *pszFilename, unsigned uOpenFlags); 248 VBOXDDU_DECL(int) VDOpen(PVBOXHDD pDisk, const char *pszFilename, 249 unsigned uOpenFlags); 239 250 240 251 /** … … 242 253 * 243 254 * @returns VBox status code. 244 * @param pDisk Pointer to VBoxHDD container.255 * @param pDisk Pointer to HDD container. 245 256 * @param pszFilename Name of the image file to create. 246 257 * @param enmType Image type, only base image types are acceptable. … … 248 259 * @param uImageFlags Flags specifying special image features. 249 260 * @param pszComment Pointer to image comment. NULL is ok. 250 * @param cCylinders Number of cylinders (must be <= 16383). 251 * @param cHeads Number of heads (must be <= 16). 252 * @param cSectors Number of sectors (must be <= 63); 261 * @param pPCHSGeometry Pointer to physical disk geometry <= (16383,16,63). Not NULL. 262 * @param pLCHSGeometry Pointer to logical disk geometry <= (1024,255,63). Not NULL. 253 263 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. 254 264 * @param pfnProgress Progress callback. Optional. NULL if not to be used. … … 258 268 VDIMAGETYPE enmType, uint64_t cbSize, 259 269 unsigned uImageFlags, const char *pszComment, 260 unsigned cCylinders, unsigned cHeads, 261 unsigned cSectors, unsigned uOpenFlags, 262 PFNVMPROGRESS pfnProgress, void *pvUser); 270 PCPDMMEDIAGEOMETRY pPCHSGeometry, 271 PCPDMMEDIAGEOMETRY pLCHSGeometry, 272 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 273 void *pvUser); 263 274 264 275 /** … … 267 278 * 268 279 * @returns VBox status code. 269 * @param pDisk Pointer to VBoxHDD container.280 * @param pDisk Pointer to HDD container. 270 281 * @param pszFilename Name of the differencing image file to create. 271 282 * @param uImageFlags Flags specifying special image features. … … 277 288 VBOXDDU_DECL(int) VDCreateDiff(PVBOXHDD pDisk, const char *pszFilename, 278 289 unsigned uImageFlags, const char *pszComment, 279 unsigned uOpenFlags, 280 PFNVMPROGRESS pfnProgress, void *pvUser); 281 282 /** 283 * Merges two images having a parent/child relationship (both directions). 284 * As a side effect the source image is deleted from both the disk and 285 * the images in the VBox HDD container. 286 * 287 * @returns VBox status code. 288 * @param pDisk Pointer to VBox HDD container. 290 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 291 void *pvUser); 292 293 /** 294 * Merges two images (not necessarily with direct parent/child relationship). 295 * As a side effect the source image and potentially the other images which 296 * are also merged to the destination are deleted from both the disk and the 297 * images in the HDD container. 298 * 299 * @returns VBox status code. 300 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 301 * @param pDisk Pointer to HDD container. 289 302 * @param nImageFrom Name of the image file to merge from. 290 303 * @param nImageTo Name of the image file to merge to. … … 292 305 * @param pvUser User argument for the progress callback. 293 306 */ 294 VBOXDDU_DECL(int) VDMerge(PVBOXHDD pDisk, unsigned nImageFrom, unsigned nImageTo, 295 PFNVMPROGRESS pfnProgress, void *pvUser); 296 297 /** 298 * Copies an image from one VBox HDD container to another. 299 * The copy is opened in the target VBox HDD container. 307 VBOXDDU_DECL(int) VDMerge(PVBOXHDD pDisk, unsigned nImageFrom, 308 unsigned nImageTo, PFNVMPROGRESS pfnProgress, 309 void *pvUser); 310 311 /** 312 * Copies an image from one HDD container to another. 313 * The copy is opened in the target HDD container. 300 314 * It is possible to convert between different image formats, because the 301 * backend for the destination VBoxHDD container may be different from the315 * backend for the destination HDD container may be different from the 302 316 * source container. 303 * If both the source and destination reference the same VBoxHDD container,304 * then the image is moved (by copying/deleting ) to the new location.317 * If both the source and destination reference the same HDD container, 318 * then the image is moved (by copying/deleting or renaming) to the new location. 305 319 * The source container is unchanged if the move operation fails, otherwise 306 320 * the image at the new location is opened in the same way as the old one was. 307 321 * 308 322 * @returns VBox status code. 309 * @param pDiskFrom Pointer to source VBox HDD container. 310 * @param nImage Image number, counts from 0. 0 is always base image of container. 311 * @param pDiskTo Pointer to destination VBox HDD container. 323 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 324 * @param pDiskFrom Pointer to source HDD container. 325 * @param nImage Image number, counts from 0. 0 is always base image of container. 326 * @param pDiskTo Pointer to destination HDD container. 327 * @param pszFilename New name of the image (may be NULL if pDiskFrom == pDiskTo). 328 * @param fMoveByRename If true, attempt to perform a move by renaming (if successful the new size is ignored). 329 * @param cbSize New image size (0 means leave unchanged). 312 330 * @param pfnProgress Progress callback. Optional. NULL if not to be used. 313 331 * @param pvUser User argument for the progress callback. 314 332 */ 315 333 VBOXDDU_DECL(int) VDCopy(PVBOXHDD pDiskFrom, unsigned nImage, PVBOXHDD pDiskTo, 316 PFNVMPROGRESS pfnProgress, void *pvUser); 317 318 /** 319 * Compacts a growing image file by removing zeroed data blocks. 320 * Optionally defragments data in the image so that ascending sector numbers 321 * are stored in ascending location in the image file. 322 * 323 * @todo maybe include this function in VDCopy. 324 * 325 * @returns VBox status code. 326 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 327 * @param pDisk Pointer to VBox HDD container. 328 * @param nImage Image number, counts from 0. 0 is always base image of container. 329 * @param fDefragment If true, reorder file data so that sectors are stored in ascending order. 330 * @param pfnProgress Progress callback. Optional. NULL if not to be used. 331 * @param pvUser User argument for the progress callback. 332 */ 333 VBOXDDU_DECL(int) VDCompact(PVBOXHDD pDisk, unsigned nImage, 334 bool fDefragment, 335 PFNVMPROGRESS pfnProgress, void *pvUser); 336 337 /** 338 * Resizes an image. Allows setting the disk size to both larger and smaller 339 * values than the current disk size. 340 * 341 * @returns VBox status code. 342 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 343 * @param pDisk Pointer to VBox HDD container. 344 * @param nImage Image number, counts from 0. 0 is always base image of container. 345 * @param cbSize New image size in bytes. 346 * @param pfnProgress Progress callback. Optional. NULL if not to be used. 347 * @param pvUser User argument for the progress callback. 348 */ 349 VBOXDDU_DECL(int) VDResize(PVBOXHDD pDisk, unsigned nImage, uint64_t cbSize, 350 PFNVMPROGRESS pfnProgress, void *pvUser); 351 352 /** 353 * Closes the last opened image file in the HDD container. Leaves all changes inside it. 334 const char *pszFilename, bool fMoveByRename, 335 uint64_t cbSize, PFNVMPROGRESS pfnProgress, 336 void *pvUser); 337 338 /** 339 * Closes the last opened image file in HDD container. 354 340 * If previous image file was opened in read-only mode (that is normal) and closing image 355 341 * was opened in read-write mode (the whole disk was in read-write mode) - the previous image 356 342 * will be reopened in read/write mode. 357 343 * 358 * @param pDisk Pointer to VBox HDD container. 344 * @returns VBox status code. 345 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 346 * @param pDisk Pointer to HDD container. 359 347 * @param fDelete If true, delete the image from the host disk. 360 348 */ … … 364 352 * Closes all opened image files in HDD container. 365 353 * 366 * @param pDisk Pointer to VBox HDD container. 354 * @returns VBox status code. 355 * @param pDisk Pointer to HDD container. 367 356 */ 368 357 VBOXDDU_DECL(int) VDCloseAll(PVBOXHDD pDisk); … … 373 362 * @returns VBox status code. 374 363 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 375 * @param pDisk Pointer to VBoxHDD container.364 * @param pDisk Pointer to HDD container. 376 365 * @param uOffset Offset of first reading byte from start of disk. 377 366 * @param pvBuf Pointer to buffer for reading data. … … 385 374 * @returns VBox status code. 386 375 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 387 * @param pDisk Pointer to VBoxHDD container.376 * @param pDisk Pointer to HDD container. 388 377 * @param uOffset Offset of first writing byte from start of disk. 389 378 * @param pvBuf Pointer to buffer for writing data. … … 397 386 * @returns VBox status code. 398 387 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 399 * @param pDisk Pointer to VBoxHDD container.388 * @param pDisk Pointer to HDD container. 400 389 */ 401 390 VBOXDDU_DECL(int) VDFlush(PVBOXHDD pDisk); … … 405 394 * 406 395 * @returns Number of opened images for HDD container. 0 if no images have been opened. 407 * @param pDisk Pointer to VBoxHDD container.396 * @param pDisk Pointer to HDD container. 408 397 */ 409 398 VBOXDDU_DECL(unsigned) VDGetCount(PVBOXHDD pDisk); 410 399 411 400 /** 412 * Get read/write mode of the VBoxHDD container.401 * Get read/write mode of HDD container. 413 402 * 414 403 * @returns Virtual disk ReadOnly status. 415 404 * @returns true if no image is opened in HDD container. 416 * @param pDisk Pointer to VBoxHDD container.405 * @param pDisk Pointer to HDD container. 417 406 */ 418 407 VBOXDDU_DECL(bool) VDIsReadOnly(PVBOXHDD pDisk); 419 408 420 409 /** 421 * Get total disk size of the VBoxHDD container.410 * Get total capacity of an image in HDD container. 422 411 * 423 412 * @returns Virtual disk size in bytes. 424 * @returns 0 if no image is opened in HDD container. 425 * @param pDisk Pointer to VBox HDD container. 426 */ 427 VBOXDDU_DECL(uint64_t) VDGetSize(PVBOXHDD pDisk); 428 429 /** 430 * Get virtual disk geometry stored in HDD container. 431 * 432 * @returns VBox status code. 433 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 413 * @returns 0 if image with specified number was not opened. 414 * @param pDisk Pointer to HDD container. 415 * @param nImage Image number, counts from 0. 0 is always base image of container. 416 */ 417 VBOXDDU_DECL(uint64_t) VDGetSize(PVBOXHDD pDisk, unsigned nImage); 418 419 /** 420 * Get total file size of an image in HDD container. 421 * 422 * @returns Virtual disk size in bytes. 423 * @returns 0 if image with specified number was not opened. 424 * @param pDisk Pointer to HDD container. 425 * @param nImage Image number, counts from 0. 0 is always base image of container. 426 */ 427 VBOXDDU_DECL(uint64_t) VDGetFileSize(PVBOXHDD pDisk, unsigned nImage); 428 429 /** 430 * Get virtual disk PCHS geometry of an image in HDD container. 431 * 432 * @returns VBox status code. 433 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 434 434 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 435 * @param pDisk Pointer to VBox HDD container. 436 * @param pcCylinders Where to store the number of cylinders. NULL is ok. 437 * @param pcHeads Where to store the number of heads. NULL is ok. 438 * @param pcSectors Where to store the number of sectors. NULL is ok. 439 */ 440 VBOXDDU_DECL(int) VDGetGeometry(PVBOXHDD pDisk, 441 unsigned *pcCylinders, unsigned *pcHeads, unsigned *pcSectors); 442 443 /** 444 * Store virtual disk geometry in HDD container. 445 * 446 * Note that in case of unrecoverable error all images in HDD container will be closed. 447 * 448 * @returns VBox status code. 449 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 450 * @param pDisk Pointer to VBox HDD container. 451 * @param cCylinders Number of cylinders. 452 * @param cHeads Number of heads. 453 * @param cSectors Number of sectors. 454 */ 455 VBOXDDU_DECL(int) VDSetGeometry(PVBOXHDD pDisk, 456 unsigned cCylinders, unsigned cHeads, unsigned cSectors); 457 458 /** 459 * Get virtual disk translation mode stored in HDD container. 460 * 461 * @returns VBox status code. 462 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 435 * @param pDisk Pointer to HDD container. 436 * @param nImage Image number, counts from 0. 0 is always base image of container. 437 * @param pPCHSGeometry Where to store PCHS geometry. Not NULL. 438 */ 439 VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 440 PPDMMEDIAGEOMETRY pPCHSGeometry); 441 442 /** 443 * Store virtual disk PCHS geometry of an image in HDD container. 444 * 445 * @returns VBox status code. 446 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 447 * @param pDisk Pointer to HDD container. 448 * @param nImage Image number, counts from 0. 0 is always base image of container. 449 * @param pPCHSGeometry Where to load PCHS geometry from. Not NULL. 450 */ 451 VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 452 PCPDMMEDIAGEOMETRY pPCHSGeometry); 453 454 /** 455 * Get virtual disk LCHS geometry of an image in HDD container. 456 * 457 * @returns VBox status code. 458 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 463 459 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 464 * @param pDisk Pointer to VBox HDD container. 465 * @param penmTranslation Where to store the translation mode (see pdm.h). 466 */ 467 VBOXDDU_DECL(int) VDGetTranslation(PVBOXHDD pDisk, PPDMBIOSTRANSLATION penmTranslation); 468 469 /** 470 * Store virtual disk translation mode in HDD container. 471 * 472 * Note that in case of unrecoverable error all images in HDD container will be closed. 473 * 474 * @returns VBox status code. 475 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 476 * @param pDisk Pointer to VBox HDD container. 477 * @param enmTranslation Translation mode (see pdm.h). 478 */ 479 VBOXDDU_DECL(int) VDSetTranslation(PVBOXHDD pDisk, PDMBIOSTRANSLATION enmTranslation); 460 * @param pDisk Pointer to HDD container. 461 * @param nImage Image number, counts from 0. 0 is always base image of container. 462 * @param pLCHSGeometry Where to store LCHS geometry. Not NULL. 463 */ 464 VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 465 PPDMMEDIAGEOMETRY pLCHSGeometry); 466 467 /** 468 * Store virtual disk LCHS geometry of an image in HDD container. 469 * 470 * @returns VBox status code. 471 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 472 * @param pDisk Pointer to HDD container. 473 * @param nImage Image number, counts from 0. 0 is always base image of container. 474 * @param pLCHSGeometry Where to load LCHS geometry from. Not NULL. 475 */ 476 VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 477 PCPDMMEDIAGEOMETRY pLCHSGeometry); 480 478 481 479 /** … … 484 482 * @returns VBox status code. 485 483 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 486 * @param pDisk Pointer to VBoxHDD container.484 * @param pDisk Pointer to HDD container. 487 485 * @param nImage Image number, counts from 0. 0 is always base image of container. 488 486 * @param puVersion Where to store the image version. 489 487 */ 490 VBOXDDU_DECL(int) VDGetVersion(PVBOXHDD pDisk, unsigned nImage, unsigned *puVersion); 488 VBOXDDU_DECL(int) VDGetVersion(PVBOXHDD pDisk, unsigned nImage, 489 unsigned *puVersion); 491 490 492 491 /** … … 495 494 * @returns VBox status code. 496 495 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 497 * @param pDisk Pointer to VBoxHDD container.496 * @param pDisk Pointer to HDD container. 498 497 * @param nImage Image number, counts from 0. 0 is always base image of container. 499 498 * @param penmType Where to store the image type. 500 499 */ 501 VBOXDDU_DECL(int) VDGetImageType(PVBOXHDD pDisk, unsigned nImage, PVDIMAGETYPE penmType); 500 VBOXDDU_DECL(int) VDGetImageType(PVBOXHDD pDisk, unsigned nImage, 501 PVDIMAGETYPE penmType); 502 502 503 503 /** … … 506 506 * @returns VBox status code. 507 507 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 508 * @param pDisk Pointer to VBoxHDD container.508 * @param pDisk Pointer to HDD container. 509 509 * @param nImage Image number, counts from 0. 0 is always base image of container. 510 510 * @param puImageFlags Where to store the image flags. … … 513 513 514 514 /** 515 * Get open flags of last opened image in HDD container. 516 * 517 * @returns VBox status code. 518 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 519 * @param pDisk Pointer to VBox HDD container. 515 * Get open flags of image in HDD container. 516 * 517 * @returns VBox status code. 518 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 519 * @param pDisk Pointer to HDD container. 520 * @param nImage Image number, counts from 0. 0 is always base image of container. 520 521 * @param puOpenFlags Where to store the image open flags. 521 522 */ 522 VBOXDDU_DECL(int) VDGetOpenFlags(PVBOXHDD pDisk, unsigned *puOpenFlags); 523 524 /** 525 * Set open flags of last opened image in HDD container. 523 VBOXDDU_DECL(int) VDGetOpenFlags(PVBOXHDD pDisk, unsigned nImage, 524 unsigned *puOpenFlags); 525 526 /** 527 * Set open flags of image in HDD container. 526 528 * This operation may cause file locking changes and/or files being reopened. 527 529 * Note that in case of unrecoverable error all images in HDD container will be closed. … … 529 531 * @returns VBox status code. 530 532 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 531 * @param pDisk Pointer to VBox HDD container. 533 * @param pDisk Pointer to HDD container. 534 * @param nImage Image number, counts from 0. 0 is always base image of container. 532 535 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. 533 536 */ 534 VBOXDDU_DECL(int) VDSetOpenFlags(PVBOXHDD pDisk, unsigned uOpenFlags); 537 VBOXDDU_DECL(int) VDSetOpenFlags(PVBOXHDD pDisk, unsigned nImage, 538 unsigned uOpenFlags); 535 539 536 540 /** 537 541 * Get base filename of image in HDD container. Some image formats use 538 * other filenames as well, so don't use this for anything but forinformational542 * other filenames as well, so don't use this for anything but informational 539 543 * purposes. 540 544 * … … 542 546 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 543 547 * @returns VERR_BUFFER_OVERFLOW if pszFilename buffer too small to hold filename. 544 * @param pDisk Pointer to VBoxHDD container.548 * @param pDisk Pointer to HDD container. 545 549 * @param nImage Image number, counts from 0. 0 is always base image of container. 546 550 * @param pszFilename Where to store the image file name. 547 551 * @param cbFilename Size of buffer pszFilename points to. 548 552 */ 549 VBOXDDU_DECL(int) VDGetFilename(PVBOXHDD pDisk, unsigned nImage, char *pszFilename, unsigned cbFilename); 553 VBOXDDU_DECL(int) VDGetFilename(PVBOXHDD pDisk, unsigned nImage, 554 char *pszFilename, unsigned cbFilename); 550 555 551 556 /** … … 555 560 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 556 561 * @returns VERR_BUFFER_OVERFLOW if pszComment buffer too small to hold comment text. 557 * @param pDisk Pointer to VBoxHDD container.562 * @param pDisk Pointer to HDD container. 558 563 * @param nImage Image number, counts from 0. 0 is always base image of container. 559 564 * @param pszComment Where to store the comment string of image. NULL is ok. 560 565 * @param cbComment The size of pszComment buffer. 0 is ok. 561 566 */ 562 VBOXDDU_DECL(int) VDGetComment(PVBOXHDD pDisk, unsigned nImage, char *pszComment, unsigned cbComment); 567 VBOXDDU_DECL(int) VDGetComment(PVBOXHDD pDisk, unsigned nImage, 568 char *pszComment, unsigned cbComment); 563 569 564 570 /** … … 567 573 * @returns VBox status code. 568 574 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 569 * @param pDisk Pointer to VBoxHDD container.575 * @param pDisk Pointer to HDD container. 570 576 * @param nImage Image number, counts from 0. 0 is always base image of container. 571 577 * @param pszComment New comment string (UTF-8). NULL is allowed to reset the comment. 572 578 */ 573 VBOXDDU_DECL(int) VDSetComment(PVBOXHDD pDisk, unsigned nImage, const char *pszComment); 579 VBOXDDU_DECL(int) VDSetComment(PVBOXHDD pDisk, unsigned nImage, 580 const char *pszComment); 574 581 575 582 /** … … 578 585 * @returns VBox status code. 579 586 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 580 * @param pDisk Pointer to VBoxHDD container.587 * @param pDisk Pointer to HDD container. 581 588 * @param nImage Image number, counts from 0. 0 is always base image of container. 582 589 * @param pUuid Where to store the image UUID. … … 589 596 * @returns VBox status code. 590 597 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 591 * @param pDisk Pointer to VBoxHDD container.592 * @param nImage Image number, counts from 0. 0 is always base image of container. 593 * @param pUuid Optional parameter, new UUID of the image.598 * @param pDisk Pointer to HDD container. 599 * @param nImage Image number, counts from 0. 0 is always base image of container. 600 * @param pUuid New UUID of the image. If NULL, a new UUID is created. 594 601 */ 595 602 VBOXDDU_DECL(int) VDSetUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid); … … 600 607 * @returns VBox status code. 601 608 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 602 * @param pDisk Pointer to VBoxHDD container.609 * @param pDisk Pointer to HDD container. 603 610 * @param nImage Image number, counts from 0. 0 is always base image of container. 604 611 * @param pUuid Where to store the image modification UUID. 605 612 */ 606 VBOXDDU_DECL(int) VDGetModificationUuid(PVBOXHDD pDisk, unsigned nImage, PRTUUID pUuid); 613 VBOXDDU_DECL(int) VDGetModificationUuid(PVBOXHDD pDisk, unsigned nImage, 614 PRTUUID pUuid); 607 615 608 616 /** … … 611 619 * @returns VBox status code. 612 620 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 613 * @param pDisk Pointer to VBox HDD container. 614 * @param nImage Image number, counts from 0. 0 is always base image of container. 615 * @param pUuid Optional parameter, new last modification UUID of the image. 616 */ 617 VBOXDDU_DECL(int) VDSetModificationUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid); 621 * @param pDisk Pointer to HDD container. 622 * @param nImage Image number, counts from 0. 0 is always base image of container. 623 * @param pUuid New modification UUID of the image. If NULL, a new UUID is created. 624 */ 625 VBOXDDU_DECL(int) VDSetModificationUuid(PVBOXHDD pDisk, unsigned nImage, 626 PCRTUUID pUuid); 618 627 619 628 /** … … 622 631 * @returns VBox status code. 623 632 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 624 * @param pDisk Pointer to VBoxHDD container.633 * @param pDisk Pointer to HDD container. 625 634 * @param nImage Image number, counts from 0. 0 is always base image of the container. 626 635 * @param pUuid Where to store the parent image UUID. 627 636 */ 628 VBOXDDU_DECL(int) VDGetParentUuid(PVBOXHDD pDisk, unsigned nImage, PRTUUID pUuid); 637 VBOXDDU_DECL(int) VDGetParentUuid(PVBOXHDD pDisk, unsigned nImage, 638 PRTUUID pUuid); 629 639 630 640 /** … … 632 642 * 633 643 * @returns VBox status code. 634 * @param pDisk Pointer to VBox HDD container. 635 * @param nImage Image number, counts from 0. 0 is always base image of container. 636 * @param pUuid Optional parameter, new parent UUID of the image. 637 */ 638 VBOXDDU_DECL(int) VDSetParentUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid); 644 * @param pDisk Pointer to HDD container. 645 * @param nImage Image number, counts from 0. 0 is always base image of container. 646 * @param pUuid New parent UUID of the image. If NULL, a new UUID is created. 647 */ 648 VBOXDDU_DECL(int) VDSetParentUuid(PVBOXHDD pDisk, unsigned nImage, 649 PCRTUUID pUuid); 639 650 640 651 … … 642 653 * Debug helper - dumps all opened images in HDD container into the log file. 643 654 * 644 * @param pDisk Pointer to VBoxHDD container.655 * @param pDisk Pointer to HDD container. 645 656 */ 646 657 VBOXDDU_DECL(void) VDDumpImages(PVBOXHDD pDisk); -
trunk/include/VBox/VBoxHDD.h
r5999 r6291 374 374 375 375 /** 376 * Get virtual disk geometry stored in image file.376 * Get virtual disk PCHS geometry stored in image file. 377 377 * 378 378 * @returns VBox status code. … … 380 380 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 381 381 * @param pDisk Pointer to VDI HDD container. 382 * @param pcCylinders Where to store the number of cylinders. NULL is ok. 383 * @param pcHeads Where to store the number of heads. NULL is ok. 384 * @param pcSectors Where to store the number of sectors. NULL is ok. 385 */ 386 VBOXDDU_DECL(int) VDIDiskGetGeometry(PVDIDISK pDisk, unsigned *pcCylinders, unsigned *pcHeads, unsigned *pcSectors); 387 388 /** 389 * Store virtual disk geometry into base image file of HDD container. 382 * @param pPCHSGeometry Where to store PCHS geometry. Not NULL. 383 */ 384 VBOXDDU_DECL(int) VDIDiskGetPCHSGeometry(PVDIDISK pDisk, PPDMMEDIAGEOMETRY pPCHSGeometry); 385 386 /** 387 * Store virtual disk PCHS geometry into base image file of HDD container. 390 388 * 391 389 * Note that in case of unrecoverable error all images of HDD container will be closed. … … 394 392 * @returns VERR_VDI_NOT_OPENED if no one VDI image is opened in HDD container. 395 393 * @param pDisk Pointer to VDI HDD container. 396 * @param cCylinders Number of cylinders. 397 * @param cHeads Number of heads. 398 * @param cSectors Number of sectors. 399 */ 400 VBOXDDU_DECL(int) VDIDiskSetGeometry(PVDIDISK pDisk, unsigned cCylinders, unsigned cHeads, unsigned cSectors); 401 402 /** 403 * Get virtual disk translation mode stored in image file. 394 * @param pPCHSGeometry Where to store LCHS geometry. Not NULL. 395 */ 396 VBOXDDU_DECL(int) VDIDiskSetPCHSGeometry(PVDIDISK pDisk, PCPDMMEDIAGEOMETRY pPCHSGeometry); 397 398 /** 399 * Get virtual disk LCHS geometry stored in image file. 404 400 * 405 401 * @returns VBox status code. 406 402 * @returns VERR_VDI_NOT_OPENED if no one VDI image is opened in HDD container. 407 * @param pDisk Pointer to VDI HDD container. 408 * @param penmTranslation Where to store the translation mode (see pdm.h). 409 */ 410 VBOXDDU_DECL(int) VDIDiskGetTranslation(PVDIDISK pDisk, PPDMBIOSTRANSLATION penmTranslation); 411 412 /** 413 * Store virtual disk translation mode into base image file of HDD container. 403 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 404 * @param pDisk Pointer to VDI HDD container. 405 * @param pLCHSGeometry Where to store LCHS geometry. Not NULL. 406 */ 407 VBOXDDU_DECL(int) VDIDiskGetLCHSGeometry(PVDIDISK pDisk, PPDMMEDIAGEOMETRY pLCHSGeometry); 408 409 /** 410 * Store virtual disk LCHS geometry into base image file of HDD container. 414 411 * 415 412 * Note that in case of unrecoverable error all images of HDD container will be closed. … … 418 415 * @returns VERR_VDI_NOT_OPENED if no one VDI image is opened in HDD container. 419 416 * @param pDisk Pointer to VDI HDD container. 420 * @param enmTranslation Translation mode (see pdm.h).421 */ 422 VBOXDDU_DECL(int) VDIDiskSet Translation(PVDIDISK pDisk, PDMBIOSTRANSLATION enmTranslation);417 * @param pLCHSGeometry Where to store LCHS geometry. Not NULL. 418 */ 419 VBOXDDU_DECL(int) VDIDiskSetLCHSGeometry(PVDIDISK pDisk, PCPDMMEDIAGEOMETRY pLCHSGeometry); 423 420 424 421 /** -
trunk/include/VBox/log.h
r6116 r6291 146 146 /** Host floppy block driver group. */ 147 147 LOG_GROUP_DRV_HOST_FLOPPY, 148 /** Host hard disk (raw partition) media driver group. */149 LOG_GROUP_DRV_HOST_HDD,150 148 /** Host Parallel Driver group */ 151 149 LOG_GROUP_DRV_HOST_PARALLEL, … … 348 346 "DRV_HOST_DVD", \ 349 347 "DRV_HOST_FLOPPY", \ 350 "DRV_HOST_HDD", \351 348 "DRV_HOST_PARALLEL", \ 352 349 "DRV_HOST_SERIAL", \ -
trunk/include/VBox/pdmifs.h
r6225 r6291 4 4 5 5 /* 6 * Copyright (C) 2006-200 7innotek GmbH6 * Copyright (C) 2006-2008 innotek GmbH 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 771 771 772 772 /** 773 * BIOS translation mode. 774 */ 775 typedef enum PDMBIOSTRANSLATION 776 { 777 /** No translation. */ 778 PDMBIOSTRANSLATION_NONE = 1, 779 /** LBA translation. */ 780 PDMBIOSTRANSLATION_LBA, 781 /** Automatic select mode. */ 782 PDMBIOSTRANSLATION_AUTO 783 } PDMBIOSTRANSLATION; 784 785 /** Pointer to BIOS translation mode. */ 786 typedef PDMBIOSTRANSLATION *PPDMBIOSTRANSLATION; 773 * Media geometry structure. 774 */ 775 typedef struct PDMMEDIAGEOMETRY 776 { 777 /** Number of cylinders. */ 778 uint32_t cCylinders; 779 /** Number of heads. */ 780 uint32_t cHeads; 781 /** Number of sectors. */ 782 uint32_t cSectors; 783 } PDMMEDIAGEOMETRY; 784 785 /** Pointer to media geometry structure. */ 786 typedef PDMMEDIAGEOMETRY *PPDMMEDIAGEOMETRY; 787 /** Pointer to constant media geometry structure. */ 788 typedef const PDMMEDIAGEOMETRY *PCPDMMEDIAGEOMETRY; 787 789 788 790 /** Pointer to a media interface. */ … … 790 792 /** 791 793 * Media interface. 792 * Makes up the f undation for PDMIBLOCK and PDMIBLOCKBIOS.794 * Makes up the foundation for PDMIBLOCK and PDMIBLOCKBIOS. 793 795 */ 794 796 typedef struct PDMIMEDIA … … 847 849 848 850 /** 849 * Get stored media geometry - BIOS property.851 * Get stored media geometry (physical CHS, PCHS) - BIOS property. 850 852 * This is an optional feature of a media. 851 853 * 852 854 * @returns VBox status code. 853 855 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 854 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetGeometry() yet. 855 * @param pInterface Pointer to the interface structure containing the called function pointer. 856 * @param pcCylinders Number of cylinders. 857 * @param pcHeads Number of heads. 858 * @param pcSectors Number of sectors. This number is 1-based. 859 * @remark This have no influence on the read/write operations. 860 * @thread Any thread. 861 */ 862 DECLR3CALLBACKMEMBER(int, pfnBiosGetGeometry,(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)); 863 864 /** 865 * Store the media geometry - BIOS property. 856 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetPCHSGeometry() yet. 857 * @param pInterface Pointer to the interface structure containing the called function pointer. 858 * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors). 859 * @remark This has no influence on the read/write operations. 860 * @thread Any thread. 861 */ 862 DECLR3CALLBACKMEMBER(int, pfnBiosGetPCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)); 863 864 /** 865 * Store the media geometry (physical CHS, PCHS) - BIOS property. 866 866 * This is an optional feature of a media. 867 867 * … … 869 869 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 870 870 * @param pInterface Pointer to the interface structure containing the called function pointer. 871 * @param cCylinders Number of cylinders. 872 * @param cHeads Number of heads. 873 * @param cSectors Number of sectors. This number is 1-based. 874 * @remark This have no influence on the read/write operations. 875 * @thread The emulation thread. 876 */ 877 DECLR3CALLBACKMEMBER(int, pfnBiosSetGeometry,(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)); 878 879 /** 880 * Get stored geometry translation mode - BIOS property. 871 * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors). 872 * @remark This has no influence on the read/write operations. 873 * @thread The emulation thread. 874 */ 875 DECLR3CALLBACKMEMBER(int, pfnBiosSetPCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)); 876 877 /** 878 * Get stored media geometry (logical CHS, LCHS) - BIOS property. 881 879 * This is an optional feature of a media. 882 880 * 883 881 * @returns VBox status code. 884 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry translation mode.885 * @returns VERR_PDM_ TRANSLATION_NOT_SET if the translation hasn't been set using pfnBiosSetTranslation() yet.886 * @param pInterface Pointer to the interface structure containing the called function pointer. 887 * @param p enmTranslation Where to store the translation type.888 * @remark This ha veno influence on the read/write operations.889 * @thread Any thread. 890 */ 891 DECLR3CALLBACKMEMBER(int, pfnBiosGet Translation,(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation));892 893 /** 894 * Store media geometry- BIOS property.882 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 883 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetLCHSGeometry() yet. 884 * @param pInterface Pointer to the interface structure containing the called function pointer. 885 * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors). 886 * @remark This has no influence on the read/write operations. 887 * @thread Any thread. 888 */ 889 DECLR3CALLBACKMEMBER(int, pfnBiosGetLCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)); 890 891 /** 892 * Store the media geometry (logical CHS, LCHS) - BIOS property. 895 893 * This is an optional feature of a media. 896 894 * … … 898 896 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 899 897 * @param pInterface Pointer to the interface structure containing the called function pointer. 900 * @param enmTranslation The translation type.901 * @remark This ha veno influence on the read/write operations.902 * @thread The emulation thread. 903 */ 904 DECLR3CALLBACKMEMBER(int, pfnBiosSet Translation,(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation));898 * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors). 899 * @remark This has no influence on the read/write operations. 900 * @thread The emulation thread. 901 */ 902 DECLR3CALLBACKMEMBER(int, pfnBiosSetLCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)); 905 903 906 904 /** … … 926 924 { 927 925 /** 928 * Get stored media geometry - BIOS property.926 * Get stored media geometry (physical CHS, PCHS) - BIOS property. 929 927 * This is an optional feature of a media. 930 928 * 931 929 * @returns VBox status code. 932 930 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 933 * @param pInterface Pointer to the interface structure containing the called function pointer. 934 * @param pcCylinders Number of cylinders. 935 * @param pcHeads Number of heads. 936 * @param pcSectors Number of sectors. This number is 1-based. 937 * @remark This have no influence on the read/write operations. 938 * @thread Any thread. 939 */ 940 DECLR3CALLBACKMEMBER(int, pfnGetGeometry,(PPDMIBLOCKBIOS pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)); 941 942 /** 943 * Store the media geometry - BIOS property. 931 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnSetPCHSGeometry() yet. 932 * @param pInterface Pointer to the interface structure containing the called function pointer. 933 * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors). 934 * @remark This has no influence on the read/write operations. 935 * @thread Any thread. 936 */ 937 DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry,(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)); 938 939 /** 940 * Store the media geometry (physical CHS, PCHS) - BIOS property. 944 941 * This is an optional feature of a media. 945 942 * … … 947 944 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 948 945 * @param pInterface Pointer to the interface structure containing the called function pointer. 949 * @param cCylinders Number of cylinders. 950 * @param cHeads Number of heads. 951 * @param cSectors Number of sectors. This number is 1-based. 952 * @remark This have no influence on the read/write operations. 953 * @thread The emulation thread. 954 */ 955 DECLR3CALLBACKMEMBER(int, pfnSetGeometry,(PPDMIBLOCKBIOS pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)); 956 957 /** 958 * Get stored geometry translation mode - BIOS property. 946 * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors). 947 * @remark This has no influence on the read/write operations. 948 * @thread The emulation thread. 949 */ 950 DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry,(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)); 951 952 /** 953 * Get stored media geometry (logical CHS, LCHS) - BIOS property. 959 954 * This is an optional feature of a media. 960 955 * 961 956 * @returns VBox status code. 962 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry translation mode. 963 * @param pInterface Pointer to the interface structure containing the called function pointer. 964 * @param penmTranslation Where to store the translation type. 965 * @remark This have no influence on the read/write operations. 966 * @thread Any thread. 967 */ 968 DECLR3CALLBACKMEMBER(int, pfnGetTranslation,(PPDMIBLOCKBIOS pInterface, PPDMBIOSTRANSLATION penmTranslation)); 969 970 /** 971 * Store media geometry - BIOS property. 957 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 958 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnSetLCHSGeometry() yet. 959 * @param pInterface Pointer to the interface structure containing the called function pointer. 960 * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors). 961 * @remark This has no influence on the read/write operations. 962 * @thread Any thread. 963 */ 964 DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry,(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)); 965 966 /** 967 * Store the media geometry (logical CHS, LCHS) - BIOS property. 972 968 * This is an optional feature of a media. 973 969 * … … 975 971 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 976 972 * @param pInterface Pointer to the interface structure containing the called function pointer. 977 * @param enmTranslation The translation type.978 * @remark This ha veno influence on the read/write operations.979 * @thread The emulation thread. 980 */ 981 DECLR3CALLBACKMEMBER(int, pfnSet Translation,(PPDMIBLOCKBIOS pInterface, PDMBIOSTRANSLATION enmTranslation));973 * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors). 974 * @remark This has no influence on the read/write operations. 975 * @thread The emulation thread. 976 */ 977 DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry,(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)); 982 978 983 979 /** … … 1323 1319 1324 1320 /** 1325 * Get stored media geometry - BIOS property.1321 * Get stored media geometry (physical CHS, PCHS) - BIOS property. 1326 1322 * This is an optional feature of a media. 1327 1323 * 1328 1324 * @returns VBox status code. 1329 1325 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 1330 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetGeometry() yet. 1331 * @param pInterface Pointer to the interface structure containing the called function pointer. 1332 * @param pcCylinders Number of cylinders. 1333 * @param pcHeads Number of heads. 1334 * @param pcSectors Number of sectors. This number is 1-based. 1335 * @remark This have no influence on the read/write operations. 1336 * @thread Any thread. 1337 */ 1338 DECLR3CALLBACKMEMBER(int, pfnBiosGetGeometry,(PPDMIMEDIAASYNC pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)); 1339 1340 /** 1341 * Store the media geometry - BIOS property. 1326 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetPCHSGeometry() yet. 1327 * @param pInterface Pointer to the interface structure containing the called function pointer. 1328 * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors). 1329 * @remark This has no influence on the read/write operations. 1330 * @thread Any thread. 1331 */ 1332 DECLR3CALLBACKMEMBER(int, pfnBiosGetPCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry)); 1333 1334 /** 1335 * Store the media geometry (physical CHS, PCHS) - BIOS property. 1342 1336 * This is an optional feature of a media. 1343 1337 * … … 1345 1339 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 1346 1340 * @param pInterface Pointer to the interface structure containing the called function pointer. 1347 * @param cCylinders Number of cylinders. 1348 * @param cHeads Number of heads. 1349 * @param cSectors Number of sectors. This number is 1-based. 1350 * @remark This have no influence on the read/write operations. 1351 * @thread The emulation thread. 1352 */ 1353 DECLR3CALLBACKMEMBER(int, pfnBiosSetGeometry,(PPDMIMEDIAASYNC pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)); 1354 1355 /** 1356 * Get stored geometry translation mode - BIOS property. 1341 * @param pPCHSGeometry Pointer to PCHS geometry (cylinders/heads/sectors). 1342 * @remark This has no influence on the read/write operations. 1343 * @thread The emulation thread. 1344 */ 1345 DECLR3CALLBACKMEMBER(int, pfnBiosSetPCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry)); 1346 1347 /** 1348 * Get stored media geometry (logical CHS, LCHS) - BIOS property. 1357 1349 * This is an optional feature of a media. 1358 1350 * 1359 1351 * @returns VBox status code. 1360 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry translation mode.1361 * @returns VERR_PDM_ TRANSLATION_NOT_SET if the translation hasn't been set using pfnBiosSetTranslation() yet.1362 * @param pInterface Pointer to the interface structure containing the called function pointer. 1363 * @param p enmTranslation Where to store the translation type.1364 * @remark This ha veno influence on the read/write operations.1365 * @thread Any thread. 1366 */ 1367 DECLR3CALLBACKMEMBER(int, pfnBiosGet Translation,(PPDMIMEDIAASYNC pInterface, PPDMBIOSTRANSLATION penmTranslation));1368 1369 /** 1370 * Store media geometry- BIOS property.1352 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 1353 * @returns VERR_PDM_GEOMETRY_NOT_SET if the geometry hasn't been set using pfnBiosSetLCHSGeometry() yet. 1354 * @param pInterface Pointer to the interface structure containing the called function pointer. 1355 * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors). 1356 * @remark This has no influence on the read/write operations. 1357 * @thread Any thread. 1358 */ 1359 DECLR3CALLBACKMEMBER(int, pfnBiosGetLCHSGeometry,(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry)); 1360 1361 /** 1362 * Store the media geometry (logical CHS, LCHS) - BIOS property. 1371 1363 * This is an optional feature of a media. 1372 1364 * … … 1374 1366 * @returns VERR_NOT_IMPLEMENTED if the media doesn't support storing the geometry. 1375 1367 * @param pInterface Pointer to the interface structure containing the called function pointer. 1376 * @param enmTranslation The translation type.1377 * @remark This ha veno influence on the read/write operations.1378 * @thread The emulation thread. 1379 */ 1380 DECLR3CALLBACKMEMBER(int, pfnBiosSet Translation,(PPDMIMEDIAASYNC pInterface, PDMBIOSTRANSLATION enmTranslation));1368 * @param pLCHSGeometry Pointer to LCHS geometry (cylinders/heads/sectors). 1369 * @remark This has no influence on the read/write operations. 1370 * @thread The emulation thread. 1371 */ 1372 DECLR3CALLBACKMEMBER(int, pfnBiosSetLCHSGeometry,(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry)); 1381 1373 1382 1374 /** … … 1632 1624 /** 1633 1625 * Stream interface. 1634 * Makes up the f undation for PDMICHAR.1626 * Makes up the foundation for PDMICHAR. 1635 1627 */ 1636 1628 typedef struct PDMISTREAM -
trunk/src/VBox/Devices/Builtins.cpp
r5999 r6291 5 5 6 6 /* 7 * Copyright (C) 2006-200 7innotek GmbH7 * Copyright (C) 2006-2008 innotek GmbH 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 172 172 if (VBOX_FAILURE(rc)) 173 173 return rc; 174 #ifndef RT_OS_L4175 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvVmdkHDD);176 if (VBOX_FAILURE(rc))177 return rc;178 #endif179 174 #if defined(RT_OS_DARWIN) || defined(RT_OS_LINUX) || defined(RT_OS_SOLARIS) || defined(RT_OS_WINDOWS) 180 175 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostDVD); … … 193 188 if (VBOX_FAILURE(rc)) 194 189 return rc; 195 #if defined(RT_OS_WINDOWS) || defined(RT_OS_LINUX)196 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvHostHDD);197 if (VBOX_FAILURE(rc))198 return rc;199 #endif200 190 #ifdef VBOX_WITH_ISCSI 201 191 rc = pCallbacks->pfnRegister(pCallbacks, &g_DrvISCSI); -
trunk/src/VBox/Devices/Builtins.h
r5999 r6291 65 65 extern const PDMDRVREG g_DrvVBoxHDD; 66 66 extern const PDMDRVREG g_DrvVD; 67 extern const PDMDRVREG g_DrvVmdkHDD;68 67 extern const PDMDRVREG g_DrvHostDVD; 69 68 extern const PDMDRVREG g_DrvHostFloppy; 70 69 extern const PDMDRVREG g_DrvMediaISO; 71 70 extern const PDMDRVREG g_DrvRawImage; 72 extern const PDMDRVREG g_DrvHostHDD;73 71 extern const PDMDRVREG g_DrvISCSI; 74 72 extern const PDMDRVREG g_DrvISCSITransportTcp; -
trunk/src/VBox/Devices/Makefile.kmk
r6221 r6291 492 492 Storage/DrvHostDVD.cpp \ 493 493 Storage/DrvHostFloppy.cpp \ 494 Storage/DrvHostRawDisk.cpp \495 494 Storage/DrvMediaISO.cpp \ 496 495 Storage/DrvRawImage.cpp \ 497 496 Storage/DrvVD.cpp \ 498 Storage/DrvVmdk.cpp \499 497 Storage/VBoxHDD.cpp 500 498 … … 564 562 Network/DrvTAP.cpp \ 565 563 Storage/DrvHostBase.cpp \ 566 Storage/DrvHostDVD.cpp \ 567 Storage/DrvHostRawDisk.cpp 564 Storage/DrvHostDVD.cpp 568 565 ifdef VBOX_WITH_CROSSBOW 569 566 Drivers_DEFS += VBOX_WITH_CROSSBOW -
trunk/src/VBox/Devices/PC/BIOS/rombios.c
r5757 r6291 93 93 // - EBDA segment. 94 94 // I used memory starting at 0x121 in the segment 95 #ifndef VBOX 95 96 // - the translation policy is defined in cmos regs 0x39 & 0x3a 97 #endif /* !VBOX */ 96 98 // 97 99 // TODO : … … 202 204 #if BX_APM && BX_CPU<3 203 205 # error APM BIOS can only be used with 386+ cpu 206 #endif 207 208 #if defined(VBOX) && !BX_USE_ATADRV 209 # error VBOX requires enabling the ATA/ATAPI driver 204 210 #endif 205 211 … … 2390 2396 Bit32u sectors; 2391 2397 Bit16u cylinders, heads, spt, blksize; 2398 #ifdef VBOX 2399 Bit16u lcylinders, lheads, lspt; 2400 Bit8u chsgeo_base; 2401 #endif /* VBOX */ 2392 2402 Bit8u translation, removable, mode; 2393 2403 … … 2416 2426 if (sectors == 268435455) 2417 2427 sectors = read_dword(get_SS(),buffer+(100*2)); // words 100 to 103 (someday) 2428 switch (device) 2429 { 2430 case 0: 2431 chsgeo_base = 0x1e; 2432 break; 2433 case 1: 2434 chsgeo_base = 0x26; 2435 break; 2436 case 2: 2437 chsgeo_base = 0x67; 2438 break; 2439 case 3: 2440 chsgeo_base = 0x70; 2441 break; 2442 default: 2443 chsgeo_base = 0; 2444 } 2445 if (chsgeo_base != 0) 2446 { 2447 lcylinders = inb_cmos(chsgeo_base) + (inb_cmos(chsgeo_base+1) << 8); 2448 lheads = inb_cmos(chsgeo_base+2); 2449 lspt = inb_cmos(chsgeo_base+7); 2450 } 2451 else 2452 { 2453 lcylinders = 0; 2454 lheads = 0; 2455 lspt = 0; 2456 } 2418 2457 #endif /* VBOX */ 2419 2458 … … 2426 2465 write_word(ebda_seg,&EbdaData->ata.devices[device].pchs.spt, spt); 2427 2466 write_dword(ebda_seg,&EbdaData->ata.devices[device].sectors, sectors); 2467 #ifdef VBOX 2468 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, lheads); 2469 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, lcylinders); 2470 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, lspt); 2471 #else /* !VBOX */ 2428 2472 BX_INFO("ata%d-%d: PCHS=%u/%d/%d translation=", channel, slave,cylinders, heads, spt); 2429 2473 … … 2436 2480 switch (translation) { 2437 2481 case ATA_TRANSLATION_NONE: 2438 #ifndef VBOX2439 2482 BX_INFO("none"); 2440 #else /* VBOX */2441 bios_printf(BIOS_PRINTF_INFO, "none");2442 #endif /* VBOX */2443 2483 break; 2444 2484 case ATA_TRANSLATION_LBA: 2445 #ifndef VBOX2446 2485 BX_INFO("lba"); 2447 #else /* VBOX */2448 bios_printf(BIOS_PRINTF_INFO, "lba");2449 #endif /* VBOX */2450 2486 break; 2451 2487 case ATA_TRANSLATION_LARGE: 2452 #ifndef VBOX2453 2488 BX_INFO("large"); 2454 #else /* VBOX */2455 bios_printf(BIOS_PRINTF_INFO, "large");2456 #endif /* VBOX */2457 2489 break; 2458 2490 case ATA_TRANSLATION_RECHS: 2459 #ifndef VBOX2460 2491 BX_INFO("r-echs"); 2461 #else /* VBOX */2462 bios_printf(BIOS_PRINTF_INFO, "r-echs");2463 #endif /* VBOX */2464 2492 break; 2465 2493 } … … 2498 2526 // clip to 1024 cylinders in lchs 2499 2527 if (cylinders > 1024) cylinders=1024; 2500 #ifndef VBOX2501 2528 BX_INFO(" LCHS=%d/%d/%d\n", cylinders, heads, spt); 2502 #else /* VBOX */2503 bios_printf(BIOS_PRINTF_INFO, " LCHS=%d/%d/%d\n", cylinders, heads, spt);2504 #endif /* VBOX */2505 2529 2506 2530 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.heads, heads); 2507 2531 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.cylinders, cylinders); 2508 2532 write_word(ebda_seg,&EbdaData->ata.devices[device].lchs.spt, spt); 2533 #endif /* VBOX */ 2509 2534 2510 2535 // fill hdidmap -
trunk/src/VBox/Devices/PC/DevPcBios.cpp
r5999 r6291 5 5 6 6 /* 7 * Copyright (C) 2006-200 7innotek GmbH7 * Copyright (C) 2006-2008 innotek GmbH 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 265 265 __END_DECLS 266 266 267 /* Attempt to guess the LCHS disk geometry from the MS-DOS master boot 268 * record (partition table). */ 269 static int biosGuessDiskLCHS(PPDMIBLOCK pBlock, PPDMMEDIAGEOMETRY pLCHSGeometry) 270 { 271 uint8_t aMBR[512], *p; 272 int rc; 273 uint32_t iEndHead, iEndSector, cLCHSCylinders, cLCHSHeads, cLCHSSectors; 274 275 if (!pBlock) 276 return VERR_INVALID_PARAMETER; 277 rc = pBlock->pfnRead(pBlock, 0, aMBR, sizeof(aMBR)); 278 if (VBOX_FAILURE(rc)) 279 return rc; 280 /* Test MBR magic number. */ 281 if (aMBR[510] != 0x55 || aMBR[511] != 0xaa) 282 return VERR_INVALID_PARAMETER; 283 for (uint32_t i = 0; i < 4; i++) 284 { 285 /* Figure out the start of a partition table entry. */ 286 p = &aMBR[0x1be + i * 16]; 287 iEndHead = p[5]; 288 iEndSector = p[6] & 63; 289 if ((p[12] | p[13] | p[14] | p[15]) && iEndSector & iEndHead) 290 { 291 /* Assumption: partition terminates on a cylinder boundary. */ 292 cLCHSHeads = iEndHead + 1; 293 cLCHSSectors = iEndSector; 294 cLCHSCylinders = pBlock->pfnGetSize(pBlock) / (512 * cLCHSHeads * cLCHSSectors); 295 if (cLCHSCylinders >= 1) 296 { 297 pLCHSGeometry->cCylinders = cLCHSCylinders; 298 pLCHSGeometry->cHeads = cLCHSHeads; 299 pLCHSGeometry->cSectors = cLCHSSectors; 300 Log(("%s: LCHS=%d %d %d\n", __FUNCTION__, cLCHSCylinders, cLCHSHeads, cLCHSSectors)); 301 return VINF_SUCCESS; 302 } 303 } 304 } 305 return VERR_INVALID_PARAMETER; 306 } 307 267 308 268 309 /** … … 293 334 static void pcbiosCmosInitHardDisk(PPDMDEVINS pDevIns, int offType, int offInfo, PPDMIBLOCKBIOS pBlockBios) 294 335 { 295 if ( pBlockBios->pfnGetType(pBlockBios) == PDMBLOCKTYPE_HARD_DISK 296 && pBlockBios->pfnIsVisible(pBlockBios)) 297 { 298 uint32_t cCylinders; 299 uint32_t cHeads; 300 uint32_t cSectors; 301 int rc = pBlockBios->pfnGetGeometry(pBlockBios, &cCylinders, &cHeads, &cSectors); 302 if (VBOX_SUCCESS(rc)) 303 { 304 Log2(("pcbiosCmosInitHardDisk: offInfo=%#x: CHS=%d/%d/%d\n", offInfo, cCylinders, cHeads, cSectors)); 305 pcbiosCmosWrite(pDevIns, offType, 47); /* 19h - First Extended Hard Disk Drive Type */ 306 pcbiosCmosWrite(pDevIns, offInfo + 0, RT_MIN(cCylinders, 16383) & 0xff); /* 1Bh - (AMI) First Hard Disk (type 47) user defined: # of Cylinders, LSB */ 307 pcbiosCmosWrite(pDevIns, offInfo + 1, RT_MIN(cCylinders, 16383) >> 8); /* 1Ch - (AMI) First Hard Disk user defined: # of Cylinders, High Byte */ 308 pcbiosCmosWrite(pDevIns, offInfo + 2, cHeads); /* 1Dh - (AMI) First Hard Disk user defined: Number of Heads */ 309 pcbiosCmosWrite(pDevIns, offInfo + 3, 0xff); /* 1Eh - (AMI) First Hard Disk user defined: Write Precompensation Cylinder, Low Byte */ 310 pcbiosCmosWrite(pDevIns, offInfo + 4, 0xff); /* 1Fh - (AMI) First Hard Disk user defined: Write Precompensation Cylinder, High Byte */ 311 pcbiosCmosWrite(pDevIns, offInfo + 5, 0xc0 | ((cHeads > 8) << 3)); /* 20h - (AMI) First Hard Disk user defined: Control Byte */ 312 pcbiosCmosWrite(pDevIns, offInfo + 6, 0xff); /* 21h - (AMI) First Hard Disk user defined: Landing Zone, Low Byte */ 313 pcbiosCmosWrite(pDevIns, offInfo + 7, 0xff); /* 22h - (AMI) First Hard Disk user defined: Landing Zone, High Byte */ 314 pcbiosCmosWrite(pDevIns, offInfo + 8, cSectors); /* 23h - (AMI) First Hard Disk user defined: # of Sectors per track */ 315 return; 316 } 317 } 318 pcbiosCmosWrite(pDevIns, offType, 0); 336 PDMMEDIAGEOMETRY LCHSGeometry; 337 int rc = pBlockBios->pfnGetLCHSGeometry(pBlockBios, &LCHSGeometry); 338 if (VBOX_SUCCESS(rc)) 339 { 340 Log2(("%s: offInfo=%#x: LCHS=%d/%d/%d\n", __FUNCTION__, offInfo, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors)); 341 if (offType) 342 pcbiosCmosWrite(pDevIns, offType, 48); 343 /* Cylinders low */ 344 pcbiosCmosWrite(pDevIns, offInfo + 0, RT_MIN(LCHSGeometry.cCylinders, 1024) & 0xff); 345 /* Cylinders high */ 346 pcbiosCmosWrite(pDevIns, offInfo + 1, RT_MIN(LCHSGeometry.cCylinders, 1024) >> 8); 347 /* Heads */ 348 pcbiosCmosWrite(pDevIns, offInfo + 2, LCHSGeometry.cHeads); 349 /* Landing zone low */ 350 pcbiosCmosWrite(pDevIns, offInfo + 3, 0xff); 351 /* Landing zone high */ 352 pcbiosCmosWrite(pDevIns, offInfo + 4, 0xff); 353 /* Write precomp low */ 354 pcbiosCmosWrite(pDevIns, offInfo + 5, 0xff); 355 /* Write precomp high */ 356 pcbiosCmosWrite(pDevIns, offInfo + 6, 0xff); 357 /* Sectors */ 358 pcbiosCmosWrite(pDevIns, offInfo + 7, LCHSGeometry.cSectors); 359 return; 360 } 361 if (offType) 362 pcbiosCmosWrite(pDevIns, offType, 0); 319 363 } 320 364 … … 450 494 switch (u32) 451 495 { 452 case 1: u32 = 0x01; break; /* floppy installed, 1 drive. */ 453 case 2: u32 = 0x41; break; /* floppy installed, 2 drives. */ 496 case 1: u32 = 0x01; break; /* floppy installed, 2 drives. */ 454 497 default:u32 = 0; break; /* floppy not installed. */ 455 498 } … … 468 511 if (VBOX_SUCCESS(rc)) 469 512 apHDs[i] = (PPDMIBLOCKBIOS)pBase->pfnQueryInterface(pBase, PDMINTERFACE_BLOCK_BIOS); 470 } 471 472 u32 = (apHDs[0] ? 0xf0 : 0) | (apHDs[1] ? 0x0f : 0); /* 0Fh means extended and points to 1Ah, 1Bh */ 473 pcbiosCmosWrite(pDevIns, 0x12, u32); /* 12h - Hard Disk Data (type) */ 474 if (apHDs[0]) 475 pcbiosCmosInitHardDisk(pDevIns, 0x19, 0x1b, apHDs[0]); /* 19h - First Extended Hard Disk Drive Type */ 476 if (apHDs[1]) 477 pcbiosCmosInitHardDisk(pDevIns, 0x1a, 0x24, apHDs[1]); /* 1Ah - Second Extended Hard Disk Drive Type */ 478 479 /* 480 * Translation type - Bochs BIOS specific. 481 */ 482 u32 = 0; 483 for (i = 0; i < 4; i++) 484 { 513 if ( apHDs[i] 514 && ( apHDs[i]->pfnGetType(apHDs[i]) != PDMBLOCKTYPE_HARD_DISK 515 || !apHDs[i]->pfnIsVisible(apHDs[i]))) 516 apHDs[i] = NULL; 485 517 if (apHDs[i]) 486 518 { 487 PDMBIOSTRANSLATION enmTranslation; 488 int rc = apHDs[i]->pfnGetTranslation(apHDs[i], &enmTranslation); 489 if (VBOX_FAILURE(rc) || enmTranslation == PDMBIOSTRANSLATION_AUTO) 519 PDMMEDIAGEOMETRY LCHSGeometry; 520 int rc = apHDs[i]->pfnGetLCHSGeometry(apHDs[i], &LCHSGeometry); 521 if ( rc == VERR_PDM_GEOMETRY_NOT_SET 522 || LCHSGeometry.cCylinders == 0 523 || LCHSGeometry.cCylinders > 1024 524 || LCHSGeometry.cHeads == 0 525 || LCHSGeometry.cHeads > 255 526 || LCHSGeometry.cSectors == 0 527 || LCHSGeometry.cSectors > 63) 490 528 { 491 uint32_t cCylinders, cHeads, cSectors; 492 rc = apHDs[i]->pfnGetGeometry(apHDs[i], &cCylinders, &cHeads, &cSectors); 529 PPDMIBLOCK pBlock; 530 pBlock = (PPDMIBLOCK)pBase->pfnQueryInterface(pBase, PDMINTERFACE_BLOCK); 531 /* No LCHS geometry, autodetect and set. */ 532 rc = biosGuessDiskLCHS(pBlock, &LCHSGeometry); 493 533 if (VBOX_FAILURE(rc)) 494 534 { 495 AssertMsg(rc == VERR_PDM_MEDIA_NOT_MOUNTED, ("This shouldn't happen! rc=%Vrc\n", rc));496 enmTranslation = PDMBIOSTRANSLATION_NONE;535 /* Try if PCHS geometry works, otherwise fall back. */ 536 rc = apHDs[i]->pfnGetPCHSGeometry(apHDs[i], &LCHSGeometry); 497 537 } 498 else if (cCylinders <= 1024 && cHeads <= 16 && cSectors <= 63) 538 if ( VBOX_FAILURE(rc) 539 || LCHSGeometry.cCylinders == 0 540 || LCHSGeometry.cCylinders > 1024 541 || LCHSGeometry.cHeads == 0 542 || LCHSGeometry.cHeads > 16 543 || LCHSGeometry.cSectors == 0 544 || LCHSGeometry.cSectors > 63) 499 545 { 500 /* Disk <= 512 MByte not needing LBA translation. */ 501 enmTranslation = PDMBIOSTRANSLATION_NONE; 546 uint64_t cSectors = pBlock->pfnGetSize(pBlock) / 512; 547 if (cSectors / 16 / 63 <= 1024) 548 { 549 LCHSGeometry.cCylinders = RT_MAX(cSectors / 16 / 63, 1); 550 LCHSGeometry.cHeads = 16; 551 } 552 else if (cSectors / 32 / 63 <= 1024) 553 { 554 LCHSGeometry.cCylinders = RT_MAX(cSectors / 32 / 63, 1); 555 LCHSGeometry.cHeads = 32; 556 } 557 else if (cSectors / 64 / 63 <= 1024) 558 { 559 LCHSGeometry.cCylinders = cSectors / 64 / 63; 560 LCHSGeometry.cHeads = 64; 561 } 562 else if (cSectors / 128 / 63 <= 1024) 563 { 564 LCHSGeometry.cCylinders = cSectors / 128 / 63; 565 LCHSGeometry.cHeads = 128; 566 } 567 else 568 { 569 LCHSGeometry.cCylinders = RT_MIN(cSectors / 255 / 63, 1024); 570 LCHSGeometry.cHeads = 255; 571 } 572 LCHSGeometry.cSectors = 63; 573 502 574 } 503 else if (cSectors != 63 || (cHeads != 16 && cHeads != 32 && cHeads != 64 && cHeads != 128 && cHeads != 255)) 504 { 505 /* Disk with strange geometry. Using LBA here can 506 * break booting of the guest OS. Especially operating 507 * systems from Microsoft are sensitive to BIOS CHS not 508 * matching what the partition table says. */ 509 enmTranslation = PDMBIOSTRANSLATION_NONE; 510 } 511 else 512 enmTranslation = PDMBIOSTRANSLATION_LBA; 575 rc = apHDs[i]->pfnSetLCHSGeometry(apHDs[i], &LCHSGeometry); 576 AssertRC(rc); 513 577 } 514 switch (enmTranslation) 515 { 516 case PDMBIOSTRANSLATION_AUTO: /* makes gcc happy */ 517 case PDMBIOSTRANSLATION_NONE: 518 /* u32 |= 0 << (i * 2) */ 519 break; 520 default: 521 AssertMsgFailed(("bad enmTranslation=%d\n", enmTranslation)); 522 case PDMBIOSTRANSLATION_LBA: 523 u32 |= 1 << (i * 2); 524 break; 525 } 526 } 527 } 528 Log2(("pcbiosInitComplete: translation byte: %#02x\n", u32)); 529 pcbiosCmosWrite(pDevIns, 0x39, u32); 530 531 LogFlow(("pcbiosInitComplete: returns VINF_SUCCESS\n")); 578 LogRel(("DevPcBios: ATA LUN#%d LCHS=%u/%u/%u\n", i, LCHSGeometry.cCylinders, LCHSGeometry.cHeads, LCHSGeometry.cSectors)); 579 pcbiosCmosWrite(pDevIns, 0x40 + i * 4, LCHSGeometry.cCylinders & 0xff); 580 pcbiosCmosWrite(pDevIns, 0x41 + i * 4, LCHSGeometry.cCylinders >> 8); 581 pcbiosCmosWrite(pDevIns, 0x42 + i * 4, LCHSGeometry.cHeads & 0xff); 582 pcbiosCmosWrite(pDevIns, 0x43 + i * 4, LCHSGeometry.cSectors & 0xff); 583 } 584 } 585 586 /* 0Fh means extended and points to 19h, 1Ah */ 587 u32 = (apHDs[0] ? 0xf0 : 0) | (apHDs[1] ? 0x0f : 0); 588 pcbiosCmosWrite(pDevIns, 0x12, u32); 589 /* Award BIOS extended drive types for first and second disk, and 590 * extended drive types for third and fourth disk. Used by the BIOS. */ 591 if (apHDs[0]) 592 pcbiosCmosInitHardDisk(pDevIns, 0x19, 0x1e, apHDs[0]); 593 if (apHDs[1]) 594 pcbiosCmosInitHardDisk(pDevIns, 0x1a, 0x26, apHDs[1]); 595 if (apHDs[2]) 596 pcbiosCmosInitHardDisk(pDevIns, 0x00, 0x67, apHDs[2]); 597 if (apHDs[3]) 598 pcbiosCmosInitHardDisk(pDevIns, 0x00, 0x70, apHDs[3]); 599 600 LogFlow(("%s: returns VINF_SUCCESS\n", __FUNCTION__)); 532 601 return VINF_SUCCESS; 533 602 } -
trunk/src/VBox/Devices/Storage/DevATA.cpp
r6062 r6291 6 6 7 7 /* 8 * Copyright (C) 2006-200 7innotek GmbH8 * Copyright (C) 2006-2008 innotek GmbH 9 9 * 10 10 * This file is part of VirtualBox Open Source Edition (OSE), as … … 84 84 uint8_t cMultSectors; 85 85 /** PCHS disk geometry. */ 86 uint32_t cCHSCylinders, cCHSHeads, cCHSSectors;86 PDMMEDIAGEOMETRY PCHSGeometry; 87 87 /** Total number of sectors on this disk. */ 88 88 uint64_t cTotalSectors; … … 1062 1062 memset(p, 0, 512); 1063 1063 p[0] = RT_H2LE_U16(0x0040); 1064 p[1] = RT_H2LE_U16(RT_MIN(s-> cCHSCylinders, 16383));1065 p[3] = RT_H2LE_U16(s-> cCHSHeads);1064 p[1] = RT_H2LE_U16(RT_MIN(s->PCHSGeometry.cCylinders, 16383)); 1065 p[3] = RT_H2LE_U16(s->PCHSGeometry.cHeads); 1066 1066 /* Block size; obsolete, but required for the BIOS. */ 1067 1067 p[5] = RT_H2LE_U16(512); 1068 p[6] = RT_H2LE_U16(s-> cCHSSectors);1068 p[6] = RT_H2LE_U16(s->PCHSGeometry.cSectors); 1069 1069 ataPadString((uint8_t *)(p + 10), aSerial, 20); /* serial number */ 1070 1070 p[20] = RT_H2LE_U16(3); /* XXX: retired, cache type */ … … 1082 1082 p[52] = RT_H2LE_U16(240); /* DMA transfer cycle */ 1083 1083 p[53] = RT_H2LE_U16(1 | 1 << 1 | 1 << 2); /* words 54-58,64-70,88 valid */ 1084 p[54] = RT_H2LE_U16(RT_MIN(s->cCHSCylinders, 16383)); 1085 p[55] = RT_H2LE_U16(s->cCHSHeads); 1086 p[56] = RT_H2LE_U16(s->cCHSSectors); 1087 p[57] = RT_H2LE_U16(RT_MIN(s->cCHSCylinders, 16383) * s->cCHSHeads * s->cCHSSectors); 1088 p[58] = RT_H2LE_U16(RT_MIN(s->cCHSCylinders, 16383) * s->cCHSHeads * s->cCHSSectors >> 16); 1084 p[54] = RT_H2LE_U16(RT_MIN(s->PCHSGeometry.cCylinders, 16383)); 1085 p[55] = RT_H2LE_U16(s->PCHSGeometry.cHeads); 1086 p[56] = RT_H2LE_U16(s->PCHSGeometry.cSectors); 1087 p[57] = RT_H2LE_U16( RT_MIN(s->PCHSGeometry.cCylinders, 16383) 1088 * s->PCHSGeometry.cHeads 1089 * s->PCHSGeometry.cSectors); 1090 p[58] = RT_H2LE_U16( RT_MIN(s->PCHSGeometry.cCylinders, 16383) 1091 * s->PCHSGeometry.cHeads 1092 * s->PCHSGeometry.cSectors >> 16); 1089 1093 if (s->cMultSectors) 1090 1094 p[59] = RT_H2LE_U16(0x100 | s->cMultSectors); … … 1268 1272 { 1269 1273 /* CHS */ 1270 iLBA = ((s->uATARegHCyl << 8) | s->uATARegLCyl) * s-> cCHSHeads * s->cCHSSectors +1271 (s->uATARegSelect & 0x0f) * s-> cCHSSectors +1274 iLBA = ((s->uATARegHCyl << 8) | s->uATARegLCyl) * s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors + 1275 (s->uATARegSelect & 0x0f) * s->PCHSGeometry.cSectors + 1272 1276 (s->uATARegSector - 1); 1273 1277 } … … 1303 1307 { 1304 1308 /* CHS */ 1305 cyl = iLBA / (s-> cCHSHeads * s->cCHSSectors);1306 r = iLBA % (s-> cCHSHeads * s->cCHSSectors);1309 cyl = iLBA / (s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors); 1310 r = iLBA % (s->PCHSGeometry.cHeads * s->PCHSGeometry.cSectors); 1307 1311 s->uATARegHCyl = cyl >> 8; 1308 1312 s->uATARegLCyl = cyl; 1309 s->uATARegSelect = (s->uATARegSelect & 0xf0) | ((r / s-> cCHSSectors) & 0x0f);1310 s->uATARegSector = (r % s-> cCHSSectors) + 1;1313 s->uATARegSelect = (s->uATARegSelect & 0xf0) | ((r / s->PCHSGeometry.cSectors) & 0x0f); 1314 s->uATARegSector = (r % s->PCHSGeometry.cSectors) + 1; 1311 1315 } 1312 1316 } … … 3868 3872 #ifdef IN_RING3 3869 3873 3870 /* Attempt to guess the LCHS disk geometry from the MS-DOS master boot3871 * record (partition table). */3872 static int ataGuessDiskLCHS(ATADevState *s, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)3873 {3874 uint8_t aMBR[512], *p;3875 int rc;3876 uint32_t iEndHead, iEndSector, cCHSCylinders, cCHSHeads, cCHSSectors;3877 3878 if (s->fATAPI || !s->pDrvBlock)3879 return VERR_INVALID_PARAMETER;3880 rc = s->pDrvBlock->pfnRead(s->pDrvBlock, 0, aMBR, 1 * 512);3881 if (VBOX_FAILURE(rc))3882 return rc;3883 /* Test MBR magic number. */3884 if (aMBR[510] != 0x55 || aMBR[511] != 0xaa)3885 return VERR_INVALID_PARAMETER;3886 for (uint32_t i = 0; i < 4; i++)3887 {3888 /* Figure out the start of a partition table entry. */3889 p = &aMBR[0x1be + i * 16];3890 iEndHead = p[5];3891 iEndSector = p[6] & 63;3892 if ((p[12] | p[13] | p[14] | p[15]) && iEndSector & iEndHead)3893 {3894 /* Assumption: partition terminates on a cylinder boundary. */3895 cCHSHeads = iEndHead + 1;3896 cCHSSectors = iEndSector;3897 cCHSCylinders = s->cTotalSectors / (cCHSHeads * cCHSSectors);3898 if (cCHSCylinders >= 1)3899 {3900 *pcHeads = cCHSHeads;3901 *pcSectors = cCHSSectors;3902 *pcCylinders = cCHSCylinders;3903 Log(("%s: LCHS=%d %d %d\n", __FUNCTION__, cCHSCylinders, cCHSHeads, cCHSSectors));3904 return VINF_SUCCESS;3905 }3906 }3907 }3908 return VERR_INVALID_PARAMETER;3909 }3910 3911 3912 3874 static void ataDMATransferStop(ATADevState *s) 3913 3875 { … … 5447 5409 5448 5410 /* 5449 * Init geometry .5411 * Init geometry (only for non-CD/DVD media). 5450 5412 */ 5451 5413 if (pIf->fATAPI) 5452 5414 { 5453 5415 pIf->cTotalSectors = pIf->pDrvBlock->pfnGetSize(pIf->pDrvBlock) / 2048; 5454 rc = pIf->pDrvBlockBios->pfnGetGeometry(pIf->pDrvBlockBios, &pIf->cCHSCylinders, &pIf->cCHSHeads, &pIf->cCHSSectors); 5455 pIf->cCHSCylinders = 0; /* dummy */ 5456 pIf->cCHSHeads = 0; /* dummy */ 5457 pIf->cCHSSectors = 0; /* dummy */ 5458 if (rc != VERR_PDM_MEDIA_NOT_MOUNTED) 5459 { 5460 pIf->pDrvBlockBios->pfnSetTranslation(pIf->pDrvBlockBios, PDMBIOSTRANSLATION_NONE); 5461 pIf->pDrvBlockBios->pfnSetGeometry(pIf->pDrvBlockBios, pIf->cCHSCylinders, pIf->cCHSHeads, pIf->cCHSSectors); 5462 } 5416 pIf->PCHSGeometry.cCylinders = 0; /* dummy */ 5417 pIf->PCHSGeometry.cHeads = 0; /* dummy */ 5418 pIf->PCHSGeometry.cSectors = 0; /* dummy */ 5463 5419 LogRel(("PIIX3 ATA: LUN#%d: CD/DVD, total number of sectors %Ld, passthrough %s\n", pIf->iLUN, pIf->cTotalSectors, (pIf->fATAPIPassthrough ? "enabled" : "disabled"))); 5464 5420 } … … 5466 5422 { 5467 5423 pIf->cTotalSectors = pIf->pDrvBlock->pfnGetSize(pIf->pDrvBlock) / 512; 5468 rc = pIf->pDrvBlockBios->pfnGetGeometry(pIf->pDrvBlockBios, &pIf->cCHSCylinders, &pIf->cCHSHeads, &pIf->cCHSSectors); 5424 rc = pIf->pDrvBlockBios->pfnGetPCHSGeometry(pIf->pDrvBlockBios, 5425 &pIf->PCHSGeometry); 5469 5426 if (rc == VERR_PDM_MEDIA_NOT_MOUNTED) 5470 5427 { 5471 pIf->cCHSCylinders = 0; 5472 pIf->cCHSHeads = 16; /*??*/ 5473 pIf->cCHSSectors = 63; /*??*/ 5474 } 5475 else if (VBOX_FAILURE(rc)) 5476 { 5477 PDMBIOSTRANSLATION enmTranslation; 5478 rc = pIf->pDrvBlockBios->pfnGetTranslation(pIf->pDrvBlockBios, &enmTranslation); 5479 if (rc == VERR_PDM_TRANSLATION_NOT_SET) 5480 { 5481 enmTranslation = PDMBIOSTRANSLATION_AUTO; 5482 pIf->cCHSCylinders = 0; 5483 rc = VINF_SUCCESS; 5484 } 5485 AssertRC(rc); 5486 5487 if ( enmTranslation == PDMBIOSTRANSLATION_AUTO 5488 && ( pIf->cCHSCylinders == 0 5489 || pIf->cCHSHeads == 0 5490 || pIf->cCHSSectors == 0 5491 ) 5492 ) 5493 { 5494 /* Image contains no geometry information, detect geometry. */ 5495 rc = ataGuessDiskLCHS(pIf, &pIf->cCHSCylinders, &pIf->cCHSHeads, &pIf->cCHSSectors); 5496 if (VBOX_SUCCESS(rc)) 5497 { 5498 /* Caution: the above function returns LCHS, but the 5499 * disk must report proper PCHS values for disks bigger 5500 * than approximately 512MB. */ 5501 if (pIf->cCHSSectors == 63 && (pIf->cCHSHeads != 16 || pIf->cCHSCylinders >= 1024)) 5502 { 5503 pIf->cCHSCylinders = pIf->cTotalSectors / 63 / 16; 5504 pIf->cCHSHeads = 16; 5505 pIf->cCHSSectors = 63; 5506 /* Set the disk CHS translation mode. */ 5507 pIf->pDrvBlockBios->pfnSetTranslation(pIf->pDrvBlockBios, PDMBIOSTRANSLATION_LBA); 5508 } 5509 /* Set the disk geometry information. */ 5510 rc = pIf->pDrvBlockBios->pfnSetGeometry(pIf->pDrvBlockBios, pIf->cCHSCylinders, pIf->cCHSHeads, pIf->cCHSSectors); 5511 } 5512 else 5513 { 5514 /* Flag geometry as invalid, will be replaced below by the 5515 * default geometry. */ 5516 pIf->cCHSCylinders = 0; 5517 } 5518 } 5519 if (!pIf->cCHSCylinders) 5520 { 5521 /* If there is no geometry, use standard physical disk geometry. 5522 * This uses LCHS to LBA translation in the BIOS (which selects 5523 * the logical sector count 63 and the logical head count to be 5524 * the smallest of 16,32,64,128,255 which makes the logical 5525 * cylinder count smaller than 1024 - if that's not possible, it 5526 * uses 255 heads, so up to about 8 GByte maximum with the 5527 * standard int13 interface, which supports 1024 cylinders). */ 5528 uint64_t cCHSCylinders = pIf->cTotalSectors / (16 * 63); 5529 pIf->cCHSCylinders = (uint32_t)RT_MAX(cCHSCylinders, 1); 5530 pIf->cCHSHeads = 16; 5531 pIf->cCHSSectors = 63; 5532 /* Set the disk geometry information. */ 5533 rc = pIf->pDrvBlockBios->pfnSetGeometry(pIf->pDrvBlockBios, pIf->cCHSCylinders, pIf->cCHSHeads, pIf->cCHSSectors); 5534 } 5535 } 5536 else 5537 { 5538 PDMBIOSTRANSLATION enmTranslation; 5539 rc = pIf->pDrvBlockBios->pfnGetTranslation(pIf->pDrvBlockBios, &enmTranslation); 5540 if (( rc == VERR_PDM_TRANSLATION_NOT_SET 5541 || enmTranslation == PDMBIOSTRANSLATION_LBA) 5542 && pIf->cCHSSectors == 63 5543 && (pIf->cCHSHeads != 16 || pIf->cCHSCylinders >= 1024)) 5544 { 5545 /* Use the official LBA physical CHS geometry. */ 5546 uint64_t cCHSCylinders = pIf->cTotalSectors / (16 * 63); 5547 pIf->cCHSCylinders = RT_MAX((uint32_t)RT_MIN(cCHSCylinders, 16383), 1); 5548 pIf->cCHSHeads = 16; 5549 pIf->cCHSSectors = 63; 5550 /* DO NOT write back the disk geometry information. This 5551 * intentionally sets the ATA geometry only. */ 5552 } 5553 } 5554 LogRel(("PIIX3 ATA: LUN#%d: disk, CHS=%d/%d/%d, total number of sectors %Ld\n", pIf->iLUN, pIf->cCHSCylinders, pIf->cCHSHeads, pIf->cCHSSectors, pIf->cTotalSectors)); 5428 pIf->PCHSGeometry.cCylinders = 0; 5429 pIf->PCHSGeometry.cHeads = 16; /*??*/ 5430 pIf->PCHSGeometry.cSectors = 63; /*??*/ 5431 } 5432 else if (rc == VERR_PDM_GEOMETRY_NOT_SET) 5433 { 5434 pIf->PCHSGeometry.cCylinders = 0; /* autodetect marker */ 5435 rc = VINF_SUCCESS; 5436 } 5437 AssertRC(rc); 5438 5439 if ( pIf->PCHSGeometry.cCylinders == 0 5440 || pIf->PCHSGeometry.cHeads == 0 5441 || pIf->PCHSGeometry.cSectors == 0 5442 ) 5443 { 5444 uint64_t cCylinders = pIf->cTotalSectors / (16 * 63); 5445 pIf->PCHSGeometry.cCylinders = RT_MAX(RT_MIN(cCylinders, 16383), 1); 5446 pIf->PCHSGeometry.cHeads = 16; 5447 pIf->PCHSGeometry.cSectors = 63; 5448 /* Set the disk geometry information. */ 5449 rc = pIf->pDrvBlockBios->pfnSetPCHSGeometry(pIf->pDrvBlockBios, 5450 &pIf->PCHSGeometry); 5451 } 5452 LogRel(("PIIX3 ATA: LUN#%d: disk, PCHS=%u/%u/%u, total number of sectors %Ld\n", pIf->iLUN, pIf->PCHSGeometry.cCylinders, pIf->PCHSGeometry.cHeads, pIf->PCHSGeometry.cSectors, pIf->cTotalSectors)); 5555 5453 } 5556 5454 return VINF_SUCCESS; … … 5720 5618 SSMR3PutBool(pSSMHandle, pData->aCts[i].aIfs[j].fIrqPending); 5721 5619 SSMR3PutU8(pSSMHandle, pData->aCts[i].aIfs[j].cMultSectors); 5722 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j]. cCHSCylinders);5723 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j]. cCHSHeads);5724 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j]. cCHSSectors);5620 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].PCHSGeometry.cCylinders); 5621 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].PCHSGeometry.cHeads); 5622 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].PCHSGeometry.cSectors); 5725 5623 SSMR3PutU32(pSSMHandle, pData->aCts[i].aIfs[j].cSectorsPerIRQ); 5726 5624 SSMR3PutU64(pSSMHandle, pData->aCts[i].aIfs[j].cTotalSectors); … … 5825 5723 SSMR3GetBool(pSSMHandle, &pData->aCts[i].aIfs[j].fIrqPending); 5826 5724 SSMR3GetU8(pSSMHandle, &pData->aCts[i].aIfs[j].cMultSectors); 5827 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j]. cCHSCylinders);5828 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j]. cCHSHeads);5829 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j]. cCHSSectors);5725 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].PCHSGeometry.cCylinders); 5726 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].PCHSGeometry.cHeads); 5727 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].PCHSGeometry.cSectors); 5830 5728 SSMR3GetU32(pSSMHandle, &pData->aCts[i].aIfs[j].cSectorsPerIRQ); 5831 5729 SSMR3GetU64(pSSMHandle, &pData->aCts[i].aIfs[j].cTotalSectors); -
trunk/src/VBox/Devices/Storage/DrvBlock.cpp
r5999 r6291 71 71 /** Visible to the BIOS. */ 72 72 bool fBiosVisible; 73 /** Whether or not enmTranslation is valid. */74 bool fTranslationSet;75 73 #ifdef VBOX_PERIODIC_FLUSH 76 74 /** HACK: Configuration value for number of bytes written after which to flush. */ … … 100 98 RTUUID Uuid; 101 99 102 /** BIOS Geometry: Translation mode. */ 103 PDMBIOSTRANSLATION enmTranslation; 104 /** BIOS Geometry: Cylinders. */ 105 uint32_t cCylinders; 106 /** BIOS Geometry: Heads. */ 107 uint32_t cHeads; 108 /** BIOS Geometry: Sectors. */ 109 uint32_t cSectors; 100 /** BIOS PCHS Geometry. */ 101 PDMMEDIAGEOMETRY PCHSGeometry; 102 /** BIOS LCHS Geometry. */ 103 PDMMEDIAGEOMETRY LCHSGeometry; 110 104 } DRVBLOCK, *PDRVBLOCK; 111 105 … … 254 248 255 249 256 /** @copydoc PDMIBLOCKBIOS::pfnGet Geometry */257 static DECLCALLBACK(int) drvblockGet Geometry(PPDMIBLOCKBIOS pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)250 /** @copydoc PDMIBLOCKBIOS::pfnGetPCHSGeometry */ 251 static DECLCALLBACK(int) drvblockGetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry) 258 252 { 259 253 PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface); … … 268 262 * Use configured/cached values if present. 269 263 */ 270 if ( pData->cCylinders > 0 271 && pData->cHeads > 0 272 && pData->cSectors > 0) 273 { 274 *pcCylinders = pData->cCylinders; 275 *pcHeads = pData->cHeads; 276 *pcSectors = pData->cSectors; 277 LogFlow(("drvblockGetGeometry: returns VINF_SUCCESS {%d,%d,%d}\n", pData->cCylinders, pData->cHeads, pData->cSectors)); 264 if ( pData->PCHSGeometry.cCylinders > 0 265 && pData->PCHSGeometry.cHeads > 0 266 && pData->PCHSGeometry.cSectors > 0) 267 { 268 *pPCHSGeometry = pData->PCHSGeometry; 269 LogFlow(("%s: returns VINF_SUCCESS {%d,%d,%d}\n", __FUNCTION__, pData->PCHSGeometry.cCylinders, pData->PCHSGeometry.cHeads, pData->PCHSGeometry.cSectors)); 278 270 return VINF_SUCCESS; 279 271 } … … 282 274 * Call media. 283 275 */ 284 int rc = pData->pDrvMedia->pfnBiosGet Geometry(pData->pDrvMedia, pcCylinders, pcHeads, pcSectors);276 int rc = pData->pDrvMedia->pfnBiosGetPCHSGeometry(pData->pDrvMedia, &pData->PCHSGeometry); 285 277 if (VBOX_SUCCESS(rc)) 286 278 { 287 pData->cCylinders = *pcCylinders; 288 pData->cHeads = *pcHeads; 289 pData->cSectors = *pcSectors; 290 LogFlow(("drvblockGetGeometry: returns %Vrc {%d,%d,%d}\n", rc, pData->cCylinders, pData->cHeads, pData->cSectors)); 279 *pPCHSGeometry = pData->PCHSGeometry; 280 LogFlow(("%s: returns %Vrc {%d,%d,%d}\n", __FUNCTION__, rc, pData->PCHSGeometry.cCylinders, pData->PCHSGeometry.cHeads, pData->PCHSGeometry.cSectors)); 291 281 } 292 282 else if (rc == VERR_NOT_IMPLEMENTED) 293 283 { 294 284 rc = VERR_PDM_GEOMETRY_NOT_SET; 295 LogFlow((" drvblockGetGeometry: returns %Vrc\n", rc));285 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 296 286 } 297 287 return rc; … … 299 289 300 290 301 /** @copydoc PDMIBLOCKBIOS::pfnSet Geometry */302 static DECLCALLBACK(int) drvblockSet Geometry(PPDMIBLOCKBIOS pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)303 { 304 LogFlow((" drvblockSetGeometry: cCylinders=%d cHeads=%d cSectors=%d\n", cCylinders, cHeads,cSectors));291 /** @copydoc PDMIBLOCKBIOS::pfnSetPCHSGeometry */ 292 static DECLCALLBACK(int) drvblockSetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry) 293 { 294 LogFlow(("%s: cCylinders=%d cHeads=%d cSectors=%d\n", __FUNCTION__, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 305 295 PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface); 306 296 … … 317 307 * Call media. Ignore the not implemented return code. 318 308 */ 319 int rc = pData->pDrvMedia->pfnBiosSet Geometry(pData->pDrvMedia, cCylinders, cHeads, cSectors);309 int rc = pData->pDrvMedia->pfnBiosSetPCHSGeometry(pData->pDrvMedia, pPCHSGeometry); 320 310 if ( VBOX_SUCCESS(rc) 321 311 || rc == VERR_NOT_IMPLEMENTED) 322 312 { 323 pData->cCylinders = cCylinders; 324 pData->cHeads = cHeads; 325 pData->cSectors = cSectors; 313 pData->PCHSGeometry = *pPCHSGeometry; 326 314 rc = VINF_SUCCESS; 327 315 } … … 330 318 331 319 332 /** @copydoc PDMIBLOCKBIOS::pfnGet Translation*/333 static DECLCALLBACK(int) drvblockGet Translation(PPDMIBLOCKBIOS pInterface, PPDMBIOSTRANSLATION penmTranslation)320 /** @copydoc PDMIBLOCKBIOS::pfnGetLCHSGeometry */ 321 static DECLCALLBACK(int) drvblockGetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry) 334 322 { 335 323 PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface); … … 339 327 */ 340 328 if (!pData->pDrvMedia) 341 {342 LogFlow(("drvblockGetTranslation: returns VERR_PDM_MEDIA_NOT_MOUNTED\n"));343 329 return VERR_PDM_MEDIA_NOT_MOUNTED; 344 } 345 346 /* 347 * Use configured/cached data if present. 348 */ 349 if (pData->fTranslationSet) 350 { 351 *penmTranslation = pData->enmTranslation; 352 LogFlow(("drvblockGetTranslation: returns VINF_SUCCESS *penmTranslation=%d\n", *penmTranslation)); 330 331 /* 332 * Use configured/cached values if present. 333 */ 334 if ( pData->LCHSGeometry.cCylinders > 0 335 && pData->LCHSGeometry.cHeads > 0 336 && pData->LCHSGeometry.cSectors > 0) 337 { 338 *pLCHSGeometry = pData->LCHSGeometry; 339 LogFlow(("%s: returns VINF_SUCCESS {%d,%d,%d}\n", __FUNCTION__, pData->LCHSGeometry.cCylinders, pData->LCHSGeometry.cHeads, pData->LCHSGeometry.cSectors)); 353 340 return VINF_SUCCESS; 354 341 } 355 342 356 343 /* 357 * Call media. Handle the not implemented status code.358 */ 359 int rc = pData->pDrvMedia->pfnBiosGet Translation(pData->pDrvMedia, penmTranslation);344 * Call media. 345 */ 346 int rc = pData->pDrvMedia->pfnBiosGetLCHSGeometry(pData->pDrvMedia, &pData->LCHSGeometry); 360 347 if (VBOX_SUCCESS(rc)) 361 348 { 362 pData->enmTranslation = *penmTranslation;363 pData->fTranslationSet = true;349 *pLCHSGeometry = pData->LCHSGeometry; 350 LogFlow(("%s: returns %Vrc {%d,%d,%d}\n", __FUNCTION__, rc, pData->LCHSGeometry.cCylinders, pData->LCHSGeometry.cHeads, pData->LCHSGeometry.cSectors)); 364 351 } 365 352 else if (rc == VERR_NOT_IMPLEMENTED) 366 rc = VERR_PDM_TRANSLATION_NOT_SET; 367 LogFlow(("drvblockGetTranslation: returns %Vrc *penmTranslation=%d\n", rc, *penmTranslation)); 353 { 354 rc = VERR_PDM_GEOMETRY_NOT_SET; 355 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 356 } 368 357 return rc; 369 358 } 370 359 371 360 372 /** @copydoc PDMIBLOCKBIOS::pfnSet Translation*/373 static DECLCALLBACK(int) drvblockSet Translation(PPDMIBLOCKBIOS pInterface, PDMBIOSTRANSLATION enmTranslation)374 { 375 LogFlow((" drvblockSetTranslation: enmTranslation=%d\n", enmTranslation));361 /** @copydoc PDMIBLOCKBIOS::pfnSetLCHSGeometry */ 362 static DECLCALLBACK(int) drvblockSetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry) 363 { 364 LogFlow(("%s: cCylinders=%d cHeads=%d cSectors=%d\n", __FUNCTION__, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 376 365 PDRVBLOCK pData = PDMIBLOCKBIOS_2_DRVBLOCK(pInterface); 377 366 … … 388 377 * Call media. Ignore the not implemented return code. 389 378 */ 390 int rc = pData->pDrvMedia->pfnBiosSet Translation(pData->pDrvMedia, enmTranslation);379 int rc = pData->pDrvMedia->pfnBiosSetLCHSGeometry(pData->pDrvMedia, pLCHSGeometry); 391 380 if ( VBOX_SUCCESS(rc) 392 381 || rc == VERR_NOT_IMPLEMENTED) 393 382 { 394 pData->fTranslationSet = true; 395 pData->enmTranslation = enmTranslation; 383 pData->LCHSGeometry = *pLCHSGeometry; 396 384 rc = VINF_SUCCESS; 397 385 } … … 471 459 */ 472 460 pData->fLocked = false; 473 pData->enmTranslation = PDMBIOSTRANSLATION_NONE; 474 pData->cCylinders = pData->cHeads = pData->cSectors = 0; 461 pData->PCHSGeometry.cCylinders = 0; 462 pData->PCHSGeometry.cHeads = 0; 463 pData->PCHSGeometry.cSectors = 0; 464 pData->LCHSGeometry.cCylinders = 0; 465 pData->LCHSGeometry.cHeads = 0; 466 pData->LCHSGeometry.cSectors = 0; 475 467 #ifdef VBOX_PERIODIC_FLUSH 476 468 pData->cbDataWritten = 0; … … 627 619 */ 628 620 #if defined(VBOX_PERIODIC_FLUSH) || defined(VBOX_IGNORE_FLUSH) 629 if (!CFGMR3AreValuesValid(pCfgHandle, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0 Translation\0Mountable\0FlushInterval\0IgnoreFlush\0"))621 if (!CFGMR3AreValuesValid(pCfgHandle, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0Mountable\0FlushInterval\0IgnoreFlush\0")) 630 622 #else /* !(VBOX_PERIODIC_FLUSH || VBOX_IGNORE_FLUSH) */ 631 if (!CFGMR3AreValuesValid(pCfgHandle, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0 Translation\0Mountable\0"))623 if (!CFGMR3AreValuesValid(pCfgHandle, "Type\0Locked\0BIOSVisible\0AttachFailError\0Cylinders\0Heads\0Sectors\0Mountable\0")) 632 624 #endif /* !(VBOX_PERIODIC_FLUSH || VBOX_IGNORE_FLUSH) */ 633 625 return VERR_PDM_DRVINS_UNKNOWN_CFG_VALUES; … … 651 643 652 644 /* IBlockBios. */ 653 pData->IBlockBios.pfnGet Geometry = drvblockGetGeometry;654 pData->IBlockBios.pfnSet Geometry = drvblockSetGeometry;655 pData->IBlockBios.pfnGet Translation = drvblockGetTranslation;656 pData->IBlockBios.pfnSet Translation = drvblockSetTranslation;645 pData->IBlockBios.pfnGetPCHSGeometry = drvblockGetPCHSGeometry; 646 pData->IBlockBios.pfnSetPCHSGeometry = drvblockSetPCHSGeometry; 647 pData->IBlockBios.pfnGetLCHSGeometry = drvblockGetLCHSGeometry; 648 pData->IBlockBios.pfnSetLCHSGeometry = drvblockSetLCHSGeometry; 657 649 pData->IBlockBios.pfnIsVisible = drvblockIsVisible; 658 650 pData->IBlockBios.pfnGetType = drvblockBiosGetType; … … 746 738 747 739 /* Cylinders */ 748 rc = CFGMR3QueryU32(pCfgHandle, "Cylinders", &pData-> cCylinders);740 rc = CFGMR3QueryU32(pCfgHandle, "Cylinders", &pData->LCHSGeometry.cCylinders); 749 741 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 750 pData-> cCylinders = 0;742 pData->LCHSGeometry.cCylinders = 0; 751 743 else if (VBOX_FAILURE(rc)) 752 744 { … … 756 748 757 749 /* Heads */ 758 rc = CFGMR3QueryU32(pCfgHandle, "Heads", &pData-> cHeads);750 rc = CFGMR3QueryU32(pCfgHandle, "Heads", &pData->LCHSGeometry.cHeads); 759 751 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 760 pData-> cHeads = 0;752 pData->LCHSGeometry.cHeads = 0; 761 753 else if (VBOX_FAILURE(rc)) 762 754 { … … 766 758 767 759 /* Sectors */ 768 rc = CFGMR3QueryU32(pCfgHandle, "Sectors", &pData-> cSectors);760 rc = CFGMR3QueryU32(pCfgHandle, "Sectors", &pData->LCHSGeometry.cSectors); 769 761 if (rc == VERR_CFGM_VALUE_NOT_FOUND) 770 pData-> cSectors = 0;762 pData->LCHSGeometry.cSectors = 0; 771 763 else if (VBOX_FAILURE(rc)) 772 764 { 773 765 AssertMsgFailed(("Configuration error: Query \"Sectors\" resulted in %Vrc.\n", rc)); 774 766 return rc; 775 }776 777 /* Translation */778 rc = CFGMR3QueryStringAlloc(pCfgHandle, "Translation", &psz);779 if (rc == VERR_CFGM_VALUE_NOT_FOUND)780 {781 pData->enmTranslation = PDMBIOSTRANSLATION_NONE;782 pData->fTranslationSet = false;783 }784 else if (VBOX_SUCCESS(rc))785 {786 if (!strcmp(psz, "None"))787 pData->enmTranslation = PDMBIOSTRANSLATION_NONE;788 else if (!strcmp(psz, "LBA"))789 pData->enmTranslation = PDMBIOSTRANSLATION_LBA;790 else if (!strcmp(psz, "Auto"))791 pData->enmTranslation = PDMBIOSTRANSLATION_AUTO;792 else793 {794 AssertMsgFailed(("Configuration error: Unknown translation \"%s\".\n", psz));795 MMR3HeapFree(psz);796 return VERR_PDM_BLOCK_UNKNOWN_TRANSLATION;797 }798 MMR3HeapFree(psz); psz = NULL;799 pData->fTranslationSet = true;800 }801 else802 {803 AssertMsgFailed(("Configuration error: Failed to obtain the translation, rc=%Vrc.\n", rc));804 return VERR_PDM_BLOCK_NO_TYPE;805 767 } 806 768 -
trunk/src/VBox/Devices/Storage/DrvHostBase.cpp
r5999 r6291 321 321 322 322 323 /** @copydoc PDMIBLOCKBIOS::pfnGet Geometry */324 static DECLCALLBACK(int) drvHostBaseGet Geometry(PPDMIBLOCKBIOS pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)323 /** @copydoc PDMIBLOCKBIOS::pfnGetPCHSGeometry */ 324 static DECLCALLBACK(int) drvHostBaseGetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry) 325 325 { 326 326 PDRVHOSTBASE pThis = PDMIBLOCKBIOS_2_DRVHOSTBASE(pInterface); … … 330 330 if (pThis->fMediaPresent) 331 331 { 332 if ( pThis->cCylinders > 0 333 && pThis->cHeads > 0 334 && pThis->cSectors > 0) 335 { 336 *pcCylinders = pThis->cCylinders; 337 *pcHeads = pThis->cHeads; 338 *pcSectors = pThis->cSectors; 332 if ( pThis->PCHSGeometry.cCylinders > 0 333 && pThis->PCHSGeometry.cHeads > 0 334 && pThis->PCHSGeometry.cSectors > 0) 335 { 336 *pPCHSGeometry = pThis->PCHSGeometry; 339 337 } 340 338 else … … 345 343 346 344 RTCritSectLeave(&pThis->CritSect); 347 LogFlow(("%s-%d: drvHostBaseGetGeometry: returns %Vrc CHS={%d,%d,%d}\n",348 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc, *pcCylinders, *pcHeads, *pcSectors));345 LogFlow(("%s-%d: %s: returns %Vrc CHS={%d,%d,%d}\n", 346 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, rc, pThis->PCHSGeometry.cCylinders, pThis->PCHSGeometry.cHeads, pThis->PCHSGeometry.cSectors)); 349 347 return rc; 350 348 } 351 349 352 350 353 /** @copydoc PDMIBLOCKBIOS::pfnSet Geometry */354 static DECLCALLBACK(int) drvHostBaseSet Geometry(PPDMIBLOCKBIOS pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)351 /** @copydoc PDMIBLOCKBIOS::pfnSetPCHSGeometry */ 352 static DECLCALLBACK(int) drvHostBaseSetPCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry) 355 353 { 356 354 PDRVHOSTBASE pThis = PDMIBLOCKBIOS_2_DRVHOSTBASE(pInterface); 357 LogFlow(("%s-%d: drvHostBaseSetGeometry: cCylinders=%d cHeads=%d cSectors=%d\n",358 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, cCylinders, cHeads,cSectors));355 LogFlow(("%s-%d: %s: cCylinders=%d cHeads=%d cSectors=%d\n", 356 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 359 357 RTCritSectEnter(&pThis->CritSect); 360 358 … … 362 360 if (pThis->fMediaPresent) 363 361 { 364 pThis->cCylinders = cCylinders; 365 pThis->cHeads = cHeads; 366 pThis->cSectors = cSectors; 362 pThis->PCHSGeometry = *pPCHSGeometry; 367 363 } 368 364 else … … 377 373 378 374 379 /** @copydoc PDMIBLOCKBIOS::pfnGet Translation*/380 static DECLCALLBACK(int) drvHostBaseGet Translation(PPDMIBLOCKBIOS pInterface, PPDMBIOSTRANSLATION penmTranslation)381 { 382 PDRVHOSTBASE pThis = PDMIBLOCKBIOS_2_DRVHOSTBASE(pInterface);375 /** @copydoc PDMIBLOCKBIOS::pfnGetLCHSGeometry */ 376 static DECLCALLBACK(int) drvHostBaseGetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry) 377 { 378 PDRVHOSTBASE pThis = PDMIBLOCKBIOS_2_DRVHOSTBASE(pInterface); 383 379 RTCritSectEnter(&pThis->CritSect); 384 380 … … 386 382 if (pThis->fMediaPresent) 387 383 { 388 if (pThis->fTranslationSet) 389 *penmTranslation = pThis->enmTranslation; 384 if ( pThis->LCHSGeometry.cCylinders > 0 385 && pThis->LCHSGeometry.cHeads > 0 386 && pThis->LCHSGeometry.cSectors > 0) 387 { 388 *pLCHSGeometry = pThis->LCHSGeometry; 389 } 390 390 else 391 rc = VERR_PDM_ TRANSLATION_NOT_SET;391 rc = VERR_PDM_GEOMETRY_NOT_SET; 392 392 } 393 393 else … … 395 395 396 396 RTCritSectLeave(&pThis->CritSect); 397 LogFlow(("%s-%d: drvHostBaseGetTranslation: returns %Vrc *penmTranslation=%d\n",398 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, rc, *penmTranslation));397 LogFlow(("%s-%d: %s: returns %Vrc CHS={%d,%d,%d}\n", 398 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, rc, pThis->LCHSGeometry.cCylinders, pThis->LCHSGeometry.cHeads, pThis->LCHSGeometry.cSectors)); 399 399 return rc; 400 400 } 401 401 402 402 403 /** @copydoc PDMIBLOCKBIOS::pfnSet Translation*/404 static DECLCALLBACK(int) drvHostBaseSet Translation(PPDMIBLOCKBIOS pInterface, PDMBIOSTRANSLATION enmTranslation)403 /** @copydoc PDMIBLOCKBIOS::pfnSetLCHSGeometry */ 404 static DECLCALLBACK(int) drvHostBaseSetLCHSGeometry(PPDMIBLOCKBIOS pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry) 405 405 { 406 406 PDRVHOSTBASE pThis = PDMIBLOCKBIOS_2_DRVHOSTBASE(pInterface); 407 LogFlow(("%s-%d: drvHostBaseSetTranslation: enmTranslation=%d\n",408 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, enmTranslation));407 LogFlow(("%s-%d: %s: cCylinders=%d cHeads=%d cSectors=%d\n", 408 pThis->pDrvIns->pDrvReg->szDriverName, pThis->pDrvIns->iInstance, __FUNCTION__, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 409 409 RTCritSectEnter(&pThis->CritSect); 410 410 … … 412 412 if (pThis->fMediaPresent) 413 413 { 414 pThis->fTranslationSet = true; 415 pThis->enmTranslation = enmTranslation; 414 pThis->LCHSGeometry = *pLCHSGeometry; 416 415 } 417 416 else … … 1277 1276 pThis->fMediaPresent = false; 1278 1277 pThis->fLocked = false; 1279 pThis->fTranslationSet = false; 1280 pThis->cSectors = 0; 1278 pThis->PCHSGeometry.cCylinders = 0; 1279 pThis->PCHSGeometry.cHeads = 0; 1280 pThis->PCHSGeometry.cSectors = 0; 1281 pThis->LCHSGeometry.cCylinders = 0; 1282 pThis->LCHSGeometry.cHeads = 0; 1283 pThis->LCHSGeometry.cSectors = 0; 1281 1284 if (pThis->pDrvMountNotify) 1282 1285 pThis->pDrvMountNotify->pfnUnmountNotify(pThis->pDrvMountNotify); … … 1701 1704 1702 1705 /* IBlockBios. */ 1703 pThis->IBlockBios.pfnGet Geometry = drvHostBaseGetGeometry;1704 pThis->IBlockBios.pfnSet Geometry = drvHostBaseSetGeometry;1705 pThis->IBlockBios.pfnGet Translation = drvHostBaseGetTranslation;1706 pThis->IBlockBios.pfnSet Translation = drvHostBaseSetTranslation;1706 pThis->IBlockBios.pfnGetPCHSGeometry = drvHostBaseGetPCHSGeometry; 1707 pThis->IBlockBios.pfnSetPCHSGeometry = drvHostBaseSetPCHSGeometry; 1708 pThis->IBlockBios.pfnGetLCHSGeometry = drvHostBaseGetLCHSGeometry; 1709 pThis->IBlockBios.pfnSetLCHSGeometry = drvHostBaseSetLCHSGeometry; 1707 1710 pThis->IBlockBios.pfnIsVisible = drvHostBaseIsVisible; 1708 1711 pThis->IBlockBios.pfnGetType = drvHostBaseBiosGetType; -
trunk/src/VBox/Devices/Storage/DrvHostBase.h
r5999 r6291 97 97 bool volatile fShutdownPoller; 98 98 99 /** Whether or not enmTranslation is valid. */ 100 bool fTranslationSet; 101 /** BIOS Geometry: Translation mode. */ 102 PDMBIOSTRANSLATION enmTranslation; 103 /** BIOS Geometry: Cylinders. */ 104 uint32_t cCylinders; 105 /** BIOS Geometry: Heads. */ 106 uint32_t cHeads; 107 /** BIOS Geometry: Sectors. */ 108 uint32_t cSectors; 99 /** BIOS PCHS geometry. */ 100 PDMMEDIAGEOMETRY PCHSGeometry; 101 /** BIOS LCHS geometry. */ 102 PDMMEDIAGEOMETRY LCHSGeometry; 109 103 110 104 /** The number of errors that could go into the release log. (flood gate) */ -
trunk/src/VBox/Devices/Storage/DrvMediaISO.cpp
r5999 r6291 73 73 static DECLCALLBACK(uint64_t) drvMediaISOGetSize(PPDMIMEDIA pInterface); 74 74 static DECLCALLBACK(int) drvMediaISOGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid); 75 static DECLCALLBACK(int) drvMediaISOBiosGet Geometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors);76 static DECLCALLBACK(int) drvMediaISOBiosSet Geometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors);77 static DECLCALLBACK(int) drvMediaISOBiosGet Translation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation);78 static DECLCALLBACK(int) drvMediaISOBiosSet Translation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation);75 static DECLCALLBACK(int) drvMediaISOBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry); 76 static DECLCALLBACK(int) drvMediaISOBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry); 77 static DECLCALLBACK(int) drvMediaISOBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry); 78 static DECLCALLBACK(int) drvMediaISOBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry); 79 79 80 80 static DECLCALLBACK(void *) drvMediaISOQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface); … … 111 111 pData->IMedia.pfnGetUuid = drvMediaISOGetUuid; 112 112 pData->IMedia.pfnIsReadOnly = drvMediaISOIsReadOnly; 113 pData->IMedia.pfnBiosGet Geometry = drvMediaISOBiosGetGeometry;114 pData->IMedia.pfnBiosSet Geometry = drvMediaISOBiosSetGeometry;115 pData->IMedia.pfnBiosGet Translation = drvMediaISOBiosGetTranslation;116 pData->IMedia.pfnBiosSet Translation = drvMediaISOBiosSetTranslation;113 pData->IMedia.pfnBiosGetPCHSGeometry = drvMediaISOBiosGetPCHSGeometry; 114 pData->IMedia.pfnBiosSetPCHSGeometry = drvMediaISOBiosSetPCHSGeometry; 115 pData->IMedia.pfnBiosGetLCHSGeometry = drvMediaISOBiosGetLCHSGeometry; 116 pData->IMedia.pfnBiosSetLCHSGeometry = drvMediaISOBiosSetLCHSGeometry; 117 117 118 118 /* … … 192 192 193 193 194 /** @copydoc PDMIMEDIA::pfnBiosGetGeometry */ 195 static DECLCALLBACK(int) drvMediaISOBiosGetGeometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors) 196 { 197 return VERR_NOT_IMPLEMENTED; 198 } 199 200 201 /** @copydoc PDMIMEDIA::pfnBiosSetGeometry */ 202 static DECLCALLBACK(int) drvMediaISOBiosSetGeometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors) 194 /** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */ 195 static DECLCALLBACK(int) drvMediaISOBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry) 196 { 197 return VERR_NOT_IMPLEMENTED; 198 } 199 200 201 /** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */ 202 static DECLCALLBACK(int) drvMediaISOBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry) 203 { 204 return VERR_NOT_IMPLEMENTED; 205 } 206 207 208 /** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */ 209 static DECLCALLBACK(int) drvMediaISOBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry) 210 { 211 return VERR_NOT_IMPLEMENTED; 212 } 213 214 215 /** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */ 216 static DECLCALLBACK(int) drvMediaISOBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry) 203 217 { 204 218 return VERR_NOT_IMPLEMENTED; … … 272 286 { 273 287 return true; 274 }275 276 277 /**278 * Stub - operation not supported.279 *280 * @copydoc PDMIMEDIA::pfnBiosGetTranslation281 */282 static DECLCALLBACK(int) drvMediaISOBiosGetTranslation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation)283 {284 NOREF(pInterface); NOREF(penmTranslation);285 return VERR_NOT_IMPLEMENTED;286 }287 288 289 /**290 * Stub - operation not supported.291 *292 * @copydoc PDMIMEDIA::pfnBiosSetTranslation293 */294 static DECLCALLBACK(int) drvMediaISOBiosSetTranslation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation)295 {296 NOREF(pInterface); NOREF(enmTranslation);297 return VERR_NOT_IMPLEMENTED;298 288 } 299 289 -
trunk/src/VBox/Devices/Storage/DrvRawImage.cpp
r6198 r6291 76 76 static DECLCALLBACK(uint64_t) drvRawImageGetSize(PPDMIMEDIA pInterface); 77 77 static DECLCALLBACK(int) drvRawImageGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid); 78 static DECLCALLBACK(int) drvRawImageBiosGet Geometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors);79 static DECLCALLBACK(int) drvRawImageBiosSet Geometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors);80 static DECLCALLBACK(int) drvRawImageBiosGet Translation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation);81 static DECLCALLBACK(int) drvRawImageBiosSet Translation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation);78 static DECLCALLBACK(int) drvRawImageBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry); 79 static DECLCALLBACK(int) drvRawImageBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry); 80 static DECLCALLBACK(int) drvRawImageBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry); 81 static DECLCALLBACK(int) drvRawImageBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry); 82 82 83 83 static DECLCALLBACK(void *) drvRawImageQueryInterface(PPDMIBASE pInterface, PDMINTERFACE enmInterface); … … 114 114 pData->IMedia.pfnGetUuid = drvRawImageGetUuid; 115 115 pData->IMedia.pfnIsReadOnly = drvRawImageIsReadOnly; 116 pData->IMedia.pfnBiosGet Geometry = drvRawImageBiosGetGeometry;117 pData->IMedia.pfnBiosSet Geometry = drvRawImageBiosSetGeometry;118 pData->IMedia.pfnBiosGet Translation = drvRawImageBiosGetTranslation;119 pData->IMedia.pfnBiosSet Translation = drvRawImageBiosSetTranslation;116 pData->IMedia.pfnBiosGetPCHSGeometry = drvRawImageBiosGetPCHSGeometry; 117 pData->IMedia.pfnBiosSetPCHSGeometry = drvRawImageBiosSetPCHSGeometry; 118 pData->IMedia.pfnBiosGetLCHSGeometry = drvRawImageBiosGetLCHSGeometry; 119 pData->IMedia.pfnBiosSetLCHSGeometry = drvRawImageBiosSetLCHSGeometry; 120 120 121 121 /* … … 207 207 208 208 209 /** @copydoc PDMIMEDIA::pfnBiosGet Geometry */210 static DECLCALLBACK(int) drvRawImageBiosGet Geometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors)209 /** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */ 210 static DECLCALLBACK(int) drvRawImageBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry) 211 211 { 212 212 return VERR_NOT_IMPLEMENTED; … … 214 214 215 215 216 /** @copydoc PDMIMEDIA::pfnBiosSetGeometry */ 217 static DECLCALLBACK(int) drvRawImageBiosSetGeometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors) 216 /** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */ 217 static DECLCALLBACK(int) drvRawImageBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry) 218 { 219 return VERR_NOT_IMPLEMENTED; 220 } 221 222 223 /** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */ 224 static DECLCALLBACK(int) drvRawImageBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry) 225 { 226 return VERR_NOT_IMPLEMENTED; 227 } 228 229 230 /** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */ 231 static DECLCALLBACK(int) drvRawImageBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry) 218 232 { 219 233 return VERR_NOT_IMPLEMENTED; … … 319 333 PDRVRAWIMAGE pData = PDMIMEDIA_2_DRVRAWIMAGE(pInterface); 320 334 return pData->fReadOnly; 321 }322 323 324 /**325 * Stub - operation not supported.326 *327 * @copydoc PDMIMEDIA::pfnBiosGetTranslation328 */329 static DECLCALLBACK(int) drvRawImageBiosGetTranslation(PPDMIMEDIA pInterface, PPDMBIOSTRANSLATION penmTranslation)330 {331 NOREF(pInterface); NOREF(penmTranslation);332 return VERR_NOT_IMPLEMENTED;333 }334 335 336 /**337 * Stub - operation not supported.338 *339 * @copydoc PDMIMEDIA::pfnBiosSetTranslation340 */341 static DECLCALLBACK(int) drvRawImageBiosSetTranslation(PPDMIMEDIA pInterface, PDMBIOSTRANSLATION enmTranslation)342 {343 NOREF(pInterface); NOREF(enmTranslation);344 return VERR_NOT_IMPLEMENTED;345 335 } 346 336 -
trunk/src/VBox/Devices/Storage/DrvVD.cpp
r5999 r6291 7 7 8 8 /* 9 * Copyright (C) 2006-200 7innotek GmbH9 * Copyright (C) 2006-2008 innotek GmbH 10 10 * 11 11 * This file is part of VirtualBox Open Source Edition (OSE), as … … 72 72 *******************************************************************************/ 73 73 74 static void vdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL, const char *pszFormat, va_list va) 74 static void drvvdErrorCallback(void *pvUser, int rc, RT_SRC_POS_DECL, 75 const char *pszFormat, va_list va) 75 76 { 76 77 PPDMDRVINS pDrvIns = (PPDMDRVINS)pvUser; … … 83 84 84 85 /** @copydoc PDMIMEDIA::pfnRead */ 85 static DECLCALLBACK(int) vdRead(PPDMIMEDIA pInterface,86 uint64_t off, void *pvBuf, size_t cbRead)86 static DECLCALLBACK(int) drvvdRead(PPDMIMEDIA pInterface, 87 uint64_t off, void *pvBuf, size_t cbRead) 87 88 { 88 89 LogFlow(("%s: off=%#llx pvBuf=%p cbRead=%d\n", __FUNCTION__, … … 98 99 99 100 /** @copydoc PDMIMEDIA::pfnWrite */ 100 static DECLCALLBACK(int) vdWrite(PPDMIMEDIA pInterface,101 uint64_t off, const void *pvBuf,102 size_t cbWrite)101 static DECLCALLBACK(int) drvvdWrite(PPDMIMEDIA pInterface, 102 uint64_t off, const void *pvBuf, 103 size_t cbWrite) 103 104 { 104 105 LogFlow(("%s: off=%#llx pvBuf=%p cbWrite=%d\n", __FUNCTION__, … … 113 114 114 115 /** @copydoc PDMIMEDIA::pfnFlush */ 115 static DECLCALLBACK(int) vdFlush(PPDMIMEDIA pInterface)116 static DECLCALLBACK(int) drvvdFlush(PPDMIMEDIA pInterface) 116 117 { 117 118 LogFlow(("%s:\n", __FUNCTION__)); … … 123 124 124 125 /** @copydoc PDMIMEDIA::pfnGetSize */ 125 static DECLCALLBACK(uint64_t) vdGetSize(PPDMIMEDIA pInterface)126 { 127 LogFlow(("%s:\n", __FUNCTION__)); 128 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 129 uint64_t cb = VDGetSize(pData->pDisk );126 static DECLCALLBACK(uint64_t) drvvdGetSize(PPDMIMEDIA pInterface) 127 { 128 LogFlow(("%s:\n", __FUNCTION__)); 129 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 130 uint64_t cb = VDGetSize(pData->pDisk, VD_LAST_IMAGE); 130 131 LogFlow(("%s: returns %#llx (%llu)\n", __FUNCTION__, cb, cb)); 131 132 return cb; … … 133 134 134 135 /** @copydoc PDMIMEDIA::pfnIsReadOnly */ 135 static DECLCALLBACK(bool) vdIsReadOnly(PPDMIMEDIA pInterface)136 static DECLCALLBACK(bool) drvvdIsReadOnly(PPDMIMEDIA pInterface) 136 137 { 137 138 LogFlow(("%s:\n", __FUNCTION__)); … … 142 143 } 143 144 144 /** @copydoc PDMIMEDIA::pfnBiosGetGeometry */ 145 static DECLCALLBACK(int) vdBiosGetGeometry(PPDMIMEDIA pInterface, 146 uint32_t *pcCylinders, 147 uint32_t *pcHeads, 148 uint32_t *pcSectors) 149 { 150 LogFlow(("%s:\n", __FUNCTION__)); 151 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 152 int rc = VDGetGeometry(pData->pDisk, pcCylinders, pcHeads, pcSectors); 145 /** @copydoc PDMIMEDIA::pfnBiosGetPCHSGeometry */ 146 static DECLCALLBACK(int) drvvdBiosGetPCHSGeometry(PPDMIMEDIA pInterface, 147 PPDMMEDIAGEOMETRY pPCHSGeometry) 148 { 149 LogFlow(("%s:\n", __FUNCTION__)); 150 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 151 int rc = VDGetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry); 153 152 if (VBOX_FAILURE(rc)) 154 153 { … … 157 156 } 158 157 LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__, 159 rc, *pcCylinders, *pcHeads, *pcSectors)); 160 return rc; 161 } 162 163 /** @copydoc PDMIMEDIA::pfnBiosSetGeometry */ 164 static DECLCALLBACK(int) vdBiosSetGeometry(PPDMIMEDIA pInterface, 165 uint32_t cCylinders, 166 uint32_t cHeads, 167 uint32_t cSectors) 158 rc, pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 159 return rc; 160 } 161 162 /** @copydoc PDMIMEDIA::pfnBiosSetPCHSGeometry */ 163 static DECLCALLBACK(int) drvvdBiosSetPCHSGeometry(PPDMIMEDIA pInterface, 164 PCPDMMEDIAGEOMETRY pPCHSGeometry) 168 165 { 169 166 LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__, 170 cCylinders, cHeads,cSectors));171 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 172 int rc = VDSet Geometry(pData->pDisk, cCylinders, cHeads, cSectors);167 pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 168 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 169 int rc = VDSetPCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pPCHSGeometry); 173 170 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 174 171 return rc; 175 172 } 176 173 177 /** @copydoc PDMIMEDIA::pfnBiosGetTranslation */ 178 static DECLCALLBACK(int) vdBiosGetTranslation(PPDMIMEDIA pInterface, 179 PPDMBIOSTRANSLATION penmTranslation) 180 { 181 LogFlow(("%s:\n", __FUNCTION__)); 182 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 183 int rc = VDGetTranslation(pData->pDisk, penmTranslation); 184 LogFlow(("%s: returns %Vrc (%d)\n", __FUNCTION__, rc, *penmTranslation)); 185 return rc; 186 } 187 188 /** @copydoc PDMIMEDIA::pfnBiosSetTranslation */ 189 static DECLCALLBACK(int) vdBiosSetTranslation(PPDMIMEDIA pInterface, 190 PDMBIOSTRANSLATION enmTranslation) 191 { 192 LogFlow(("%s:\n", __FUNCTION__)); 193 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 194 int rc = VDSetTranslation(pData->pDisk, enmTranslation); 195 LogFlow(("%s: returns %Vrc (%d)\n", __FUNCTION__, rc, enmTranslation)); 174 /** @copydoc PDMIMEDIA::pfnBiosGetLCHSGeometry */ 175 static DECLCALLBACK(int) drvvdBiosGetLCHSGeometry(PPDMIMEDIA pInterface, 176 PPDMMEDIAGEOMETRY pLCHSGeometry) 177 { 178 LogFlow(("%s:\n", __FUNCTION__)); 179 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 180 int rc = VDGetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry); 181 if (VBOX_FAILURE(rc)) 182 { 183 Log(("%s: geometry not available.\n", __FUNCTION__)); 184 rc = VERR_PDM_GEOMETRY_NOT_SET; 185 } 186 LogFlow(("%s: returns %Vrc (CHS=%d/%d/%d)\n", __FUNCTION__, 187 rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 188 return rc; 189 } 190 191 /** @copydoc PDMIMEDIA::pfnBiosSetLCHSGeometry */ 192 static DECLCALLBACK(int) drvvdBiosSetLCHSGeometry(PPDMIMEDIA pInterface, 193 PCPDMMEDIAGEOMETRY pLCHSGeometry) 194 { 195 LogFlow(("%s: CHS=%d/%d/%d\n", __FUNCTION__, 196 pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 197 PVBOXDISK pData = PDMIMEDIA_2_VBOXDISK(pInterface); 198 int rc = VDSetLCHSGeometry(pData->pDisk, VD_LAST_IMAGE, pLCHSGeometry); 199 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 196 200 return rc; 197 201 } 198 202 199 203 /** @copydoc PDMIMEDIA::pfnGetUuid */ 200 static DECLCALLBACK(int) vdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid)204 static DECLCALLBACK(int) drvvdGetUuid(PPDMIMEDIA pInterface, PRTUUID pUuid) 201 205 { 202 206 LogFlow(("%s:\n", __FUNCTION__)); … … 213 217 214 218 /** @copydoc PDMIBASE::pfnQueryInterface */ 215 static DECLCALLBACK(void *) vdQueryInterface(PPDMIBASE pInterface,216 PDMINTERFACE enmInterface)219 static DECLCALLBACK(void *) drvvdQueryInterface(PPDMIBASE pInterface, 220 PDMINTERFACE enmInterface) 217 221 { 218 222 PPDMDRVINS pDrvIns = PDMIBASE_2_DRVINS(pInterface); … … 245 249 * to be used frequently in this function. 246 250 */ 247 static DECLCALLBACK(int) vdConstruct(PPDMDRVINS pDrvIns, PCFGMNODE pCfgHandle) 251 static DECLCALLBACK(int) drvvdConstruct(PPDMDRVINS pDrvIns, 252 PCFGMNODE pCfgHandle) 248 253 { 249 254 LogFlow(("%s:\n", __FUNCTION__)); … … 257 262 * Init the static parts. 258 263 */ 259 pDrvIns->IBase.pfnQueryInterface = vdQueryInterface;264 pDrvIns->IBase.pfnQueryInterface = drvvdQueryInterface; 260 265 pData->pDrvIns = pDrvIns; 261 266 pData->fTempReadOnly = false; 262 267 263 268 /* IMedia */ 264 pData->IMedia.pfnRead = vdRead;265 pData->IMedia.pfnWrite = vdWrite;266 pData->IMedia.pfnFlush = vdFlush;267 pData->IMedia.pfnGetSize = vdGetSize;268 pData->IMedia.pfnIsReadOnly = vdIsReadOnly;269 pData->IMedia.pfnBiosGet Geometry = vdBiosGetGeometry;270 pData->IMedia.pfnBiosSet Geometry = vdBiosSetGeometry;271 pData->IMedia.pfnBiosGet Translation = vdBiosGetTranslation;272 pData->IMedia.pfnBiosSet Translation = vdBiosSetTranslation;273 pData->IMedia.pfnGetUuid = vdGetUuid;269 pData->IMedia.pfnRead = drvvdRead; 270 pData->IMedia.pfnWrite = drvvdWrite; 271 pData->IMedia.pfnFlush = drvvdFlush; 272 pData->IMedia.pfnGetSize = drvvdGetSize; 273 pData->IMedia.pfnIsReadOnly = drvvdIsReadOnly; 274 pData->IMedia.pfnBiosGetPCHSGeometry = drvvdBiosGetPCHSGeometry; 275 pData->IMedia.pfnBiosSetPCHSGeometry = drvvdBiosSetPCHSGeometry; 276 pData->IMedia.pfnBiosGetLCHSGeometry = drvvdBiosGetLCHSGeometry; 277 pData->IMedia.pfnBiosSetLCHSGeometry = drvvdBiosSetLCHSGeometry; 278 pData->IMedia.pfnGetUuid = drvvdGetUuid; 274 279 275 280 /* … … 326 331 if (VBOX_SUCCESS(rc)) 327 332 { 328 rc = VDCreate(pData->szFormat, vdErrorCallback, pDrvIns, &pData->pDisk);333 rc = VDCreate(pData->szFormat, drvvdErrorCallback, pDrvIns, &pData->pDisk); 329 334 /* Error message is already set correctly. */ 330 335 } … … 420 425 * @param pDrvIns The driver instance data. 421 426 */ 422 static DECLCALLBACK(void) vdDestruct(PPDMDRVINS pDrvIns)427 static DECLCALLBACK(void) drvvdDestruct(PPDMDRVINS pDrvIns) 423 428 { 424 429 LogFlow(("%s:\n", __FUNCTION__)); … … 436 441 * @param pDrvIns The driver instance data. 437 442 */ 438 static DECLCALLBACK(void) vdSuspend(PPDMDRVINS pDrvIns)443 static DECLCALLBACK(void) drvvdSuspend(PPDMDRVINS pDrvIns) 439 444 { 440 445 LogFlow(("%s:\n", __FUNCTION__)); … … 443 448 { 444 449 unsigned uOpenFlags; 445 int rc = VDGetOpenFlags(pData->pDisk, &uOpenFlags);450 int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags); 446 451 AssertRC(rc); 447 452 uOpenFlags |= VD_OPEN_FLAGS_READONLY; 448 rc = VDSetOpenFlags(pData->pDisk, uOpenFlags);453 rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags); 449 454 AssertRC(rc); 450 455 pData->fTempReadOnly = true; … … 454 459 /** 455 460 * Before the VM resumes we'll have to undo the read-only mode change 456 * done in vdSuspend.461 * done in drvvdSuspend. 457 462 * 458 463 * @param pDrvIns The driver instance data. 459 464 */ 460 static DECLCALLBACK(void) vdResume(PPDMDRVINS pDrvIns)465 static DECLCALLBACK(void) drvvdResume(PPDMDRVINS pDrvIns) 461 466 { 462 467 LogFlow(("%s:\n", __FUNCTION__)); … … 465 470 { 466 471 unsigned uOpenFlags; 467 int rc = VDGetOpenFlags(pData->pDisk, &uOpenFlags);472 int rc = VDGetOpenFlags(pData->pDisk, VD_LAST_IMAGE, &uOpenFlags); 468 473 AssertRC(rc); 469 474 uOpenFlags &= ~VD_OPEN_FLAGS_READONLY; 470 rc = VDSetOpenFlags(pData->pDisk, uOpenFlags);475 rc = VDSetOpenFlags(pData->pDisk, VD_LAST_IMAGE, uOpenFlags); 471 476 AssertRC(rc); 472 477 pData->fTempReadOnly = false; … … 484 489 PDM_DRVREG_VERSION, 485 490 /* szDriverName */ 486 " VD",491 "DrvVD", 487 492 /* pszDescription */ 488 493 "Generic VBox disk media driver.", … … 496 501 sizeof(VBOXDISK), 497 502 /* pfnConstruct */ 498 vdConstruct,503 drvvdConstruct, 499 504 /* pfnDestruct */ 500 vdDestruct,505 drvvdDestruct, 501 506 /* pfnIOCtl */ 502 507 NULL, … … 506 511 NULL, 507 512 /* pfnSuspend */ 508 vdSuspend,513 drvvdSuspend, 509 514 /* pfnResume */ 510 vdResume,515 drvvdResume, 511 516 /* pfnDetach */ 512 517 NULL -
trunk/src/VBox/Devices/Storage/VBoxHDD-new.cpp
-
Property svn:eol-style
set to
native
-
Property svn:keywords
set to
Author Date Id Revision
r6204 r6291 5 5 6 6 /* 7 * Copyright (C) 2006-200 7innotek GmbH7 * Copyright (C) 2006-2008 innotek GmbH 8 8 * 9 9 * This file is part of VirtualBox Open Source Edition (OSE), as … … 33 33 #include <iprt/dir.h> 34 34 #include <iprt/path.h> 35 #include <iprt/param.h> 35 36 36 37 #include "VBoxHDD-newInternal.h" … … 39 40 #define VBOXHDDDISK_SIGNATURE 0x6f0e2a7d 40 41 42 /** Buffer size used for merging images. */ 43 #define VD_MERGE_BUFFER_SIZE (1024 * 1024) 41 44 42 45 /** … … 89 92 /** Cached size of this disk. */ 90 93 uint64_t cbSize; 91 /** Cached CHS geometry for this disk, cylinders. */ 92 unsigned cCylinders; 93 /** Cached CHS geometry for this disk, heads. */ 94 unsigned cHeads; 95 /** Cached CHS geometry for this disk, sectors. */ 96 unsigned cSectors; 97 /** Cached translation mode for this disk. */ 98 PDMBIOSTRANSLATION enmTranslation; 94 /** Cached PCHS geometry for this disk. */ 95 PDMMEDIAGEOMETRY PCHSGeometry; 96 /** Cached LCHS geometry for this disk. */ 97 PDMMEDIAGEOMETRY LCHSGeometry; 99 98 100 99 /** Error message processing callback. */ … … 106 105 RTLDRMOD hPlugin; 107 106 /** Function pointers for the various backend methods. */ 108 P VBOXHDDBACKENDBackend;107 PCVBOXHDDBACKEND Backend; 109 108 }; 110 111 112 typedef struct113 {114 const char *pszBackendName;115 PVBOXHDDBACKEND Backend;116 } VBOXHDDBACKENDENTRY;117 109 118 110 … … 122 114 #endif 123 115 124 static const VBOXHDDBACKENDENTRY aBackends[] = 125 { 126 { "VMDK", &g_VmdkBackend }, 127 #ifndef VBOX_OSE 128 { "VHD", &g_VhdBackend}, 129 #endif 130 { NULL, NULL } 116 static PCVBOXHDDBACKEND aBackends[] = 117 { 118 { &g_VmdkBackend }, 119 { &g_VhdBackend}, 120 { NULL } 131 121 }; 132 122 … … 214 204 { 215 205 PVDIMAGE pImage = pDisk->pBase; 206 if (nImage == VD_LAST_IMAGE) 207 return pDisk->pLast; 216 208 while (pImage && nImage) 217 209 { … … 231 223 int rc; 232 224 size_t cbThisRead; 233 PVDIMAGE pCurrImage;234 225 235 226 /* Loop until all read. */ … … 241 232 cbThisRead = cbRead; 242 233 rc = VINF_VDI_BLOCK_FREE; 243 for ( pCurrImage = pImage;234 for (PVDIMAGE pCurrImage = pImage; 244 235 pCurrImage != NULL && rc == VINF_VDI_BLOCK_FREE; 245 236 pCurrImage = pCurrImage->pPrev) … … 320 311 if (cbPreRead) 321 312 { 322 rc = vdReadHelper(pDisk, pImage->pPrev, uOffset - cbPreRead, 323 pvTmp,cbPreRead);313 rc = vdReadHelper(pDisk, pImage->pPrev, uOffset - cbPreRead, pvTmp, 314 cbPreRead); 324 315 if (VBOX_FAILURE(rc)) 325 316 return rc; … … 417 408 /* Read the entire data of the block so that we can compare whether it will 418 409 * be modified by the write or not. */ 419 rc = vdReadHelper(pDisk, pImage->pPrev, uOffset - cbPreRead, 420 pvTmp,cbPreRead + cbThisWrite + cbPostRead - cbFill);410 rc = vdReadHelper(pDisk, pImage->pPrev, uOffset - cbPreRead, pvTmp, 411 cbPreRead + cbThisWrite + cbPostRead - cbFill); 421 412 if (VBOX_FAILURE(rc)) 422 413 return rc; … … 462 453 463 454 /** 464 * Allocates and initializes an empty VBox HDD container. 455 * internal: write buffer to the image, taking care of block boundaries and 456 * write optimizations. 457 */ 458 static int vdWriteHelper(PVBOXHDD pDisk, PVDIMAGE pImage, uint64_t uOffset, 459 const void *pvBuf, size_t cbWrite) 460 { 461 int rc; 462 size_t cbThisWrite; 463 size_t cbPreRead, cbPostRead; 464 465 /* Loop until all written. */ 466 do 467 { 468 /* Try to write the possibly partial block to the last opened image. 469 * This works when the block is already allocated in this image or 470 * if it is a full-block write, which automatically allocates a new 471 * block if needed. */ 472 cbThisWrite = cbWrite; 473 rc = pDisk->Backend->pfnWrite(pImage->pvBackendData, uOffset, pvBuf, 474 cbThisWrite, &cbThisWrite, &cbPreRead, 475 &cbPostRead); 476 if (rc == VINF_VDI_BLOCK_FREE) 477 { 478 void *pvTmp = RTMemTmpAlloc(cbPreRead + cbThisWrite + cbPostRead); 479 AssertBreak(!pvTmp, rc = VERR_NO_MEMORY); 480 481 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME)) 482 { 483 /* Optimized write, suppress writing to a so far unallocated 484 * block if the data is in fact not changed. */ 485 rc = vdWriteHelperOptimized(pDisk, pImage, uOffset, cbWrite, 486 cbThisWrite, cbPreRead, cbPostRead, 487 pvBuf, pvTmp); 488 } 489 else 490 { 491 /* Normal write, not optimized in any way. The block will 492 * be written no matter what. This will usually (unless the 493 * backend has some further optimization enabled) cause the 494 * block to be allocated. */ 495 rc = vdWriteHelperStandard(pDisk, pImage, uOffset, cbWrite, 496 cbThisWrite, cbPreRead, cbPostRead, 497 pvBuf, pvTmp); 498 } 499 RTMemTmpFree(pvTmp); 500 if (VBOX_FAILURE(rc)) 501 break; 502 } 503 504 cbWrite -= cbThisWrite; 505 uOffset += cbThisWrite; 506 pvBuf = (char *)pvBuf + cbThisWrite; 507 } while (cbWrite != 0 && VBOX_SUCCESS(rc)); 508 509 return rc; 510 } 511 512 513 /** 514 * Allocates and initializes an empty HDD container. 465 515 * No image files are opened. 466 516 * … … 469 519 * @param pfnError Callback for setting extended error information. 470 520 * @param pvErrorUser Opaque parameter for pfnError. 471 * @param ppDisk Where to store the reference to the VBoxHDD container.521 * @param ppDisk Where to store the reference to HDD container. 472 522 */ 473 523 VBOXDDU_DECL(int) VDCreate(const char *pszBackend, PFNVDERROR pfnError, … … 475 525 { 476 526 int rc = VINF_SUCCESS; 477 P VBOXHDDBACKEND pBackend = NULL;527 PCVBOXHDDBACKEND pBackend = NULL; 478 528 PVBOXHDD pDisk = NULL; 479 480 /* Passing an error callback is strictly not necessary any more. Any code 481 * calling the HDD container functions should provide one, as otherwise 482 * many detailed error messages will go unnoticed. If you find a situation 483 * where you get no sensible error message from this code but you think 484 * there should be one, shout loudly. There are no error messages for rare 485 * and obvious error codes such as VERR_NO_MEMORY, and for situations which 486 * the user cannot be made responsible for, such as program bugs causing 487 * parameter checks to fail etc. */ 488 Assert(pfnError); 489 490 /* Find backend. */ 491 for (unsigned i = 0; aBackends[i].pszBackendName != NULL; i++) 492 { 493 if (!strcmp(pszBackend, aBackends[i].pszBackendName)) 494 { 495 pBackend = aBackends[i].Backend; 496 break; 497 } 498 } 499 500 /* If no static backend is found try loading a shared module with pszBackend as filename. */ 501 if (!pBackend) 502 { 503 RTLDRMOD hPlugin; 504 char *pszPluginName; 505 int cbPluginName; 506 507 /* HDD Format Plugins have VBoxHDD as prefix, thatswhy we have to prepend it. 508 * @todo: find out what to do if filenames are case sensitive. 509 */ 510 cbPluginName = RTStrAPrintf(&pszPluginName, "%s%s", VBOX_HDDFORMAT_PLUGIN_PREFIX, pszBackend); 511 if (cbPluginName == -1) 512 { 513 rc = VERR_NO_MEMORY; 514 } 515 else 516 { 517 /* Try to load the plugin (RTLdrLoad appends the suffix for the shared object/DLL). */ 529 RTLDRMOD hPlugin = NULL; 530 531 LogFlowFunc(("pszBackend=\"%s\" pfnError=%#p pvErrorUser=%#p\n", 532 pszBackend, pfnError, pvErrorUser)); 533 do 534 { 535 /* Check arguments. */ 536 AssertMsgBreak(VALID_PTR(pszBackend) && *pszBackend, 537 ("pszBackend=%#p \"%s\"\n", pszBackend, pszBackend), 538 rc = VERR_INVALID_PARAMETER); 539 AssertMsgBreak(VALID_PTR(pfnError), 540 ("pfnError=%#p\n", pfnError), 541 rc = VERR_INVALID_PARAMETER); 542 AssertMsgBreak(VALID_PTR(ppDisk), 543 ("ppDisk=%#p\n", ppDisk), 544 rc = VERR_INVALID_PARAMETER); 545 546 /* Find backend. */ 547 for (unsigned i = 0; aBackends[i] != NULL; i++) 548 { 549 if (!strcmp(pszBackend, aBackends[i]->pszBackendName)) 550 { 551 pBackend = aBackends[i]; 552 break; 553 } 554 } 555 556 /* If no static backend is found try loading a shared module with 557 * pszBackend as filename. */ 558 if (!pBackend) 559 { 560 char *pszPluginName; 561 562 /* HDD Format Plugins have VBoxHDD as prefix, prepend it. */ 563 RTStrAPrintf(&pszPluginName, "%s%s", 564 VBOX_HDDFORMAT_PLUGIN_PREFIX, pszBackend); 565 if (!pszPluginName) 566 { 567 rc = VERR_NO_MEMORY; 568 break; 569 } 570 571 /* Try to load the plugin (RTldrLoad takes care of the suffix). */ 518 572 rc = RTLdrLoad(pszPluginName, &hPlugin); 519 573 if (VBOX_SUCCESS(rc)) … … 521 575 PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad; 522 576 523 rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad); 577 rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, 578 (void**)&pfnHDDFormatLoad); 579 if (VBOX_FAILURE(rc) || !pfnHDDFormatLoad) 580 { 581 LogFunc(("error resolving the entry point %s in plugin %s, rc=%Vrc, pfnHDDFormat=%#p\n", VBOX_HDDFORMAT_LOAD_NAME, pszPluginName, rc, pfnHDDFormatLoad)); 582 if (VBOX_SUCCESS(rc)) 583 rc = VERR_SYMBOL_NOT_FOUND; 584 break; 585 } 586 587 /* Get the function table. */ 588 PVBOXHDDBACKEND pBE; 589 rc = pfnHDDFormatLoad(&pBE); 524 590 if (VBOX_FAILURE(rc)) 591 break; 592 /* Check if the sizes match. If not this plugin is too old. */ 593 if (pBE->cbSize != sizeof(VBOXHDDBACKEND)) 525 594 { 526 Log(("%s: Error resolving the entry point %s, rc = %d, pfnHDDFormat = %p\n", VBOX_HDDFORMAT_LOAD_NAME, rc, pfnHDDFormatLoad)); 527 if (VBOX_SUCCESS(rc)) 528 rc = VERR_SYMBOL_NOT_FOUND; 595 rc = VERR_VDI_UNSUPPORTED_VERSION; 596 break; 529 597 } 530 else 531 { 532 /* Get the function table. */ 533 rc = pfnHDDFormatLoad(&pBackend); 534 if (VBOX_FAILURE(rc)) 535 pBackend = NULL; 536 537 /* 538 * Check if the sizes match. 539 * If not this plugin is too old to load. 540 */ 541 if (pBackend->cbSize != sizeof(VBOXHDDBACKEND)) 542 { 543 rc = VERR_VDI_UNSUPPORTED_VERSION; 544 pBackend = NULL; 545 RTLdrClose(hPlugin); 546 } 547 } 598 pBackend = pBE; 548 599 } 600 549 601 RTStrFree(pszPluginName); 550 602 } 551 } 552 553 if (pBackend) 554 { 555 pDisk = (PVBOXHDD)RTMemAllocZ(sizeof(VBOXHDD)); 603 604 if (pBackend) 605 { 606 pDisk = (PVBOXHDD)RTMemAllocZ(sizeof(VBOXHDD)); 607 if (pDisk) 608 { 609 pDisk->u32Signature = VBOXHDDDISK_SIGNATURE; 610 pDisk->cImages = 0; 611 pDisk->pBase = NULL; 612 pDisk->pLast = NULL; 613 pDisk->cbSize = 0; 614 pDisk->PCHSGeometry.cCylinders = 0; 615 pDisk->PCHSGeometry.cHeads = 0; 616 pDisk->PCHSGeometry.cSectors = 0; 617 pDisk->LCHSGeometry.cCylinders = 0; 618 pDisk->LCHSGeometry.cHeads = 0; 619 pDisk->LCHSGeometry.cSectors = 0; 620 pDisk->pfnError = pfnError; 621 pDisk->pvErrorUser = pvErrorUser; 622 pDisk->Backend = pBackend; 623 pDisk->hPlugin = hPlugin; 624 *ppDisk = pDisk; 625 } 626 else 627 { 628 rc = VERR_NO_MEMORY; 629 break; 630 } 631 } 632 else 633 rc = vdEarlyError(pfnError, pvErrorUser, VERR_INVALID_PARAMETER, 634 RT_SRC_POS, "VD: unknown backend name '%s'", 635 pszBackend); 636 } while (0); 637 638 if (VBOX_FAILURE(rc) && hPlugin) 639 RTLdrClose(hPlugin); 640 641 LogFlowFunc(("returns %Vrc (pDisk=%#p)\n", rc, pDisk)); 642 return rc; 643 } 644 645 /** 646 * Destroys HDD container. 647 * If container has opened image files they will be closed. 648 * 649 * @param pDisk Pointer to HDD container. 650 */ 651 VBOXDDU_DECL(void) VDDestroy(PVBOXHDD pDisk) 652 { 653 LogFlowFunc(("pDisk=%#p\n", pDisk)); 654 do 655 { 656 /* sanity check */ 657 AssertBreak(VALID_PTR(pDisk), ); 658 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 659 556 660 if (pDisk) 557 661 { 558 pDisk->u32Signature = VBOXHDDDISK_SIGNATURE; 559 pDisk->cImages = 0; 560 pDisk->pBase = NULL; 561 pDisk->pLast = NULL; 562 pDisk->cbSize = 0; 563 pDisk->cCylinders = 0; 564 pDisk->cHeads = 0; 565 pDisk->cSectors = 0; 566 pDisk->pfnError = pfnError; 567 pDisk->pvErrorUser = pvErrorUser; 568 pDisk->Backend = pBackend; 569 pDisk->hPlugin = NIL_RTLDRMOD; 570 *ppDisk = pDisk; 571 } 572 else 573 rc = VERR_NO_MEMORY; 574 } 575 else 576 rc = vdEarlyError(pfnError, pvErrorUser, VERR_INVALID_PARAMETER, 577 RT_SRC_POS, "VD: unknown backend name '%s'", 578 pszBackend); 579 580 LogFlow(("%s: returns %Vrc (pDisk=%#p)\n", __FUNCTION__, rc, pDisk)); 581 return rc; 582 } 583 584 /** 585 * Try to get the backend name which can use this image. 662 VDCloseAll(pDisk); 663 if (pDisk->hPlugin != NIL_RTLDRMOD) 664 { 665 RTLdrClose(pDisk->hPlugin); 666 pDisk->hPlugin = NIL_RTLDRMOD; 667 } 668 RTMemFree(pDisk); 669 } 670 } while (0); 671 LogFlowFunc(("returns\n")); 672 } 673 674 /** 675 * Try to get the backend name which can use this image. 586 676 * 587 677 * @returns VBox status code. … … 590 680 * VERR_NOT_SUPPORTED if no plugin was found. 591 681 * @param pszFilename Name of the image file for which the backend is queried. 592 * @param ppszFormat Where to store the name of the plugin. 682 * @param ppszFormat Receives pointer of the UTF-8 string which contains the format name. 683 * The returned pointer must be freed using RTStrFree(). 593 684 */ 594 685 VBOXDDU_DECL(int) VDGetFormat(const char *pszFilename, char **ppszFormat) 595 686 { 596 char pszProgramPath[1024]; /* Far too much I think but to be on the safe side. */597 char *pszPluginFilter;598 687 PRTDIR pPluginDir = NULL; 599 PRTDIRENTRY pPluginDirEntry = NULL;600 unsigned cbPluginDirEntry;601 688 int rc = VERR_NOT_SUPPORTED; 602 689 int rcCheck = VINF_SUCCESS; 603 690 bool fPluginFound = false; 604 691 605 if (!ppszFormat) 606 return VERR_INVALID_PARAMETER; 692 LogFlowFunc(("pszFilename=\"%s\"\n", pszFilename)); 693 do 694 { 695 /* Check arguments. */ 696 AssertMsgBreak(VALID_PTR(pszFilename) && *pszFilename, 697 ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename), 698 rc = VERR_INVALID_PARAMETER); 699 AssertMsgBreak(VALID_PTR(ppszFormat), 700 ("ppszFormat=%#p\n", ppszFormat), 701 rc = VERR_INVALID_PARAMETER); 607 702 608 memset(pszProgramPath, 0, 1024); 609 rc = RTPathProgram(pszProgramPath, 1024); 610 if (VBOX_FAILURE(rc)) 611 return rc; 612 613 /* To get all entries with VBoxHDD as prefix. */ 614 rc = RTStrAPrintf(&pszPluginFilter, "%s/%s*", pszProgramPath, VBOX_HDDFORMAT_PLUGIN_PREFIX); 615 if (VBOX_FAILURE(rc)) 616 { 617 RTStrFree(pszProgramPath); 618 return VERR_NO_MEMORY; 619 } 620 621 /* The plugins are in the same directory as the program. */ 622 rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT); 623 if (VBOX_FAILURE(rc)) 624 goto out; 625 626 pPluginDirEntry = (PRTDIRENTRY)RTMemAllocZ(sizeof(RTDIRENTRY)); 627 if (!pPluginDir) 628 { 629 rc = VERR_NO_MEMORY; 630 goto out; 631 } 632 633 while ((rc = RTDirRead(pPluginDir, pPluginDirEntry, &cbPluginDirEntry)) != VERR_NO_MORE_FILES) 634 { 635 RTLDRMOD hPlugin = NIL_RTLDRMOD; 636 PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad = NULL; 637 PVBOXHDDBACKEND pBackend = NULL; 638 639 if (rc == VERR_BUFFER_OVERFLOW) 640 { 641 /* allocate new buffer. */ 642 RTMemFree(pPluginDirEntry); 643 pPluginDirEntry = (PRTDIRENTRY)RTMemAllocZ(cbPluginDirEntry); 644 /* Retry. */ 645 rc = RTDirRead(pPluginDir, pPluginDirEntry, &cbPluginDirEntry); 646 } 647 703 /* First check if static backends support this file format. */ 704 for (unsigned i = 0; aBackends[i] != NULL; i++) 705 { 706 if (aBackends[i]->pfnCheckIfValid) 707 { 708 rc = aBackends[i]->pfnCheckIfValid(pszFilename); 709 if (VBOX_SUCCESS(rc)) 710 { 711 fPluginFound = true; 712 /* Copy the name into the new string. */ 713 char *pszFormat = RTStrDup(aBackends[i]->pszBackendName); 714 if (!pszFormat) 715 { 716 rc = VERR_NO_MEMORY; 717 break; 718 } 719 *ppszFormat = pszFormat; 720 break; 721 } 722 } 723 } 724 725 /* Then check if plugin backends support this file format. */ 726 char szPath[RTPATH_MAX]; 727 rc = RTPathSharedLibs(szPath, sizeof(szPath)); 648 728 if (VBOX_FAILURE(rc)) 649 729 break; 650 730 651 /* We got the new entry. */ 652 if (pPluginDirEntry->enmType != RTDIRENTRYTYPE_FILE) 653 continue; 654 655 rc = RTLdrLoad(pPluginDirEntry->szName, &hPlugin); 656 if (VBOX_SUCCESS(rc)) 657 { 658 rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad); 659 if (VBOX_FAILURE(rc) || !pfnHDDFormatLoad) 731 /* To get all entries with VBoxHDD as prefix. */ 732 char *pszPluginFilter; 733 rc = RTStrAPrintf(&pszPluginFilter, "%s/%s*", szPath, 734 VBOX_HDDFORMAT_PLUGIN_PREFIX); 735 if (VBOX_FAILURE(rc)) 736 { 737 rc = VERR_NO_MEMORY; 738 break; 739 } 740 741 /* The plugins are in the same directory as the other shared libs. */ 742 rc = RTDirOpenFiltered(&pPluginDir, pszPluginFilter, RTDIRFILTER_WINNT); 743 if (VBOX_FAILURE(rc)) 744 break; 745 746 PRTDIRENTRY pPluginDirEntry = NULL; 747 unsigned cbPluginDirEntry; 748 pPluginDirEntry = (PRTDIRENTRY)RTMemAllocZ(sizeof(RTDIRENTRY)); 749 if (!pPluginDir) 750 { 751 rc = VERR_NO_MEMORY; 752 break; 753 } 754 755 while ((rc = RTDirRead(pPluginDir, pPluginDirEntry, &cbPluginDirEntry)) != VERR_NO_MORE_FILES) 756 { 757 RTLDRMOD hPlugin = NIL_RTLDRMOD; 758 PFNVBOXHDDFORMATLOAD pfnHDDFormatLoad = NULL; 759 PVBOXHDDBACKEND pBackend = NULL; 760 761 if (rc == VERR_BUFFER_OVERFLOW) 660 762 { 661 Log(("%s: Error resolving the entry point %s, rc = %d, pfnHDDFormat = %p\n", VBOX_HDDFORMAT_LOAD_NAME, rc, pfnHDDFormatLoad)); 763 /* allocate new buffer. */ 764 RTMemFree(pPluginDirEntry); 765 pPluginDirEntry = (PRTDIRENTRY)RTMemAllocZ(cbPluginDirEntry); 766 /* Retry. */ 767 rc = RTDirRead(pPluginDir, pPluginDirEntry, &cbPluginDirEntry); 768 if (VBOX_FAILURE(rc)) 769 break; 770 } 771 else if (VBOX_FAILURE(rc)) 772 break; 773 774 /* We got the new entry. */ 775 if (pPluginDirEntry->enmType != RTDIRENTRYTYPE_FILE) 776 continue; 777 778 rc = RTLdrLoad(pPluginDirEntry->szName, &hPlugin); 779 if (VBOX_SUCCESS(rc)) 780 { 781 rc = RTLdrGetSymbol(hPlugin, VBOX_HDDFORMAT_LOAD_NAME, (void**)&pfnHDDFormatLoad); 782 if (VBOX_FAILURE(rc) || !pfnHDDFormatLoad) 783 { 784 LogFunc(("error resolving the entry point %s in plugin %s, rc=%Vrc, pfnHDDFormat=%#p\n", VBOX_HDDFORMAT_LOAD_NAME, pPluginDirEntry->szName, rc, pfnHDDFormatLoad)); 785 if (VBOX_SUCCESS(rc)) 786 rc = VERR_SYMBOL_NOT_FOUND; 787 } 788 662 789 if (VBOX_SUCCESS(rc)) 663 rc = VERR_SYMBOL_NOT_FOUND;664 }665 else666 {667 rc = pfnHDDFormatLoad(&pBackend);668 if (VBOX_SUCCESS(rc) && (pBackend->cbSize == sizeof(VBOXHDDBACKEND)))669 790 { 670 /* Check if the plugin can handle this file. */671 rc Check = pBackend->pfnCheckIfValid(pszFilename);672 if (VBOX_SUCCESS(rc Check))791 /* Get the function table. */ 792 rc = pfnHDDFormatLoad(&pBackend); 793 if (VBOX_SUCCESS(rc) && pBackend->cbSize == sizeof(VBOXHDDBACKEND)) 673 794 { 674 fPluginFound = true; 675 676 /* Report the format name. */ 677 char *pszName = pPluginDirEntry->szName + VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH; /* Point to the rest after the prefix. */ 678 char *pszFormat = NULL; 679 unsigned cbFormat = 0; 680 681 while((*pszName != '.') && (*pszName != '\0')) 795 796 /* Check if the plugin can handle this file. */ 797 rc = pBackend->pfnCheckIfValid(pszFilename); 798 if (VBOX_SUCCESS(rc)) 682 799 { 683 cbFormat++; 684 pszName++; 685 } 686 687 pszName = pPluginDirEntry->szName + VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH; 688 689 /* Copy the name into the new string. */ 690 pszFormat = (char *)RTMemAllocZ(cbFormat+1); 691 692 if (pszFormat) 693 { 694 memcpy(pszFormat, pszName, cbFormat); 800 fPluginFound = true; 801 rc = VINF_SUCCESS; 802 803 /* Report the format name. */ 804 RTPathStripExt(pPluginDirEntry->szName); 805 char *pszFormat = NULL; 806 AssertBreak(strlen(pszFormat) >= VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH, 807 rc = VERR_INVALID_NAME); 808 pszFormat = RTStrDup(pPluginDirEntry->szName + VBOX_HDDFORMAT_PLUGIN_PREFIX_LENGTH); 809 if (!pszFormat) 810 rc = VERR_NO_MEMORY; 695 811 *ppszFormat = pszFormat; 696 812 } 697 else698 rc = VERR_NO_MEMORY;699 813 } 700 else701 rcCheck = VERR_NOT_SUPPORTED;702 814 } 703 815 else … … 711 823 break; 712 824 } 713 } 714 715 out: 716 if (pPluginDirEntry) 717 RTMemFree(pPluginDirEntry); 718 if (pPluginDir) 719 RTDirClose(pPluginDir); 720 721 RTStrFree(pszPluginFilter); 722 RTStrFree(pszProgramPath); 723 724 if ((fPluginFound == true) && (*ppszFormat != NULL)) 725 rc = VINF_SUCCESS; 726 else if ((rcCheck == VERR_NOT_SUPPORTED) && (rc == VINF_SUCCESS)) 727 rc = rcCheck; 728 729 return rc; 730 } 731 732 /** 733 * Destroys the VBox HDD container. 734 * If container has opened image files they will be closed. 735 * 736 * @param pDisk Pointer to VBox HDD container. 737 */ 738 VBOXDDU_DECL(void) VDDestroy(PVBOXHDD pDisk) 739 { 740 LogFlow(("%s: pDisk=%#p\n", __FUNCTION__, pDisk)); 741 /* sanity check */ 742 Assert(pDisk); 743 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 744 745 if (pDisk) 746 { 747 VDCloseAll(pDisk); 748 if (pDisk->hPlugin != NIL_RTLDRMOD) 749 { 750 RTLdrClose(pDisk->hPlugin); 751 pDisk->hPlugin = NIL_RTLDRMOD; 752 } 753 RTMemFree(pDisk); 754 } 825 RTStrFree(pszPluginFilter); 826 if (pPluginDirEntry) 827 RTMemFree(pPluginDirEntry); 828 if (pPluginDir) 829 RTDirClose(pPluginDir); 830 } while (0); 831 832 LogFlowFunc(("returns %Vrc *ppszFormat=\"%s\"\n", rc, *ppszFormat)); 833 return rc; 755 834 } 756 835 … … 758 837 * Opens an image file. 759 838 * 760 * The first opened image file in aHDD container must have a base image type,839 * The first opened image file in HDD container must have a base image type, 761 840 * others (next opened images) must be a differencing or undo images. 762 841 * Linkage is checked for differencing image to be in consistence with the previously opened image. … … 765 844 * other processes to use images in read-only mode too. 766 845 * 767 * Note that the image can beopened in read-only mode if a read/write open is not possible.846 * Note that the image is opened in read-only mode if a read/write open is not possible. 768 847 * Use VDIsReadOnly to check open mode. 769 848 * 770 849 * @returns VBox status code. 771 * @param pDisk Pointer to VBoxHDD container.850 * @param pDisk Pointer to HDD container. 772 851 * @param pszFilename Name of the image file to open. 773 852 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. … … 777 856 { 778 857 int rc = VINF_SUCCESS; 779 LogFlow(("%s: pszFilename=\"%s\" uOpenFlags=%#x\n", __FUNCTION__, 780 pszFilename, uOpenFlags)); 781 /* sanity check */ 782 Assert(pDisk); 783 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 784 785 /* Check arguments. */ 786 if ( !pszFilename 787 || *pszFilename == '\0' 788 || (uOpenFlags & ~VD_OPEN_FLAGS_MASK)) 789 { 790 AssertMsgFailed(("Invalid arguments: pszFilename=%#p uOpenFlags=%#x\n", pszFilename, uOpenFlags)); 791 return VERR_INVALID_PARAMETER; 792 } 793 794 /* Force readonly for images without base/diff consistency checking. */ 795 if (uOpenFlags & VD_OPEN_FLAGS_INFO) 796 uOpenFlags |= VD_OPEN_FLAGS_READONLY; 797 798 /* Set up image descriptor. */ 799 PVDIMAGE pImage = (PVDIMAGE)RTMemAllocZ(sizeof(VDIMAGE)); 800 if (!pImage) 801 return VERR_NO_MEMORY; 802 pImage->pszFilename = RTStrDup(pszFilename); 803 if (!pImage->pszFilename) 804 rc = VERR_NO_MEMORY; 805 806 if (VBOX_SUCCESS(rc)) 807 { 858 PVDIMAGE pImage = NULL; 859 860 LogFlowFunc(("pDisk=%#p pszFilename=\"%s\" uOpenFlags=%#x\n", 861 pszFilename, uOpenFlags)); 862 do 863 { 864 /* sanity check */ 865 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 866 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 867 868 /* Check arguments. */ 869 AssertMsgBreak(VALID_PTR(pszFilename) && *pszFilename, 870 ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename), 871 rc = VERR_INVALID_PARAMETER); 872 AssertMsgBreak((uOpenFlags & ~VD_OPEN_FLAGS_MASK) == 0, 873 ("uOpenFlags=%#x\n", uOpenFlags), 874 rc = VERR_INVALID_PARAMETER); 875 876 /* Force readonly for images without base/diff consistency checking. */ 877 if (uOpenFlags & VD_OPEN_FLAGS_INFO) 878 uOpenFlags |= VD_OPEN_FLAGS_READONLY; 879 880 /* Set up image descriptor. */ 881 pImage = (PVDIMAGE)RTMemAllocZ(sizeof(VDIMAGE)); 882 if (!pImage) 883 { 884 rc = VERR_NO_MEMORY; 885 break; 886 } 887 pImage->pszFilename = RTStrDup(pszFilename); 888 if (!pImage->pszFilename) 889 { 890 rc = VERR_NO_MEMORY; 891 break; 892 } 893 808 894 pImage->uOpenFlags = uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME; 809 895 rc = pDisk->Backend->pfnOpen(pImage->pszFilename, … … 811 897 pDisk->pfnError, pDisk->pvErrorUser, 812 898 &pImage->pvBackendData); 813 } 814 /* If the open in read-write mode failed, retry in read-only mode. */ 815 if (VBOX_FAILURE(rc)) 816 { 817 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY) 818 && (rc == VERR_ACCESS_DENIED 819 || rc == VERR_PERMISSION_DENIED 820 || rc == VERR_WRITE_PROTECT 821 || rc == VERR_SHARING_VIOLATION 822 || rc == VERR_FILE_LOCK_FAILED)) 823 rc = pDisk->Backend->pfnOpen(pImage->pszFilename, 824 (uOpenFlags & ~VD_OPEN_FLAGS_HONOR_SAME) 825 | VD_OPEN_FLAGS_READONLY, 826 pDisk->pfnError, pDisk->pvErrorUser, 827 &pImage->pvBackendData); 899 /* If the open in read-write mode failed, retry in read-only mode. */ 828 900 if (VBOX_FAILURE(rc)) 829 rc = vdError(pDisk, rc, RT_SRC_POS, 830 N_("VD: error opening image file '%s'"), pszFilename); 831 } 832 833 if (VBOX_SUCCESS(rc)) 834 { 901 { 902 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY) 903 && (rc == VERR_ACCESS_DENIED 904 || rc == VERR_PERMISSION_DENIED 905 || rc == VERR_WRITE_PROTECT 906 || rc == VERR_SHARING_VIOLATION 907 || rc == VERR_FILE_LOCK_FAILED)) 908 rc = pDisk->Backend->pfnOpen(pImage->pszFilename, 909 (uOpenFlags & ~VD_OPEN_FLAGS_HONOR_SAME) 910 | VD_OPEN_FLAGS_READONLY, 911 pDisk->pfnError, pDisk->pvErrorUser, 912 &pImage->pvBackendData); 913 if (VBOX_FAILURE(rc)) 914 { 915 rc = vdError(pDisk, rc, RT_SRC_POS, 916 N_("VD: error opening image file '%s'"), pszFilename); 917 break; 918 } 919 } 920 835 921 VDIMAGETYPE enmImageType; 836 922 rc = pDisk->Backend->pfnGetImageType(pImage->pvBackendData, … … 843 929 && pDisk->cImages != 0 844 930 && enmImageType != VD_IMAGE_TYPE_NORMAL) 931 { 845 932 rc = VERR_VDI_INVALID_TYPE; 933 break; 934 } 846 935 847 936 /** @todo optionally check UUIDs */ 848 937 849 if (VBOX_SUCCESS(rc)) 850 { 851 uint64_t cbSize = pDisk->Backend->pfnGetSize(pImage->pvBackendData); 852 if (pDisk->cImages == 0) 853 { 854 /* Cache disk information. */ 855 pDisk->cbSize = cbSize; 856 857 /* Cache CHS geometry. */ 858 int rc2 = pDisk->Backend->pfnGetGeometry(pImage->pvBackendData, 859 &pDisk->cCylinders, 860 &pDisk->cHeads, 861 &pDisk->cSectors); 862 if (VBOX_FAILURE(rc2)) 863 { 864 pDisk->cCylinders = 0; 865 pDisk->cHeads = 0; 866 pDisk->cSectors = 0; 867 } 868 else 869 { 870 /* Make sure the CHS geometry is properly clipped. */ 871 pDisk->cCylinders = RT_MIN(pDisk->cCylinders, 16383); 872 pDisk->cHeads = RT_MIN(pDisk->cHeads, 255); 873 pDisk->cSectors = RT_MIN(pDisk->cSectors, 255); 874 } 875 876 /* Cache translation mode. */ 877 rc2 = pDisk->Backend->pfnGetTranslation(pImage->pvBackendData, 878 &pDisk->enmTranslation); 879 if (VBOX_FAILURE(rc2)) 880 pDisk->enmTranslation = (PDMBIOSTRANSLATION)0; 881 } 882 else 883 { 884 /* Check image size/block size for consistency. */ 885 if (cbSize != pDisk->cbSize) 886 rc = VERR_VDI_INVALID_TYPE; 887 } 888 } 889 890 if (VBOX_SUCCESS(rc) && pDisk->cImages != 0) 938 int rc2; 939 940 /* Cache disk information. */ 941 pDisk->cbSize = pDisk->Backend->pfnGetSize(pImage->pvBackendData); 942 943 /* Cache PCHS geometry. */ 944 rc2 = pDisk->Backend->pfnGetPCHSGeometry(pImage->pvBackendData, 945 &pDisk->PCHSGeometry); 946 if (VBOX_FAILURE(rc2)) 947 { 948 pDisk->PCHSGeometry.cCylinders = 0; 949 pDisk->PCHSGeometry.cHeads = 0; 950 pDisk->PCHSGeometry.cSectors = 0; 951 } 952 else 953 { 954 /* Make sure the PCHS geometry is properly clipped. */ 955 pDisk->PCHSGeometry.cCylinders = RT_MIN(pDisk->PCHSGeometry.cCylinders, 16383); 956 pDisk->PCHSGeometry.cHeads = RT_MIN(pDisk->PCHSGeometry.cHeads, 16); 957 pDisk->PCHSGeometry.cSectors = RT_MIN(pDisk->PCHSGeometry.cSectors, 63); 958 } 959 960 /* Cache LCHS geometry. */ 961 rc2 = pDisk->Backend->pfnGetLCHSGeometry(pImage->pvBackendData, 962 &pDisk->LCHSGeometry); 963 if (VBOX_FAILURE(rc2)) 964 { 965 pDisk->LCHSGeometry.cCylinders = 0; 966 pDisk->LCHSGeometry.cHeads = 0; 967 pDisk->LCHSGeometry.cSectors = 0; 968 } 969 else 970 { 971 /* Make sure the LCHS geometry is properly clipped. */ 972 pDisk->LCHSGeometry.cCylinders = RT_MIN(pDisk->LCHSGeometry.cCylinders, 1024); 973 pDisk->LCHSGeometry.cHeads = RT_MIN(pDisk->LCHSGeometry.cHeads, 255); 974 pDisk->LCHSGeometry.cSectors = RT_MIN(pDisk->LCHSGeometry.cSectors, 63); 975 } 976 977 if (pDisk->cImages != 0) 891 978 { 892 979 /* Switch previous image to read-only mode. */ … … 913 1000 pImage->pvBackendData = NULL; 914 1001 } 915 } 1002 } while (0); 916 1003 917 1004 if (VBOX_FAILURE(rc)) … … 925 1012 } 926 1013 927 LogFlow (("%s: returns %Vrc\n", __FUNCTION__, rc));1014 LogFlowFunc(("returns %Vrc\n", rc)); 928 1015 return rc; 929 1016 } … … 933 1020 * 934 1021 * @returns VBox status code. 935 * @param pDisk Pointer to VBoxHDD container.1022 * @param pDisk Pointer to HDD container. 936 1023 * @param pszFilename Name of the image file to create. 937 1024 * @param enmType Image type, only base image types are acceptable. … … 939 1026 * @param uImageFlags Flags specifying special image features. 940 1027 * @param pszComment Pointer to image comment. NULL is ok. 941 * @param cCylinders Number of cylinders (must be <= 16383). 942 * @param cHeads Number of heads (must be <= 16). 943 * @param cSectors Number of sectors (must be <= 63); 1028 * @param pPCHSGeometry Pointer to physical disk geometry <= (16383,16,63). Not NULL. 1029 * @param pLCHSGeometry Pointer to logical disk geometry <= (1024,255,63). Not NULL. 944 1030 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. 945 1031 * @param pfnProgress Progress callback. Optional. NULL if not to be used. … … 949 1035 VDIMAGETYPE enmType, uint64_t cbSize, 950 1036 unsigned uImageFlags, const char *pszComment, 951 unsigned cCylinders, unsigned cHeads, 952 unsigned cSectors, unsigned uOpenFlags, 953 PFNVMPROGRESS pfnProgress, void *pvUser) 1037 PCPDMMEDIAGEOMETRY pPCHSGeometry, 1038 PCPDMMEDIAGEOMETRY pLCHSGeometry, 1039 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 1040 void *pvUser) 954 1041 { 955 1042 int rc = VINF_SUCCESS; 956 LogFlow(("%s: pszFilename=\"%s\" uOpenFlags=%#x\n", __FUNCTION__, 957 pszFilename, uOpenFlags)); 958 /* sanity check */ 959 Assert(pDisk); 960 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 961 962 /* Check arguments. */ 963 if ( !pszFilename 964 || *pszFilename == '\0' 965 || (enmType != VD_IMAGE_TYPE_NORMAL && enmType != VD_IMAGE_TYPE_FIXED) 966 || !cbSize 967 || (uOpenFlags & ~VD_OPEN_FLAGS_MASK) 968 || cCylinders == 0 969 || cCylinders > 16383 970 || cHeads == 0 971 || cHeads > 16 972 || cSectors == 0 973 || cSectors > 63) 974 { 975 AssertMsgFailed(("Invalid arguments: pszFilename=%#p uOpenFlags=%#x\n", pszFilename, uOpenFlags)); 976 return VERR_INVALID_PARAMETER; 977 } 978 979 /* Check state. */ 980 if (pDisk->cImages != 0) 981 { 982 AssertMsgFailed(("Create base image cannot be done with other images open\n")); 983 return VERR_VDI_INVALID_STATE; 984 } 985 986 /* Set up image descriptor. */ 987 PVDIMAGE pImage = (PVDIMAGE)RTMemAllocZ(sizeof(VDIMAGE)); 988 if (!pImage) 989 return VERR_NO_MEMORY; 990 pImage->pszFilename = RTStrDup(pszFilename); 991 if (!pImage->pszFilename) 992 rc = VERR_NO_MEMORY; 993 994 if (VBOX_SUCCESS(rc)) 1043 PVDIMAGE pImage = NULL; 1044 1045 LogFlowFunc(("pszFilename=\"%s\" enmType=%#x cbSize=%llu uImageFlags=%#x pszComment=\"%s\" PCHS=%u/%u/%u LCHS=%u/%u/%u uOpenFlags=%#x pfnProgress=%#p pvUser=%#p\n", 1046 pszFilename, enmType, cbSize, uImageFlags, pszComment, 1047 pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, 1048 pPCHSGeometry->cSectors, pLCHSGeometry->cCylinders, 1049 pLCHSGeometry->cHeads, pLCHSGeometry->cSectors, uOpenFlags, 1050 pfnProgress, pvUser)); 1051 do 1052 { 1053 /* sanity check */ 1054 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 1055 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1056 1057 /* Check arguments. */ 1058 AssertMsgBreak(VALID_PTR(pszFilename) && *pszFilename, 1059 ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename), 1060 rc = VERR_INVALID_PARAMETER); 1061 AssertMsgBreak(enmType == VD_IMAGE_TYPE_NORMAL || enmType == VD_IMAGE_TYPE_FIXED, 1062 ("enmType=%#x\n", enmType), 1063 rc = VERR_INVALID_PARAMETER); 1064 AssertMsgBreak(cbSize, 1065 ("cbSize=%llu\n", cbSize), 1066 rc = VERR_INVALID_PARAMETER); 1067 AssertMsgBreak((uImageFlags & ~VD_IMAGE_FLAGS_MASK) == 0, 1068 ("uImageFlags=%#x\n", uImageFlags), 1069 rc = VERR_INVALID_PARAMETER); 1070 AssertMsgBreak( VALID_PTR(pPCHSGeometry) 1071 && pPCHSGeometry->cCylinders <= 16383 1072 && pPCHSGeometry->cCylinders != 0 1073 && pPCHSGeometry->cHeads <= 16 1074 && pPCHSGeometry->cHeads != 0 1075 && pPCHSGeometry->cSectors <= 63 1076 && pPCHSGeometry->cSectors != 0, 1077 ("pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pPCHSGeometry, 1078 pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, 1079 pPCHSGeometry->cSectors), 1080 rc = VERR_INVALID_PARAMETER); 1081 AssertMsgBreak( VALID_PTR(pLCHSGeometry) 1082 && pLCHSGeometry->cCylinders <= 16383 1083 && pLCHSGeometry->cCylinders != 0 1084 && pLCHSGeometry->cHeads <= 16 1085 && pLCHSGeometry->cHeads != 0 1086 && pLCHSGeometry->cSectors <= 63 1087 && pLCHSGeometry->cSectors != 0, 1088 ("pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pLCHSGeometry, 1089 pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, 1090 pLCHSGeometry->cSectors), 1091 rc = VERR_INVALID_PARAMETER); 1092 AssertMsgBreak((uOpenFlags & ~VD_OPEN_FLAGS_MASK) == 0, 1093 ("uOpenFlags=%#x\n", uOpenFlags), 1094 rc = VERR_INVALID_PARAMETER); 1095 1096 /* Check state. */ 1097 if (pDisk->cImages != 0) 1098 AssertMsgFailedBreak(("Create base image cannot be done with other images open\n"), 1099 rc = VERR_VDI_INVALID_STATE); 1100 1101 /* Set up image descriptor. */ 1102 pImage = (PVDIMAGE)RTMemAllocZ(sizeof(VDIMAGE)); 1103 if (!pImage) 1104 { 1105 rc = VERR_NO_MEMORY; 1106 break; 1107 } 1108 pImage->pszFilename = RTStrDup(pszFilename); 1109 if (!pImage->pszFilename) 1110 { 1111 rc = VERR_NO_MEMORY; 1112 break; 1113 } 1114 995 1115 rc = pDisk->Backend->pfnCreate(pImage->pszFilename, enmType, cbSize, 996 uImageFlags, pszComment, cCylinders,997 cHeads, cSectors, uOpenFlags,998 p fnProgress, pvUser,999 pDisk->p fnError, pDisk->pvErrorUser,1116 uImageFlags, pszComment, pPCHSGeometry, 1117 pLCHSGeometry, uOpenFlags, pfnProgress, 1118 pvUser, 0, 99, pDisk->pfnError, 1119 pDisk->pvErrorUser, 1000 1120 &pImage->pvBackendData); 1001 1121 1002 if (VBOX_SUCCESS(rc))1003 {1004 /** @todo optionally check UUIDs */1005 1006 1122 if (VBOX_SUCCESS(rc)) 1007 1123 { 1008 uint64_t cbSize = pDisk->Backend->pfnGetSize(pImage->pvBackendData); 1009 if (pDisk->cImages == 0) 1124 /** @todo optionally check UUIDs */ 1125 1126 int rc2; 1127 1128 /* Cache disk information. */ 1129 pDisk->cbSize = pDisk->Backend->pfnGetSize(pImage->pvBackendData); 1130 1131 /* Cache PCHS geometry. */ 1132 rc2 = pDisk->Backend->pfnGetPCHSGeometry(pImage->pvBackendData, 1133 &pDisk->PCHSGeometry); 1134 if (VBOX_FAILURE(rc2)) 1010 1135 { 1011 /* Cache disk information. */ 1012 pDisk->cbSize = cbSize; 1013 1014 /* Cache CHS geometry. */ 1015 int rc2 = pDisk->Backend->pfnGetGeometry(pImage->pvBackendData, 1016 &pDisk->cCylinders, 1017 &pDisk->cHeads, 1018 &pDisk->cSectors); 1019 if (VBOX_FAILURE(rc2)) 1020 { 1021 pDisk->cCylinders = 0; 1022 pDisk->cHeads = 0; 1023 pDisk->cSectors = 0; 1024 } 1025 else 1026 { 1027 /* Make sure the CHS geometry is properly clipped. */ 1028 pDisk->cCylinders = RT_MIN(pDisk->cCylinders, 16383); 1029 pDisk->cHeads = RT_MIN(pDisk->cHeads, 255); 1030 pDisk->cSectors = RT_MIN(pDisk->cSectors, 255); 1031 } 1032 1033 /* Cache translation mode. */ 1034 rc2 = pDisk->Backend->pfnGetTranslation(pImage->pvBackendData, 1035 &pDisk->enmTranslation); 1036 if (VBOX_FAILURE(rc2)) 1037 pDisk->enmTranslation = (PDMBIOSTRANSLATION)0; 1136 pDisk->PCHSGeometry.cCylinders = 0; 1137 pDisk->PCHSGeometry.cHeads = 0; 1138 pDisk->PCHSGeometry.cSectors = 0; 1038 1139 } 1039 1140 else 1040 1141 { 1041 /* Check image size/block size for consistency. */ 1042 if (cbSize != pDisk->cbSize) 1043 rc = VERR_VDI_INVALID_TYPE; 1142 /* Make sure the CHS geometry is properly clipped. */ 1143 pDisk->PCHSGeometry.cCylinders = RT_MIN(pDisk->PCHSGeometry.cCylinders, 16383); 1144 pDisk->PCHSGeometry.cHeads = RT_MIN(pDisk->PCHSGeometry.cHeads, 16); 1145 pDisk->PCHSGeometry.cSectors = RT_MIN(pDisk->PCHSGeometry.cSectors, 63); 1146 } 1147 1148 /* Cache LCHS geometry. */ 1149 rc2 = pDisk->Backend->pfnGetLCHSGeometry(pImage->pvBackendData, 1150 &pDisk->LCHSGeometry); 1151 if (VBOX_FAILURE(rc2)) 1152 { 1153 pDisk->LCHSGeometry.cCylinders = 0; 1154 pDisk->LCHSGeometry.cHeads = 0; 1155 pDisk->LCHSGeometry.cSectors = 0; 1156 } 1157 else 1158 { 1159 /* Make sure the CHS geometry is properly clipped. */ 1160 pDisk->LCHSGeometry.cCylinders = RT_MIN(pDisk->LCHSGeometry.cCylinders, 1024); 1161 pDisk->LCHSGeometry.cHeads = RT_MIN(pDisk->LCHSGeometry.cHeads, 255); 1162 pDisk->LCHSGeometry.cSectors = RT_MIN(pDisk->LCHSGeometry.cSectors, 63); 1044 1163 } 1045 1164 } … … 1058 1177 pImage->pvBackendData = NULL; 1059 1178 } 1060 } 1179 } while (0); 1061 1180 1062 1181 if (VBOX_FAILURE(rc)) … … 1070 1189 } 1071 1190 1072 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 1191 if (VBOX_SUCCESS(rc) && pfnProgress) 1192 pfnProgress(NULL /* WARNING! pVM=NULL */, 100, pvUser); 1193 1194 LogFlowFunc(("returns %Vrc\n", rc)); 1073 1195 return rc; 1074 1196 } … … 1079 1201 * 1080 1202 * @returns VBox status code. 1081 * @param pDisk Pointer to VBoxHDD container.1203 * @param pDisk Pointer to HDD container. 1082 1204 * @param pszFilename Name of the differencing image file to create. 1083 1205 * @param uImageFlags Flags specifying special image features. … … 1089 1211 VBOXDDU_DECL(int) VDCreateDiff(PVBOXHDD pDisk, const char *pszFilename, 1090 1212 unsigned uImageFlags, const char *pszComment, 1091 unsigned uOpenFlags, 1092 PFNVMPROGRESS pfnProgress, void *pvUser) 1093 { 1094 return VERR_NOT_IMPLEMENTED; 1095 } 1096 1097 /** 1098 * Merges two images having a parent/child relationship (both directions). 1099 * As a side effect the source image is deleted from both the disk and 1100 * the images in the VBox HDD container. 1101 * 1102 * @returns VBox status code. 1103 * @param pDisk Pointer to VBox HDD container. 1213 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 1214 void *pvUser) 1215 { 1216 int rc = VINF_SUCCESS; 1217 PVDIMAGE pImage = NULL; 1218 1219 LogFlowFunc(("pDisk=%#p pszFilename=\"%s\" uImageFlags=%#x pszComment=\"%s\" uOpenFlags=%#x pfnProgress=%#p pvUser=%#p\n", 1220 pDisk, pszFilename, uImageFlags, pszComment, uOpenFlags, 1221 pfnProgress, pvUser)); 1222 do 1223 { 1224 /* sanity check */ 1225 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 1226 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1227 1228 /* Check arguments. */ 1229 AssertMsgBreak(VALID_PTR(pszFilename) && *pszFilename, 1230 ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename), 1231 rc = VERR_INVALID_PARAMETER); 1232 AssertMsgBreak((uImageFlags & ~VD_IMAGE_FLAGS_MASK) == 0, 1233 ("uImageFlags=%#x\n", uImageFlags), 1234 rc = VERR_INVALID_PARAMETER); 1235 AssertMsgBreak((uOpenFlags & ~VD_OPEN_FLAGS_MASK) == 0, 1236 ("uOpenFlags=%#x\n", uOpenFlags), 1237 rc = VERR_INVALID_PARAMETER); 1238 1239 /* Check state. */ 1240 if (pDisk->cImages == 0) 1241 AssertMsgFailedBreak(("Create diff image cannot be done without other images open\n"), 1242 rc = VERR_VDI_INVALID_STATE); 1243 1244 /* Set up image descriptor. */ 1245 pImage = (PVDIMAGE)RTMemAllocZ(sizeof(VDIMAGE)); 1246 if (!pImage) 1247 { 1248 rc = VERR_NO_MEMORY; 1249 break; 1250 } 1251 pImage->pszFilename = RTStrDup(pszFilename); 1252 if (!pImage->pszFilename) 1253 { 1254 rc = VERR_NO_MEMORY; 1255 break; 1256 } 1257 1258 rc = pDisk->Backend->pfnCreate(pImage->pszFilename, 1259 VD_IMAGE_TYPE_NORMAL, pDisk->cbSize, 1260 uImageFlags, pszComment, 1261 &pDisk->PCHSGeometry, 1262 &pDisk->LCHSGeometry, uOpenFlags, 1263 pfnProgress, pvUser, 0, 99, 1264 pDisk->pfnError, pDisk->pvErrorUser, 1265 &pImage->pvBackendData); 1266 1267 if (VBOX_SUCCESS(rc)) 1268 { 1269 /** @todo optionally check UUIDs */ 1270 } 1271 1272 if (VBOX_SUCCESS(rc)) 1273 { 1274 /* Image successfully opened, make it the last image. */ 1275 vdAddImageToList(pDisk, pImage); 1276 } 1277 else 1278 { 1279 /* Error detected, but image opened. Close and delete image. */ 1280 int rc2; 1281 rc2 = pDisk->Backend->pfnClose(pImage->pvBackendData, true); 1282 AssertRC(rc2); 1283 pImage->pvBackendData = NULL; 1284 } 1285 } while (0); 1286 1287 if (VBOX_FAILURE(rc)) 1288 { 1289 if (pImage) 1290 { 1291 if (pImage->pszFilename) 1292 RTStrFree(pImage->pszFilename); 1293 RTMemFree(pImage); 1294 } 1295 } 1296 1297 if (VBOX_SUCCESS(rc) && pfnProgress) 1298 pfnProgress(NULL /* WARNING! pVM=NULL */, 100, pvUser); 1299 1300 LogFlowFunc(("returns %Vrc\n", rc)); 1301 return rc; 1302 } 1303 1304 /** 1305 * Merges two images (not necessarily with direct parent/child relationship). 1306 * As a side effect the source image and potentially the other images which 1307 * are also merged to the destination are deleted from both the disk and the 1308 * images in the HDD container. 1309 * 1310 * @returns VBox status code. 1311 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1312 * @param pDisk Pointer to HDD container. 1104 1313 * @param nImageFrom Name of the image file to merge from. 1105 1314 * @param nImageTo Name of the image file to merge to. … … 1111 1320 void *pvUser) 1112 1321 { 1113 return VERR_NOT_IMPLEMENTED; 1114 } 1115 1116 /** 1117 * Copies an image from one VBox HDD container to another. 1118 * The copy is opened in the target VBox HDD container. 1322 int rc = VINF_SUCCESS; 1323 void *pvBuf = NULL; 1324 1325 LogFlowFunc(("pDisk=%#p nImageFrom=%u nImageTo=%u pfnProgress=%#p pvUser=%#p\n", 1326 pDisk, nImageFrom, nImageTo, pfnProgress, pvUser)); 1327 do 1328 { 1329 /* sanity check */ 1330 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 1331 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1332 1333 PVDIMAGE pImageFrom = vdGetImageByNumber(pDisk, nImageFrom); 1334 PVDIMAGE pImageTo = vdGetImageByNumber(pDisk, nImageTo); 1335 if (!pImageFrom || !pImageTo) 1336 { 1337 rc = VERR_VDI_IMAGE_NOT_FOUND; 1338 break; 1339 } 1340 AssertBreak(pImageFrom != pImageTo, rc = VERR_INVALID_PARAMETER); 1341 1342 /* Check if destination image is writable. */ 1343 unsigned uOpenFlags = pDisk->Backend->pfnGetOpenFlags(pImageTo->pvBackendData); 1344 if (uOpenFlags & VD_OPEN_FLAGS_READONLY) 1345 { 1346 rc = VERR_VDI_IMAGE_READ_ONLY; 1347 break; 1348 } 1349 1350 /* Get size of destination image. */ 1351 uint64_t cbSize = pDisk->Backend->pfnGetSize(pImageTo->pvBackendData); 1352 1353 /* Allocate tmp buffer. */ 1354 pvBuf = RTMemTmpAlloc(VD_MERGE_BUFFER_SIZE); 1355 if (!pvBuf) 1356 { 1357 rc = VERR_NO_MEMORY; 1358 break; 1359 } 1360 1361 /* Merging is done directly on the images itself. This potentially 1362 * causes trouble if the disk is full in the middle of operation. */ 1363 /** @todo write alternative implementation which works with temporary 1364 * images (which is safer, but requires even more space). Also has the 1365 * drawback that merging into a raw disk parent simply isn't possible 1366 * this way (but in that case disk full isn't really a problem). */ 1367 if (nImageFrom < nImageTo) 1368 { 1369 /* Merge parent state into child. This means writing all not 1370 * allocated blocks in the destination image which are allocated in 1371 * the images to be merged. */ 1372 uint64_t uOffset = 0; 1373 uint64_t cbRemaining = cbSize; 1374 do 1375 { 1376 size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining); 1377 rc = pDisk->Backend->pfnRead(pImageTo->pvBackendData, uOffset, 1378 pvBuf, cbThisRead, &cbThisRead); 1379 if (VBOX_FAILURE(rc)) 1380 break; 1381 if (rc == VINF_VDI_BLOCK_FREE) 1382 { 1383 /* Search for image with allocated block. Do not attempt to 1384 * read more than the previous reads marked as valid. 1385 * Otherwise this would return stale data when different 1386 * block sizes are used for the images. */ 1387 for (PVDIMAGE pCurrImage = pImageTo->pPrev; 1388 pCurrImage != NULL && pCurrImage != pImageFrom->pPrev && rc == VINF_VDI_BLOCK_FREE; 1389 pCurrImage = pCurrImage->pPrev) 1390 { 1391 rc = pDisk->Backend->pfnRead(pCurrImage->pvBackendData, 1392 uOffset, pvBuf, 1393 cbThisRead, &cbThisRead); 1394 } 1395 if (VBOX_FAILURE(rc)) 1396 break; 1397 1398 if (rc != VINF_VDI_BLOCK_FREE) 1399 { 1400 rc = vdWriteHelper(pDisk, pImageTo, uOffset, pvBuf, 1401 cbThisRead); 1402 if (VBOX_FAILURE(rc)) 1403 break; 1404 } 1405 } 1406 1407 uOffset += cbThisRead; 1408 cbRemaining -= cbThisRead; 1409 } while (uOffset < cbSize); 1410 } 1411 else 1412 { 1413 /* Merge child state into parent. This means writing all blocks 1414 * which are allocated in the image up to the source image to the 1415 * destination image. */ 1416 uint64_t uOffset = 0; 1417 uint64_t cbRemaining = cbSize; 1418 do 1419 { 1420 size_t cbThisRead = RT_MIN(VD_MERGE_BUFFER_SIZE, cbRemaining); 1421 /* Search for image with allocated block. Do not attempt to 1422 * read more than the previous reads marked as valid. Otherwise 1423 * this would return stale data when different block sizes are 1424 * used for the images. */ 1425 for (PVDIMAGE pCurrImage = pImageFrom; 1426 pCurrImage != NULL && pCurrImage != pImageTo && rc == VINF_VDI_BLOCK_FREE; 1427 pCurrImage = pCurrImage->pPrev) 1428 { 1429 rc = pDisk->Backend->pfnRead(pCurrImage->pvBackendData, 1430 uOffset, pvBuf, 1431 cbThisRead, &cbThisRead); 1432 } 1433 if (VBOX_FAILURE(rc)) 1434 break; 1435 1436 if (rc != VINF_VDI_BLOCK_FREE) 1437 { 1438 rc = vdWriteHelper(pDisk, pImageTo, uOffset, pvBuf, 1439 cbThisRead); 1440 if (VBOX_FAILURE(rc)) 1441 break; 1442 } 1443 1444 uOffset += cbThisRead; 1445 cbRemaining -= cbThisRead; 1446 } while (uOffset < cbSize); 1447 } 1448 1449 /* Update parent UUID so that image chain is consistent. */ 1450 RTUUID Uuid; 1451 if (nImageFrom < nImageTo) 1452 { 1453 if (pImageTo->pPrev) 1454 { 1455 rc = pDisk->Backend->pfnGetUuid(pImageTo->pPrev->pvBackendData, 1456 &Uuid); 1457 AssertRC(rc); 1458 } 1459 else 1460 RTUuidClear(&Uuid); 1461 rc = pDisk->Backend->pfnSetParentUuid(pImageTo->pvBackendData, 1462 &Uuid); 1463 AssertRC(rc); 1464 } 1465 else 1466 { 1467 if (pImageFrom->pNext) 1468 { 1469 rc = pDisk->Backend->pfnGetUuid(pImageTo->pvBackendData, 1470 &Uuid); 1471 AssertRC(rc); 1472 rc = pDisk->Backend->pfnSetParentUuid(pImageFrom->pNext, 1473 &Uuid); 1474 AssertRC(rc); 1475 } 1476 } 1477 1478 /* Delete the no longer needed images. */ 1479 PVDIMAGE pImg = pImageFrom, pTmp; 1480 while (pImg != pImageTo) 1481 { 1482 if (nImageFrom < nImageTo) 1483 pTmp = pImg->pNext; 1484 else 1485 pTmp = pImg->pPrev; 1486 vdRemoveImageFromList(pDisk, pImg); 1487 pDisk->Backend->pfnClose(pImg->pvBackendData, true); 1488 pImg = pTmp; 1489 } 1490 } while (0); 1491 1492 if (pvBuf) 1493 RTMemTmpFree(pvBuf); 1494 1495 if (VBOX_SUCCESS(rc) && pfnProgress) 1496 pfnProgress(NULL /* WARNING! pVM=NULL */, 100, pvUser); 1497 1498 LogFlowFunc(("returns %Vrc\n", rc)); 1499 return rc; 1500 } 1501 1502 /** 1503 * Copies an image from one HDD container to another. 1504 * The copy is opened in the target HDD container. 1119 1505 * It is possible to convert between different image formats, because the 1120 * backend for the destination VBoxHDD container may be different from the1506 * backend for the destination HDD container may be different from the 1121 1507 * source container. 1122 * If both the source and destination reference the same VBoxHDD container,1123 * then the image is moved (by copying/deleting ) to the new location.1508 * If both the source and destination reference the same HDD container, 1509 * then the image is moved (by copying/deleting or renaming) to the new location. 1124 1510 * The source container is unchanged if the move operation fails, otherwise 1125 1511 * the image at the new location is opened in the same way as the old one was. 1126 1512 * 1127 1513 * @returns VBox status code. 1128 * @param pDiskFrom Pointer to source VBox HDD container. 1514 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1515 * @param pDiskFrom Pointer to source HDD container. 1129 1516 * @param nImage Image number, counts from 0. 0 is always base image of container. 1130 * @param pDiskTo Pointer to destination VBox HDD container. 1517 * @param pDiskTo Pointer to destination HDD container. 1518 * @param pszFilename New name of the image (may be NULL if pDiskFrom == pDiskTo). 1519 * @param fMoveByRename If true, attempt to perform a move by renaming (if successful the new size is ignored). 1520 * @param cbSize New image size (0 means leave unchanged). 1131 1521 * @param pfnProgress Progress callback. Optional. NULL if not to be used. 1132 1522 * @param pvUser User argument for the progress callback. 1133 1523 */ 1134 1524 VBOXDDU_DECL(int) VDCopy(PVBOXHDD pDiskFrom, unsigned nImage, PVBOXHDD pDiskTo, 1135 PFNVMPROGRESS pfnProgress, void *pvUser) 1525 const char *pszFilename, bool fMoveByRename, 1526 uint64_t cbSize, PFNVMPROGRESS pfnProgress, 1527 void *pvUser) 1136 1528 { 1137 1529 return VERR_NOT_IMPLEMENTED; … … 1139 1531 1140 1532 /** 1141 * Compacts a growing image file by removing zeroed data blocks. 1142 * Optionally defragments data in the image so that ascending sector numbers 1143 * are stored in ascending location in the image file. 1144 * 1145 * @todo maybe include this function in VDCopy. 1146 * 1147 * @returns VBox status code. 1148 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1149 * @param pDisk Pointer to VBox HDD container. 1150 * @param nImage Image number, counts from 0. 0 is always base image of container. 1151 * @param fDefragment If true, reorder file data so that sectors are stored in ascending order. 1152 * @param pfnProgress Progress callback. Optional. NULL if not to be used. 1153 * @param pvUser User argument for the progress callback. 1154 */ 1155 VBOXDDU_DECL(int) VDCompact(PVBOXHDD pDisk, unsigned nImage, 1156 bool fDefragment, 1157 PFNVMPROGRESS pfnProgress, void *pvUser) 1158 { 1159 return VERR_NOT_IMPLEMENTED; 1160 } 1161 1162 /** 1163 * Resizes an image. Allows setting the disk size to both larger and smaller 1164 * values than the current disk size. 1165 * 1166 * @returns VBox status code. 1167 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1168 * @param pDisk Pointer to VBox HDD container. 1169 * @param nImage Image number, counts from 0. 0 is always base image of container. 1170 * @param cbSize New image size in bytes. 1171 * @param pfnProgress Progress callback. Optional. NULL if not to be used. 1172 * @param pvUser User argument for the progress callback. 1173 */ 1174 VBOXDDU_DECL(int) VDResize(PVBOXHDD pDisk, unsigned nImage, uint64_t cbSize, 1175 PFNVMPROGRESS pfnProgress, void *pvUser) 1176 { 1177 return VERR_NOT_IMPLEMENTED; 1178 } 1179 1180 /** 1181 * Closes the last opened image file in the HDD container. Leaves all changes inside it. 1533 * Closes the last opened image file in HDD container. 1182 1534 * If previous image file was opened in read-only mode (that is normal) and closing image 1183 1535 * was opened in read-write mode (the whole disk was in read-write mode) - the previous image 1184 1536 * will be reopened in read/write mode. 1185 1537 * 1186 * @param pDisk Pointer to VBox HDD container. 1538 * @returns VBox status code. 1539 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1540 * @param pDisk Pointer to HDD container. 1187 1541 * @param fDelete If true, delete the image from the host disk. 1188 1542 */ 1189 1543 VBOXDDU_DECL(int) VDClose(PVBOXHDD pDisk, bool fDelete) 1190 1544 { 1191 LogFlow(("%s: fDelete=%d\n", __FUNCTION__, fDelete)); 1192 /* sanity check */ 1193 Assert(pDisk); 1194 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1195 1196 PVDIMAGE pImage = pDisk->pLast; 1197 unsigned uOpenFlags = pDisk->Backend->pfnGetOpenFlags(pImage->pvBackendData); 1198 /* Remove image from list of opened images. */ 1199 vdRemoveImageFromList(pDisk, pImage); 1200 /* Close (and optionally delete) image. */ 1201 int rc = pDisk->Backend->pfnClose(pImage->pvBackendData, fDelete); 1202 /* Free remaining resources related to the image. */ 1203 RTStrFree(pImage->pszFilename); 1204 RTMemFree(pImage); 1205 1206 /* If disk was previously in read/write mode, make sure it will stay like 1207 * this after closing this image. Set the open flags accordingly. */ 1208 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1209 { 1210 uOpenFlags = pDisk->Backend->pfnGetOpenFlags(pDisk->pLast->pvBackendData); 1211 uOpenFlags &= ~ VD_OPEN_FLAGS_READONLY; 1212 rc = pDisk->Backend->pfnSetOpenFlags(pDisk->pLast->pvBackendData, 1213 uOpenFlags); 1214 } 1215 1216 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 1217 return rc; 1218 } 1219 1220 /** 1221 * Closes all opened image files in HDD container. 1222 * 1223 * @param pDisk Pointer to VDI HDD container. 1224 */ 1225 VBOXDDU_DECL(int) VDCloseAll(PVBOXHDD pDisk) 1226 { 1227 LogFlow(("%s:\n", __FUNCTION__)); 1228 /* sanity check */ 1229 Assert(pDisk); 1230 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1231 1232 PVDIMAGE pImage = pDisk->pLast; 1233 int rc = VINF_SUCCESS; 1234 while (pImage) 1235 { 1236 PVDIMAGE pPrev = pImage->pPrev; 1545 int rc = VINF_SUCCESS;; 1546 1547 LogFlowFunc(("fDelete=%d\n", fDelete)); 1548 do 1549 { 1550 /* sanity check */ 1551 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 1552 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1553 1554 PVDIMAGE pImage = pDisk->pLast; 1555 if (RT_UNLIKELY(!pImage)) 1556 { 1557 Assert(pImage); 1558 rc = VERR_VDI_NOT_OPENED; 1559 break; 1560 } 1561 unsigned uOpenFlags = pDisk->Backend->pfnGetOpenFlags(pImage->pvBackendData); 1237 1562 /* Remove image from list of opened images. */ 1238 1563 vdRemoveImageFromList(pDisk, pImage); 1239 /* Close image. */ 1240 int rc2 = pDisk->Backend->pfnClose(pImage->pvBackendData, false); 1241 if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc)) 1242 rc = rc2; 1564 /* Close (and optionally delete) image. */ 1565 rc = pDisk->Backend->pfnClose(pImage->pvBackendData, fDelete); 1243 1566 /* Free remaining resources related to the image. */ 1244 1567 RTStrFree(pImage->pszFilename); 1245 1568 RTMemFree(pImage); 1246 pImage = pPrev; 1247 } 1248 Assert(pDisk->pLast == NULL); 1249 1250 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 1569 1570 pImage = pDisk->pLast; 1571 if (!pImage) 1572 break; 1573 1574 /* If disk was previously in read/write mode, make sure it will stay 1575 * like this (if possible) after closing this image. Set the open flags 1576 * accordingly. */ 1577 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1578 { 1579 uOpenFlags = pDisk->Backend->pfnGetOpenFlags(pImage->pvBackendData); 1580 uOpenFlags &= ~ VD_OPEN_FLAGS_READONLY; 1581 rc = pDisk->Backend->pfnSetOpenFlags(pImage->pvBackendData, uOpenFlags); 1582 } 1583 1584 int rc2; 1585 1586 /* Cache disk information. */ 1587 pDisk->cbSize = pDisk->Backend->pfnGetSize(pImage->pvBackendData); 1588 1589 /* Cache PCHS geometry. */ 1590 rc2 = pDisk->Backend->pfnGetPCHSGeometry(pImage->pvBackendData, 1591 &pDisk->PCHSGeometry); 1592 if (VBOX_FAILURE(rc2)) 1593 { 1594 pDisk->PCHSGeometry.cCylinders = 0; 1595 pDisk->PCHSGeometry.cHeads = 0; 1596 pDisk->PCHSGeometry.cSectors = 0; 1597 } 1598 else 1599 { 1600 /* Make sure the PCHS geometry is properly clipped. */ 1601 pDisk->PCHSGeometry.cCylinders = RT_MIN(pDisk->PCHSGeometry.cCylinders, 16383); 1602 pDisk->PCHSGeometry.cHeads = RT_MIN(pDisk->PCHSGeometry.cHeads, 16); 1603 pDisk->PCHSGeometry.cSectors = RT_MIN(pDisk->PCHSGeometry.cSectors, 63); 1604 } 1605 1606 /* Cache LCHS geometry. */ 1607 rc2 = pDisk->Backend->pfnGetLCHSGeometry(pImage->pvBackendData, 1608 &pDisk->LCHSGeometry); 1609 if (VBOX_FAILURE(rc2)) 1610 { 1611 pDisk->LCHSGeometry.cCylinders = 0; 1612 pDisk->LCHSGeometry.cHeads = 0; 1613 pDisk->LCHSGeometry.cSectors = 0; 1614 } 1615 else 1616 { 1617 /* Make sure the LCHS geometry is properly clipped. */ 1618 pDisk->LCHSGeometry.cCylinders = RT_MIN(pDisk->LCHSGeometry.cCylinders, 1024); 1619 pDisk->LCHSGeometry.cHeads = RT_MIN(pDisk->LCHSGeometry.cHeads, 255); 1620 pDisk->LCHSGeometry.cSectors = RT_MIN(pDisk->LCHSGeometry.cSectors, 63); 1621 } 1622 } while (0); 1623 1624 LogFlowFunc(("returns %Vrc\n", rc)); 1625 return rc; 1626 } 1627 1628 /** 1629 * Closes all opened image files in HDD container. 1630 * 1631 * @returns VBox status code. 1632 * @param pDisk Pointer to HDD container. 1633 */ 1634 VBOXDDU_DECL(int) VDCloseAll(PVBOXHDD pDisk) 1635 { 1636 int rc = VINF_SUCCESS; 1637 1638 LogFlowFunc(("pDisk=%#p\n", pDisk)); 1639 do 1640 { 1641 /* sanity check */ 1642 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 1643 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1644 1645 PVDIMAGE pImage = pDisk->pLast; 1646 while (pImage) 1647 { 1648 PVDIMAGE pPrev = pImage->pPrev; 1649 /* Remove image from list of opened images. */ 1650 vdRemoveImageFromList(pDisk, pImage); 1651 /* Close image. */ 1652 int rc2 = pDisk->Backend->pfnClose(pImage->pvBackendData, false); 1653 if (VBOX_FAILURE(rc2) && VBOX_SUCCESS(rc)) 1654 rc = rc2; 1655 /* Free remaining resources related to the image. */ 1656 RTStrFree(pImage->pszFilename); 1657 RTMemFree(pImage); 1658 pImage = pPrev; 1659 } 1660 Assert(pDisk->pLast == NULL); 1661 } while (0); 1662 1663 LogFlowFunc(("returns %Vrc\n", rc)); 1251 1664 return rc; 1252 1665 } … … 1256 1669 * 1257 1670 * @returns VBox status code. 1258 * @param pDisk Pointer to VBox HDD container. 1671 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1672 * @param pDisk Pointer to HDD container. 1259 1673 * @param uOffset Offset of first reading byte from start of disk. 1260 1674 * @param pvBuf Pointer to buffer for reading data. 1261 1675 * @param cbRead Number of bytes to read. 1262 1676 */ 1263 VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuf, size_t cbRead) 1264 { 1265 /* sanity check */ 1266 LogFlow(("%s: offset=%llu cbRead=%u\n", __FUNCTION__, uOffset, (unsigned)cbRead)); 1267 Assert(pDisk); 1268 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1269 1270 int rc = VINF_SUCCESS; 1271 PVDIMAGE pImage = pDisk->pLast; 1272 if (RT_UNLIKELY(!pImage)) 1273 { 1274 Assert(pImage); 1275 rc = VERR_VDI_NOT_OPENED; 1276 goto out; 1277 } 1278 1279 /* Check params. */ 1280 if (uOffset + cbRead > pDisk->cbSize || cbRead == 0) 1281 { 1282 AssertMsgFailed(("uOffset=%llu cbRead=%u\n", uOffset, cbRead)); 1283 return VERR_INVALID_PARAMETER; 1284 } 1285 1286 rc = vdReadHelper(pDisk, pImage, uOffset, pvBuf, cbRead); 1287 out: 1288 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 1677 VBOXDDU_DECL(int) VDRead(PVBOXHDD pDisk, uint64_t uOffset, void *pvBuf, 1678 size_t cbRead) 1679 { 1680 int rc; 1681 1682 LogFlowFunc(("pDisk=%#p uOffset=%llu pvBuf=%p cbRead=%llu\n", 1683 pDisk, uOffset, pvBuf, cbRead)); 1684 do 1685 { 1686 /* sanity check */ 1687 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 1688 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1689 1690 /* Check arguments. */ 1691 AssertMsgBreak(VALID_PTR(pvBuf), 1692 ("pvBuf=%#p\n", pvBuf), 1693 rc = VERR_INVALID_PARAMETER); 1694 AssertMsgBreak(cbRead, 1695 ("cbRead=%llu\n", cbRead), 1696 rc = VERR_INVALID_PARAMETER); 1697 AssertMsgBreak(uOffset + cbRead > pDisk->cbSize, 1698 ("uOffset=%llu cbRead=%llu pDisk->cbSize=%llu\n", 1699 uOffset, cbRead, pDisk->cbSize), 1700 rc = VERR_INVALID_PARAMETER); 1701 1702 PVDIMAGE pImage = pDisk->pLast; 1703 AssertBreak(pImage, rc = VERR_VDI_NOT_OPENED); 1704 1705 rc = vdReadHelper(pDisk, pImage, uOffset, pvBuf, cbRead); 1706 } while (0); 1707 1708 LogFlowFunc(("returns %Vrc\n", rc)); 1289 1709 return rc; 1290 1710 } … … 1294 1714 * 1295 1715 * @returns VBox status code. 1296 * @param pDisk Pointer to VBox HDD container. 1716 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1717 * @param pDisk Pointer to HDD container. 1297 1718 * @param uOffset Offset of first reading byte from start of disk. 1298 1719 * @param pvBuf Pointer to buffer for writing data. … … 1301 1722 VBOXDDU_DECL(int) VDWrite(PVBOXHDD pDisk, uint64_t uOffset, const void *pvBuf, size_t cbWrite) 1302 1723 { 1303 /* sanity check */1304 Assert(pDisk);1305 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));1306 1307 1724 int rc = VINF_SUCCESS; 1308 size_t cbThisWrite; 1309 size_t cbPreRead, cbPostRead; 1310 PVDIMAGE pImage = pDisk->pLast; 1311 if (RT_UNLIKELY(!pImage)) 1312 { 1313 Assert(pImage); 1314 rc = VERR_VDI_NOT_OPENED; 1315 goto out; 1316 } 1317 1318 /* Check params. */ 1319 if (uOffset + cbWrite > pDisk->cbSize || cbWrite == 0) 1320 { 1321 AssertMsgFailed(("uOffset=%llu cbWrite=%u\n", uOffset, cbWrite)); 1322 rc = VERR_INVALID_PARAMETER; 1323 goto out; 1324 } 1325 1326 vdSetModifiedFlag(pDisk); 1327 1328 /* Loop until all written. */ 1329 do 1330 { 1331 /* Try to write the possibly partial block to the last opened image. 1332 * This works when the block is already allocated in this image or 1333 * if it is a full-block write, which automatically allocates a new 1334 * block if needed. */ 1335 cbThisWrite = cbWrite; 1336 rc = pDisk->Backend->pfnWrite(pImage->pvBackendData, uOffset, pvBuf, 1337 cbThisWrite, &cbThisWrite, 1338 &cbPreRead, &cbPostRead); 1339 if (rc == VINF_VDI_BLOCK_FREE) 1340 { 1341 void *pvTmp = RTMemTmpAlloc(cbPreRead + cbThisWrite + cbPostRead); 1342 if (!pvBuf) 1343 { 1344 Assert(!pvBuf); 1345 rc = VERR_NO_MEMORY; 1346 break; 1347 } 1348 1349 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_HONOR_SAME)) 1350 { 1351 /* Optimized write, suppress writing to a so far unallocated 1352 * block when the data is identical than as of the parent. */ 1353 rc = vdWriteHelperOptimized(pDisk, pImage, uOffset, 1354 cbWrite, cbThisWrite, 1355 cbPreRead, cbPostRead, 1356 pvBuf, pvTmp); 1357 } 1358 else 1359 { 1360 /* Normal write, not optimized in any way. The block will be 1361 * written no matter what. This will usually (unless the 1362 * backend has some further optimization enabled) cause the 1363 * block to be allocated. */ 1364 rc = vdWriteHelperStandard(pDisk, pImage, uOffset, 1365 cbWrite, cbThisWrite, 1366 cbPreRead, cbPostRead, 1367 pvBuf, pvTmp); 1368 } 1369 RTMemTmpFree(pvTmp); 1370 if (VBOX_FAILURE(rc)) 1371 break; 1372 } 1373 1374 cbWrite -= cbThisWrite; 1375 uOffset += cbThisWrite; 1376 pvBuf = (char *)pvBuf + cbThisWrite; 1377 } while (cbWrite != 0 && VBOX_SUCCESS(rc)); 1378 1379 out: 1380 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 1725 1726 LogFlowFunc(("pDisk=%#p uOffset=%llu pvBuf=%p cbWrite=%llu\n", 1727 pDisk, uOffset, pvBuf, cbWrite)); 1728 do 1729 { 1730 /* sanity check */ 1731 AssertBreak(VALID_PTR(pDisk), VERR_INVALID_PARAMETER); 1732 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1733 1734 /* Check arguments. */ 1735 AssertMsgBreak(VALID_PTR(pvBuf), 1736 ("pvBuf=%#p\n", pvBuf), 1737 rc = VERR_INVALID_PARAMETER); 1738 AssertMsgBreak(cbWrite, 1739 ("cbWrite=%llu\n", cbWrite), 1740 rc = VERR_INVALID_PARAMETER); 1741 AssertMsgBreak(uOffset + cbWrite > pDisk->cbSize, 1742 ("uOffset=%llu cbWrite=%llu pDisk->cbSize=%llu\n", 1743 uOffset, cbWrite, pDisk->cbSize), 1744 rc = VERR_INVALID_PARAMETER); 1745 1746 PVDIMAGE pImage = pDisk->pLast; 1747 AssertBreak(pImage, rc = VERR_VDI_NOT_OPENED); 1748 1749 vdSetModifiedFlag(pDisk); 1750 rc = vdWriteHelper(pDisk, pImage, uOffset, pvBuf, cbWrite); 1751 } while (0); 1752 1753 LogFlowFunc(("returns %Vrc\n", rc)); 1381 1754 return rc; 1382 1755 } … … 1386 1759 * 1387 1760 * @returns VBox status code. 1388 * @param pDisk Pointer to VBox HDD container. 1761 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1762 * @param pDisk Pointer to HDD container. 1389 1763 */ 1390 1764 VBOXDDU_DECL(int) VDFlush(PVBOXHDD pDisk) 1391 1765 { 1392 /* sanity check */1393 Assert(pDisk);1394 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));1395 1396 1766 int rc = VINF_SUCCESS; 1397 PVDIMAGE pImage = pDisk->pLast; 1398 if (RT_UNLIKELY(!pImage)) 1399 { 1400 Assert(pImage); 1401 rc = VERR_VDI_NOT_OPENED; 1402 } 1403 else 1404 { 1767 1768 LogFlowFunc(("pDisk=%#p\n", pDisk)); 1769 do 1770 { 1771 /* sanity check */ 1772 AssertBreak(VALID_PTR(pDisk), VERR_INVALID_PARAMETER); 1773 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1774 1775 PVDIMAGE pImage = pDisk->pLast; 1776 AssertBreak(pImage, rc = VERR_VDI_NOT_OPENED); 1777 1405 1778 vdResetModifiedFlag(pDisk); 1406 1779 rc = pDisk->Backend->pfnFlush(pImage->pvBackendData); 1407 } 1408 1409 LogFlow (("%s: returns %Vrc\n", __FUNCTION__, rc));1780 } while (0); 1781 1782 LogFlowFunc(("returns %Vrc\n", rc)); 1410 1783 return rc; 1411 1784 } … … 1415 1788 * 1416 1789 * @returns Number of opened images for HDD container. 0 if no images have been opened. 1417 * @param pDisk Pointer to VBoxHDD container.1790 * @param pDisk Pointer to HDD container. 1418 1791 */ 1419 1792 VBOXDDU_DECL(unsigned) VDGetCount(PVBOXHDD pDisk) 1420 1793 { 1421 /* sanity check */ 1422 Assert(pDisk); 1423 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1424 1425 unsigned c = pDisk->cImages; 1426 LogFlow(("%s: returns %d\n", __FUNCTION__, c)); 1427 return c; 1428 } 1429 1430 /** 1431 * Get read/write mode of the VBox HDD container. 1794 unsigned cImages; 1795 1796 LogFlowFunc(("pDisk=%#p\n", pDisk)); 1797 do 1798 { 1799 /* sanity check */ 1800 AssertBreak(VALID_PTR(pDisk), cImages = 0); 1801 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1802 1803 cImages = pDisk->cImages; 1804 } while (0); 1805 1806 LogFlowFunc(("returns %u\n", cImages)); 1807 return cImages; 1808 } 1809 1810 /** 1811 * Get read/write mode of HDD container. 1432 1812 * 1433 1813 * @returns Virtual disk ReadOnly status. 1434 1814 * @returns true if no image is opened in HDD container. 1435 * @param pDisk Pointer to VBoxHDD container.1815 * @param pDisk Pointer to HDD container. 1436 1816 */ 1437 1817 VBOXDDU_DECL(bool) VDIsReadOnly(PVBOXHDD pDisk) 1438 1818 { 1439 /* sanity check */ 1440 Assert(pDisk); 1441 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1442 1443 bool f; 1444 if (pDisk->pLast) 1445 { 1819 bool fReadOnly; 1820 1821 LogFlowFunc(("pDisk=%#p\n", pDisk)); 1822 do 1823 { 1824 /* sanity check */ 1825 AssertBreak(VALID_PTR(pDisk), fReadOnly = false); 1826 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1827 1828 PVDIMAGE pImage = pDisk->pLast; 1829 AssertBreak(pImage, fReadOnly = true); 1830 1446 1831 unsigned uOpenFlags; 1447 1832 uOpenFlags = pDisk->Backend->pfnGetOpenFlags(pDisk->pLast->pvBackendData); 1448 f = !!(uOpenFlags & VD_OPEN_FLAGS_READONLY); 1449 } 1450 else 1451 { 1452 AssertMsgFailed(("No disk image is opened!\n")); 1453 f = true; 1454 } 1455 1456 LogFlow(("%s: returns %d\n", __FUNCTION__, f)); 1457 return f; 1458 } 1459 1460 /** 1461 * Get total disk size of the VBox HDD container. 1833 fReadOnly = !!(uOpenFlags & VD_OPEN_FLAGS_READONLY); 1834 } while (0); 1835 1836 LogFlowFunc(("returns %d\n", fReadOnly)); 1837 return fReadOnly; 1838 } 1839 1840 /** 1841 * Get total capacity of an image in HDD container. 1842 * 1843 * @returns Virtual disk size in bytes. 1844 * @returns 0 if no image with specified number was not opened. 1845 * @param pDisk Pointer to HDD container. 1846 * @param nImage Image number, counds from 0. 0 is always base image of container. 1847 */ 1848 VBOXDDU_DECL(uint64_t) VDGetSize(PVBOXHDD pDisk, unsigned nImage) 1849 { 1850 uint64_t cbSize; 1851 1852 LogFlowFunc(("pDisk=%#p nImage=%u\n", pDisk, nImage)); 1853 do 1854 { 1855 /* sanity check */ 1856 AssertBreak(VALID_PTR(pDisk), cbSize = 0); 1857 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1858 1859 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 1860 AssertBreak(pImage, cbSize = 0); 1861 cbSize = pDisk->Backend->pfnGetSize(pImage->pvBackendData); 1862 } while (0); 1863 1864 LogFlowFunc(("returns %llu\n", cbSize)); 1865 return cbSize; 1866 } 1867 1868 /** 1869 * Get total file size of an image in HDD container. 1462 1870 * 1463 1871 * @returns Virtual disk size in bytes. 1464 1872 * @returns 0 if no image is opened in HDD container. 1465 * @param pDisk Pointer to VBox HDD container. 1466 */ 1467 VBOXDDU_DECL(uint64_t) VDGetSize(PVBOXHDD pDisk) 1468 { 1469 /* sanity check */ 1470 Assert(pDisk); 1471 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1472 1473 uint64_t cb = pDisk->cbSize; 1474 LogFlow(("%s: returns %lld\n", __FUNCTION__, cb)); 1475 return cb; 1476 } 1477 1478 /** 1479 * Get virtual disk geometry stored in HDD container. 1480 * 1481 * @returns VBox status code. 1482 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1873 * @param pDisk Pointer to HDD container. 1874 * @param nImage Image number, counts from 0. 0 is always base image of container. 1875 */ 1876 VBOXDDU_DECL(uint64_t) VDGetFileSize(PVBOXHDD pDisk, unsigned nImage) 1877 { 1878 uint64_t cbSize; 1879 1880 LogFlowFunc(("pDisk=%#p nImage=%u\n", pDisk, nImage)); 1881 do 1882 { 1883 /* sanity check */ 1884 AssertBreak(VALID_PTR(pDisk), cbSize = 0); 1885 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1886 1887 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 1888 AssertBreak(pImage, cbSize = 0); 1889 cbSize = pDisk->Backend->pfnGetFileSize(pImage->pvBackendData); 1890 } while (0); 1891 1892 LogFlowFunc(("returns %llu\n", cbSize)); 1893 return cbSize; 1894 } 1895 1896 /** 1897 * Get virtual disk PCHS geometry stored in HDD container. 1898 * 1899 * @returns VBox status code. 1900 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1483 1901 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 1484 * @param pDisk Pointer to VBox HDD container. 1485 * @param pcCylinders Where to store the number of cylinders. NULL is ok. 1486 * @param pcHeads Where to store the number of heads. NULL is ok. 1487 * @param pcSectors Where to store the number of sectors. NULL is ok. 1488 */ 1489 VBOXDDU_DECL(int) VDGetGeometry(PVBOXHDD pDisk, unsigned *pcCylinders, 1490 unsigned *pcHeads, unsigned *pcSectors) 1491 { 1492 /* sanity check */ 1493 Assert(pDisk); 1494 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1495 1902 * @param pDisk Pointer to HDD container. 1903 * @param nImage Image number, counts from 0. 0 is always base image of container. 1904 * @param pPCHSGeometry Where to store PCHS geometry. Not NULL. 1905 */ 1906 VBOXDDU_DECL(int) VDGetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 1907 PPDMMEDIAGEOMETRY pPCHSGeometry) 1908 { 1496 1909 int rc = VINF_SUCCESS; 1497 PVDIMAGE pImage = pDisk->pBase; 1498 if (RT_UNLIKELY(!pImage)) 1499 { 1500 Assert(pImage); 1501 rc = VERR_VDI_NOT_OPENED; 1502 } 1503 else 1504 { 1505 if (pDisk->cCylinders != 0) 1506 { 1507 if (pcCylinders) 1508 *pcCylinders = pDisk->cCylinders; 1509 if (pcHeads) 1510 *pcHeads = pDisk->cHeads; 1511 if (pcSectors) 1512 *pcSectors = pDisk->cSectors; 1910 1911 LogFlowFunc(("pDisk=%#p nImage=%u pPCHSGeometry=%#p\n", 1912 pDisk, nImage, pPCHSGeometry)); 1913 do 1914 { 1915 /* sanity check */ 1916 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 1917 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1918 1919 /* Check arguments. */ 1920 AssertMsgBreak(VALID_PTR(pPCHSGeometry), 1921 ("pPCHSGeometry=%#p\n", pPCHSGeometry), 1922 rc = VERR_INVALID_PARAMETER); 1923 1924 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 1925 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 1926 1927 if (pImage == pDisk->pLast) 1928 { 1929 /* Use cached information if possible. */ 1930 if (pDisk->PCHSGeometry.cCylinders != 0) 1931 *pPCHSGeometry = pDisk->PCHSGeometry; 1932 else 1933 rc = VERR_VDI_GEOMETRY_NOT_SET; 1513 1934 } 1514 1935 else 1515 rc = VERR_VDI_GEOMETRY_NOT_SET; 1516 } 1517 LogFlow(("%s: %Vrc (CHS=%u/%u/%u)\n", __FUNCTION__, rc, 1518 pDisk->cCylinders, pDisk->cHeads, pDisk->cSectors)); 1519 return rc; 1520 } 1521 1522 /** 1523 * Store virtual disk geometry in HDD container. 1936 rc = pDisk->Backend->pfnGetPCHSGeometry(pImage->pvBackendData, 1937 pPCHSGeometry); 1938 } while (0); 1939 1940 LogFlowFunc(("%s: %Vrc (PCHS=%u/%u/%u)\n", rc, 1941 pDisk->PCHSGeometry.cCylinders, pDisk->PCHSGeometry.cHeads, 1942 pDisk->PCHSGeometry.cSectors)); 1943 return rc; 1944 } 1945 1946 /** 1947 * Store virtual disk PCHS geometry in HDD container. 1524 1948 * 1525 1949 * Note that in case of unrecoverable error all images in HDD container will be closed. 1526 1950 * 1527 1951 * @returns VBox status code. 1528 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1529 * @param pDisk Pointer to VBox HDD container. 1530 * @param cCylinders Number of cylinders. 1531 * @param cHeads Number of heads. 1532 * @param cSectors Number of sectors. 1533 */ 1534 VBOXDDU_DECL(int) VDSetGeometry(PVBOXHDD pDisk, unsigned cCylinders, 1535 unsigned cHeads, unsigned cSectors) 1536 { 1537 /* sanity check */ 1538 Assert(pDisk); 1539 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1540 1952 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1953 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 1954 * @param pDisk Pointer to HDD container. 1955 * @param nImage Image number, counts from 0. 0 is always base image of container. 1956 * @param pPCHSGeometry Where to load PCHS geometry from. Not NULL. 1957 */ 1958 VBOXDDU_DECL(int) VDSetPCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 1959 PCPDMMEDIAGEOMETRY pPCHSGeometry) 1960 { 1541 1961 int rc = VINF_SUCCESS; 1542 PVDIMAGE pImage = pDisk->pBase; 1543 if (RT_UNLIKELY(!pImage)) 1544 { 1545 Assert(pImage); 1546 rc = VERR_VDI_NOT_OPENED; 1547 } 1548 else 1549 { 1550 if ( cCylinders != pDisk->cCylinders 1551 || cHeads != pDisk->cHeads 1552 || cSectors != pDisk->cSectors) 1553 { 1554 /* Only update geometry if it is changed. Avoids similar checks 1555 * in every backend. Most of the time the new geometry is set to 1556 * the previous values, so no need to go through the hassle of 1557 * updating an image which could be opened in read-only mode right 1558 * now. */ 1559 rc = pDisk->Backend->pfnSetGeometry(pImage->pvBackendData, 1560 cCylinders, cHeads, cSectors); 1561 1562 /* Cache new geometry values in any case, whether successful or not. */ 1563 int rc2 = pDisk->Backend->pfnGetGeometry(pImage->pvBackendData, 1564 &pDisk->cCylinders, 1565 &pDisk->cHeads, 1566 &pDisk->cSectors); 1567 if (VBOX_FAILURE(rc2)) 1962 1963 LogFlowFunc(("pDisk=%#p nImage=%u pPCHSGeometry=%#p PCHS=%u/%u/%u\n", 1964 pDisk, nImage, pPCHSGeometry, pPCHSGeometry->cCylinders, 1965 pPCHSGeometry->cHeads, pPCHSGeometry->cSectors)); 1966 do 1967 { 1968 /* sanity check */ 1969 AssertBreak(VALID_PTR(pDisk), VERR_INVALID_PARAMETER); 1970 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1971 1972 /* Check arguments. */ 1973 AssertMsgBreak( VALID_PTR(pPCHSGeometry) 1974 && pPCHSGeometry->cCylinders <= 16383 1975 && pPCHSGeometry->cCylinders != 0 1976 && pPCHSGeometry->cHeads <= 16 1977 && pPCHSGeometry->cHeads != 0 1978 && pPCHSGeometry->cSectors <= 63 1979 && pPCHSGeometry->cSectors != 0, 1980 ("pPCHSGeometry=%#p PCHS=%u/%u/%u\n", pPCHSGeometry, 1981 pPCHSGeometry->cCylinders, pPCHSGeometry->cHeads, 1982 pPCHSGeometry->cSectors), 1983 rc = VERR_INVALID_PARAMETER); 1984 1985 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 1986 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 1987 1988 if (pImage == pDisk->pLast) 1989 { 1990 if ( pPCHSGeometry->cCylinders != pDisk->PCHSGeometry.cCylinders 1991 || pPCHSGeometry->cHeads != pDisk->PCHSGeometry.cHeads 1992 || pPCHSGeometry->cSectors != pDisk->PCHSGeometry.cSectors) 1568 1993 { 1569 pDisk->cCylinders = 0; 1570 pDisk->cHeads = 0; 1571 pDisk->cSectors = 0; 1994 /* Only update geometry if it is changed. Avoids similar checks 1995 * in every backend. Most of the time the new geometry is set 1996 * to the previous values, so no need to go through the hassle 1997 * of updating an image which could be opened in read-only mode 1998 * right now. */ 1999 rc = pDisk->Backend->pfnSetPCHSGeometry(pImage->pvBackendData, 2000 pPCHSGeometry); 2001 2002 /* Cache new geometry values in any case. */ 2003 int rc2 = pDisk->Backend->pfnGetPCHSGeometry(pImage->pvBackendData, 2004 &pDisk->PCHSGeometry); 2005 if (VBOX_FAILURE(rc2)) 2006 { 2007 pDisk->PCHSGeometry.cCylinders = 0; 2008 pDisk->PCHSGeometry.cHeads = 0; 2009 pDisk->PCHSGeometry.cSectors = 0; 2010 } 2011 else 2012 { 2013 /* Make sure the CHS geometry is properly clipped. */ 2014 pDisk->PCHSGeometry.cCylinders = RT_MIN(pDisk->PCHSGeometry.cCylinders, 1024); 2015 pDisk->PCHSGeometry.cHeads = RT_MIN(pDisk->PCHSGeometry.cHeads, 255); 2016 pDisk->PCHSGeometry.cSectors = RT_MIN(pDisk->PCHSGeometry.cSectors, 63); 2017 } 1572 2018 } 2019 } 2020 else 2021 { 2022 PDMMEDIAGEOMETRY PCHS; 2023 rc = pDisk->Backend->pfnGetPCHSGeometry(pImage->pvBackendData, 2024 &PCHS); 2025 if ( VBOX_FAILURE(rc) 2026 || pPCHSGeometry->cCylinders != PCHS.cCylinders 2027 || pPCHSGeometry->cHeads != PCHS.cHeads 2028 || pPCHSGeometry->cSectors != PCHS.cSectors) 2029 { 2030 /* Only update geometry if it is changed. Avoids similar checks 2031 * in every backend. Most of the time the new geometry is set 2032 * to the previous values, so no need to go through the hassle 2033 * of updating an image which could be opened in read-only mode 2034 * right now. */ 2035 rc = pDisk->Backend->pfnSetPCHSGeometry(pImage->pvBackendData, 2036 pPCHSGeometry); 2037 } 2038 } 2039 } while (0); 2040 2041 LogFlowFunc(("returns %Vrc\n", rc)); 2042 return rc; 2043 } 2044 2045 /** 2046 * Get virtual disk LCHS geometry stored in HDD container. 2047 * 2048 * @returns VBox status code. 2049 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 2050 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 2051 * @param pDisk Pointer to HDD container. 2052 * @param nImage Image number, counts from 0. 0 is always base image of container. 2053 * @param pLCHSGeometry Where to store LCHS geometry. Not NULL. 2054 */ 2055 VBOXDDU_DECL(int) VDGetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 2056 PPDMMEDIAGEOMETRY pLCHSGeometry) 2057 { 2058 int rc = VINF_SUCCESS; 2059 2060 LogFlowFunc(("pDisk=%#p nImage=%u pLCHSGeometry=%#p\n", 2061 pDisk, nImage, pLCHSGeometry)); 2062 do 2063 { 2064 /* sanity check */ 2065 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2066 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2067 2068 /* Check arguments. */ 2069 AssertMsgBreak(VALID_PTR(pLCHSGeometry), 2070 ("pLCHSGeometry=%#p\n", pLCHSGeometry), 2071 rc = VERR_INVALID_PARAMETER); 2072 2073 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2074 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2075 2076 if (pImage == pDisk->pLast) 2077 { 2078 /* Use cached information if possible. */ 2079 if (pDisk->LCHSGeometry.cCylinders != 0) 2080 *pLCHSGeometry = pDisk->LCHSGeometry; 1573 2081 else 2082 rc = VERR_VDI_GEOMETRY_NOT_SET; 2083 } 2084 else 2085 rc = pDisk->Backend->pfnGetLCHSGeometry(pImage->pvBackendData, 2086 pLCHSGeometry); 2087 } while (0); 2088 2089 LogFlowFunc(("%s: %Vrc (LCHS=%u/%u/%u)\n", rc, 2090 pDisk->LCHSGeometry.cCylinders, pDisk->LCHSGeometry.cHeads, 2091 pDisk->LCHSGeometry.cSectors)); 2092 return rc; 2093 } 2094 2095 /** 2096 * Store virtual disk LCHS geometry in HDD container. 2097 * 2098 * Note that in case of unrecoverable error all images in HDD container will be closed. 2099 * 2100 * @returns VBox status code. 2101 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 2102 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container. 2103 * @param pDisk Pointer to HDD container. 2104 * @param nImage Image number, counts from 0. 0 is always base image of container. 2105 * @param pLCHSGeometry Where to load LCHS geometry from. Not NULL. 2106 */ 2107 VBOXDDU_DECL(int) VDSetLCHSGeometry(PVBOXHDD pDisk, unsigned nImage, 2108 PCPDMMEDIAGEOMETRY pLCHSGeometry) 2109 { 2110 int rc = VINF_SUCCESS; 2111 2112 LogFlowFunc(("pDisk=%#p nImage=%u pLCHSGeometry=%#p LCHS=%u/%u/%u\n", 2113 pDisk, nImage, pLCHSGeometry, pLCHSGeometry->cCylinders, 2114 pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2115 do 2116 { 2117 /* sanity check */ 2118 AssertBreak(VALID_PTR(pDisk), VERR_INVALID_PARAMETER); 2119 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2120 2121 /* Check arguments. */ 2122 AssertMsgBreak( VALID_PTR(pLCHSGeometry) 2123 && pLCHSGeometry->cCylinders <= 1024 2124 && pLCHSGeometry->cCylinders != 0 2125 && pLCHSGeometry->cHeads <= 255 2126 && pLCHSGeometry->cHeads != 0 2127 && pLCHSGeometry->cSectors <= 63 2128 && pLCHSGeometry->cSectors != 0, 2129 ("pLCHSGeometry=%#p LCHS=%u/%u/%u\n", pLCHSGeometry, 2130 pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, 2131 pLCHSGeometry->cSectors), 2132 rc = VERR_INVALID_PARAMETER); 2133 2134 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2135 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2136 2137 if (pImage == pDisk->pLast) 2138 { 2139 if ( pLCHSGeometry->cCylinders != pDisk->LCHSGeometry.cCylinders 2140 || pLCHSGeometry->cHeads != pDisk->LCHSGeometry.cHeads 2141 || pLCHSGeometry->cSectors != pDisk->LCHSGeometry.cSectors) 1574 2142 { 1575 /* Make sure the CHS geometry is properly clipped. */ 1576 pDisk->cCylinders = RT_MIN(pDisk->cCylinders, 16383); 1577 pDisk->cHeads = RT_MIN(pDisk->cHeads, 255); 1578 pDisk->cSectors = RT_MIN(pDisk->cSectors, 255); 2143 /* Only update geometry if it is changed. Avoids similar checks 2144 * in every backend. Most of the time the new geometry is set 2145 * to the previous values, so no need to go through the hassle 2146 * of updating an image which could be opened in read-only mode 2147 * right now. */ 2148 rc = pDisk->Backend->pfnSetLCHSGeometry(pImage->pvBackendData, 2149 pLCHSGeometry); 2150 2151 /* Cache new geometry values in any case. */ 2152 int rc2 = pDisk->Backend->pfnGetLCHSGeometry(pImage->pvBackendData, 2153 &pDisk->LCHSGeometry); 2154 if (VBOX_FAILURE(rc2)) 2155 { 2156 pDisk->LCHSGeometry.cCylinders = 0; 2157 pDisk->LCHSGeometry.cHeads = 0; 2158 pDisk->LCHSGeometry.cSectors = 0; 2159 } 2160 else 2161 { 2162 /* Make sure the CHS geometry is properly clipped. */ 2163 pDisk->LCHSGeometry.cCylinders = RT_MIN(pDisk->LCHSGeometry.cCylinders, 1024); 2164 pDisk->LCHSGeometry.cHeads = RT_MIN(pDisk->LCHSGeometry.cHeads, 255); 2165 pDisk->LCHSGeometry.cSectors = RT_MIN(pDisk->LCHSGeometry.cSectors, 63); 2166 } 1579 2167 } 1580 2168 } 1581 }1582 1583 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc));1584 return rc;1585 }1586 1587 /**1588 * Get virtual disk translation mode stored in HDD container.1589 *1590 * @returns VBox status code.1591 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container.1592 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the HDD container.1593 * @param pDisk Pointer to VBox HDD container.1594 * @param penmTranslation Where to store the translation mode (see pdm.h).1595 */1596 VBOXDDU_DECL(int) VDGetTranslation(PVBOXHDD pDisk,1597 PPDMBIOSTRANSLATION penmTranslation)1598 {1599 /* sanity check */1600 Assert(pDisk);1601 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));1602 1603 int rc = VINF_SUCCESS;1604 PVDIMAGE pImage = pDisk->pBase;1605 if (RT_UNLIKELY(!pImage))1606 {1607 Assert(pImage);1608 rc = VERR_VDI_NOT_OPENED;1609 }1610 else1611 {1612 if (pDisk->enmTranslation != 0)1613 *penmTranslation = pDisk->enmTranslation;1614 2169 else 1615 rc = VERR_VDI_GEOMETRY_NOT_SET; 1616 } 1617 LogFlow(("%s: %Vrc (translation=%u)\n", __FUNCTION__, rc, 1618 pDisk->enmTranslation)); 1619 return rc; 1620 } 1621 1622 /** 1623 * Store virtual disk translation mode in HDD container. 1624 * 1625 * Note that in case of unrecoverable error all images in HDD container will be closed. 1626 * 1627 * @returns VBox status code. 1628 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1629 * @param pDisk Pointer to VBox HDD container. 1630 * @param enmTranslation Translation mode (see pdm.h). 1631 */ 1632 VBOXDDU_DECL(int) VDSetTranslation(PVBOXHDD pDisk, 1633 PDMBIOSTRANSLATION enmTranslation) 1634 { 1635 /* sanity check */ 1636 Assert(pDisk); 1637 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1638 1639 int rc = VINF_SUCCESS; 1640 PVDIMAGE pImage = pDisk->pBase; 1641 if (RT_UNLIKELY(!pImage)) 1642 { 1643 Assert(pImage); 1644 rc = VERR_VDI_NOT_OPENED; 1645 } 1646 else 1647 { 1648 if (enmTranslation == 0) 1649 rc = VERR_INVALID_PARAMETER; 1650 else if (enmTranslation != pDisk->enmTranslation) 1651 { 1652 /* Only update translation mode if it is changed. Avoids similar 1653 * checks in every backend. Most of the time the new translation 1654 * mode is set to the previous value, so no need to go through the 1655 * hassle of updating an image which could be opened in read-only 1656 * mode right now. */ 1657 rc = pDisk->Backend->pfnSetTranslation(pImage->pvBackendData, 1658 enmTranslation); 1659 1660 /* Cache new translation mode in any case, whether successful or not. */ 1661 int rc2 = pDisk->Backend->pfnGetTranslation(pImage->pvBackendData, 1662 &pDisk->enmTranslation); 1663 if (VBOX_FAILURE(rc2)) 1664 pDisk->enmTranslation = (PDMBIOSTRANSLATION)0; 1665 } 1666 } 1667 1668 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 2170 { 2171 PDMMEDIAGEOMETRY LCHS; 2172 rc = pDisk->Backend->pfnGetLCHSGeometry(pImage->pvBackendData, 2173 &LCHS); 2174 if ( VBOX_FAILURE(rc) 2175 || pLCHSGeometry->cCylinders != LCHS.cCylinders 2176 || pLCHSGeometry->cHeads != LCHS.cHeads 2177 || pLCHSGeometry->cSectors != LCHS.cSectors) 2178 { 2179 /* Only update geometry if it is changed. Avoids similar checks 2180 * in every backend. Most of the time the new geometry is set 2181 * to the previous values, so no need to go through the hassle 2182 * of updating an image which could be opened in read-only mode 2183 * right now. */ 2184 rc = pDisk->Backend->pfnSetLCHSGeometry(pImage->pvBackendData, 2185 pLCHSGeometry); 2186 } 2187 } 2188 } while (0); 2189 2190 LogFlowFunc(("returns %Vrc\n", rc)); 1669 2191 return rc; 1670 2192 } … … 1675 2197 * @returns VBox status code. 1676 2198 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1677 * @param pDisk Pointer to VBoxHDD container.2199 * @param pDisk Pointer to HDD container. 1678 2200 * @param nImage Image number, counts from 0. 0 is always base image of container. 1679 2201 * @param puVersion Where to store the image version. … … 1682 2204 unsigned *puVersion) 1683 2205 { 1684 return VERR_NOT_IMPLEMENTED; 2206 int rc = VINF_SUCCESS; 2207 2208 LogFlowFunc(("pDisk=%#p nImage=%u puVersion=%#p\n", 2209 pDisk, nImage, puVersion)); 2210 do 2211 { 2212 /* sanity check */ 2213 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2214 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2215 2216 /* Check arguments. */ 2217 AssertMsgBreak(VALID_PTR(puVersion), 2218 ("puVersion=%#p\n", puVersion), 2219 rc = VERR_INVALID_PARAMETER); 2220 2221 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2222 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2223 2224 *puVersion = pDisk->Backend->pfnGetVersion(pImage->pvBackendData); 2225 } while (0); 2226 2227 LogFlowFunc(("returns %Vrc uVersion=%#x\n", rc, *puVersion)); 2228 return rc; 1685 2229 } 1686 2230 … … 1690 2234 * @returns VBox status code. 1691 2235 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1692 * @param pDisk Pointer to VBoxHDD container.2236 * @param pDisk Pointer to HDD container. 1693 2237 * @param nImage Image number, counts from 0. 0 is always base image of container. 1694 2238 * @param penmType Where to store the image type. … … 1697 2241 PVDIMAGETYPE penmType) 1698 2242 { 1699 return VERR_NOT_IMPLEMENTED; 2243 int rc; 2244 2245 LogFlowFunc(("pDisk=%#p nImage=%u penmType=%#p\n", 2246 pDisk, nImage, penmType)); 2247 do 2248 { 2249 /* sanity check */ 2250 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2251 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2252 2253 /* Check arguments. */ 2254 AssertMsgBreak(VALID_PTR(penmType), 2255 ("penmType=%#p\n", penmType), 2256 rc = VERR_INVALID_PARAMETER); 2257 2258 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2259 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2260 2261 rc = pDisk->Backend->pfnGetImageType(pImage->pvBackendData, 2262 penmType); 2263 } while (0); 2264 2265 LogFlowFunc(("returns %Vrc uenmType=%u\n", rc, *penmType)); 2266 return rc; 1700 2267 } 1701 2268 … … 1705 2272 * @returns VBox status code. 1706 2273 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1707 * @param pDisk Pointer to VBoxHDD container.2274 * @param pDisk Pointer to HDD container. 1708 2275 * @param nImage Image number, counts from 0. 0 is always base image of container. 1709 2276 * @param puImageFlags Where to store the image flags. … … 1712 2279 unsigned *puImageFlags) 1713 2280 { 1714 return VERR_NOT_IMPLEMENTED; 1715 } 1716 1717 /** 1718 * Get open flags of last opened image in HDD container. 1719 * 1720 * @returns VBox status code. 1721 * @returns VERR_VDI_NOT_OPENED if no image is opened in HDD container. 1722 * @param pDisk Pointer to VBox HDD container. 2281 int rc = VINF_SUCCESS; 2282 2283 LogFlowFunc(("pDisk=%#p nImage=%u puImageFlags=%#p\n", 2284 pDisk, nImage, puImageFlags)); 2285 do 2286 { 2287 /* sanity check */ 2288 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2289 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2290 2291 /* Check arguments. */ 2292 AssertMsgBreak(VALID_PTR(puImageFlags), 2293 ("puImageFlags=%#p\n", puImageFlags), 2294 rc = VERR_INVALID_PARAMETER); 2295 2296 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2297 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2298 2299 *puImageFlags = pDisk->Backend->pfnGetImageFlags(pImage->pvBackendData); 2300 } while (0); 2301 2302 LogFlowFunc(("returns %Vrc uImageFlags=%#x\n", rc, *puImageFlags)); 2303 return rc; 2304 } 2305 2306 /** 2307 * Get open flags of image in HDD container. 2308 * 2309 * @returns VBox status code. 2310 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 2311 * @param pDisk Pointer to HDD container. 2312 * @param nImage Image number, counts from 0. 0 is always base image of container. 1723 2313 * @param puOpenFlags Where to store the image open flags. 1724 2314 */ 1725 VBOXDDU_DECL(int) VDGetOpenFlags(PVBOXHDD pDisk, unsigned *puOpenFlags) 1726 { 1727 /* sanity check */ 1728 Assert(pDisk); 1729 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1730 1731 unsigned uOpenFlags = 0; 2315 VBOXDDU_DECL(int) VDGetOpenFlags(PVBOXHDD pDisk, unsigned nImage, 2316 unsigned *puOpenFlags) 2317 { 1732 2318 int rc = VINF_SUCCESS; 1733 PVDIMAGE pImage = pDisk->pLast; 1734 if (RT_UNLIKELY(!pImage)) 1735 { 1736 Assert(pImage); 1737 rc = VERR_VDI_NOT_OPENED; 1738 } 1739 else 1740 { 1741 uOpenFlags = pDisk->Backend->pfnGetOpenFlags(pDisk->pLast->pvBackendData); 1742 *puOpenFlags = uOpenFlags; 1743 } 1744 LogFlow(("%s: returns %Vrc uOpenFlags=%#x\n", __FUNCTION__, rc, uOpenFlags)); 1745 return uOpenFlags; 1746 } 1747 1748 /** 1749 * Set open flags of last opened image in HDD container. 2319 2320 LogFlowFunc(("pDisk=%#p nImage=%u puOpenFlags=%#p\n", 2321 pDisk, nImage, puOpenFlags)); 2322 do 2323 { 2324 /* sanity check */ 2325 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2326 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2327 2328 /* Check arguments. */ 2329 AssertMsgBreak(VALID_PTR(puOpenFlags), 2330 ("puOpenFlags=%#p\n", puOpenFlags), 2331 rc = VERR_INVALID_PARAMETER); 2332 2333 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2334 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2335 2336 *puOpenFlags = pDisk->Backend->pfnGetOpenFlags(pImage->pvBackendData); 2337 } while (0); 2338 2339 LogFlowFunc(("returns %Vrc uOpenFlags=%#x\n", rc, *puOpenFlags)); 2340 return rc; 2341 } 2342 2343 /** 2344 * Set open flags of image in HDD container. 1750 2345 * This operation may cause file locking changes and/or files being reopened. 1751 2346 * Note that in case of unrecoverable error all images in HDD container will be closed. 1752 2347 * 1753 * @returns V irtual disk block size in bytes.2348 * @returns VBox status code. 1754 2349 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1755 * @ returns VBox status code.1756 * @param pDisk Pointer to VBox HDDcontainer.2350 * @param pDisk Pointer to HDD container. 2351 * @param nImage Image number, counts from 0. 0 is always base image of container. 1757 2352 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. 1758 2353 */ 1759 VBOXDDU_DECL(int) VDSetOpenFlags(PVBOXHDD pDisk, unsigned uOpenFlags) 1760 { 1761 /* sanity check */ 1762 Assert(pDisk); 1763 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1764 1765 int rc = VINF_SUCCESS; 1766 PVDIMAGE pImage = pDisk->pLast; 1767 if (RT_UNLIKELY(!pImage)) 1768 { 1769 Assert(pImage); 1770 rc = VERR_VDI_NOT_OPENED; 1771 } 1772 else 1773 rc = pDisk->Backend->pfnSetOpenFlags(pDisk->pLast->pvBackendData, 2354 VBOXDDU_DECL(int) VDSetOpenFlags(PVBOXHDD pDisk, unsigned nImage, 2355 unsigned uOpenFlags) 2356 { 2357 int rc; 2358 2359 LogFlowFunc(("pDisk=%#p uOpenFlags=%#u\n", pDisk, uOpenFlags)); 2360 do 2361 { 2362 /* sanity check */ 2363 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2364 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2365 2366 /* Check arguments. */ 2367 AssertMsgBreak((uOpenFlags & ~VD_OPEN_FLAGS_MASK) == 0, 2368 ("uOpenFlags=%#x\n", uOpenFlags), 2369 rc = VERR_INVALID_PARAMETER); 2370 2371 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2372 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2373 2374 rc = pDisk->Backend->pfnSetOpenFlags(pImage->pvBackendData, 1774 2375 uOpenFlags); 1775 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 2376 } while (0); 2377 2378 LogFlowFunc(("returns %Vrc\n", rc)); 1776 2379 return rc; 1777 2380 } … … 1779 2382 /** 1780 2383 * Get base filename of image in HDD container. Some image formats use 1781 * other filenames as well, so don't use this for anything but forinformational2384 * other filenames as well, so don't use this for anything but informational 1782 2385 * purposes. 1783 2386 * … … 1785 2388 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1786 2389 * @returns VERR_BUFFER_OVERFLOW if pszFilename buffer too small to hold filename. 1787 * @param pDisk Pointer to VBoxHDD container.2390 * @param pDisk Pointer to HDD container. 1788 2391 * @param nImage Image number, counts from 0. 0 is always base image of container. 1789 2392 * @param pszFilename Where to store the image file name. … … 1793 2396 char *pszFilename, unsigned cbFilename) 1794 2397 { 1795 return VERR_NOT_IMPLEMENTED; 2398 int rc; 2399 2400 LogFlowFunc(("pDisk=%#p nImage=%u pszFilename=%#p cbFilename=%u\n", 2401 pDisk, nImage, pszFilename, cbFilename)); 2402 do 2403 { 2404 /* sanity check */ 2405 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2406 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2407 2408 /* Check arguments. */ 2409 AssertMsgBreak(VALID_PTR(pszFilename) && *pszFilename, 2410 ("pszFilename=%#p \"%s\"\n", pszFilename, pszFilename), 2411 rc = VERR_INVALID_PARAMETER); 2412 AssertMsgBreak(cbFilename, 2413 ("cbFilename=%u\n", cbFilename), 2414 rc = VERR_INVALID_PARAMETER); 2415 2416 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2417 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2418 2419 size_t cb = strlen(pImage->pszFilename); 2420 if (cb <= cbFilename) 2421 { 2422 strcpy(pszFilename, pImage->pszFilename); 2423 rc = VINF_SUCCESS; 2424 } 2425 else 2426 { 2427 strncpy(pszFilename, pImage->pszFilename, cbFilename - 1); 2428 pszFilename[cbFilename - 1] = '\0'; 2429 rc = VERR_BUFFER_OVERFLOW; 2430 } 2431 } while (0); 2432 2433 LogFlowFunc(("returns %Vrc, pszFilename=\"%s\"\n", rc, pszFilename)); 2434 return rc; 1796 2435 } 1797 2436 … … 1802 2441 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1803 2442 * @returns VERR_BUFFER_OVERFLOW if pszComment buffer too small to hold comment text. 1804 * @param pDisk Pointer to VBoxHDD container.2443 * @param pDisk Pointer to HDD container. 1805 2444 * @param nImage Image number, counts from 0. 0 is always base image of container. 1806 2445 * @param pszComment Where to store the comment string of image. NULL is ok. … … 1810 2449 char *pszComment, unsigned cbComment) 1811 2450 { 1812 /* sanity check */1813 Assert(pDisk);1814 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));1815 Assert(pszComment);1816 1817 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);1818 2451 int rc; 1819 if (pImage) 2452 2453 LogFlowFunc(("pDisk=%#p nImage=%u pszComment=%#p cbComment=%u\n", 2454 pDisk, nImage, pszComment, cbComment)); 2455 do 2456 { 2457 /* sanity check */ 2458 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2459 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2460 2461 /* Check arguments. */ 2462 AssertMsgBreak(VALID_PTR(pszComment), 2463 ("pszComment=%#p \"%s\"\n", pszComment, pszComment), 2464 rc = VERR_INVALID_PARAMETER); 2465 AssertMsgBreak(cbComment, 2466 ("cbComment=%u\n", cbComment), 2467 rc = VERR_INVALID_PARAMETER); 2468 2469 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2470 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2471 1820 2472 rc = pDisk->Backend->pfnGetComment(pImage->pvBackendData, pszComment, 1821 2473 cbComment); 1822 else 1823 rc = VERR_VDI_IMAGE_NOT_FOUND; 1824 1825 LogFlow(("%s: returns %Vrc, comment='%s' nImage=%u\n", __FUNCTION__, 1826 rc, pszComment, nImage)); 2474 } while (0); 2475 2476 LogFlowFunc(("returns %Vrc, pszComment=\"%s\"\n", rc, pszComment)); 1827 2477 return rc; 1828 2478 } … … 1833 2483 * @returns VBox status code. 1834 2484 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1835 * @param pDisk Pointer to VBoxHDD container.2485 * @param pDisk Pointer to HDD container. 1836 2486 * @param nImage Image number, counts from 0. 0 is always base image of container. 1837 2487 * @param pszComment New comment string (UTF-8). NULL is allowed to reset the comment. … … 1840 2490 const char *pszComment) 1841 2491 { 1842 /* sanity check */1843 Assert(pDisk);1844 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));1845 LogFlow(("%s: comment='%s' nImage=%u\n", __FUNCTION__, pszComment, nImage));1846 1847 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);1848 2492 int rc; 1849 if (pImage) 2493 2494 LogFlowFunc(("pDisk=%#p nImage=%u pszComment=%#p \"%s\"\n", 2495 pDisk, nImage, pszComment, pszComment)); 2496 do 2497 { 2498 /* sanity check */ 2499 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2500 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2501 2502 /* Check arguments. */ 2503 AssertMsgBreak(VALID_PTR(pszComment) || pszComment == NULL, 2504 ("pszComment=%#p \"%s\"\n", pszComment, pszComment), 2505 rc = VERR_INVALID_PARAMETER); 2506 2507 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2508 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2509 1850 2510 rc = pDisk->Backend->pfnSetComment(pImage->pvBackendData, pszComment); 1851 else 1852 rc = VERR_VDI_IMAGE_NOT_FOUND; 1853 1854 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 2511 } while (0); 2512 2513 LogFlowFunc(("returns %Vrc\n", rc)); 1855 2514 return rc; 1856 2515 } … … 1862 2521 * @returns VBox status code. 1863 2522 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1864 * @param pDisk Pointer to VBoxHDD container.2523 * @param pDisk Pointer to HDD container. 1865 2524 * @param nImage Image number, counts from 0. 0 is always base image of container. 1866 2525 * @param pUuid Where to store the image creation UUID. … … 1868 2527 VBOXDDU_DECL(int) VDGetUuid(PVBOXHDD pDisk, unsigned nImage, PRTUUID pUuid) 1869 2528 { 1870 /* sanity check */1871 Assert(pDisk);1872 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));1873 Assert(pUuid);1874 1875 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);1876 2529 int rc; 1877 if (pImage) 2530 2531 LogFlowFunc(("pDisk=%#p nImage=%u pUuid=%#p\n", pDisk, nImage, pUuid)); 2532 do 2533 { 2534 /* sanity check */ 2535 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2536 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2537 2538 /* Check arguments. */ 2539 AssertMsgBreak(VALID_PTR(pUuid), 2540 ("pUuid=%#p\n", pUuid), 2541 rc = VERR_INVALID_PARAMETER); 2542 2543 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2544 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2545 1878 2546 rc = pDisk->Backend->pfnGetUuid(pImage->pvBackendData, pUuid); 1879 else 1880 rc = VERR_VDI_IMAGE_NOT_FOUND; 1881 1882 LogFlow(("%s: returns %Vrc, uuid={%Vuuid} nImage=%u\n", __FUNCTION__, 1883 rc, pUuid, nImage)); 2547 } while (0); 2548 2549 LogFlowFunc(("returns %Vrc, Uuid={%Vuuid}\n", rc, pUuid)); 1884 2550 return rc; 1885 2551 } … … 1890 2556 * @returns VBox status code. 1891 2557 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1892 * @param pDisk Pointer to VBoxHDD container.2558 * @param pDisk Pointer to HDD container. 1893 2559 * @param nImage Image number, counts from 0. 0 is always base image of container. 1894 * @param pUuid Optional parameter, new UUID of the image.2560 * @param pUuid New UUID of the image. If NULL, a new UUID is created. 1895 2561 */ 1896 2562 VBOXDDU_DECL(int) VDSetUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid) 1897 2563 { 1898 LogFlow(("%s: uuid={%Vuuid} nImage=%u\n", __FUNCTION__, pUuid, nImage));1899 /* sanity check */1900 Assert(pDisk);1901 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));1902 Assert(pUuid);1903 1904 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);1905 2564 int rc; 1906 if (pImage) 2565 2566 LogFlowFunc(("pDisk=%#p nImage=%u pUuid=%#p {%Vuuid}\n", 2567 pDisk, nImage, pUuid, pUuid)); 2568 do 2569 { 2570 /* sanity check */ 2571 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2572 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2573 2574 AssertMsgBreak(VALID_PTR(pUuid) || pUuid == NULL, 2575 ("pUuid=%#p\n", pUuid), 2576 rc = VERR_INVALID_PARAMETER); 2577 2578 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2579 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2580 2581 RTUUID Uuid; 2582 if (!pUuid) 2583 { 2584 RTUuidCreate(&Uuid); 2585 pUuid = &Uuid; 2586 } 1907 2587 rc = pDisk->Backend->pfnSetUuid(pImage->pvBackendData, pUuid); 1908 else 1909 rc = VERR_VDI_IMAGE_NOT_FOUND; 1910 1911 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 2588 } while (0); 2589 2590 LogFlowFunc(("returns %Vrc\n", rc)); 1912 2591 return rc; 1913 2592 } … … 1918 2597 * @returns VBox status code. 1919 2598 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1920 * @param pDisk Pointer to VBoxHDD container.2599 * @param pDisk Pointer to HDD container. 1921 2600 * @param nImage Image number, counts from 0. 0 is always base image of container. 1922 2601 * @param pUuid Where to store the image modification UUID. … … 1924 2603 VBOXDDU_DECL(int) VDGetModificationUuid(PVBOXHDD pDisk, unsigned nImage, PRTUUID pUuid) 1925 2604 { 1926 /* sanity check */ 1927 Assert(pDisk); 1928 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1929 Assert(pUuid); 1930 1931 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2605 int rc = VINF_SUCCESS; 2606 2607 LogFlowFunc(("pDisk=%#p nImage=%u pUuid=%#p\n", pDisk, nImage, pUuid)); 2608 do 2609 { 2610 /* sanity check */ 2611 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2612 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2613 2614 /* Check arguments. */ 2615 AssertMsgBreak(VALID_PTR(pUuid), 2616 ("pUuid=%#p\n", pUuid), 2617 rc = VERR_INVALID_PARAMETER); 2618 2619 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2620 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2621 2622 rc = pDisk->Backend->pfnGetModificationUuid(pImage->pvBackendData, 2623 pUuid); 2624 } while (0); 2625 2626 LogFlowFunc(("returns %Vrc, Uuid={%Vuuid}\n", rc, pUuid)); 2627 return rc; 2628 } 2629 2630 /** 2631 * Set the image's last modification UUID. Should not be used by normal applications. 2632 * 2633 * @returns VBox status code. 2634 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 2635 * @param pDisk Pointer to HDD container. 2636 * @param nImage Image number, counts from 0. 0 is always base image of container. 2637 * @param pUuid New modification UUID of the image. If NULL, a new UUID is created. 2638 */ 2639 VBOXDDU_DECL(int) VDSetModificationUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid) 2640 { 1932 2641 int rc; 1933 if (pImage) 1934 rc = pDisk->Backend->pfnGetModificationUuid(pImage->pvBackendData, pUuid); 1935 else 1936 rc = VERR_VDI_IMAGE_NOT_FOUND; 1937 1938 LogFlow(("%s: returns %Vrc, uuid={%Vuuid} nImage=%u\n", __FUNCTION__, 1939 rc, pUuid, nImage)); 1940 return rc; 1941 } 1942 1943 /** 1944 * Set the image's last modification UUID. Should not be used by normal applications. 2642 2643 LogFlowFunc(("pDisk=%#p nImage=%u pUuid=%#p {%Vuuid}\n", 2644 pDisk, nImage, pUuid, pUuid)); 2645 do 2646 { 2647 /* sanity check */ 2648 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2649 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2650 2651 /* Check arguments. */ 2652 AssertMsgBreak(VALID_PTR(pUuid) || pUuid == NULL, 2653 ("pUuid=%#p\n", pUuid), 2654 rc = VERR_INVALID_PARAMETER); 2655 2656 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2657 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2658 2659 RTUUID Uuid; 2660 if (!pUuid) 2661 { 2662 RTUuidCreate(&Uuid); 2663 pUuid = &Uuid; 2664 } 2665 rc = pDisk->Backend->pfnSetModificationUuid(pImage->pvBackendData, 2666 pUuid); 2667 } while (0); 2668 2669 LogFlowFunc(("returns %Vrc\n", rc)); 2670 return rc; 2671 } 2672 2673 /** 2674 * Get parent UUID of image in HDD container. 1945 2675 * 1946 2676 * @returns VBox status code. 1947 2677 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1948 * @param pDisk Pointer to VBox HDD container. 1949 * @param nImage Image number, counts from 0. 0 is always base image of container. 1950 * @param pUuid Optional parameter, new last modification UUID of the image. 1951 */ 1952 VBOXDDU_DECL(int) VDSetModificationUuid(PVBOXHDD pDisk, unsigned nImage, PCRTUUID pUuid) 1953 { 1954 LogFlow(("%s: uuid={%Vuuid} nImage=%u\n", __FUNCTION__, pUuid, nImage)); 1955 /* sanity check */ 1956 Assert(pDisk); 1957 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1958 Assert(pUuid); 1959 1960 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 1961 int rc; 1962 if (pImage) 1963 rc = pDisk->Backend->pfnSetModificationUuid(pImage->pvBackendData, pUuid); 1964 else 1965 rc = VERR_VDI_IMAGE_NOT_FOUND; 1966 1967 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 1968 return rc; 1969 } 1970 1971 /** 1972 * Get parent UUID of image in HDD container. 1973 * 1974 * @returns VBox status code. 1975 * @returns VERR_VDI_IMAGE_NOT_FOUND if image with specified number was not opened. 1976 * @param pDisk Pointer to VBox HDD container. 2678 * @param pDisk Pointer to HDD container. 1977 2679 * @param nImage Image number, counts from 0. 0 is always base image of container. 1978 2680 * @param pUuid Where to store the parent image UUID. … … 1981 2683 PRTUUID pUuid) 1982 2684 { 1983 /* sanity check */ 1984 Assert(pDisk); 1985 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 1986 Assert(pUuid); 1987 1988 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 1989 int rc; 1990 if (pImage) 2685 int rc = VINF_SUCCESS; 2686 2687 LogFlowFunc(("pDisk=%#p nImage=%u pUuid=%#p\n", pDisk, nImage, pUuid)); 2688 do 2689 { 2690 /* sanity check */ 2691 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2692 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2693 2694 /* Check arguments. */ 2695 AssertMsgBreak(VALID_PTR(pUuid), 2696 ("pUuid=%#p\n", pUuid), 2697 rc = VERR_INVALID_PARAMETER); 2698 2699 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2700 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2701 1991 2702 rc = pDisk->Backend->pfnGetParentUuid(pImage->pvBackendData, pUuid); 1992 else 1993 rc = VERR_VDI_IMAGE_NOT_FOUND; 1994 1995 LogFlow(("%s: returns %Vrc, uuid={%Vuuid} nImage=%u\n", __FUNCTION__, 1996 rc, pUuid, nImage)); 2703 } while (0); 2704 2705 LogFlowFunc(("returns %Vrc, Uuid={%Vuuid}\n", rc, pUuid)); 1997 2706 return rc; 1998 2707 } … … 2002 2711 * 2003 2712 * @returns VBox status code. 2004 * @param pDisk Pointer to VBoxHDD container.2713 * @param pDisk Pointer to HDD container. 2005 2714 * @param nImage Image number, counts from 0. 0 is always base image of container. 2006 * @param pUuid Optional parameter, new parent UUID of the image.2715 * @param pUuid New parent UUID of the image. If NULL, a new UUID is created. 2007 2716 */ 2008 2717 VBOXDDU_DECL(int) VDSetParentUuid(PVBOXHDD pDisk, unsigned nImage, 2009 2718 PCRTUUID pUuid) 2010 2719 { 2011 LogFlow(("%s: uuid={%Vuuid} nImage=%u\n", __FUNCTION__, pUuid, nImage));2012 /* sanity check */2013 Assert(pDisk);2014 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature));2015 Assert(pUuid);2016 2017 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage);2018 2720 int rc; 2019 if (pImage) 2721 2722 LogFlowFunc(("pDisk=%#p nImage=%u pUuid=%#p {%Vuuid}\n", 2723 pDisk, nImage, pUuid, pUuid)); 2724 do 2725 { 2726 /* sanity check */ 2727 AssertBreak(VALID_PTR(pDisk), rc = VERR_INVALID_PARAMETER); 2728 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2729 2730 /* Check arguments. */ 2731 AssertMsgBreak(VALID_PTR(pUuid) || pUuid == NULL, 2732 ("pUuid=%#p\n", pUuid), 2733 rc = VERR_INVALID_PARAMETER); 2734 2735 PVDIMAGE pImage = vdGetImageByNumber(pDisk, nImage); 2736 AssertBreak(pImage, rc = VERR_VDI_IMAGE_NOT_FOUND); 2737 2738 RTUUID Uuid; 2739 if (!pUuid) 2740 { 2741 RTUuidCreate(&Uuid); 2742 pUuid = &Uuid; 2743 } 2020 2744 rc = pDisk->Backend->pfnSetParentUuid(pImage->pvBackendData, pUuid); 2021 else 2022 rc = VERR_VDI_IMAGE_NOT_FOUND; 2023 2024 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 2745 } while (0); 2746 2747 LogFlowFunc(("returns %Vrc\n", rc)); 2025 2748 return rc; 2026 2749 } … … 2030 2753 * Debug helper - dumps all opened images in HDD container into the log file. 2031 2754 * 2032 * @param pDisk Pointer to VDIHDD container.2755 * @param pDisk Pointer to HDD container. 2033 2756 */ 2034 2757 VBOXDDU_DECL(void) VDDumpImages(PVBOXHDD pDisk) 2035 2758 { 2036 /* sanity check */ 2037 Assert(pDisk); 2038 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2039 2040 RTLogPrintf("--- Dumping VDI Disk, Images=%u\n", pDisk->cImages); 2041 for (PVDIMAGE pImage = pDisk->pBase; pImage; pImage = pImage->pNext) 2042 { 2043 RTLogPrintf("Dumping VDI image \"%s\" file=%#p\n", pImage->pszFilename); 2044 /** @todo call backend to print its part. */ 2045 } 2046 } 2047 2759 do 2760 { 2761 /* sanity check */ 2762 AssertBreak(VALID_PTR(pDisk), ); 2763 AssertMsg(pDisk->u32Signature == VBOXHDDDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2764 2765 RTLogPrintf("--- Dumping VD Disk, Backend=%s, Images=%u\n", 2766 pDisk->Backend->pszBackendName, pDisk->cImages); 2767 for (PVDIMAGE pImage = pDisk->pBase; pImage; pImage = pImage->pNext) 2768 { 2769 RTLogPrintf("Dumping VD image \"%s\"\n", pImage->pszFilename); 2770 pDisk->Backend->pfnDump(pImage->pvBackendData); 2771 } 2772 } while (0); 2773 } 2774 -
Property svn:eol-style
set to
-
trunk/src/VBox/Devices/Storage/VBoxHDD-newInternal.h
-
Property svn:eol-style
set to
native
r6196 r6291 4 4 5 5 /* 6 * Copyright (C) 2006-200 7innotek GmbH6 * Copyright (C) 2006-2008 innotek GmbH 7 7 * 8 8 * This file is part of VirtualBox Open Source Edition (OSE), as … … 27 27 { 28 28 /** 29 * The name of the backend (constant string). 30 */ 31 const char *pszBackendName; 32 33 /** 29 34 * The size of the structure. 30 35 */ … … 32 37 33 38 /** 34 * Check if an file is valid for the backend. 35 * 36 * @returns VBox status code. 37 * @param pszFilename Name of the image file to open. Guaranteed to be available and 38 * unchanged during the lifetime of this image. 39 * Check if a file is valid for the backend. 40 * 41 * @returns VBox status code. 42 * @param pszFilename Name of the image file. 39 43 */ 40 44 DECLR3CALLBACKMEMBER(int, pfnCheckIfValid, (const char *pszFilename)); … … 63 67 * @param uImageFlags Flags specifying special image features. 64 68 * @param pszComment Pointer to image comment. NULL is ok. 65 * @param cCylinders Number of cylinders (must be <= 16383). 66 * @param cHeads Number of heads (must be <= 16). 67 * @param cSectors Number of sectors (must be <= 63). 69 * @param pPCHSGeometry Physical drive geometry CHS <= (16383,16,255). 70 * @param pLCHSGeometry Logical drive geometry CHS <= (1024,255,63). 68 71 * @param uOpenFlags Image file open mode, see VD_OPEN_FLAGS_* constants. 69 72 * @param pfnProgress Progress callback. Optional. NULL if not to be used. 70 73 * @param pvUser User argument for the progress callback. 74 * @param uPercentStart Starting value for progress percentage. 75 * @param uPercentSpan Span for varying progress percentage. 71 76 * @param pfnError Callback for setting extended error information. 72 77 * @param pvErrorUser Opaque parameter for pfnError. 73 78 * @param ppvBackendData Opaque state data for this image. 74 79 */ 75 DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, VDIMAGETYPE enmType, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors, unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, void *pvUser, PFNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData)); 80 DECLR3CALLBACKMEMBER(int, pfnCreate, (const char *pszFilename, VDIMAGETYPE enmType, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, PCPDMMEDIAGEOMETRY pPCHSGeometry, PCPDMMEDIAGEOMETRY pLCHSGeometry, unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, void *pvUser, unsigned uPercentStart, unsigned uPercentSpan, PFNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData)); 81 82 /** 83 * Rename a disk image. Only needs to work as long as the operating 84 * system's rename file functionality is usable. If an attempt is made to 85 * rename an image to a location on another disk/filesystem, this function 86 * may just fail with an appropriate error code (not changing the opened 87 * image data at all). Also works only on images which actually refer to 88 * files (and not for raw disk images). 89 * 90 * @returns VBox status code. 91 * @param pvBackendData Opaque state data for this image. 92 * @param pszFilename New name of the image file. Guaranteed to be available and 93 * unchanged during the lifetime of this image. 94 */ 95 DECLR3CALLBACKMEMBER(int, pfnRename, (void *pvBackendData, const char *pszFilename)); 76 96 77 97 /** … … 90 110 * @returns VBox status code. 91 111 * @returns VINF_VDI_BLOCK_FREE if this image contains no data for this block. 112 * @returns VINF_VDI_BLOCK_ZERO if this image contains a zero data block. 92 113 * @param pvBackendData Opaque state data for this image. 93 114 * @param off Offset to start reading from. … … 135 156 136 157 /** 158 * Get the version of a disk image. 159 * 160 * @returns version of disk image. 161 * @param pvBackendData Opaque state data for this image. 162 */ 163 DECLR3CALLBACKMEMBER(unsigned, pfnGetVersion, (void *pvBackendData)); 164 165 /** 137 166 * Get the type information for a disk image. 138 167 * … … 144 173 145 174 /** 146 * Get the sizeof a disk image.147 * 148 * @returns size of disk image .175 * Get the capacity of a disk image. 176 * 177 * @returns size of disk image in bytes. 149 178 * @param pvBackendData Opaque state data for this image. 150 179 */ … … 152 181 153 182 /** 154 * Get virtual disk geometry stored in a disk image. 183 * Get the file size of a disk image. 184 * 185 * @returns size of disk image in bytes. 186 * @param pvBackendData Opaque state data for this image. 187 */ 188 DECLR3CALLBACKMEMBER(uint64_t, pfnGetFileSize, (void *pvBackendData)); 189 190 /** 191 * Get virtual disk PCHS geometry stored in a disk image. 155 192 * 156 193 * @returns VBox status code. 157 194 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the image. 158 195 * @param pvBackendData Opaque state data for this image. 159 * @param pcCylinders Where to store the number of cylinders. Never NULL. 160 * @param pcHeads Where to store the number of heads. Never NULL. 161 * @param pcSectors Where to store the number of sectors. Never NULL. 162 */ 163 DECLR3CALLBACKMEMBER(int, pfnGetGeometry, (void *pvBackendData, unsigned *pcCylinders, unsigned *pcHeads, unsigned *pcSectors)); 164 165 /** 166 * Set virtual disk geometry stored in a disk image. 196 * @param pPCHSGeometry Where to store the geometry. Not NULL. 197 */ 198 DECLR3CALLBACKMEMBER(int, pfnGetPCHSGeometry, (void *pvBackendData, PPDMMEDIAGEOMETRY pPCHSGeometry)); 199 200 /** 201 * Set virtual disk PCHS geometry stored in a disk image. 167 202 * Only called if geometry is different than before. 168 203 * 169 204 * @returns VBox status code. 170 205 * @param pvBackendData Opaque state data for this image. 171 * @param cCylinders Number of cylinders. 172 * @param cHeads Number of heads. 173 * @param cSectors Number of sectors. 174 */ 175 DECLR3CALLBACKMEMBER(int, pfnSetGeometry, (void *pvBackendData, unsigned cCylinders, unsigned cHeads, unsigned cSectors)); 176 177 /** 178 * Get virtual disk translation mode stored in a disk image. 206 * @param pPCHSGeometry Where to load the geometry from. Not NULL. 207 */ 208 DECLR3CALLBACKMEMBER(int, pfnSetPCHSGeometry, (void *pvBackendData, PCPDMMEDIAGEOMETRY pPCHSGeometry)); 209 210 /** 211 * Get virtual disk LCHS geometry stored in a disk image. 179 212 * 180 213 * @returns VBox status code. 181 214 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry present in the image. 182 215 * @param pvBackendData Opaque state data for this image. 183 * @param penmTranslation Where to store the translation mode. Never NULL. 184 */ 185 DECLR3CALLBACKMEMBER(int, pfnGetTranslation, (void *pvBackendData, PPDMBIOSTRANSLATION penmTranslation)); 186 187 /** 188 * Set virtual disk translation mode stored in a disk image. 189 * Only called if translation mode is different than before. 190 * 191 * @returns VBox status code. 192 * @param pvBackendData Opaque state data for this image. 193 * @param enmTranslation New translation mode. 194 */ 195 DECLR3CALLBACKMEMBER(int, pfnSetTranslation, (void *pvBackendData, PDMBIOSTRANSLATION enmTranslation)); 216 * @param pLCHSGeometry Where to store the geometry. Not NULL. 217 */ 218 DECLR3CALLBACKMEMBER(int, pfnGetLCHSGeometry, (void *pvBackendData, PPDMMEDIAGEOMETRY pLCHSGeometry)); 219 220 /** 221 * Set virtual disk LCHS geometry stored in a disk image. 222 * Only called if geometry is different than before. 223 * 224 * @returns VBox status code. 225 * @param pvBackendData Opaque state data for this image. 226 * @param pLCHSGeometry Where to load the geometry from. Not NULL. 227 */ 228 DECLR3CALLBACKMEMBER(int, pfnSetLCHSGeometry, (void *pvBackendData, PCPDMMEDIAGEOMETRY pLCHSGeometry)); 229 230 /** 231 * Get the image flags of a disk image. 232 * 233 * @returns image flags of disk image. 234 * @param pvBackendData Opaque state data for this image. 235 */ 236 DECLR3CALLBACKMEMBER(unsigned, pfnGetImageFlags, (void *pvBackendData)); 196 237 197 238 /** … … 288 329 DECLR3CALLBACKMEMBER(int, pfnSetParentUuid, (void *pvBackendData, PCRTUUID pUuid)); 289 330 290 } VBOXHDDBACKEND, *PVBOXHDDBACKEND; 331 /** 332 * Dump information about a disk image. 333 * 334 * @param pvBackendData Opaque state data for this image. 335 */ 336 DECLR3CALLBACKMEMBER(void, pfnDump, (void *pvBackendData)); 337 338 } VBOXHDDBACKEND; 339 340 /** Pointer to VD backend. */ 341 typedef VBOXHDDBACKEND *PVBOXHDDBACKEND; 342 343 /** Constant pointer to VD backend. */ 344 typedef const VBOXHDDBACKEND *PCVBOXHDDBACKEND; 291 345 292 346 /** Initialization entry point. */ -
Property svn:eol-style
set to
-
trunk/src/VBox/Devices/Storage/VBoxHDD.cpp
r5999 r6291 60 60 61 61 /** 62 * Get stored media geometry - BIOS property. 63 * 64 * @see PDMIMEDIA::pfnBiosGetGeometry for details. 65 */ 66 static DECLCALLBACK(int) vdiBiosGetGeometry(PPDMIMEDIA pInterface, uint32_t *pcCylinders, uint32_t *pcHeads, uint32_t *pcSectors) 67 { 68 PVDIDISK pData = PDMIMEDIA_2_VDIDISK(pInterface); 69 int rc = VDIDiskGetGeometry(pData, pcCylinders, pcHeads, pcSectors); 62 * Get stored media PCHS geometry - BIOS property. 63 * 64 * @see PDMIMEDIA::pfnBiosGetPCHSGeometry for details. 65 */ 66 static DECLCALLBACK(int) vdiBiosGetPCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pPCHSGeometry) 67 { 68 LogFlow(("%s: returns VERR_NOT_IMPLEMENTED\n", __FUNCTION__)); 69 return VERR_NOT_IMPLEMENTED; 70 } 71 72 73 /** 74 * Set stored media PCHS geometry - BIOS property. 75 * 76 * @see PDMIMEDIA::pfnBiosSetPCHSGeometry for details. 77 */ 78 static DECLCALLBACK(int) vdiBiosSetPCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pPCHSGeometry) 79 { 80 LogFlow(("%s: returns VERR_NOT_IMPLEMENTED\n", __FUNCTION__)); 81 return VERR_NOT_IMPLEMENTED; 82 } 83 84 85 /** 86 * Get stored media LCHS geometry - BIOS property. 87 * 88 * @see PDMIMEDIA::pfnBiosGetLCHSGeometry for details. 89 */ 90 static DECLCALLBACK(int) vdiBiosGetLCHSGeometry(PPDMIMEDIA pInterface, PPDMMEDIAGEOMETRY pLCHSGeometry) 91 { 92 PVDIDISK pData = PDMIMEDIA_2_VDIDISK(pInterface); 93 int rc = VDIDiskGetLCHSGeometry(pData, pLCHSGeometry); 70 94 if (VBOX_SUCCESS(rc)) 71 95 { 72 LogFlow((" vdiBiosGetGeometry: returns VINF_SUCCESS\n"));96 LogFlow(("%s: returns VINF_SUCCESS\n", __FUNCTION__)); 73 97 return VINF_SUCCESS; 74 98 } 75 Log((" vdiBiosGetGeometry: The Bios geometry data was not available.\n"));99 Log(("%s: The Bios geometry data was not available.\n", __FUNCTION__)); 76 100 return VERR_PDM_GEOMETRY_NOT_SET; 77 101 } … … 79 103 80 104 /** 81 * Set stored media geometry - BIOS property.82 * 83 * @see PDMIMEDIA::pfnBiosSet Geometry for details.84 */ 85 static DECLCALLBACK(int) vdiBiosSet Geometry(PPDMIMEDIA pInterface, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)86 { 87 PVDIDISK pData = PDMIMEDIA_2_VDIDISK(pInterface); 88 int rc = VDIDiskSet Geometry(pData, cCylinders, cHeads, cSectors);89 LogFlow((" vdiBiosSetGeometry: returns %Vrc (%d,%d,%d)\n", rc, cCylinders, cHeads,cSectors));105 * Set stored media LCHS geometry - BIOS property. 106 * 107 * @see PDMIMEDIA::pfnBiosSetLCHSGeometry for details. 108 */ 109 static DECLCALLBACK(int) vdiBiosSetLCHSGeometry(PPDMIMEDIA pInterface, PCPDMMEDIAGEOMETRY pLCHSGeometry) 110 { 111 PVDIDISK pData = PDMIMEDIA_2_VDIDISK(pInterface); 112 int rc = VDIDiskSetLCHSGeometry(pData, pLCHSGeometry); 113 LogFlow(("%s: returns %Vrc (%d,%d,%d)\n", __FUNCTION__, rc, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 90 114 return rc; 91 115 } … … 161 185 LogFlow(("vdiIsReadOnly: returns %d\n", VDIDiskIsReadOnly(pData))); 162 186 return VDIDiskIsReadOnly(pData); 163 }164 165 166 /** @copydoc PDMIMEDIA::pfnBiosGetTranslation */167 static DECLCALLBACK(int) vdiBiosGetTranslation(PPDMIMEDIA pInterface,168 PPDMBIOSTRANSLATION penmTranslation)169 {170 PVDIDISK pData = PDMIMEDIA_2_VDIDISK(pInterface);171 int rc = VDIDiskGetTranslation(pData, penmTranslation);172 LogFlow(("vdiBiosGetTranslation: returns %Vrc (%d)\n", rc, *penmTranslation));173 return rc;174 }175 176 177 /** @copydoc PDMIMEDIA::pfnBiosSetTranslation */178 static DECLCALLBACK(int) vdiBiosSetTranslation(PPDMIMEDIA pInterface,179 PDMBIOSTRANSLATION enmTranslation)180 {181 PVDIDISK pData = PDMIMEDIA_2_VDIDISK(pInterface);182 int rc = VDIDiskSetTranslation(pData, enmTranslation);183 LogFlow(("vdiBiosSetTranslation: returns %Vrc (%d)\n", rc, enmTranslation));184 return rc;185 187 } 186 188 … … 301 303 pData->IMedia.pfnGetUuid = vdiGetUuid; 302 304 pData->IMedia.pfnIsReadOnly = vdiIsReadOnly; 303 pData->IMedia.pfnBiosGet Geometry = vdiBiosGetGeometry;304 pData->IMedia.pfnBiosSet Geometry = vdiBiosSetGeometry;305 pData->IMedia.pfnBiosGet Translation = vdiBiosGetTranslation;306 pData->IMedia.pfnBiosSet Translation = vdiBiosSetTranslation;305 pData->IMedia.pfnBiosGetPCHSGeometry = vdiBiosGetPCHSGeometry; 306 pData->IMedia.pfnBiosSetPCHSGeometry = vdiBiosSetPCHSGeometry; 307 pData->IMedia.pfnBiosGetLCHSGeometry = vdiBiosGetLCHSGeometry; 308 pData->IMedia.pfnBiosSetLCHSGeometry = vdiBiosSetLCHSGeometry; 307 309 308 310 /* -
trunk/src/VBox/Devices/Storage/VDICore.cpp
r5999 r6291 144 144 145 145 /* Mark the geometry not-calculated. */ 146 pHeader->u.v1. Geometry.cCylinders = 0;147 pHeader->u.v1. Geometry.cHeads = 0;148 pHeader->u.v1. Geometry.cSectors = 0;149 pHeader->u.v1. Geometry.cbSector = VDI_GEOMETRY_SECTOR_SIZE;150 pHeader->u.v1.u32 Translation = PDMBIOSTRANSLATION_AUTO;146 pHeader->u.v1.LCHSGeometry.cCylinders = 0; 147 pHeader->u.v1.LCHSGeometry.cHeads = 0; 148 pHeader->u.v1.LCHSGeometry.cSectors = 0; 149 pHeader->u.v1.LCHSGeometry.cbSector = VDI_GEOMETRY_SECTOR_SIZE; 150 pHeader->u.v1.u32Dummy = 0; 151 151 152 152 pHeader->u.v1.cbDisk = cbDisk; … … 246 246 } 247 247 248 if ((getImage Geometry(pHeader))->cbSector != VDI_GEOMETRY_SECTOR_SIZE)248 if ((getImageLCHSGeometry(pHeader))->cbSector != VDI_GEOMETRY_SECTOR_SIZE) 249 249 { 250 250 LogRel(("VDI: wrong sector size (%d != %d)\n", 251 (getImage Geometry(pHeader))->cbSector, VDI_GEOMETRY_SECTOR_SIZE));251 (getImageLCHSGeometry(pHeader))->cbSector, VDI_GEOMETRY_SECTOR_SIZE)); 252 252 fFailed = true; 253 253 } … … 2266 2266 0); 2267 2267 setImageBlocksAllocated(&Header, getImageBlocksAllocated(&pImage->Header)); 2268 *getImageGeometry(&Header) = *getImageGeometry(&pImage->Header); 2269 setImageTranslation(&Header, getImageTranslation(&pImage->Header)); 2268 *getImageLCHSGeometry(&Header) = *getImageLCHSGeometry(&pImage->Header); 2270 2269 *getImageCreationUUID(&Header) = *getImageCreationUUID(&pImage->Header); 2271 2270 *getImageModificationUUID(&Header) = *getImageModificationUUID(&pImage->Header); … … 2801 2800 } 2802 2801 2803 AssertMsgFailed(("No onedisk image is opened!\n"));2802 AssertMsgFailed(("No disk image is opened!\n")); 2804 2803 return true; 2805 2804 } … … 2823 2822 } 2824 2823 2825 AssertMsgFailed(("No onedisk image is opened!\n"));2824 AssertMsgFailed(("No disk image is opened!\n")); 2826 2825 return 0; 2827 2826 } … … 2845 2844 } 2846 2845 2847 AssertMsgFailed(("No onedisk image is opened!\n"));2846 AssertMsgFailed(("No disk image is opened!\n")); 2848 2847 return 0; 2849 2848 } 2850 2849 2851 2850 /** 2852 * Get virtual disk geometry stored in image file.2851 * Get virtual disk LCHS geometry stored in image file. 2853 2852 * 2854 2853 * @returns VBox status code. … … 2856 2855 * @returns VERR_VDI_GEOMETRY_NOT_SET if no geometry has been setted. 2857 2856 * @param pDisk Pointer to VDI HDD container. 2858 * @param pcCylinders Where to store the number of cylinders. NULL is ok. 2859 * @param pcHeads Where to store the number of heads. NULL is ok. 2860 * @param pcSectors Where to store the number of sectors. NULL is ok. 2861 */ 2862 VBOXDDU_DECL(int) VDIDiskGetGeometry(PVDIDISK pDisk, unsigned *pcCylinders, unsigned *pcHeads, unsigned *pcSectors) 2857 * @param pLCHSGeometry Where to store LCHS geometry. Not NULL. 2858 */ 2859 VBOXDDU_DECL(int) VDIDiskGetLCHSGeometry(PVDIDISK pDisk, PPDMMEDIAGEOMETRY pLCHSGeometry) 2863 2860 { 2864 2861 /* sanity check */ … … 2869 2866 { 2870 2867 int rc = VINF_SUCCESS; 2871 PVDIDISKGEOMETRY pGeometry = getImage Geometry(&pDisk->pBase->Header);2872 LogFlow((" VDIDiskGetGeometry: C/H/S = %u/%u/%u\n",2873 pGeometry->cCylinders, pGeometry->cHeads, pGeometry->cSectors));2868 PVDIDISKGEOMETRY pGeometry = getImageLCHSGeometry(&pDisk->pBase->Header); 2869 LogFlow(("%s: C/H/S = %u/%u/%u\n", 2870 __FUNCTION__, pGeometry->cCylinders, pGeometry->cHeads, pGeometry->cSectors)); 2874 2871 if ( pGeometry->cCylinders > 0 2875 2872 && pGeometry->cHeads > 0 2876 2873 && pGeometry->cSectors > 0) 2877 2874 { 2878 if (pcCylinders) 2879 *pcCylinders = pGeometry->cCylinders; 2880 if (pcHeads) 2881 *pcHeads = pGeometry->cHeads; 2882 if (pcSectors) 2883 *pcSectors = pGeometry->cSectors; 2875 pLCHSGeometry->cCylinders = pGeometry->cCylinders; 2876 pLCHSGeometry->cHeads = pGeometry->cHeads; 2877 pLCHSGeometry->cSectors = pGeometry->cSectors; 2884 2878 } 2885 2879 else 2886 2880 rc = VERR_VDI_GEOMETRY_NOT_SET; 2887 2881 2888 LogFlow((" VDIDiskGetGeometry: returns %Vrc\n", rc));2882 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 2889 2883 return rc; 2890 2884 } 2891 2885 2892 AssertMsgFailed(("No onedisk image is opened!\n"));2886 AssertMsgFailed(("No disk image is opened!\n")); 2893 2887 return VERR_VDI_NOT_OPENED; 2894 2888 } 2895 2889 2896 2890 /** 2897 * Store virtual disk geometry into base image file of HDD container.2891 * Store virtual disk LCHS geometry into base image file of HDD container. 2898 2892 * 2899 2893 * Note that in case of unrecoverable error all images of HDD container will be closed. … … 2902 2896 * @returns VERR_VDI_NOT_OPENED if no one VDI image is opened in HDD container. 2903 2897 * @param pDisk Pointer to VDI HDD container. 2904 * @param cCylinders Number of cylinders. 2905 * @param cHeads Number of heads. 2906 * @param cSectors Number of sectors. 2907 */ 2908 VBOXDDU_DECL(int) VDIDiskSetGeometry(PVDIDISK pDisk, unsigned cCylinders, unsigned cHeads, unsigned cSectors) 2909 { 2910 LogFlow(("VDIDiskSetGeometry: C/H/S = %u/%u/%u\n", cCylinders, cHeads, cSectors)); 2898 * @param pLCHSGeometry Where to load LCHS geometry from. Not NULL. 2899 */ 2900 VBOXDDU_DECL(int) VDIDiskSetLCHSGeometry(PVDIDISK pDisk, PCPDMMEDIAGEOMETRY pLCHSGeometry) 2901 { 2902 LogFlow(("%s: C/H/S = %u/%u/%u\n", __FUNCTION__, pLCHSGeometry->cCylinders, pLCHSGeometry->cHeads, pLCHSGeometry->cSectors)); 2911 2903 /* sanity check */ 2912 2904 Assert(pDisk); … … 2915 2907 if (pDisk->pBase) 2916 2908 { 2917 PVDIDISKGEOMETRY pGeometry = getImage Geometry(&pDisk->pBase->Header);2918 pGeometry->cCylinders = cCylinders;2919 pGeometry->cHeads = cHeads;2920 pGeometry->cSectors = cSectors;2909 PVDIDISKGEOMETRY pGeometry = getImageLCHSGeometry(&pDisk->pBase->Header); 2910 pGeometry->cCylinders = pLCHSGeometry->cCylinders; 2911 pGeometry->cHeads = pLCHSGeometry->cHeads; 2912 pGeometry->cSectors = pLCHSGeometry->cSectors; 2921 2913 pGeometry->cbSector = VDI_GEOMETRY_SECTOR_SIZE; 2922 2914 2923 2915 /* Update header information in base image file. */ 2924 2916 int rc = vdiUpdateReadOnlyHeader(pDisk->pBase); 2925 LogFlow((" VDIDiskSetGeometry: returns %Vrc\n", rc));2917 LogFlow(("%s: returns %Vrc\n", __FUNCTION__, rc)); 2926 2918 return rc; 2927 2919 } 2928 2920 2929 AssertMsgFailed(("No one disk image is opened!\n")); 2930 return VERR_VDI_NOT_OPENED; 2931 } 2932 2933 /** 2934 * Get virtual disk translation mode stored in image file. 2935 * 2936 * @returns VBox status code. 2937 * @returns VERR_VDI_NOT_OPENED if no one VDI image is opened in HDD container. 2938 * @param pDisk Pointer to VDI HDD container. 2939 * @param penmTranslation Where to store the translation mode (see pdm.h). 2940 */ 2941 VBOXDDU_DECL(int) VDIDiskGetTranslation(PVDIDISK pDisk, PPDMBIOSTRANSLATION penmTranslation) 2942 { 2943 /* sanity check */ 2944 Assert(pDisk); 2945 AssertMsg(pDisk->u32Signature == VDIDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2946 Assert(penmTranslation); 2947 2948 if (pDisk->pBase) 2949 { 2950 *penmTranslation = getImageTranslation(&pDisk->pBase->Header); 2951 LogFlow(("VDIDiskGetTranslation: translation=%d\n", *penmTranslation)); 2952 return VINF_SUCCESS; 2953 } 2954 2955 AssertMsgFailed(("No one disk image is opened!\n")); 2956 return VERR_VDI_NOT_OPENED; 2957 } 2958 2959 /** 2960 * Store virtual disk translation mode into base image file of HDD container. 2961 * 2962 * Note that in case of unrecoverable error all images of HDD container will be closed. 2963 * 2964 * @returns VBox status code. 2965 * @returns VERR_VDI_NOT_OPENED if no one VDI image is opened in HDD container. 2966 * @param pDisk Pointer to VDI HDD container. 2967 * @param enmTranslation Translation mode (see pdm.h). 2968 */ 2969 VBOXDDU_DECL(int) VDIDiskSetTranslation(PVDIDISK pDisk, PDMBIOSTRANSLATION enmTranslation) 2970 { 2971 LogFlow(("VDIDiskSetTranslation: enmTranslation=%d\n", enmTranslation)); 2972 /* sanity check */ 2973 Assert(pDisk); 2974 AssertMsg(pDisk->u32Signature == VDIDISK_SIGNATURE, ("u32Signature=%08x\n", pDisk->u32Signature)); 2975 2976 if (pDisk->pBase) 2977 { 2978 setImageTranslation(&pDisk->pBase->Header, enmTranslation); 2979 2980 /* Update header information in base image file. */ 2981 int rc = vdiUpdateReadOnlyHeader(pDisk->pBase); 2982 LogFlow(("VDIDiskSetTranslation: returns %Vrc\n", rc)); 2983 return rc; 2984 } 2985 2986 AssertMsgFailed(("No one disk image is opened!\n")); 2921 AssertMsgFailed(("No disk image is opened!\n")); 2987 2922 return VERR_VDI_NOT_OPENED; 2988 2923 } … … 3528 3463 if (!pImage) 3529 3464 { 3530 AssertMsgFailed(("No onedisk image is opened!\n"));3465 AssertMsgFailed(("No disk image is opened!\n")); 3531 3466 return VERR_VDI_NOT_OPENED; 3532 3467 } … … 3597 3532 if (!pDisk->pLast) 3598 3533 { 3599 AssertMsgFailed(("No onedisk image is opened!\n"));3534 AssertMsgFailed(("No disk image is opened!\n")); 3600 3535 return VERR_VDI_NOT_OPENED; 3601 3536 } … … 3646 3581 getImageBlocksOffset(&pImage->Header), 3647 3582 getImageDataOffset(&pImage->Header)); 3648 PVDIDISKGEOMETRY pg = getImageGeometry(&pImage->Header); 3649 RTLogPrintf("Header: Geometry: C/H/S=%u/%u/%u cbSector=%u Mode=%u\n", 3650 pg->cCylinders, pg->cHeads, pg->cSectors, pg->cbSector, 3651 getImageTranslation(&pImage->Header)); 3583 PVDIDISKGEOMETRY pg = getImageLCHSGeometry(&pImage->Header); 3584 RTLogPrintf("Header: Geometry: C/H/S=%u/%u/%u cbSector=%u\n", 3585 pg->cCylinders, pg->cHeads, pg->cSectors, pg->cbSector); 3652 3586 RTLogPrintf("Header: uuidCreation={%Vuuid}\n", getImageCreationUUID(&pImage->Header)); 3653 3587 RTLogPrintf("Header: uuidModification={%Vuuid}\n", getImageModificationUUID(&pImage->Header)); -
trunk/src/VBox/Devices/Storage/VDICore.h
r5999 r6291 106 106 char szComment[VDI_IMAGE_COMMENT_SIZE]; 107 107 /** Image geometry. */ 108 VDIDISKGEOMETRY Geometry;108 VDIDISKGEOMETRY LCHSGeometry; 109 109 /** Size of disk (in bytes). */ 110 110 uint64_t cbDisk; … … 146 146 uint32_t offData; 147 147 /** Image geometry. */ 148 VDIDISKGEOMETRY Geometry;149 /** BIOS HDD translation mode, see PDMBIOSTRANSLATION. */150 uint32_t u32 Translation;148 VDIDISKGEOMETRY LCHSGeometry; 149 /** Was BIOS HDD translation mode, now unused. */ 150 uint32_t u32Dummy; 151 151 /** Size of disk (in bytes). */ 152 152 uint64_t cbDisk; … … 272 272 } 273 273 274 DECLINLINE(PVDIDISKGEOMETRY) getImage Geometry(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;274 DECLINLINE(PVDIDISKGEOMETRY) getImageLCHSGeometry(PVDIHEADER ph) 275 { 276 switch (GET_MAJOR_HEADER_VERSION(ph)) 277 { 278 case 0: return &ph->u.v0.LCHSGeometry; 279 case 1: return &ph->u.v1.LCHSGeometry; 280 280 } 281 281 AssertFailed(); 282 282 return NULL; 283 }284 285 DECLINLINE(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 296 DECLINLINE(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 283 } 305 284 -
trunk/src/VBox/Devices/Storage/VmdkHDDCore.cpp
r5999 r6291 36 36 * Constants And Macros, Structures and Typedefs * 37 37 *******************************************************************************/ 38 39 /** VMDK descriptor DDB entry for PCHS cylinders. */ 40 #define VMDK_DDB_GEO_PCHS_CYLINDERS "ddb.geometry.cylinders" 41 42 /** VMDK descriptor DDB entry for PCHS heads. */ 43 #define VMDK_DDB_GEO_PCHS_HEADS "ddb.geometry.heads" 44 45 /** VMDK descriptor DDB entry for PCHS sectors. */ 46 #define VMDK_DDB_GEO_PCHS_SECTORS "ddb.geometry.sectors" 47 48 /** VMDK descriptor DDB entry for LCHS cylinders. */ 49 #define VMDK_DDB_GEO_LCHS_CYLINDERS "ddb.geometry.biosCylinders" 50 51 /** VMDK descriptor DDB entry for LCHS heads. */ 52 #define VMDK_DDB_GEO_LCHS_HEADS "ddb.geometry.biosHeads" 53 54 /** VMDK descriptor DDB entry for LCHS sectors. */ 55 #define VMDK_DDB_GEO_LCHS_SECTORS "ddb.geometry.biosSectors" 38 56 39 57 /** … … 67 85 #pragma pack() 68 86 87 /** VMDK capacity for a single chunk when 2G splitting is turned on. Should be 88 * divisible by the default grain size (64K) */ 89 #define VMDK_2G_SPLIT_SIZE (2047 * 1024 * 1024) 90 69 91 70 92 #ifdef VBOX_WITH_VMDK_ESX … … 89 111 uint32_t freeSector; 90 112 /* The spec incompletely documents quite a few further fields, but states 91 * that they are notused by the current format. Replace them by padding. */113 * that they are unused by the current format. Replace them by padding. */ 92 114 char reserved1[1604]; 93 115 uint32_t savedGeneration; … … 274 296 typedef struct VMDKIMAGE 275 297 { 298 /** Pointer to the image extents. */ 276 299 PVMDKEXTENT pExtents; 300 /** Number of image extents. */ 277 301 unsigned cExtents; 278 302 … … 295 319 /** Total size of the image. */ 296 320 uint64_t cbSize; 297 /** BIOS translation mode. */ 298 PDMBIOSTRANSLATION enmTranslation; 299 /** Physical geometry of this image, cylinders. */ 300 uint32_t cCylinders; 301 /** Physical geometry of this image, heads. */ 302 uint32_t cHeads; 303 /** Physical geometry of this image, sectors. */ 304 uint32_t cSectors; 321 /** Physical geometry of this image. */ 322 PDMMEDIAGEOMETRY PCHSGeometry; 323 /** Logical geometry of this image. */ 324 PDMMEDIAGEOMETRY LCHSGeometry; 305 325 /** Image UUID. */ 306 326 RTUUID ImageUuid; … … 310 330 RTUUID ParentUuid; 311 331 312 /** Pointer to thegrain table cache, if this image contains sparse extents. */332 /** Pointer to grain table cache, if this image contains sparse extents. */ 313 333 PVMDKGTCACHE pGTCache; 314 334 /** Pointer to the descriptor (NULL if no separate descriptor file). */ … … 342 362 static void vmdkFreeImage(PVMDKIMAGE pImage, bool fDelete); 343 363 344 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, PFNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData);345 static int vmdkClose(void *pBackendData, bool fDelete);346 347 364 348 365 DECLINLINE(int) vmdkError(PVMDKIMAGE pImage, int rc, RT_SRC_POS_DECL, const char *pszFormat, ...) … … 350 367 va_list va; 351 368 va_start(va, pszFormat); 352 pImage->pfnError(pImage->pvErrorUser, rc, RT_SRC_POS_ARGS, pszFormat, va); 369 if (pImage->pfnError) 370 pImage->pfnError(pImage->pvErrorUser, rc, RT_SRC_POS_ARGS, pszFormat, va); 353 371 va_end(va); 354 372 return rc; … … 439 457 } 440 458 441 for (i = 0, pGDTmp = pGD, pRGDTmp = pRGD; i < pExtent->cGDEntries; i++, pGDTmp++, pRGDTmp++) 459 for (i = 0, pGDTmp = pGD, pRGDTmp = pRGD; 460 i < pExtent->cGDEntries; 461 i++, pGDTmp++, pRGDTmp++) 442 462 { 443 463 /* If no grain table is allocated skip the entry. */ … … 491 511 } 492 512 493 static int vmdkCreateGrainDirectory(PVMDKEXTENT pExtent, uint64_t uStartSector, bool fPreAlloc) 513 static int vmdkCreateGrainDirectory(PVMDKEXTENT pExtent, uint64_t uStartSector, 514 bool fPreAlloc) 494 515 { 495 516 int rc = VINF_SUCCESS; … … 539 560 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 540 561 /* Write the redundant grain directory entry to disk. */ 541 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE), &uGTSectorLE, sizeof(uGTSectorLE), NULL); 562 rc = RTFileWriteAt(pExtent->File, 563 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + i * sizeof(uGTSectorLE), 564 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 542 565 if (VBOX_FAILURE(rc)) 543 566 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new redundant grain directory entry in '%s'"), pExtent->pszFullname); … … 551 574 uGTSectorLE = RT_H2LE_U64(uOffsetSectors); 552 575 /* Write the grain directory entry to disk. */ 553 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE), &uGTSectorLE, sizeof(uGTSectorLE), NULL); 576 rc = RTFileWriteAt(pExtent->File, 577 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + i * sizeof(uGTSectorLE), 578 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 554 579 if (VBOX_FAILURE(rc)) 555 580 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write new grain directory entry in '%s'"), pExtent->pszFullname); … … 579 604 } 580 605 581 static int vmdkStringUnquote(PVMDKIMAGE pImage, const char *pszStr, char **ppszUnquoted, char **ppszNext) 606 static int vmdkStringUnquote(PVMDKIMAGE pImage, const char *pszStr, 607 char **ppszUnquoted, char **ppszNext) 582 608 { 583 609 char *pszQ; … … 632 658 if (!strncmp(pDescriptor->aLines[uStart], pszKey, cbKey)) 633 659 { 634 /* Key matches, check if there isa '=' (preceded by whitespace). */660 /* Key matches, check for a '=' (preceded by whitespace). */ 635 661 pszValue = pDescriptor->aLines[uStart] + cbKey; 636 662 while (*pszValue == ' ' || *pszValue == '\t') … … 659 685 if (!strncmp(pDescriptor->aLines[uStart], pszKey, cbKey)) 660 686 { 661 /* Key matches, check if there isa '=' (preceded by whitespace). */687 /* Key matches, check for a '=' (preceded by whitespace). */ 662 688 pszTmp = pDescriptor->aLines[uStart] + cbKey; 663 689 while (*pszTmp == ' ' || *pszTmp == '\t') … … 715 741 else 716 742 { 717 /* Key doesn't exist, append itafter the last entry in this category. */743 /* Key doesn't exist, append after the last entry in this category. */ 718 744 if (!pszValue) 719 745 { … … 765 791 const char *pszValue; 766 792 767 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDesc, pszKey, &pszValue)) 793 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDesc, pszKey, 794 &pszValue)) 768 795 return VERR_VDI_VALUE_NOT_FOUND; 769 796 return RTStrToUInt32Ex(pszValue, NULL, 10, puValue); … … 776 803 char *pszValueUnquoted; 777 804 778 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDesc, pszKey, &pszValue)) 805 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDesc, pszKey, 806 &pszValue)) 779 807 return VERR_VDI_VALUE_NOT_FOUND; 780 808 int rc = vmdkStringUnquote(pImage, pszValue, &pszValueUnquoted, NULL); … … 793 821 if (VBOX_FAILURE(rc)) 794 822 return rc; 795 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, pszKey, pszValueQuoted); 823 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, pszKey, 824 pszValueQuoted); 796 825 RTStrFree(pszValueQuoted); 797 826 return rc; 798 827 } 799 828 800 static void vmdkDescExtRemoveDummy(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor) 829 static void vmdkDescExtRemoveDummy(PVMDKIMAGE pImage, 830 PVMDKDESCRIPTOR pDescriptor) 801 831 { 802 832 unsigned uEntry = pDescriptor->uFirstExtent; … … 807 837 808 838 cbDiff = strlen(pDescriptor->aLines[uEntry]) + 1; 809 /* Move everything including the\0 in the entry marking the end of buffer. */839 /* Move everything including \0 in the entry marking the end of buffer. */ 810 840 memmove(pDescriptor->aLines[uEntry], pDescriptor->aLines[uEntry + 1], 811 841 pDescriptor->aLines[pDescriptor->cLines] - pDescriptor->aLines[uEntry + 1] + 1); … … 902 932 char *pszValueUnquoted; 903 933 904 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey, &pszValue)) 934 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey, 935 &pszValue)) 905 936 return VERR_VDI_VALUE_NOT_FOUND; 906 937 int rc = vmdkStringUnquote(pImage, pszValue, &pszValueUnquoted, NULL); … … 917 948 char *pszValueUnquoted; 918 949 919 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey, &pszValue)) 950 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey, 951 &pszValue)) 920 952 return VERR_VDI_VALUE_NOT_FOUND; 921 953 int rc = vmdkStringUnquote(pImage, pszValue, &pszValueUnquoted, NULL); … … 933 965 char *pszValueUnquoted; 934 966 935 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey, &pszValue)) 967 if (!vmdkDescGetStr(pDescriptor, pDescriptor->uFirstDDB, pszKey, 968 &pszValue)) 936 969 return VERR_VDI_VALUE_NOT_FOUND; 937 970 int rc = vmdkStringUnquote(pImage, pszValue, &pszValueUnquoted, NULL); … … 943 976 } 944 977 945 static int vmdkDescDDBSetStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, const char *pszKey, const char *pszVal) 978 static int vmdkDescDDBSetStr(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, 979 const char *pszKey, const char *pszVal) 946 980 { 947 981 int rc; … … 956 990 else 957 991 pszValQuoted = NULL; 958 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDDB, pszKey, pszValQuoted); 992 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDDB, pszKey, 993 pszValQuoted); 959 994 if (pszValQuoted) 960 995 RTStrFree(pszValQuoted); … … 962 997 } 963 998 964 static int vmdkDescDDBSetUuid(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, const char *pszKey, PCRTUUID pUuid) 999 static int vmdkDescDDBSetUuid(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, 1000 const char *pszKey, PCRTUUID pUuid) 965 1001 { 966 1002 char *pszUuid; … … 969 1005 if (VBOX_FAILURE(rc)) 970 1006 return rc; 971 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDDB, pszKey, pszUuid); 1007 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDDB, pszKey, 1008 pszUuid); 972 1009 RTStrFree(pszUuid); 973 1010 return rc; 974 1011 } 975 1012 976 int vmdkDescDDBSetU32(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, const char *pszKey, uint32_t uValue) 1013 int vmdkDescDDBSetU32(PVMDKIMAGE pImage, PVMDKDESCRIPTOR pDescriptor, 1014 const char *pszKey, uint32_t uValue) 977 1015 { 978 1016 char *pszValue; … … 981 1019 if (VBOX_FAILURE(rc)) 982 1020 return rc; 983 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDDB, pszKey, pszValue); 1021 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDDB, pszKey, 1022 pszValue); 984 1023 RTStrFree(pszValue); 985 1024 return rc; 986 1025 } 987 1026 988 static int vmdkPreprocessDescriptor(PVMDKIMAGE pImage, char *pDescData, size_t cbDescData, PVMDKDESCRIPTOR pDescriptor) 1027 static int vmdkPreprocessDescriptor(PVMDKIMAGE pImage, char *pDescData, 1028 size_t cbDescData, 1029 PVMDKDESCRIPTOR pDescriptor) 989 1030 { 990 1031 int rc = VINF_SUCCESS; … … 1101 1142 } 1102 1143 1103 static int vmdkCreateDescriptor(PVMDKIMAGE pImage, char *pDescData, size_t cbDescData, PVMDKDESCRIPTOR pDescriptor) 1144 static int vmdkDescSetPCHSGeometry(PVMDKIMAGE pImage, 1145 PCPDMMEDIAGEOMETRY pPCHSGeometry) 1146 { 1147 int rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 1148 VMDK_DDB_GEO_PCHS_CYLINDERS, 1149 pPCHSGeometry->cCylinders); 1150 if (VBOX_FAILURE(rc)) 1151 return rc; 1152 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 1153 VMDK_DDB_GEO_PCHS_HEADS, 1154 pPCHSGeometry->cHeads); 1155 if (VBOX_FAILURE(rc)) 1156 return rc; 1157 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 1158 VMDK_DDB_GEO_PCHS_SECTORS, 1159 pPCHSGeometry->cSectors); 1160 return rc; 1161 } 1162 1163 static int vmdkDescSetLCHSGeometry(PVMDKIMAGE pImage, 1164 PCPDMMEDIAGEOMETRY pLCHSGeometry) 1165 { 1166 int rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 1167 VMDK_DDB_GEO_LCHS_CYLINDERS, 1168 pLCHSGeometry->cCylinders); 1169 if (VBOX_FAILURE(rc)) 1170 return rc; 1171 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 1172 VMDK_DDB_GEO_LCHS_HEADS, 1173 pLCHSGeometry->cHeads); 1174 if (VBOX_FAILURE(rc)) 1175 return rc; 1176 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 1177 VMDK_DDB_GEO_LCHS_SECTORS, 1178 pLCHSGeometry->cSectors); 1179 return rc; 1180 } 1181 1182 static int vmdkCreateDescriptor(PVMDKIMAGE pImage, char *pDescData, 1183 size_t cbDescData, PVMDKDESCRIPTOR pDescriptor) 1104 1184 { 1105 1185 int rc; … … 1153 1233 char szBuf[9]; 1154 1234 RTStrPrintf(szBuf, sizeof(szBuf), "%08x", RTRandU32()); 1155 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, "CID", szBuf); 1156 if (VBOX_FAILURE(rc)) 1157 goto out; 1158 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, "parentCID", "ffffffff"); 1235 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, 1236 "CID", szBuf); 1237 if (VBOX_FAILURE(rc)) 1238 goto out; 1239 rc = vmdkDescSetStr(pImage, pDescriptor, pDescriptor->uFirstDesc, 1240 "parentCID", "ffffffff"); 1159 1241 if (VBOX_FAILURE(rc)) 1160 1242 goto out; … … 1168 1250 } 1169 1251 1170 static int vmdkParseDescriptor(PVMDKIMAGE pImage, char *pDescData, size_t cbDescData) 1252 static int vmdkParseDescriptor(PVMDKIMAGE pImage, char *pDescData, 1253 size_t cbDescData) 1171 1254 { 1172 1255 int rc; … … 1174 1257 unsigned uLine; 1175 1258 1176 rc = vmdkPreprocessDescriptor(pImage, pDescData, cbDescData, &pImage->Descriptor); 1259 rc = vmdkPreprocessDescriptor(pImage, pDescData, cbDescData, 1260 &pImage->Descriptor); 1177 1261 if (VBOX_FAILURE(rc)) 1178 1262 return rc; … … 1318 1402 } 1319 1403 1404 /* Determine PCHS geometry (autogenerate if necessary). */ 1320 1405 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 1321 "ddb.geometry.cylinders", &pImage->cCylinders); 1322 if (VBOX_FAILURE(rc)) 1323 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description in '%s'"), pImage->pszFilename); 1406 VMDK_DDB_GEO_PCHS_CYLINDERS, 1407 &pImage->PCHSGeometry.cCylinders); 1408 if (rc == VERR_VDI_VALUE_NOT_FOUND) 1409 pImage->PCHSGeometry.cCylinders = 0; 1410 else if (VBOX_FAILURE(rc)) 1411 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename); 1324 1412 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 1325 "ddb.geometry.heads", &pImage->cHeads); 1326 if (VBOX_FAILURE(rc)) 1327 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description in '%s'"), pImage->pszFilename); 1413 VMDK_DDB_GEO_PCHS_HEADS, 1414 &pImage->PCHSGeometry.cHeads); 1415 if (rc == VERR_VDI_VALUE_NOT_FOUND) 1416 pImage->PCHSGeometry.cHeads = 0; 1417 else if (VBOX_FAILURE(rc)) 1418 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename); 1328 1419 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 1329 "ddb.geometry.sectors", &pImage->cSectors); 1330 if (VBOX_FAILURE(rc)) 1331 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting CHS geometry from extent description in '%s'"), pImage->pszFilename); 1332 if (pImage->cCylinders >= 1024 || pImage->cHeads != 16) 1333 pImage->enmTranslation = PDMBIOSTRANSLATION_LBA; 1334 else 1335 pImage->enmTranslation = PDMBIOSTRANSLATION_NONE; 1420 VMDK_DDB_GEO_PCHS_SECTORS, 1421 &pImage->PCHSGeometry.cSectors); 1422 if (rc == VERR_VDI_VALUE_NOT_FOUND) 1423 pImage->PCHSGeometry.cSectors = 0; 1424 else if (VBOX_FAILURE(rc)) 1425 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting PCHS geometry from extent description in '%s'"), pImage->pszFilename); 1426 if ( pImage->PCHSGeometry.cCylinders == 0 1427 || pImage->PCHSGeometry.cHeads == 0 1428 || pImage->PCHSGeometry.cHeads > 16 1429 || pImage->PCHSGeometry.cSectors == 0 1430 || pImage->PCHSGeometry.cSectors > 63) 1431 { 1432 /* Mark PCHS geometry as not yet valid (can't do the calculation here 1433 * as the total image size isn't known yet). */ 1434 pImage->PCHSGeometry.cCylinders = 0; 1435 pImage->PCHSGeometry.cHeads = 16; 1436 pImage->PCHSGeometry.cSectors = 63; 1437 } 1438 1439 /* Determine LCHS geometry (set to 0 if not specified). */ 1440 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 1441 VMDK_DDB_GEO_LCHS_CYLINDERS, 1442 &pImage->LCHSGeometry.cCylinders); 1443 if (rc == VERR_VDI_VALUE_NOT_FOUND) 1444 pImage->LCHSGeometry.cCylinders = 0; 1445 else if (VBOX_FAILURE(rc)) 1446 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename); 1447 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 1448 VMDK_DDB_GEO_LCHS_HEADS, 1449 &pImage->LCHSGeometry.cHeads); 1450 if (rc == VERR_VDI_VALUE_NOT_FOUND) 1451 pImage->LCHSGeometry.cHeads = 0; 1452 else if (VBOX_FAILURE(rc)) 1453 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename); 1454 rc = vmdkDescDDBGetU32(pImage, &pImage->Descriptor, 1455 VMDK_DDB_GEO_LCHS_SECTORS, 1456 &pImage->LCHSGeometry.cSectors); 1457 if (rc == VERR_VDI_VALUE_NOT_FOUND) 1458 pImage->LCHSGeometry.cSectors = 0; 1459 else if (VBOX_FAILURE(rc)) 1460 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error getting LCHS geometry from extent description in '%s'"), pImage->pszFilename); 1461 if ( pImage->LCHSGeometry.cCylinders == 0 1462 || pImage->LCHSGeometry.cHeads == 0 1463 || pImage->LCHSGeometry.cSectors == 0) 1464 { 1465 pImage->LCHSGeometry.cCylinders = 0; 1466 pImage->LCHSGeometry.cHeads = 0; 1467 pImage->LCHSGeometry.cSectors = 0; 1468 } 1336 1469 1337 1470 /* Get image UUID. */ … … 1360 1493 1361 1494 /* Get image modification UUID. */ 1362 rc = vmdkDescDDBGetUuid(pImage, &pImage->Descriptor, "ddb.uuid.modification", 1495 rc = vmdkDescDDBGetUuid(pImage, &pImage->Descriptor, 1496 "ddb.uuid.modification", 1363 1497 &pImage->ModificationUuid); 1364 1498 if (rc == VERR_VDI_VALUE_NOT_FOUND) … … 1375 1509 return rc; 1376 1510 rc = vmdkDescDDBSetUuid(pImage, &pImage->Descriptor, 1377 "ddb.uuid.modification", &pImage->ModificationUuid); 1511 "ddb.uuid.modification", 1512 &pImage->ModificationUuid); 1378 1513 if (VBOX_FAILURE(rc)) 1379 1514 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: error storing image modification UUID in descriptor in '%s'"), pImage->pszFilename); … … 1750 1885 } 1751 1886 1752 static int vmdkOpenImage(PVMDKIMAGE pImage, const char *pszFilename, unsigned uOpenFlags) 1887 static int vmdkOpenImage(PVMDKIMAGE pImage, const char *pszFilename, 1888 unsigned uOpenFlags) 1753 1889 { 1754 1890 int rc = VINF_SUCCESS; … … 1860 1996 } 1861 1997 1862 rc = vmdkParseDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc); 1998 rc = vmdkParseDescriptor(pImage, pImage->pDescData, 1999 pImage->cbDescAlloc); 1863 2000 if (VBOX_FAILURE(rc)) 1864 2001 goto out; … … 1924 2061 goto out; 1925 2062 1926 /* Mark theextent as unclean if opened in read-write mode. */2063 /* Mark extent as unclean if opened in read-write mode. */ 1927 2064 if (!(uOpenFlags & VD_OPEN_FLAGS_READONLY)) 1928 2065 { … … 1956 2093 AssertRC(rc); 1957 2094 2095 /* Determine PCHS geometry if not set. */ 2096 if (pImage->PCHSGeometry.cCylinders == 0) 2097 { 2098 uint64_t cCylinders = VMDK_BYTE2SECTOR(pImage->cbSize) 2099 / pImage->PCHSGeometry.cHeads 2100 / pImage->PCHSGeometry.cSectors; 2101 pImage->PCHSGeometry.cCylinders = (unsigned)RT_MIN(cCylinders, 16383); 2102 if (!(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY)) 2103 { 2104 rc = vmdkDescSetPCHSGeometry(pImage, &pImage->PCHSGeometry); 2105 AssertRC(rc); 2106 } 2107 } 2108 1958 2109 /* Update the image metadata now in case has changed. */ 1959 2110 rc = vmdkFlushImage(pImage); … … 2002 2153 } 2003 2154 2004 static int vmdkCreate Image(PVMDKIMAGE pImage, const char *pszFilename, VDIMAGETYPE enmType, uint64_t cbSize, unsigned uImageFlags, const char *pszComment, uint32_t cCylinders, uint32_t cHeads, uint32_t cSectors)2005 { 2006 int rc; 2007 uint64_t cSectorsPerGDE, cSectorsPerGD;2155 static int vmdkCreateRawImage(PVMDKIMAGE pImage, const char *pszFilename, 2156 const PVBOXHDDRAW pRaw, uint64_t cbSize) 2157 { 2158 int rc = VINF_SUCCESS; 2008 2159 PVMDKEXTENT pExtent; 2009 2160 2010 pImage->uImageFlags = uImageFlags; 2011 rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc, &pImage->Descriptor); 2012 if (VBOX_FAILURE(rc)) 2013 { 2014 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new descriptor in '%s'"), pszFilename); 2015 goto out; 2016 } 2017 2018 if ( enmType == VD_IMAGE_TYPE_FIXED 2019 || (uImageFlags & VD_VMDK_IMAGE_FLAGS_SPLIT_2G) 2020 || (uImageFlags & VD_VMDK_IMAGE_FLAGS_RAWDISK)) 2021 { 2022 /* Fixed images and split images in general have a separate descriptor 2023 * file. This is the more complicated case, as it requires setting up 2024 * potentially more than one extent, including filename generation. */ 2025 2026 if ( enmType == VD_IMAGE_TYPE_FIXED 2027 && (uImageFlags & VD_VMDK_IMAGE_FLAGS_RAWDISK)) 2028 { 2029 PVBOXHDDRAW pRaw = (PVBOXHDDRAW)(void *)pszComment; 2030 /* As the comment is misused, zap it so that no garbage comment 2031 * is set below. */ 2032 pszComment = NULL; 2033 if (pRaw->fRawDisk) 2161 if (pRaw->fRawDisk) 2162 { 2163 /* Full raw disk access. This requires setting up a descriptor 2164 * file and open the (flat) raw disk. */ 2165 rc = vmdkCreateExtents(pImage, 1); 2166 if (VBOX_FAILURE(rc)) 2167 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pszFilename); 2168 pExtent = &pImage->pExtents[0]; 2169 rc = RTFileOpen(&pImage->File, pszFilename, 2170 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE); 2171 if (VBOX_FAILURE(rc)) 2172 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pszFilename); 2173 2174 /* Set up basename for extent description. Cannot use StrDup. */ 2175 size_t cbBasename = strlen(pRaw->pszRawDisk) + 1; 2176 char *pszBasename = (char *)RTMemTmpAlloc(cbBasename); 2177 if (!pszBasename) 2178 return VERR_NO_MEMORY; 2179 memcpy(pszBasename, pRaw->pszRawDisk, cbBasename); 2180 pExtent->pszBasename = pszBasename; 2181 /* For raw disks the full name is identical to the base name. */ 2182 pExtent->pszFullname = RTStrDup(pszBasename); 2183 if (!pExtent->pszFullname) 2184 return VERR_NO_MEMORY; 2185 pExtent->enmType = VMDKETYPE_FLAT; 2186 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(cbSize); 2187 pExtent->uSectorOffset = 0; 2188 pExtent->enmAccess = VMDKACCESS_READWRITE; 2189 pExtent->fMetaDirty = false; 2190 2191 /* Open flat image, the raw disk. */ 2192 rc = RTFileOpen(&pExtent->File, pExtent->pszFullname, 2193 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 2194 if (VBOX_FAILURE(rc)) 2195 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname); 2196 } 2197 else 2198 { 2199 /* Raw partition access. This requires setting up a descriptor 2200 * file, write the partition information to a flat extent and 2201 * open all the (flat) raw disk partitions. */ 2202 2203 /* First pass over the partitions to determine how many 2204 * extents we need. One partition can require up to 4 extents. 2205 * One to skip over unpartitioned space, one for the 2206 * partitioning data, one to skip over unpartitioned space 2207 * and one for the partition data. */ 2208 unsigned cExtents = 0; 2209 uint64_t uStart = 0; 2210 for (unsigned i = 0; i < pRaw->cPartitions; i++) 2211 { 2212 PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i]; 2213 if (pPart->cbPartitionData) 2034 2214 { 2035 /* Full raw disk access. This requires setting up a descriptor 2036 * file and open the (flat) raw disk. */ 2037 rc = vmdkCreateExtents(pImage, 1); 2038 if (VBOX_FAILURE(rc)) 2039 { 2040 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pszFilename); 2041 goto out; 2042 } 2043 pExtent = &pImage->pExtents[0]; 2044 rc = RTFileOpen(&pImage->File, pszFilename, 2045 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE); 2046 if (VBOX_FAILURE(rc)) 2047 { 2048 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pszFilename); 2049 goto out; 2050 } 2051 2052 /* Set up basename for extent description. Cannot use StrDup. */ 2053 size_t cbBasename = strlen(pRaw->pszRawDisk) + 1; 2054 char *pszBasename = (char *)RTMemTmpAlloc(cbBasename); 2055 if (!pszBasename) 2056 { 2057 rc = VERR_NO_MEMORY; 2058 goto out; 2059 } 2060 memcpy(pszBasename, pRaw->pszRawDisk, cbBasename); 2061 pExtent->pszBasename = pszBasename; 2062 /* For raw disks the full name is identical to the base name. */ 2063 pExtent->pszFullname = RTStrDup(pszBasename); 2064 if (!pExtent->pszFullname) 2065 { 2066 rc = VERR_NO_MEMORY; 2067 goto out; 2068 } 2069 pExtent->enmType = VMDKETYPE_FLAT; 2070 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(cbSize); 2071 pExtent->uSectorOffset = 0; 2072 pExtent->enmAccess = VMDKACCESS_READWRITE; 2073 pExtent->fMetaDirty = false; 2074 2075 pImage->enmImageType = enmType; 2076 rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType", "fullDevice"); 2077 if (VBOX_FAILURE(rc)) 2078 { 2079 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pszFilename); 2080 goto out; 2081 } 2082 2083 /* Open flat image, the raw disk. */ 2084 rc = RTFileOpen(&pExtent->File, pExtent->pszFullname, 2085 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 2086 if (VBOX_FAILURE(rc)) 2087 { 2088 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw disk file '%s'"), pExtent->pszFullname); 2089 goto out; 2090 } 2215 if (uStart > pPart->uPartitionDataStart) 2216 return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partitioning information in '%s'"), pszFilename); 2217 else if (uStart != pPart->uPartitionDataStart) 2218 cExtents++; 2219 uStart = pPart->uPartitionDataStart + pPart->cbPartitionData; 2220 cExtents++; 2091 2221 } 2092 else2222 if (pPart->cbPartition) 2093 2223 { 2094 /* Raw partition access. This requires setting up a descriptor 2095 * file, write the partition information to a flat extent and 2096 * open all the (flat) raw disk partitions. */ 2097 2098 /* First pass over the partitions to determine how many 2099 * extents we need. One partition can require up to 4 extents. 2100 * One to skip over unpartitioned space, one for the 2101 * partitioning data, one to skip over unpartitioned space 2102 * and one for the partition data. */ 2103 unsigned cExtents = 0; 2104 uint64_t uStart = 0; 2105 for (unsigned i = 0; i < pRaw->cPartitions; i++) 2106 { 2107 PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i]; 2108 if (pPart->cbPartitionData) 2109 { 2110 if (uStart > pPart->uPartitionDataStart) 2111 { 2112 rc = vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partitioning information in '%s'"), pszFilename); 2113 goto out; 2114 } else if (uStart != pPart->uPartitionDataStart) 2115 cExtents++; 2116 uStart = pPart->uPartitionDataStart + pPart->cbPartitionData; 2117 cExtents++; 2118 } 2119 if (pPart->cbPartition) 2120 { 2121 if (uStart > pPart->uPartitionStart) 2122 { 2123 rc = vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partition data in '%s'"), pszFilename); 2124 goto out; 2125 } else if (uStart != pPart->uPartitionStart) 2126 cExtents++; 2127 uStart = pPart->uPartitionStart + pPart->cbPartition; 2128 cExtents++; 2129 } 2130 } 2131 /* Another extent for filling up the rest of the image. */ 2132 if (uStart != cbSize) 2224 if (uStart > pPart->uPartitionStart) 2225 return vmdkError(pImage, VERR_INVALID_PARAMETER, RT_SRC_POS, N_("VMDK: cannot go backwards for partition data in '%s'"), pszFilename); 2226 else if (uStart != pPart->uPartitionStart) 2133 2227 cExtents++; 2134 2135 rc = vmdkCreateExtents(pImage, cExtents); 2136 if (VBOX_FAILURE(rc)) 2137 { 2138 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pszFilename); 2139 goto out; 2140 } 2141 2142 rc = RTFileOpen(&pImage->File, pszFilename, 2143 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE); 2144 if (VBOX_FAILURE(rc)) 2145 { 2146 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pszFilename); 2147 goto out; 2148 } 2149 2150 /* Create base filename for the partition table extent. */ 2151 /** @todo remove fixed buffer. */ 2152 char pszPartition[1024]; 2153 const char *pszBase = RTPathFilename(pszFilename); 2154 const char *pszExt = RTPathExt(pszBase); 2155 if (pszExt == NULL) 2156 { 2157 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: invalid filename '%s'"), pszFilename); 2158 goto out; 2159 } 2160 memcpy(pszPartition, pszBase, pszExt - pszBase); 2161 memcpy(pszPartition + (pszExt - pszBase), "-pt", 3); 2162 memcpy(pszPartition + (pszExt - pszBase) + 3, pszExt, strlen(pszExt) + 1); 2163 2164 /* Second pass over the partitions, now define all extents. */ 2165 uint64_t uPartOffset = 0; 2166 cExtents = 0; 2167 uStart = 0; 2168 for (unsigned i = 0; i < pRaw->cPartitions; i++) 2169 { 2170 PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i]; 2171 if (pPart->cbPartitionData) 2172 { 2173 if (uStart != pPart->uPartitionDataStart) 2174 { 2175 pExtent = &pImage->pExtents[cExtents++]; 2176 pExtent->pszBasename = NULL; 2177 pExtent->pszFullname = NULL; 2178 pExtent->enmType = VMDKETYPE_ZERO; 2179 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionDataStart - uStart); 2180 pExtent->uSectorOffset = 0; 2181 pExtent->enmAccess = VMDKACCESS_READWRITE; 2182 pExtent->fMetaDirty = false; 2183 } 2184 uStart = pPart->uPartitionDataStart + pPart->cbPartitionData; 2185 pExtent = &pImage->pExtents[cExtents++]; 2186 /* Set up basename for extent description. Cannot use StrDup. */ 2187 size_t cbBasename = strlen(pszPartition) + 1; 2188 char *pszBasename = (char *)RTMemTmpAlloc(cbBasename); 2189 if (!pszBasename) 2190 { 2191 rc = VERR_NO_MEMORY; 2192 goto out; 2193 } 2194 memcpy(pszBasename, pszPartition, cbBasename); 2195 pExtent->pszBasename = pszBasename; 2196 2197 /* Set up full name for partition extent. */ 2198 size_t cbDirname; 2199 char *pszDirname = RTStrDup(pImage->pszFilename); 2200 if (!pszDirname) 2201 { 2202 rc = VERR_NO_MEMORY; 2203 goto out; 2204 } 2205 RTPathStripFilename(pszDirname); 2206 cbDirname = strlen(pszDirname); 2207 char *pszFullname; 2208 rc = RTStrAPrintf(&pszFullname, "%s%c%s", pszDirname, 2209 RTPATH_SLASH, pExtent->pszBasename); 2210 RTStrFree(pszDirname); 2211 if (VBOX_FAILURE(rc)) 2212 goto out; 2213 pExtent->pszFullname = pszFullname; 2214 pExtent->enmType = VMDKETYPE_FLAT; 2215 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartitionData); 2216 pExtent->uSectorOffset = uPartOffset; 2217 pExtent->enmAccess = VMDKACCESS_READWRITE; 2218 pExtent->fMetaDirty = false; 2219 2220 rc = RTFileOpen(&pExtent->File, pExtent->pszFullname, 2221 RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); 2222 if (VBOX_FAILURE(rc)) 2223 { 2224 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname); 2225 goto out; 2226 } 2227 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(uPartOffset), pPart->pvPartitionData, pPart->cbPartitionData, NULL); 2228 if (VBOX_FAILURE(rc)) 2229 { 2230 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname); 2231 goto out; 2232 } 2233 uPartOffset += VMDK_BYTE2SECTOR(pPart->cbPartitionData); 2234 } 2235 if (pPart->cbPartition) 2236 { 2237 if (uStart != pPart->uPartitionStart) 2238 { 2239 pExtent = &pImage->pExtents[cExtents++]; 2240 pExtent->pszBasename = NULL; 2241 pExtent->pszFullname = NULL; 2242 pExtent->enmType = VMDKETYPE_ZERO; 2243 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionStart - uStart); 2244 pExtent->uSectorOffset = 0; 2245 pExtent->enmAccess = VMDKACCESS_READWRITE; 2246 pExtent->fMetaDirty = false; 2247 } 2248 uStart = pPart->uPartitionStart + pPart->cbPartition; 2249 pExtent = &pImage->pExtents[cExtents++]; 2250 if (pPart->pszRawDevice) 2251 { 2252 /* Set up basename for extent description. Cannot use StrDup. */ 2253 size_t cbBasename = strlen(pPart->pszRawDevice) + 1; 2254 char *pszBasename = (char *)RTMemTmpAlloc(cbBasename); 2255 if (!pszBasename) 2256 { 2257 rc = VERR_NO_MEMORY; 2258 goto out; 2259 } 2260 memcpy(pszBasename, pPart->pszRawDevice, cbBasename); 2261 pExtent->pszBasename = pszBasename; 2262 /* For raw disks the full name is identical to the base name. */ 2263 pExtent->pszFullname = RTStrDup(pszBasename); 2264 if (!pExtent->pszFullname) 2265 { 2266 rc = VERR_NO_MEMORY; 2267 goto out; 2268 } 2269 pExtent->enmType = VMDKETYPE_FLAT; 2270 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition); 2271 pExtent->uSectorOffset = VMDK_BYTE2SECTOR(pPart->uPartitionStartOffset); 2272 pExtent->enmAccess = VMDKACCESS_READWRITE; 2273 pExtent->fMetaDirty = false; 2274 2275 rc = RTFileOpen(&pExtent->File, pExtent->pszFullname, 2276 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 2277 if (VBOX_FAILURE(rc)) 2278 { 2279 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname); 2280 goto out; 2281 } 2282 } 2283 else 2284 { 2285 pExtent->pszBasename = NULL; 2286 pExtent->pszFullname = NULL; 2287 pExtent->enmType = VMDKETYPE_ZERO; 2288 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition); 2289 pExtent->uSectorOffset = 0; 2290 pExtent->enmAccess = VMDKACCESS_READWRITE; 2291 pExtent->fMetaDirty = false; 2292 } 2293 } 2294 } 2295 /* Another extent for filling up the rest of the image. */ 2296 if (uStart != cbSize) 2228 uStart = pPart->uPartitionStart + pPart->cbPartition; 2229 cExtents++; 2230 } 2231 } 2232 /* Another extent for filling up the rest of the image. */ 2233 if (uStart != cbSize) 2234 cExtents++; 2235 2236 rc = vmdkCreateExtents(pImage, cExtents); 2237 if (VBOX_FAILURE(rc)) 2238 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pszFilename); 2239 2240 rc = RTFileOpen(&pImage->File, pszFilename, 2241 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE); 2242 if (VBOX_FAILURE(rc)) 2243 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pszFilename); 2244 2245 /* Create base filename for the partition table extent. */ 2246 /** @todo remove fixed buffer without creating memory leaks. */ 2247 char pszPartition[1024]; 2248 const char *pszBase = RTPathFilename(pszFilename); 2249 const char *pszExt = RTPathExt(pszBase); 2250 if (pszExt == NULL) 2251 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: invalid filename '%s'"), pszFilename); 2252 char *pszBaseBase = RTStrDup(pszBase); 2253 if (!pszBaseBase) 2254 return VERR_NO_MEMORY; 2255 RTPathStripExt(pszBaseBase); 2256 RTStrPrintf(pszPartition, sizeof(pszPartition), "%s-pt%s", 2257 pszBaseBase, pszExt); 2258 RTStrFree(pszBaseBase); 2259 2260 /* Second pass over the partitions, now define all extents. */ 2261 uint64_t uPartOffset = 0; 2262 cExtents = 0; 2263 uStart = 0; 2264 for (unsigned i = 0; i < pRaw->cPartitions; i++) 2265 { 2266 PVBOXHDDRAWPART pPart = &pRaw->pPartitions[i]; 2267 if (pPart->cbPartitionData) 2268 { 2269 if (uStart != pPart->uPartitionDataStart) 2297 2270 { 2298 2271 pExtent = &pImage->pExtents[cExtents++]; … … 2300 2273 pExtent->pszFullname = NULL; 2301 2274 pExtent->enmType = VMDKETYPE_ZERO; 2302 pExtent->cNominalSectors = VMDK_BYTE2SECTOR( cbSize- uStart);2275 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionDataStart - uStart); 2303 2276 pExtent->uSectorOffset = 0; 2304 2277 pExtent->enmAccess = VMDKACCESS_READWRITE; 2305 2278 pExtent->fMetaDirty = false; 2306 2279 } 2307 2308 pImage->enmImageType = enmType; 2309 rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType", "partitionedDevice"); 2280 uStart = pPart->uPartitionDataStart + pPart->cbPartitionData; 2281 pExtent = &pImage->pExtents[cExtents++]; 2282 /* Set up basename for extent description. Can't use StrDup. */ 2283 size_t cbBasename = strlen(pszPartition) + 1; 2284 char *pszBasename = (char *)RTMemTmpAlloc(cbBasename); 2285 if (!pszBasename) 2286 return VERR_NO_MEMORY; 2287 memcpy(pszBasename, pszPartition, cbBasename); 2288 pExtent->pszBasename = pszBasename; 2289 2290 /* Set up full name for partition extent. */ 2291 size_t cbDirname; 2292 char *pszDirname = RTStrDup(pImage->pszFilename); 2293 if (!pszDirname) 2294 return VERR_NO_MEMORY; 2295 RTPathStripFilename(pszDirname); 2296 cbDirname = strlen(pszDirname); 2297 char *pszFullname; 2298 rc = RTStrAPrintf(&pszFullname, "%s%c%s", pszDirname, 2299 RTPATH_SLASH, pExtent->pszBasename); 2300 RTStrFree(pszDirname); 2310 2301 if (VBOX_FAILURE(rc)) 2302 return rc; 2303 pExtent->pszFullname = pszFullname; 2304 pExtent->enmType = VMDKETYPE_FLAT; 2305 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartitionData); 2306 pExtent->uSectorOffset = uPartOffset; 2307 pExtent->enmAccess = VMDKACCESS_READWRITE; 2308 pExtent->fMetaDirty = false; 2309 2310 rc = RTFileOpen(&pExtent->File, pExtent->pszFullname, 2311 RTFILE_O_READWRITE | RTFILE_O_OPEN_CREATE | RTFILE_O_DENY_WRITE); 2312 if (VBOX_FAILURE(rc)) 2313 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new partition data file '%s'"), pExtent->pszFullname); 2314 rc = RTFileWriteAt(pExtent->File, 2315 VMDK_SECTOR2BYTE(uPartOffset), 2316 pPart->pvPartitionData, 2317 pPart->cbPartitionData, NULL); 2318 if (VBOX_FAILURE(rc)) 2319 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not write partition data to '%s'"), pExtent->pszFullname); 2320 uPartOffset += VMDK_BYTE2SECTOR(pPart->cbPartitionData); 2321 } 2322 if (pPart->cbPartition) 2323 { 2324 if (uStart != pPart->uPartitionStart) 2311 2325 { 2312 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pszFilename); 2313 goto out; 2326 pExtent = &pImage->pExtents[cExtents++]; 2327 pExtent->pszBasename = NULL; 2328 pExtent->pszFullname = NULL; 2329 pExtent->enmType = VMDKETYPE_ZERO; 2330 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->uPartitionStart - uStart); 2331 pExtent->uSectorOffset = 0; 2332 pExtent->enmAccess = VMDKACCESS_READWRITE; 2333 pExtent->fMetaDirty = false; 2334 } 2335 uStart = pPart->uPartitionStart + pPart->cbPartition; 2336 pExtent = &pImage->pExtents[cExtents++]; 2337 if (pPart->pszRawDevice) 2338 { 2339 /* Set up basename for extent descr. Can't use StrDup. */ 2340 size_t cbBasename = strlen(pPart->pszRawDevice) + 1; 2341 char *pszBasename = (char *)RTMemTmpAlloc(cbBasename); 2342 if (!pszBasename) 2343 return VERR_NO_MEMORY; 2344 memcpy(pszBasename, pPart->pszRawDevice, cbBasename); 2345 pExtent->pszBasename = pszBasename; 2346 /* For raw disks full name is identical to base name. */ 2347 pExtent->pszFullname = RTStrDup(pszBasename); 2348 if (!pExtent->pszFullname) 2349 return VERR_NO_MEMORY; 2350 pExtent->enmType = VMDKETYPE_FLAT; 2351 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition); 2352 pExtent->uSectorOffset = VMDK_BYTE2SECTOR(pPart->uPartitionStartOffset); 2353 pExtent->enmAccess = VMDKACCESS_READWRITE; 2354 pExtent->fMetaDirty = false; 2355 2356 rc = RTFileOpen(&pExtent->File, pExtent->pszFullname, 2357 RTFILE_O_READWRITE | RTFILE_O_OPEN | RTFILE_O_DENY_WRITE); 2358 if (VBOX_FAILURE(rc)) 2359 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not open raw partition file '%s'"), pExtent->pszFullname); 2360 } 2361 else 2362 { 2363 pExtent->pszBasename = NULL; 2364 pExtent->pszFullname = NULL; 2365 pExtent->enmType = VMDKETYPE_ZERO; 2366 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(pPart->cbPartition); 2367 pExtent->uSectorOffset = 0; 2368 pExtent->enmAccess = VMDKACCESS_READWRITE; 2369 pExtent->fMetaDirty = false; 2314 2370 } 2315 2371 } 2316 2372 } 2317 else 2318 { 2319 rc = VERR_NOT_IMPLEMENTED; 2320 goto out; 2321 } 2322 } 2323 else 2324 { 2325 /* Normal (growing) image which is not split into pieces. */ 2326 rc = vmdkCreateExtents(pImage, 1); 2327 if (VBOX_FAILURE(rc)) 2328 { 2329 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pszFilename); 2330 goto out; 2331 } 2332 pExtent = &pImage->pExtents[0]; 2333 pImage->File = NIL_RTFILE; 2334 rc = RTFileOpen(&pExtent->File, pszFilename, 2373 /* Another extent for filling up the rest of the image. */ 2374 if (uStart != cbSize) 2375 { 2376 pExtent = &pImage->pExtents[cExtents++]; 2377 pExtent->pszBasename = NULL; 2378 pExtent->pszFullname = NULL; 2379 pExtent->enmType = VMDKETYPE_ZERO; 2380 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(cbSize - uStart); 2381 pExtent->uSectorOffset = 0; 2382 pExtent->enmAccess = VMDKACCESS_READWRITE; 2383 pExtent->fMetaDirty = false; 2384 } 2385 } 2386 2387 rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType", 2388 pRaw->fRawDisk ? 2389 "fullDevice" : "partitionedDevice"); 2390 if (VBOX_FAILURE(rc)) 2391 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pszFilename); 2392 return rc; 2393 } 2394 2395 static int vmdkCreateRegularImage(PVMDKIMAGE pImage, const char *pszFilename, 2396 VDIMAGETYPE enmType, uint64_t cbSize, 2397 unsigned uImageFlags, 2398 PFNVMPROGRESS pfnProgress, void *pvUser, 2399 unsigned uPercentStart, 2400 unsigned uPercentSpan) 2401 { 2402 int rc = VINF_SUCCESS; 2403 unsigned cExtents = 1; 2404 uint64_t cbOffset = 0; 2405 uint64_t cbRemaining = cbSize; 2406 2407 if (uImageFlags & VD_VMDK_IMAGE_FLAGS_SPLIT_2G) 2408 { 2409 cExtents = cbSize / VMDK_2G_SPLIT_SIZE; 2410 /* Do proper extent computation: need one smaller extent if the total 2411 * size isn't evenly divisible by the split size. */ 2412 if (cbSize % VMDK_2G_SPLIT_SIZE) 2413 cExtents++; 2414 } 2415 rc = vmdkCreateExtents(pImage, cExtents); 2416 if (VBOX_FAILURE(rc)) 2417 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new extent list in '%s'"), pszFilename); 2418 2419 /* Basename strings needed for constructing the extent names. */ 2420 char *pszBasenameSubstr = RTPathFilename(pszFilename); 2421 Assert(pszBasenameSubstr); 2422 size_t cbBasenameSubstr = strlen(pszBasenameSubstr) + 1; 2423 2424 /* Create searate descriptor file if necessary. */ 2425 if (cExtents != 1 || enmType == VD_IMAGE_TYPE_FIXED) 2426 { 2427 rc = RTFileOpen(&pImage->File, pszFilename, 2335 2428 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE); 2336 2429 if (VBOX_FAILURE(rc)) 2337 { 2338 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pszFilename); 2339 goto out; 2340 } 2341 2342 /* Set up basename for extent description. Cannot use StrDup, as it is 2343 * not guaranteed that the memory can be freed with RTMemTmpFree, which 2344 * must be used as in other code paths StrDup is not usable. */ 2345 char *pszBasenameSubstr = RTPathFilename(pszFilename); 2346 Assert(pszBasenameSubstr); 2347 size_t cbBasenameSubstr = strlen(pszBasenameSubstr) + 1; 2348 char *pszBasename = (char *)RTMemTmpAlloc(cbBasenameSubstr); 2349 if (!pszBasename) 2350 { 2351 rc = VERR_NO_MEMORY; 2352 goto out; 2353 } 2354 memcpy(pszBasename, pszBasenameSubstr, cbBasenameSubstr); 2355 pExtent->pszBasename = pszBasename; 2356 pExtent->pszFullname = RTStrDup(pszFilename); 2357 if (!pExtent->pszFullname) 2358 { 2359 rc = VERR_NO_MEMORY; 2360 goto out; 2361 } 2362 pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; 2363 pExtent->cSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(cbSize, 65536)); 2364 pExtent->cSectorsPerGrain = VMDK_BYTE2SECTOR(65536); 2365 pExtent->uDescriptorSector = 1; 2366 pExtent->cDescriptorSectors = VMDK_BYTE2SECTOR(pImage->cbDescAlloc); 2367 pExtent->cGTEntries = 512; 2368 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain; 2369 pExtent->cSectorsPerGDE = cSectorsPerGDE; 2370 pExtent->cGDEntries = (pExtent->cSectors + cSectorsPerGDE - 1) / cSectorsPerGDE; 2371 cSectorsPerGD = (pExtent->cGDEntries + (512 / sizeof(uint32_t) - 1)) / (512 / sizeof(uint32_t)); 2430 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new sparse descriptor file '%s'"), pszFilename); 2431 pImage->pszFilename = RTStrDup(pszFilename); 2432 } 2433 else 2434 pImage->File = NIL_RTFILE; 2435 2436 /* Set up all extents. */ 2437 for (unsigned i = 0; i < cExtents; i++) 2438 { 2439 PVMDKEXTENT pExtent = &pImage->pExtents[i]; 2440 uint64_t cbExtent = cbRemaining; 2441 2442 /* Set up fullname/basename for extent description. Cannot use StrDup 2443 * for basename, as it is not guaranteed that the memory can be freed 2444 * with RTMemTmpFree, which must be used as in other code paths 2445 * StrDup is not usable. */ 2446 if (cExtents == 1 && enmType != VD_IMAGE_TYPE_FIXED) 2447 { 2448 char *pszBasename = (char *)RTMemTmpAlloc(cbBasenameSubstr); 2449 if (!pszBasename) 2450 return VERR_NO_MEMORY; 2451 memcpy(pszBasename, pszBasenameSubstr, cbBasenameSubstr); 2452 pExtent->pszBasename = pszBasename; 2453 } 2454 else 2455 { 2456 char *pszBasenameExt = RTPathExt(pszBasenameSubstr); 2457 char *pszBasenameBase = RTStrDup(pszBasenameSubstr); 2458 RTPathStripExt(pszBasenameBase); 2459 char *pszTmp; 2460 size_t cbTmp; 2461 if (enmType == VD_IMAGE_TYPE_FIXED) 2462 { 2463 if (cExtents == 1) 2464 rc = RTStrAPrintf(&pszTmp, "%s-flat%s", pszBasenameBase, 2465 pszBasenameExt); 2466 else 2467 rc = RTStrAPrintf(&pszTmp, "%s-f%03d%s", pszBasenameBase, 2468 i+1, pszBasenameExt); 2469 } 2470 else 2471 rc = RTStrAPrintf(&pszTmp, "%s-s%03d%s", pszBasenameBase, i+1, 2472 pszBasenameExt); 2473 RTStrFree(pszBasenameBase); 2474 if (VBOX_FAILURE(rc)) 2475 return rc; 2476 cbTmp = strlen(pszTmp) + 1; 2477 char *pszBasename = (char *)RTMemTmpAlloc(cbTmp); 2478 if (!pszBasename) 2479 return VERR_NO_MEMORY; 2480 memcpy(pszBasename, pszTmp, cbTmp); 2481 RTStrFree(pszTmp); 2482 pExtent->pszBasename = pszBasename; 2483 cbExtent = RT_MIN(cbRemaining, VMDK_2G_SPLIT_SIZE); 2484 } 2485 char *pszBasedirectory = RTStrDup(pszFilename); 2486 RTPathStripFilename(pszBasedirectory); 2487 char *pszFN; 2488 rc = RTStrAPrintf(&pszFN, "%s%c%s", pszBasedirectory, RTPATH_SLASH, 2489 pExtent->pszBasename); 2490 RTStrFree(pszBasedirectory); 2491 if (VBOX_FAILURE(rc)) 2492 return rc; 2493 pExtent->pszFullname = pszFN; 2494 2495 /* Create file for extent. */ 2496 rc = RTFileOpen(&pExtent->File, pExtent->pszFullname, 2497 RTFILE_O_READWRITE | RTFILE_O_CREATE | RTFILE_O_DENY_WRITE); 2498 if (VBOX_FAILURE(rc)) 2499 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new file '%s'"), pExtent->pszFullname); 2500 if (enmType == VD_IMAGE_TYPE_FIXED) 2501 { 2502 rc = RTFileSetSize(pExtent->File, cbExtent); 2503 if (VBOX_FAILURE(rc)) 2504 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set size of new file '%s'"), pExtent->pszFullname); 2505 } 2506 2507 /* Place descriptor file information (where integrated). */ 2508 if (cExtents == 1 && enmType != VD_IMAGE_TYPE_FIXED) 2509 { 2510 pExtent->uDescriptorSector = 1; 2511 pExtent->cDescriptorSectors = VMDK_BYTE2SECTOR(pImage->cbDescAlloc); 2512 /* The descriptor is part of the (only) extent. */ 2513 pExtent->pDescData = pImage->pDescData; 2514 pImage->pDescData = NULL; 2515 } 2516 2517 if (enmType == VD_IMAGE_TYPE_NORMAL) 2518 { 2519 uint64_t cSectorsPerGDE, cSectorsPerGD; 2520 pExtent->enmType = VMDKETYPE_HOSTED_SPARSE; 2521 pExtent->cSectors = VMDK_BYTE2SECTOR(RT_ALIGN_64(cbExtent, 65536)); 2522 pExtent->cSectorsPerGrain = VMDK_BYTE2SECTOR(65536); 2523 pExtent->cGTEntries = 512; 2524 cSectorsPerGDE = pExtent->cGTEntries * pExtent->cSectorsPerGrain; 2525 pExtent->cSectorsPerGDE = cSectorsPerGDE; 2526 pExtent->cGDEntries = (pExtent->cSectors + cSectorsPerGDE - 1) / cSectorsPerGDE; 2527 cSectorsPerGD = (pExtent->cGDEntries + (512 / sizeof(uint32_t) - 1)) / (512 / sizeof(uint32_t)); 2528 } 2529 else 2530 pExtent->enmType = VMDKETYPE_FLAT; 2531 2372 2532 pExtent->enmAccess = VMDKACCESS_READWRITE; 2373 2533 pExtent->fUncleanShutdown = true; 2374 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(cb Size);2375 pExtent->uSectorOffset = 0;2534 pExtent->cNominalSectors = VMDK_BYTE2SECTOR(cbExtent); 2535 pExtent->uSectorOffset = VMDK_BYTE2SECTOR(cbOffset); 2376 2536 pExtent->fMetaDirty = true; 2377 2537 2378 rc = vmdkCreateGrainDirectory(pExtent, pExtent->uDescriptorSector + pExtent->cDescriptorSectors, true); 2379 if (VBOX_FAILURE(rc)) 2380 { 2381 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pszFilename); 2382 goto out; 2383 } 2384 2385 pImage->enmImageType = enmType; 2386 rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType", "monolithicSparse"); 2387 if (VBOX_FAILURE(rc)) 2388 { 2389 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pszFilename); 2390 goto out; 2391 } 2392 2393 /* The descriptor is part of the extent, move info to extent. */ 2394 pExtent->pDescData = pImage->pDescData; 2395 pImage->pDescData = NULL; 2396 } 2397 2538 if (enmType == VD_IMAGE_TYPE_NORMAL) 2539 { 2540 rc = vmdkCreateGrainDirectory(pExtent, 2541 pExtent->uDescriptorSector 2542 + pExtent->cDescriptorSectors, 2543 true); 2544 if (VBOX_FAILURE(rc)) 2545 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new grain directory in '%s'"), pExtent->pszFullname); 2546 } 2547 2548 if (VBOX_SUCCESS(rc) && pfnProgress) 2549 pfnProgress(NULL /* WARNING! pVM=NULL */, 2550 i * uPercentSpan / cExtents + uPercentStart, 2551 pvUser); 2552 2553 cbRemaining -= cbExtent; 2554 cbOffset += cbExtent; 2555 } 2556 2557 const char *pszDescType = NULL; 2558 if (enmType == VD_IMAGE_TYPE_FIXED) 2559 { 2560 pszDescType = (cExtents == 1) 2561 ? "monolithicFlat" : "twoGbMaxExtentFlat"; 2562 } 2563 else if (enmType == VD_IMAGE_TYPE_NORMAL) 2564 { 2565 pszDescType = (cExtents == 1) 2566 ? "monolithicSparse" : "twoGbMaxExtentSparse"; 2567 } 2568 else 2569 AssertMsgFailed(("invalid image type %d\n", enmType)); 2570 rc = vmdkDescBaseSetStr(pImage, &pImage->Descriptor, "createType", 2571 pszDescType); 2572 if (VBOX_FAILURE(rc)) 2573 return vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not set the image type in '%s'"), pszFilename); 2574 return rc; 2575 } 2576 2577 static int vmdkCreateImage(PVMDKIMAGE pImage, const char *pszFilename, 2578 VDIMAGETYPE enmType, uint64_t cbSize, 2579 unsigned uImageFlags, const char *pszComment, 2580 PCPDMMEDIAGEOMETRY pPCHSGeometry, 2581 PCPDMMEDIAGEOMETRY pLCHSGeometry, 2582 PFNVMPROGRESS pfnProgress, void *pvUser, 2583 unsigned uPercentStart, unsigned uPercentSpan) 2584 { 2585 int rc; 2586 2587 pImage->uImageFlags = uImageFlags; 2588 rc = vmdkCreateDescriptor(pImage, pImage->pDescData, pImage->cbDescAlloc, 2589 &pImage->Descriptor); 2590 if (VBOX_FAILURE(rc)) 2591 { 2592 rc = vmdkError(pImage, rc, RT_SRC_POS, N_("VMDK: could not create new descriptor in '%s'"), pszFilename); 2593 goto out; 2594 } 2595 2596 if ( enmType == VD_IMAGE_TYPE_FIXED 2597 && (uImageFlags & VD_VMDK_IMAGE_FLAGS_RAWDISK)) 2598 { 2599 /* Raw disk image (includes raw partition). */ 2600 const PVBOXHDDRAW pRaw = (const PVBOXHDDRAW)pszComment; 2601 /* As the comment is misused, zap it so that no garbage comment 2602 * is set below. */ 2603 pszComment = NULL; 2604 rc = vmdkCreateRawImage(pImage, pszFilename, pRaw, cbSize); 2605 } 2606 else if ( enmType == VD_IMAGE_TYPE_FIXED 2607 || enmType == VD_IMAGE_TYPE_NORMAL) 2608 { 2609 /* Regular fixed or sparse image (monolithic or split). */ 2610 rc = vmdkCreateRegularImage(pImage, pszFilename, enmType, cbSize, 2611 uImageFlags, pfnProgress, pvUser, 2612 uPercentStart, uPercentSpan * 95 / 100); 2613 } 2614 else 2615 { 2616 /* Unknown/invalid image type. */ 2617 rc = VERR_NOT_IMPLEMENTED; 2618 } 2619 2620 if (VBOX_FAILURE(rc)) 2621 goto out; 2622 2623 if (VBOX_SUCCESS(rc) && pfnProgress) 2624 pfnProgress(NULL /* WARNING! pVM=NULL */, 2625 uPercentStart + uPercentSpan * 98 / 100, pvUser); 2626 2627 pImage->enmImageType = enmType; 2398 2628 pImage->cbSize = cbSize; 2399 if (pImage->cCylinders >= 1024 || pImage->cHeads != 16)2400 pImage->enmTranslation = PDMBIOSTRANSLATION_LBA;2401 else2402 pImage->enmTranslation = PDMBIOSTRANSLATION_NONE;2403 2629 2404 2630 for (unsigned i = 0; i < pImage->cExtents; i++) 2405 2631 { 2406 pExtent = &pImage->pExtents[i];2632 PVMDKEXTENT pExtent = &pImage->pExtents[i]; 2407 2633 2408 2634 rc = vmdkDescExtInsert(pImage, &pImage->Descriptor, pExtent->enmAccess, … … 2417 2643 vmdkDescExtRemoveDummy(pImage, &pImage->Descriptor); 2418 2644 2419 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 2420 "ddb.geometry.cylinders", cCylinders); 2421 if (VBOX_FAILURE(rc)) 2422 goto out; 2423 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 2424 "ddb.geometry.heads", cHeads); 2425 if (VBOX_FAILURE(rc)) 2426 goto out; 2427 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 2428 "ddb.geometry.sectors", cSectors); 2429 if (VBOX_FAILURE(rc)) 2430 goto out; 2431 2432 pImage->cCylinders = cCylinders; 2433 pImage->cHeads = cHeads; 2434 pImage->cSectors = cSectors; 2645 if ( pPCHSGeometry->cCylinders == 0 2646 || pPCHSGeometry->cHeads == 0 2647 || pPCHSGeometry->cSectors == 0) 2648 { 2649 rc = vmdkDescSetPCHSGeometry(pImage, pPCHSGeometry); 2650 if (VBOX_FAILURE(rc)) 2651 goto out; 2652 } 2653 if ( pLCHSGeometry->cCylinders == 0 2654 || pLCHSGeometry->cHeads == 0 2655 || pLCHSGeometry->cSectors == 0) 2656 { 2657 rc = vmdkDescSetLCHSGeometry(pImage, pLCHSGeometry); 2658 if (VBOX_FAILURE(rc)) 2659 goto out; 2660 } 2661 2662 pImage->LCHSGeometry = *pLCHSGeometry; 2663 pImage->PCHSGeometry = *pPCHSGeometry; 2435 2664 2436 2665 rc = RTUuidCreate(&pImage->ImageUuid); … … 2454 2683 RTUuidClear(&pImage->ModificationUuid); 2455 2684 rc = vmdkDescDDBSetUuid(pImage, &pImage->Descriptor, 2456 "ddb.uuid.modification", &pImage->ModificationUuid); 2685 "ddb.uuid.modification", 2686 &pImage->ModificationUuid); 2457 2687 if (VBOX_FAILURE(rc)) 2458 2688 { … … 2472 2702 } 2473 2703 2704 if (VBOX_SUCCESS(rc) && pfnProgress) 2705 pfnProgress(NULL /* WARNING! pVM=NULL */, 2706 uPercentStart + uPercentSpan * 99 / 100, pvUser); 2707 2474 2708 rc = vmdkFlushImage(pImage); 2475 2709 2476 2710 out: 2711 if (VBOX_SUCCESS(rc) && pfnProgress) 2712 pfnProgress(NULL /* WARNING! pVM=NULL */, 2713 uPercentStart + uPercentSpan, pvUser); 2714 2477 2715 if (VBOX_FAILURE(rc)) 2478 2716 vmdkFreeImage(pImage, rc != VERR_ALREADY_EXISTS); … … 2587 2825 case VMDKETYPE_FLAT: 2588 2826 /** @todo implement proper path absolute check. */ 2589 if (pExtent->File != NIL_RTFILE && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 2827 if ( pExtent->File != NIL_RTFILE 2828 && !(pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 2829 && !(pExtent->pszBasename[0] == RTPATH_SLASH)) 2590 2830 rc = RTFileFlush(pExtent->File); 2591 2831 break; … … 2603 2843 } 2604 2844 2605 static int vmdkFindExtent(PVMDKIMAGE pImage, uint64_t offSector, PVMDKEXTENT *ppExtent, uint64_t *puSectorInExtent) 2845 static int vmdkFindExtent(PVMDKIMAGE pImage, uint64_t offSector, 2846 PVMDKEXTENT *ppExtent, uint64_t *puSectorInExtent) 2606 2847 { 2607 2848 PVMDKEXTENT pExtent = NULL; … … 2627 2868 } 2628 2869 2629 static uint32_t vmdkGTCacheHash(PVMDKGTCACHE pCache, uint64_t uSector, unsigned uExtent) 2870 static uint32_t vmdkGTCacheHash(PVMDKGTCACHE pCache, uint64_t uSector, 2871 unsigned uExtent) 2630 2872 { 2631 2873 /** @todo this hash function is quite simple, maybe use a better one which … … 2688 2930 */ 2689 2931 static int vmdkAllocGrain(PVMDKGTCACHE pCache, PVMDKEXTENT pExtent, 2690 uint64_t uSector, const void *pvBuf, uint64_t cbWrite) 2932 uint64_t uSector, const void *pvBuf, 2933 uint64_t cbWrite) 2691 2934 { 2692 2935 uint64_t uGDIndex, uGTSector, uRGTSector, uGTBlock; … … 2722 2965 * should be acceptable. */ 2723 2966 memset(aGTDataTmp, '\0', sizeof(aGTDataTmp)); 2724 for (unsigned i = 0; i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE; i++) 2725 { 2726 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp), aGTDataTmp, sizeof(aGTDataTmp), NULL); 2967 for (unsigned i = 0; 2968 i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE; 2969 i++) 2970 { 2971 rc = RTFileWriteAt(pExtent->File, 2972 VMDK_SECTOR2BYTE(uGTSector) + i * sizeof(aGTDataTmp), 2973 aGTDataTmp, sizeof(aGTDataTmp), NULL); 2727 2974 if (VBOX_FAILURE(rc)) 2728 2975 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain table allocation in '%s'"), pExtent->pszFullname); … … 2739 2986 * bit slower. But as this is a pretty infrequently occurring case 2740 2987 * it should be acceptable. */ 2741 for (unsigned i = 0; i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE; i++) 2988 for (unsigned i = 0; 2989 i < pExtent->cGTEntries / VMDK_GT_CACHELINE_SIZE; 2990 i++) 2742 2991 { 2743 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp), aGTDataTmp, sizeof(aGTDataTmp), NULL); 2992 rc = RTFileWriteAt(pExtent->File, 2993 VMDK_SECTOR2BYTE(uRGTSector) + i * sizeof(aGTDataTmp), 2994 aGTDataTmp, sizeof(aGTDataTmp), NULL); 2744 2995 if (VBOX_FAILURE(rc)) 2745 2996 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain table allocation in '%s'"), pExtent->pszFullname); … … 2752 3003 * some unused sectors in the extent. */ 2753 3004 uint32_t uGTSectorLE = RT_H2LE_U64(uGTSector); 2754 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), &uGTSectorLE, sizeof(uGTSectorLE), NULL); 3005 rc = RTFileWriteAt(pExtent->File, 3006 VMDK_SECTOR2BYTE(pExtent->uSectorGD) + uGDIndex * sizeof(uGTSectorLE), 3007 &uGTSectorLE, sizeof(uGTSectorLE), NULL); 2755 3008 if (VBOX_FAILURE(rc)) 2756 3009 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write grain directory entry in '%s'"), pExtent->pszFullname); … … 2758 3011 { 2759 3012 uint32_t uRGTSectorLE = RT_H2LE_U64(uRGTSector); 2760 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE), &uRGTSectorLE, sizeof(uRGTSectorLE), NULL); 3013 rc = RTFileWriteAt(pExtent->File, 3014 VMDK_SECTOR2BYTE(pExtent->uSectorRGD) + uGDIndex * sizeof(uRGTSectorLE), 3015 &uRGTSectorLE, sizeof(uRGTSectorLE), NULL); 2761 3016 if (VBOX_FAILURE(rc)) 2762 3017 return vmdkError(pExtent->pImage, rc, RT_SRC_POS, N_("VMDK: cannot write backup grain directory entry in '%s'"), pExtent->pszFullname); … … 2832 3087 } 2833 3088 2834 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, PFNVDERROR pfnError, void *pvErrorUser, void **ppvBackendData) 3089 3090 static int vmdkCheckIfValid(const char *pszFilename) 3091 { 3092 int rc = VINF_SUCCESS; 3093 PVMDKIMAGE pImage = (PVMDKIMAGE)RTMemAllocZ(sizeof(VMDKIMAGE)); 3094 if (!pImage) 3095 { 3096 rc = VERR_NO_MEMORY; 3097 goto out; 3098 } 3099 pImage->pszFilename = pszFilename; 3100 pImage->File = NIL_RTFILE; 3101 pImage->pExtents = NULL; 3102 pImage->pGTCache = NULL; 3103 pImage->pDescData = NULL; 3104 pImage->pfnError = NULL; 3105 pImage->pvErrorUser = NULL; 3106 /** @todo speed up this test open (VD_OPEN_FLAGS_INFO) by skipping as 3107 * much as possible in vmdkOpenImage. */ 3108 rc = vmdkOpenImage(pImage, pszFilename, 3109 VD_OPEN_FLAGS_INFO | VD_OPEN_FLAGS_READONLY); 3110 vmdkFreeImage(pImage, false); 3111 3112 out: 3113 return rc; 3114 } 3115 3116 static int vmdkOpen(const char *pszFilename, unsigned uOpenFlags, 3117 PFNVDERROR pfnError, void *pvErrorUser, 3118 void **ppvBackendData) 2835 3119 { 2836 3120 int rc; … … 2871 3155 static int vmdkCreate(const char *pszFilename, VDIMAGETYPE enmType, 2872 3156 uint64_t cbSize, unsigned uImageFlags, 2873 const char *pszComment, uint32_t cCylinders, 2874 uint32_t cHeads, uint32_t cSectors, unsigned uOpenFlags, 2875 PFNVMPROGRESS pfnProgress, void *pvUser, 2876 PFNVDERROR pfnError, void *pvErrorUser, 2877 void **ppvBackendData) 3157 const char *pszComment, 3158 PCPDMMEDIAGEOMETRY pPCHSGeometry, 3159 PCPDMMEDIAGEOMETRY pLCHSGeometry, 3160 unsigned uOpenFlags, PFNVMPROGRESS pfnProgress, 3161 void *pvUser, unsigned uPercentStart, 3162 unsigned uPercentSpan, PFNVDERROR pfnError, 3163 void *pvErrorUser, void **ppvBackendData) 2878 3164 { 2879 3165 int rc; … … 2911 3197 2912 3198 rc = vmdkCreateImage(pImage, pszFilename, enmType, cbSize, uImageFlags, 2913 pszComment, cCylinders, cHeads, cSectors); 3199 pszComment, pPCHSGeometry, pLCHSGeometry, 3200 pfnProgress, pvUser, uPercentStart, uPercentSpan); 2914 3201 if (VBOX_SUCCESS(rc)) 2915 3202 { … … 2927 3214 2928 3215 out: 2929 /** @todo implement meaningful progress stuff (especially for fixed images). */2930 if ( VBOX_SUCCESS(rc)2931 && pfnProgress)2932 pfnProgress(NULL /* WARNING! pVM=NULL */, 100, pvUser);2933 2934 3216 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 2935 3217 return rc; 3218 } 3219 3220 static int vmdkRename(void *pBackendData, const char *pszFilename) 3221 { 3222 return VERR_NOT_IMPLEMENTED; 2936 3223 } 2937 3224 … … 2950 3237 } 2951 3238 2952 static int vmdkRead(void *pBackendData, uint64_t uOffset, void *pvBuf, size_t cbRead, size_t *pcbActuallyRead) 3239 static int vmdkRead(void *pBackendData, uint64_t uOffset, void *pvBuf, 3240 size_t cbRead, size_t *pcbActuallyRead) 2953 3241 { 2954 3242 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; … … 3004 3292 break; 3005 3293 case VMDKETYPE_FLAT: 3006 rc = RTFileReadAt(pExtent->File, VMDK_SECTOR2BYTE(uSectorExtentRel), 3294 rc = RTFileReadAt(pExtent->File, 3295 VMDK_SECTOR2BYTE(uSectorExtentRel), 3007 3296 pvBuf, cbRead, NULL); 3008 3297 break; … … 3017 3306 } 3018 3307 3019 static int vmdkWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, size_t cbWrite, size_t *pcbWriteProcess, size_t *pcbPreRead, size_t *pcbPostRead) 3308 static int vmdkWrite(void *pBackendData, uint64_t uOffset, const void *pvBuf, 3309 size_t cbWrite, size_t *pcbWriteProcess, 3310 size_t *pcbPreRead, size_t *pcbPostRead) 3020 3311 { 3021 3312 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; … … 3100 3391 /* Clip write range to remain in this extent. */ 3101 3392 cbWrite = RT_MIN(cbWrite, VMDK_SECTOR2BYTE(pExtent->uSectorOffset + pExtent->cNominalSectors - uSectorExtentRel)); 3102 rc = RTFileWriteAt(pExtent->File, VMDK_SECTOR2BYTE(uSectorExtentRel), pvBuf, cbWrite, NULL); 3393 rc = RTFileWriteAt(pExtent->File, 3394 VMDK_SECTOR2BYTE(uSectorExtentRel), 3395 pvBuf, cbWrite, NULL); 3103 3396 break; 3104 3397 case VMDKETYPE_ZERO: … … 3123 3416 } 3124 3417 3418 static unsigned vmdkGetVersion(void *pBackendData) 3419 { 3420 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3421 3422 Assert(pImage); 3423 3424 if (pImage) 3425 return VMDK_IMAGE_VERSION; 3426 else 3427 return 0; 3428 } 3429 3125 3430 static int vmdkGetImageType(void *pBackendData, PVDIMAGETYPE penmImageType) 3126 3431 { … … 3151 3456 } 3152 3457 3153 static int vmdkGetGeometry(void *pBackendData, unsigned *pcCylinders, unsigned *pcHeads, unsigned *pcSectors) 3458 static uint64_t vmdkGetFileSize(void *pBackendData) 3459 { 3460 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3461 3462 Assert(pImage); 3463 3464 if (pImage) 3465 { 3466 int rc; 3467 uint64_t cbFile, cb = 0; 3468 if (pImage->File != NIL_RTFILE) 3469 { 3470 rc = RTFileGetSize(pImage->File, &cbFile); 3471 if (VBOX_SUCCESS(rc)) 3472 cb += cbFile; 3473 for (unsigned i = 0; i <= pImage->cExtents; i++) 3474 { 3475 rc = RTFileGetSize(pImage->File, &cbFile); 3476 if (VBOX_SUCCESS(rc)) 3477 cb += cbFile; 3478 } 3479 } 3480 return cb; 3481 } 3482 else 3483 return 0; 3484 } 3485 3486 static int vmdkGetPCHSGeometry(void *pBackendData, 3487 PPDMMEDIAGEOMETRY pPCHSGeometry) 3154 3488 { 3155 3489 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; … … 3160 3494 if (pImage) 3161 3495 { 3162 if (pImage->cCylinders) 3163 { 3164 *pcCylinders = pImage->cCylinders; 3165 *pcHeads = pImage->cHeads; 3166 *pcSectors = pImage->cSectors; 3496 if (pImage->PCHSGeometry.cCylinders) 3497 { 3498 *pPCHSGeometry = pImage->PCHSGeometry; 3167 3499 rc = VINF_SUCCESS; 3168 3500 } … … 3173 3505 rc = VERR_VDI_NOT_OPENED; 3174 3506 LogFlow(("%s: returned %Vrc (CHS=%u/%u/%u)\n", __FUNCTION__, rc, 3175 pImage->cCylinders, pImage->cHeads, pImage->cSectors)); 3176 return rc; 3177 } 3178 3179 static int vmdkSetGeometry(void *pBackendData, unsigned cCylinders, unsigned cHeads, unsigned cSectors) 3507 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors)); 3508 return rc; 3509 } 3510 3511 static int vmdkSetPCHSGeometry(void *pBackendData, 3512 PCPDMMEDIAGEOMETRY pPCHSGeometry) 3180 3513 { 3181 3514 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; … … 3191 3524 goto out; 3192 3525 } 3193 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 3194 "ddb.geometry.cylinders", cCylinders); 3526 rc = vmdkDescSetPCHSGeometry(pImage, pPCHSGeometry); 3195 3527 if (VBOX_FAILURE(rc)) 3196 3528 goto out; 3197 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 3198 "ddb.geometry.heads", cHeads); 3529 3530 pImage->PCHSGeometry = *pPCHSGeometry; 3531 rc = VINF_SUCCESS; 3532 } 3533 else 3534 rc = VERR_VDI_NOT_OPENED; 3535 3536 out: 3537 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 3538 return rc; 3539 } 3540 3541 static int vmdkGetLCHSGeometry(void *pBackendData, 3542 PPDMMEDIAGEOMETRY pLCHSGeometry) 3543 { 3544 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3545 int rc; 3546 3547 Assert(pImage); 3548 3549 if (pImage) 3550 { 3551 if (pImage->LCHSGeometry.cCylinders) 3552 { 3553 *pLCHSGeometry = pImage->LCHSGeometry; 3554 rc = VINF_SUCCESS; 3555 } 3556 else 3557 rc = VERR_VDI_GEOMETRY_NOT_SET; 3558 } 3559 else 3560 rc = VERR_VDI_NOT_OPENED; 3561 LogFlow(("%s: returned %Vrc (CHS=%u/%u/%u)\n", __FUNCTION__, rc, 3562 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors)); 3563 return rc; 3564 } 3565 3566 static int vmdkSetLCHSGeometry(void *pBackendData, 3567 PCPDMMEDIAGEOMETRY pLCHSGeometry) 3568 { 3569 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3570 int rc; 3571 3572 Assert(pImage); 3573 3574 if (pImage) 3575 { 3576 if (pImage->uOpenFlags & VD_OPEN_FLAGS_READONLY) 3577 { 3578 rc = VERR_VDI_IMAGE_READ_ONLY; 3579 goto out; 3580 } 3581 rc = vmdkDescSetLCHSGeometry(pImage, pLCHSGeometry); 3199 3582 if (VBOX_FAILURE(rc)) 3200 3583 goto out; 3201 rc = vmdkDescDDBSetU32(pImage, &pImage->Descriptor, 3202 "ddb.geometry.sectors", cSectors); 3203 if (VBOX_FAILURE(rc)) 3204 goto out; 3205 3206 pImage->cCylinders = cCylinders; 3207 pImage->cHeads = cHeads; 3208 pImage->cSectors = cSectors; 3584 3585 pImage->LCHSGeometry = *pLCHSGeometry; 3209 3586 rc = VINF_SUCCESS; 3210 3587 } … … 3217 3594 } 3218 3595 3219 static int vmdkGetTranslation(void *pBackendData, PPDMBIOSTRANSLATION penmTranslation)3596 static unsigned vmdkGetImageFlags(void *pBackendData) 3220 3597 { 3221 3598 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3222 int rc;3599 unsigned uImageFlags; 3223 3600 3224 3601 Assert(pImage); 3225 3602 3226 3603 if (pImage) 3227 { 3228 if (pImage->enmTranslation) 3229 { 3230 *penmTranslation = pImage->enmTranslation; 3231 rc = VINF_SUCCESS; 3232 } 3233 else 3234 rc = VERR_VDI_GEOMETRY_NOT_SET; 3235 } 3604 uImageFlags = pImage->uImageFlags; 3236 3605 else 3237 rc = VERR_VDI_NOT_OPENED; 3238 LogFlow(("%s: returned %Vrc (%d)\n", __FUNCTION__, rc, 3239 pImage->enmTranslation)); 3240 return rc; 3241 } 3242 3243 static int vmdkSetTranslation(void *pBackendData, PDMBIOSTRANSLATION enmTranslation) 3244 { 3245 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3246 int rc; 3247 3248 Assert(pImage); 3249 3250 if (pImage) 3251 { 3252 /** @todo maybe store this in the image descriptor */ 3253 pImage->enmTranslation = enmTranslation; 3254 rc = VINF_SUCCESS; 3255 } 3256 else 3257 rc = VERR_VDI_NOT_OPENED; 3258 LogFlow(("%s: returned %Vrc\n", __FUNCTION__, rc)); 3259 return rc; 3606 uImageFlags = 0; 3607 3608 LogFlow(("%s: returned %#x\n", __FUNCTION__, uImageFlags)); 3609 return uImageFlags; 3260 3610 } 3261 3611 … … 3300 3650 } 3301 3651 3302 static int vmdkGetComment(void *pBackendData, char *pszComment, size_t cbComment) 3652 static int vmdkGetComment(void *pBackendData, char *pszComment, 3653 size_t cbComment) 3303 3654 { 3304 3655 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; … … 3477 3828 } 3478 3829 3830 static void vmdkDump(void *pBackendData) 3831 { 3832 PVMDKIMAGE pImage = (PVMDKIMAGE)pBackendData; 3833 3834 Assert(pImage); 3835 if (pImage) 3836 { 3837 RTLogPrintf("Header: Geometry PCHS=%u/%u/%u LCHS=%u/%u/%u cbSector=%llu\n", 3838 pImage->PCHSGeometry.cCylinders, pImage->PCHSGeometry.cHeads, pImage->PCHSGeometry.cSectors, 3839 pImage->LCHSGeometry.cCylinders, pImage->LCHSGeometry.cHeads, pImage->LCHSGeometry.cSectors, 3840 VMDK_BYTE2SECTOR(pImage->cbSize)); 3841 RTLogPrintf("Header: uuidCreation={%Vuuid}\n", pImage->ImageUuid); 3842 RTLogPrintf("Header: uuidModification={%Vuuid}\n", pImage->ModificationUuid); 3843 RTLogPrintf("Header: uuidParent={%Vuuid}\n", pImage->ParentUuid); 3844 } 3845 } 3846 3479 3847 3480 3848 VBOXHDDBACKEND g_VmdkBackend = 3481 3849 { 3850 /* pszBackendName */ 3851 "VMDK", 3482 3852 /* cbSize */ 3483 3853 sizeof(VBOXHDDBACKEND), 3484 3854 /* pfnCheckIfValid */ 3485 NULL,3855 vmdkCheckIfValid, 3486 3856 /* pfnOpen */ 3487 3857 vmdkOpen, 3488 3858 /* pfnCreate */ 3489 3859 vmdkCreate, 3860 /* pfnRename */ 3861 vmdkRename, 3490 3862 /* pfnClose */ 3491 3863 vmdkClose, … … 3496 3868 /* pfnFlush */ 3497 3869 vmdkFlush, 3870 /* pfnGetVersion */ 3871 vmdkGetVersion, 3498 3872 /* pfnGetImageType */ 3499 3873 vmdkGetImageType, 3500 3874 /* pfnGetSize */ 3501 3875 vmdkGetSize, 3502 /* pfnGetGeometry */ 3503 vmdkGetGeometry, 3504 /* pfnSetGeometry */ 3505 vmdkSetGeometry, 3506 /* pfnGetTranslation */ 3507 vmdkGetTranslation, 3508 /* pfnSetTranslation */ 3509 vmdkSetTranslation, 3876 /* pfnGetFileSize */ 3877 vmdkGetFileSize, 3878 /* pfnGetPCHSGeometry */ 3879 vmdkGetPCHSGeometry, 3880 /* pfnSetPCHSGeometry */ 3881 vmdkSetPCHSGeometry, 3882 /* pfnGetLCHSGeometry */ 3883 vmdkGetLCHSGeometry, 3884 /* pfnSetLCHSGeometry */ 3885 vmdkSetLCHSGeometry, 3886 /* pfnGetImageFlags */ 3887 vmdkGetImageFlags, 3510 3888 /* pfnGetOpenFlags */ 3511 3889 vmdkGetOpenFlags, … … 3527 3905 vmdkGetParentUuid, 3528 3906 /* pfnSetParentUuid */ 3529 vmdkSetParentUuid 3907 vmdkSetParentUuid, 3908 /* pfnDump */ 3909 vmdkDump 3530 3910 }; -
trunk/src/VBox/Devices/Storage/testcase/vditool.cpp
r6285 r6291 253 253 if (VBOX_SUCCESS(rc)) 254 254 { 255 rc = VDIDiskSetGeometry(pVdi, 0, 0, 0); 256 if (VBOX_SUCCESS(rc)) 257 rc = VDIDiskSetTranslation(pVdi, PDMBIOSTRANSLATION_AUTO); 255 PDMMEDIAGEOMETRY LCHSGeometry = {0, 0, 0}; 256 rc = VDIDiskSetLCHSGeometry(pVdi, &LCHSGeometry); 258 257 } 259 258 VDIDiskCloseImage(pVdi); -
trunk/src/VBox/Devices/testcase/tstDeviceStructSizeGC.cpp
r6240 r6291 8 8 9 9 /* 10 * Copyright (C) 2006-200 7innotek GmbH10 * Copyright (C) 2006-2008 innotek GmbH 11 11 * 12 12 * This file is part of VirtualBox Open Source Edition (OSE), as … … 570 570 GEN_CHECK_OFF(ATADevState, fIrqPending); 571 571 GEN_CHECK_OFF(ATADevState, cMultSectors); 572 GEN_CHECK_OFF(ATADevState, cCHSCylinders);573 GEN_CHECK_OFF(ATADevState, cCHSHeads);574 GEN_CHECK_OFF(ATADevState, cCHSSectors);572 GEN_CHECK_OFF(ATADevState, PCHSGeometry.cCylinders); 573 GEN_CHECK_OFF(ATADevState, PCHSGeometry.cHeads); 574 GEN_CHECK_OFF(ATADevState, PCHSGeometry.cSectors); 575 575 GEN_CHECK_OFF(ATADevState, cSectorsPerIRQ); 576 576 GEN_CHECK_OFF(ATADevState, cTotalSectors); -
trunk/src/VBox/Main/HardDiskImpl.cpp
r6173 r6291 3612 3612 CHECK_READY(); 3613 3613 3614 /// @todo (r=dmik) will need this if we add suppor dfor differencing VMDKs3614 /// @todo (r=dmik) will need this if we add support for differencing VMDKs 3615 3615 // 3616 3616 // /* only a non-differencing image knows the logical size */ … … 3771 3771 mFilePathFull.raw()); 3772 3772 3773 /// @todo (r=dmik) will need this if we add suppor dfor differencing VMDKs3773 /// @todo (r=dmik) will need this if we add support for differencing VMDKs 3774 3774 // if (isDifferencing()) 3775 3775 // return setError (E_FAIL, … … 3940 3940 return E_NOTIMPL; 3941 3941 3942 /// @todo (r=dmik) will need this if we add suppor dfor differencing VMDKs3942 /// @todo (r=dmik) will need this if we add support for differencing VMDKs 3943 3943 // Use code from HVirtualDiskImage::cloneToImage as an example. 3944 3944 } … … 3960 3960 return E_NOTIMPL; 3961 3961 3962 /// @todo (r=dmik) will need this if we add suppor dfor differencing VMDKs3962 /// @todo (r=dmik) will need this if we add support for differencing VMDKs 3963 3963 // Use code from HVirtualDiskImage::createDiffImage as an example. 3964 3964 } … … 4123 4123 if (!mParent) 4124 4124 { 4125 uint64_t size = VDGetSize (mContainer );4125 uint64_t size = VDGetSize (mContainer, 0); 4126 4126 /* convert to MBytes */ 4127 4127 mSize = size / 1024 / 1024; … … 4959 4959 if (!mParent) 4960 4960 { 4961 uint64_t size = VDGetSize (mContainer );4961 uint64_t size = VDGetSize (mContainer, 0); 4962 4962 /* convert to MBytes */ 4963 4963 mSize = size / 1024 / 1024; … … 5823 5823 if (!mParent) 5824 5824 { 5825 uint64_t size = VDGetSize (mContainer );5825 uint64_t size = VDGetSize (mContainer, 0); 5826 5826 /* convert to MBytes */ 5827 5827 mSize = size / 1024 / 1024;
Note:
See TracChangeset
for help on using the changeset viewer.