Changeset 85877 in vbox
- Timestamp:
- Aug 24, 2020 5:03:23 PM (4 years ago)
- Location:
- trunk
- Files:
-
- 7 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/include/iprt/dvm.h
r85121 r85877 241 241 242 242 /** 243 * Gets the UUID of the disk if applicable. 244 * 245 * Disks using the MBR format may return the 32-bit disk identity in the 246 * u32TimeLow field and set the rest to zero. 247 * 248 * @returns IPRT status code. 249 * @retval VERR_NOT_SUPPORTED if the partition scheme doesn't do UUIDs. 250 * @retval VINF_NOT_SUPPORTED if non-UUID disk ID is returned. 251 * @param hVolMgr The volume manager handle. 252 * @param pUuid Where to return the UUID. 253 * 254 * @todo It's quite possible this should be turned into a map-level edition of 255 * RTDvmVolumeQueryProp... 256 */ 257 RTDECL(int) RTDvmMapQueryDiskUuid(RTDVM hVolMgr, PRTUUID pUuid); 258 259 /** 243 260 * Gets the number of valid partitions in the map. 244 261 * … … 355 372 356 373 /** 357 * Queries the range of the given volume on the under yling medium.374 * Queries the range of the given volume on the underlying medium. 358 375 * 359 376 * @returns IPRT status code. … … 361 378 * @param hVol The volume handle. 362 379 * @param poffStart Where to store the start offset in bytes on the underlying medium. 363 * @param poffEnd Where to store the end offset in bytes on the underlying medium (inclusive). 364 */ 365 RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffEnd); 380 * @param poffLast Where to store the last offset in bytes on the underlying medium (inclusive). 381 */ 382 RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffLast); 383 384 /** 385 * Returns the partition/whatever table location of the volume. 386 * 387 * For volume format with a single table, like GPT and BSD-labels, it will 388 * return the location of that table. Though for GPT, the fake MBR will not be 389 * included. 390 * 391 * For logical (extended) MBR-style volumes, this will return the location of 392 * the extended partition table. For primary volumes the MBR location is 393 * returned. The special MBR case is why this operation is done on the volume 394 * rather than the volume manager. 395 * 396 * Using RTDvmVolumeGetIndex with RTDVMVOLIDX_IN_PART_TABLE should get you 397 * the index in the table returned by this function. 398 * 399 * @returns IPRT status code. 400 * @param hVol The volume handle. 401 * @param poffTable Where to return the byte offset on the underlying 402 * media of the (partition/volume/whatever) table. 403 * @param pcbTable Where to return the table size in bytes. (This does 404 * not include any alignment padding or such, just 405 * padding up to sector/block size.) 406 */ 407 RTDECL(int) RTDvmVolumeQueryTableLocation(RTDVMVOLUME hVol, uint64_t *poffTable, uint64_t *pcbTable); 408 409 /** 410 * RTDvmVolumeGetIndex indexes. 411 */ 412 typedef enum RTDVMVOLIDX 413 { 414 /** Invalid zero value. */ 415 RTDVMVOLIDX_INVALID = 0, 416 /** Only consider user visible ones, i.e. don't count MBR extended partition 417 * entries and such like. */ 418 RTDVMVOLIDX_USER_VISIBLE, 419 /** Index when all volumes, user visible, hidden, special, whatever ones are 420 * included. 421 * 422 * For MBR this is 1-based index where all primary entires are included whether 423 * in use or not. Only non-empty entries in extended tables are counted, though 424 * the forward link is included. */ 425 RTDVMVOLIDX_ALL, 426 /** The raw index within the partition/volume/whatever table. This have a kind 427 * of special meaning to MBR, where there are multiple tables. */ 428 RTDVMVOLIDX_IN_TABLE, 429 /** Follows the linux /dev/sdaX convention as closely as absolutely possible. */ 430 RTDVMVOLIDX_LINUX, 431 /** End of valid indexes. */ 432 RTDVMVOLIDX_END, 433 /** Make sure the type is 32-bit. */ 434 RTDVMVOLIDX_32BIT_HACK = 0x7fffffff 435 } RTDVMVOLIDX; 436 437 /** 438 * Gets the tiven index for the specified volume. 439 * 440 * @returns The requested index, UINT32_MAX on failure. 441 * @param hVol The volume handle. 442 * @param enmIndex Which kind of index to get for the volume. 443 */ 444 RTDECL(uint32_t) RTDvmVolumeGetIndex(RTDVMVOLUME hVol, RTDVMVOLIDX enmIndex); 445 446 /** 447 * Volume properties queriable via RTDvmVolumeQueryProp. 448 * 449 * @note Integer values can typically be queried in multiple sizes. This is 450 * handled by the frontend code. The format specific backends only 451 * have to handle the smallest allowed size. 452 */ 453 typedef enum RTDVMVOLPROP 454 { 455 /** Customary invalid zero value. */ 456 RTDVMVOLPROP_INVALID = 0, 457 /** unsigned[16,32,64]: MBR first cylinder (0-based, CHS). */ 458 RTDVMVOLPROP_MBR_FIRST_CYLINDER, 459 /** unsigned[8,16,32,64]: MBR first head (0-based, CHS). */ 460 RTDVMVOLPROP_MBR_FIRST_HEAD, 461 /** unsigned[8,16,32,64]: MBR first sector (1-based, CHS). */ 462 RTDVMVOLPROP_MBR_FIRST_SECTOR, 463 /** unsigned[16,32,64]: MBR last cylinder (0-based, CHS). */ 464 RTDVMVOLPROP_MBR_LAST_CYLINDER, 465 /** unsigned[8,16,32,64]: MBR last head (0-based, CHS). */ 466 RTDVMVOLPROP_MBR_LAST_HEAD, 467 /** unsigned[8,16,32,64]: MBR last sector (1-based, CHS). */ 468 RTDVMVOLPROP_MBR_LAST_SECTOR, 469 /** unsigned[8,16,32,64]: MBR partition type. */ 470 RTDVMVOLPROP_MBR_TYPE, 471 /** RTUUID: GPT volume type. */ 472 RTDVMVOLPROP_GPT_TYPE, 473 /** RTUUID: GPT volume UUID. */ 474 RTDVMVOLPROP_GPT_UUID, 475 /** End of valid values. */ 476 RTDVMVOLPROP_END, 477 /** Make sure the type is 32-bit. */ 478 RTDVMVOLPROP_32BIT_HACK = 0x7fffffff 479 } RTDVMVOLPROP; 480 481 /** 482 * Query a generic volume property. 483 * 484 * This is an extensible interface for retriving mostly format specific 485 * information, or information that's not commonly used. (It's modelled after 486 * RTLdrQueryPropEx.) 487 * 488 * @returns IPRT status code. 489 * @retval VERR_NOT_SUPPORTED if the property query isn't supported (either all 490 * or that specific property). The caller must handle this result. 491 * @retval VERR_NOT_FOUND is currently not returned, but intended for cases 492 * where it wasn't present in the tables. 493 * @retval VERR_INVALID_FUNCTION if the @a enmProperty value is wrong. 494 * @retval VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct 495 * size in @a *pcbRet. 496 * @retval VERR_BUFFER_OVERFLOW if the property doesn't have a fixed size 497 * buffer and the buffer isn't big enough. Correct size in @a *pcbRet. 498 * @retval VERR_INVALID_HANDLE if the handle is invalid. 499 * @param hVol Handle to the volume. 500 * @param enmProperty The property to query. 501 * @param pvBuf Pointer to the input / output buffer. In most cases 502 * it's only used for returning data. 503 * @param cbBuf The size of the buffer. 504 * @param pcbRet Where to return the amount of data returned. On 505 * buffer size errors, this is set to the correct size. 506 * Optional. 507 * @sa RTDvmVolumeGetPropU64 508 */ 509 RTDECL(int) RTDvmVolumeQueryProp(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, void *pvBuf, size_t cbBuf, size_t *pcbBuf); 510 511 /** 512 * Wrapper around RTDvmVolumeQueryProp for simplifying getting unimportant 513 * integer properties. 514 * 515 * @returns The property value if supported and found, the default value if not. 516 * Errors other than VERR_NOT_SUPPORTED and VERR_NOT_FOUND are 517 * asserted. 518 * @param hVol Handle to the volume. 519 * @param enmProperty The property to query. 520 * @param uDefault The value to return on error. 521 * @sa RTDvmVolumeQueryProp 522 */ 523 RTDECL(uint64_t) RTDvmVolumeGetPropU64(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, uint64_t uDefault); 366 524 367 525 /** -
trunk/include/iprt/mangling.h
r85875 r85877 833 833 # define RTDvmMapQueryFirstVolume RT_MANGLER(RTDvmMapQueryFirstVolume) 834 834 # define RTDvmMapQueryNextVolume RT_MANGLER(RTDvmMapQueryNextVolume) 835 # define RTDvmMapQueryDiskUuid RT_MANGLER(RTDvmMapQueryDiskUuid) 835 836 # define RTDvmVolumeRetain RT_MANGLER(RTDvmVolumeRetain) 836 837 # define RTDvmVolumeRelease RT_MANGLER(RTDvmVolumeRelease) 838 # define RTDvmVolumeGetIndex RT_MANGLER(RTDvmVolumeGetIndex) 839 # define RTDvmVolumeGetPropU64 RT_MANGLER(RTDvmVolumeGetPropU64) 837 840 # define RTDvmVolumeGetSize RT_MANGLER(RTDvmVolumeGetSize) 838 841 # define RTDvmVolumeQueryName RT_MANGLER(RTDvmVolumeQueryName) 842 # define RTDvmVolumeQueryProp RT_MANGLER(RTDvmVolumeQueryProp) 843 # define RTDvmVolumeQueryTableLocation RT_MANGLER(RTDvmVolumeQueryTableLocation) 839 844 # define RTDvmVolumeGetType RT_MANGLER(RTDvmVolumeGetType) 840 845 # define RTDvmVolumeGetFlags RT_MANGLER(RTDvmVolumeGetFlags) -
trunk/src/VBox/Runtime/common/dvm/dvm.cpp
r85126 r85877 146 146 147 147 /** 148 * Read from the disk at the given offset, neither the offset nor the size is 149 * necessary sector aligned. 150 * 151 * @returns IPRT status code. 152 * @param pDisk The disk descriptor to read from. 153 * @param off Start offset. 154 * @param pvBuf Destination buffer. 155 * @param cbRead How much to read. 156 */ 157 DECLHIDDEN(int) rtDvmDiskReadUnaligned(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead) 158 { 159 size_t const cbSector = (size_t)pDisk->cbSector; 160 size_t const offDelta = off % cbSector; 161 size_t const cbDelta = cbRead % cbSector; 162 if (!cbDelta && !offDelta) 163 return rtDvmDiskRead(pDisk, off, pvBuf, cbRead); 164 165 int rc; 166 size_t cbExtra = offDelta + (cbDelta ? cbSector - cbDelta: 0); 167 uint8_t *pbTmpBuf = (uint8_t *)RTMemTmpAlloc(cbRead + cbExtra); 168 if (pbTmpBuf) 169 { 170 rc = rtDvmDiskRead(pDisk, off - offDelta, pbTmpBuf, cbRead + cbExtra); 171 if (RT_SUCCESS(rc)) 172 memcpy(pvBuf, &pbTmpBuf[offDelta], cbRead); 173 else 174 RT_BZERO(pvBuf, cbRead); 175 RTMemTmpFree(pbTmpBuf); 176 } 177 else 178 rc = VERR_NO_TMP_MEMORY; 179 return rc; 180 } 181 182 183 /** 148 184 * Creates a new volume. 149 185 * … … 424 460 425 461 return pThis->pDvmFmtOps->enmFormat; 462 } 463 464 RTDECL(int) RTDvmMapQueryDiskUuid(RTDVM hVolMgr, PRTUUID pUuid) 465 { 466 PRTDVMINTERNAL pThis = hVolMgr; 467 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 468 AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE); 469 AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE); 470 AssertPtrReturn(pUuid, VERR_INVALID_POINTER); 471 472 if (pThis->pDvmFmtOps->pfnQueryDiskUuid) 473 return pThis->pDvmFmtOps->pfnQueryDiskUuid(pThis->hVolMgrFmt, pUuid); 474 return VERR_NOT_SUPPORTED; 426 475 } 427 476 … … 670 719 } 671 720 721 RTDECL(int) RTDvmVolumeQueryTableLocation(RTDVMVOLUME hVol, uint64_t *poffTable, uint64_t *pcbTable) 722 { 723 PRTDVMVOLUMEINTERNAL pThis = hVol; 724 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 725 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE); 726 AssertPtrReturn(poffTable, VERR_INVALID_POINTER); 727 AssertPtrReturn(pcbTable, VERR_INVALID_POINTER); 728 729 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryTableLocation(pThis->hVolFmt, poffTable, pcbTable); 730 } 731 732 RTDECL(uint32_t) RTDvmVolumeGetIndex(RTDVMVOLUME hVol, RTDVMVOLIDX enmIndex) 733 { 734 PRTDVMVOLUMEINTERNAL pThis = hVol; 735 AssertPtrReturn(pThis, UINT32_MAX); 736 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX); 737 AssertReturn(enmIndex > RTDVMVOLIDX_INVALID && enmIndex < RTDVMVOLIDX_END, UINT32_MAX); 738 739 return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetIndex(pThis->hVolFmt, enmIndex); 740 } 741 742 /** 743 * Helper for RTDvmVolumeQueryProp. 744 */ 745 static void rtDvmReturnInteger(void *pvDst, size_t cbDst, PRTUINT64U pSrc, size_t cbSrc) 746 { 747 /* Read the source: */ 748 uint64_t uSrc; 749 switch (cbSrc) 750 { 751 case sizeof(uint8_t): uSrc = (uint8_t)pSrc->Words.w0; break; 752 case sizeof(uint16_t): uSrc = pSrc->Words.w0; break; 753 case sizeof(uint32_t): uSrc = pSrc->s.Lo; break; 754 default: AssertFailed(); RT_FALL_THROUGH(); 755 case sizeof(uint64_t): uSrc = pSrc->u; break; 756 } 757 758 /* Write the destination: */ 759 switch (cbDst) 760 { 761 default: AssertFailed(); RT_FALL_THROUGH(); 762 case sizeof(uint8_t): *(uint8_t *)pvDst = (uint8_t)uSrc; break; 763 case sizeof(uint16_t): *(uint16_t *)pvDst = (uint16_t)uSrc; break; 764 case sizeof(uint32_t): *(uint32_t *)pvDst = (uint32_t)uSrc; break; 765 case sizeof(uint64_t): *(uint64_t *)pvDst = uSrc; break; 766 } 767 } 768 769 RTDECL(int) RTDvmVolumeQueryProp(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, void *pvBuf, size_t cbBuf, size_t *pcbBuf) 770 { 771 PRTDVMVOLUMEINTERNAL pThis = hVol; 772 AssertPtrReturn(pThis, VERR_INVALID_HANDLE); 773 AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE); 774 size_t cbBufFallback = 0; 775 if (pcbBuf == NULL) 776 pcbBuf = &cbBufFallback; 777 AssertReturnStmt(enmProperty > RTDVMVOLPROP_INVALID && enmProperty < RTDVMVOLPROP_END, *pcbBuf = 0, VERR_INVALID_FUNCTION); 778 779 switch (enmProperty) 780 { 781 /* 8, 16, 32 or 64 bit sized integers: */ 782 case RTDVMVOLPROP_MBR_FIRST_HEAD: 783 case RTDVMVOLPROP_MBR_FIRST_SECTOR: 784 case RTDVMVOLPROP_MBR_LAST_HEAD: 785 case RTDVMVOLPROP_MBR_LAST_SECTOR: 786 case RTDVMVOLPROP_MBR_TYPE: 787 { 788 *pcbBuf = sizeof(uint8_t); 789 AssertReturn( cbBuf == sizeof(uint8_t) 790 || cbBuf == sizeof(uint16_t) 791 || cbBuf == sizeof(uint32_t) 792 || cbBuf == sizeof(uint64_t), VERR_INVALID_PARAMETER); 793 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 794 795 RTUINT64U Union64 = {0}; 796 int rc = pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryProp(pThis->hVolFmt, enmProperty, &Union64, cbBuf, pcbBuf); 797 rtDvmReturnInteger(pvBuf, cbBuf, &Union64, *pcbBuf); 798 return rc; 799 } 800 801 /* 16, 32 or 64 bit sized integers: */ 802 case RTDVMVOLPROP_MBR_FIRST_CYLINDER: 803 case RTDVMVOLPROP_MBR_LAST_CYLINDER: 804 { 805 *pcbBuf = sizeof(uint16_t); 806 AssertReturn( cbBuf == sizeof(uint16_t) 807 || cbBuf == sizeof(uint32_t) 808 || cbBuf == sizeof(uint64_t), VERR_INVALID_PARAMETER); 809 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 810 811 RTUINT64U Union64 = {0}; 812 int rc = pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryProp(pThis->hVolFmt, enmProperty, &Union64, cbBuf, pcbBuf); 813 rtDvmReturnInteger(pvBuf, cbBuf, &Union64, *pcbBuf); 814 return rc; 815 } 816 817 /* RTUUIDs: */ 818 case RTDVMVOLPROP_GPT_TYPE: 819 case RTDVMVOLPROP_GPT_UUID: 820 { 821 *pcbBuf = sizeof(RTUUID); 822 AssertReturn(cbBuf == sizeof(RTUUID), VERR_INVALID_PARAMETER); 823 AssertPtrReturn(pvBuf, VERR_INVALID_POINTER); 824 825 RTUUID Uuid = RTUUID_INITIALIZE_NULL; 826 int rc = pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryProp(pThis->hVolFmt, enmProperty, &Uuid, sizeof(RTUUID), pcbBuf); 827 memcpy(pvBuf, &Uuid, sizeof(Uuid)); 828 return rc; 829 } 830 831 case RTDVMVOLPROP_INVALID: 832 case RTDVMVOLPROP_END: 833 case RTDVMVOLPROP_32BIT_HACK: 834 break; 835 /* No default case! */ 836 } 837 AssertFailed(); 838 return VERR_NOT_SUPPORTED; 839 } 840 841 RTDECL(uint64_t) RTDvmVolumeGetPropU64(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, uint64_t uDefault) 842 { 843 uint64_t uValue = uDefault; 844 int rc = RTDvmVolumeQueryProp(hVol, enmProperty, &uValue, sizeof(uValue), NULL); 845 if (RT_SUCCESS(rc)) 846 return uValue; 847 AssertMsg(rc == VERR_NOT_SUPPORTED || rc == VERR_NOT_FOUND, ("%Rrc enmProperty=%d\n", rc, enmProperty)); 848 return uDefault; 849 } 850 672 851 RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead) 673 852 { -
trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp
r85124 r85877 53 53 * A BSD disk label partition. 54 54 */ 55 #pragma pack(1)56 55 typedef struct BsdLabelPartition 57 56 { … … 69 68 uint16_t cFsCylPerGroup; 70 69 } BsdLabelPartition; 71 #pragma pack()72 70 AssertCompileSize(BsdLabelPartition, 16); 73 71 /** Pointer to a BSD disklabel partition structure. */ … … 77 75 * On disk BSD label structure. 78 76 */ 79 #pragma pack(1)80 77 typedef struct BsdLabel 81 78 { … … 139 136 BsdLabelPartition aPartitions[RTDVM_BSDLBL_MAX_PARTITIONS]; 140 137 } BsdLabel; 141 #pragma pack()142 138 AssertCompileSize(BsdLabel, 148 + RTDVM_BSDLBL_MAX_PARTITIONS * 16); 143 139 /** Pointer to a BSD disklabel structure. */ … … 285 281 { 286 282 /* Read from the disk and check for the disk label structure. */ 287 rc = rtDvmDiskRead (pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &DiskLabel, sizeof(BsdLabel));283 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &DiskLabel, sizeof(BsdLabel)); 288 284 if ( RT_SUCCESS(rc) 289 285 && rtDvmFmtBsdLblDiskLabelDecode(&DiskLabel)) … … 305 301 306 302 /* Read from the disk and check for the disk label structure. */ 307 rc = rtDvmDiskRead (pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &pThis->DiskLabel, sizeof(BsdLabel));303 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &pThis->DiskLabel, sizeof(BsdLabel)); 308 304 if ( RT_SUCCESS(rc) 309 305 && rtDvmFmtBsdLblDiskLabelDecode(&pThis->DiskLabel)) … … 340 336 pThis->pDisk = NULL; 341 337 pThis->cPartitions = 0; 342 memset(&pThis->DiskLabel, 0, sizeof(BsdLabel));338 RT_ZERO(pThis->DiskLabel); 343 339 RTMemFree(pThis); 344 340 } … … 507 503 508 504 return fIntersect; 505 } 506 507 /** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */ 508 static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable) 509 { 510 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 511 *poffTable = RTDVM_BSDLBL_LBA2BYTE(1, pVol->pVolMgr->pDisk); 512 *pcbTable = RT_ALIGN_Z(sizeof(BsdLabel), pVol->pVolMgr->pDisk->cbSector); 513 return VINF_SUCCESS; 514 } 515 516 /** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */ 517 static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex) 518 { 519 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 520 switch (enmIndex) 521 { 522 case RTDVMVOLIDX_USER_VISIBLE: 523 case RTDVMVOLIDX_ALL: 524 case RTDVMVOLIDX_LINUX: 525 return pVol->idxEntry + 1; 526 case RTDVMVOLIDX_IN_TABLE: 527 return pVol->idxEntry; 528 529 case RTDVMVOLIDX_INVALID: 530 case RTDVMVOLIDX_END: 531 case RTDVMVOLIDX_32BIT_HACK: 532 break; 533 /* no default! */ 534 } 535 AssertFailed(); 536 return UINT32_MAX; 537 } 538 539 /** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */ 540 static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty, 541 void *pvBuf, size_t cbBuf, size_t *pcbBuf) 542 { 543 switch (enmProperty) 544 { 545 case RTDVMVOLPROP_MBR_FIRST_CYLINDER: 546 case RTDVMVOLPROP_MBR_FIRST_HEAD: 547 case RTDVMVOLPROP_MBR_FIRST_SECTOR: 548 case RTDVMVOLPROP_MBR_LAST_CYLINDER: 549 case RTDVMVOLPROP_MBR_LAST_HEAD: 550 case RTDVMVOLPROP_MBR_LAST_SECTOR: 551 case RTDVMVOLPROP_MBR_TYPE: 552 case RTDVMVOLPROP_GPT_TYPE: 553 case RTDVMVOLPROP_GPT_UUID: 554 return VERR_NOT_SUPPORTED; 555 556 case RTDVMVOLPROP_INVALID: 557 case RTDVMVOLPROP_END: 558 case RTDVMVOLPROP_32BIT_HACK: 559 break; 560 /* no default! */ 561 } 562 RT_NOREF(hVolFmt, pvBuf, cbBuf, pcbBuf); 563 return VERR_NOT_SUPPORTED; 509 564 } 510 565 … … 541 596 /* pfnQueryRangeUse */ 542 597 rtDvmFmtBsdLblQueryRangeUse, 598 /* pfnQueryDiskUuid */ 599 NULL, 543 600 /* pfnGetValidVolumes */ 544 601 rtDvmFmtBsdLblGetValidVolumes, … … 563 620 /* pfnVolumeIsRangeIntersecting */ 564 621 rtDvmFmtBsdLblVolumeIsRangeIntersecting, 622 /* pfnVolumeQueryTableLocation */ 623 rtDvmFmtBsdLblVolumeQueryTableLocation, 624 /* pfnVolumeGetIndex */ 625 rtDvmFmtBsdLblVolumeGetIndex, 626 /* pfnVolumeQueryProp */ 627 rtDvmFmtBsdLblVolumeQueryProp, 565 628 /* pfnVolumeRead */ 566 629 rtDvmFmtBsdLblVolumeRead, -
trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp
r85124 r85877 252 252 { 253 253 /* Read from the disk and check for the signature. */ 254 rc = rtDvmDiskRead (pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &Hdr, sizeof(GPTHDR));254 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &Hdr, sizeof(GPTHDR)); 255 255 if ( RT_SUCCESS(rc) 256 256 && !strncmp(&Hdr.abSignature[0], RTDVM_GPT_SIGNATURE, RT_ELEMENTS(Hdr.abSignature)) … … 275 275 276 276 /* Read the complete GPT header and convert to host endianess. */ 277 rc = rtDvmDiskRead (pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &pThis->HdrRev1, sizeof(pThis->HdrRev1));277 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &pThis->HdrRev1, sizeof(pThis->HdrRev1)); 278 278 if (RT_SUCCESS(rc)) 279 279 { … … 293 293 if (pThis->HdrRev1.cbPartitionEntry == sizeof(GPTENTRY)) 294 294 { 295 pThis->paGptEntries = (PGPTENTRY)RTMemAllocZ(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry); 295 size_t cbAlignedGptEntries = RT_ALIGN_Z(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry, pDisk->cbSector); 296 pThis->paGptEntries = (PGPTENTRY)RTMemAllocZ(cbAlignedGptEntries); 296 297 if (pThis->paGptEntries) 297 298 { 298 299 rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(pThis->HdrRev1.u64LbaPartitionEntries, pDisk), 299 pThis->paGptEntries, pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry);300 pThis->paGptEntries, cbAlignedGptEntries); 300 301 if (RT_SUCCESS(rc)) 301 302 { … … 314 315 pThis->cPartitions++; 315 316 } 317 318 if (RT_SUCCESS(rc)) 319 { 320 *phVolMgrFmt = pThis; 321 return rc; 322 } 316 323 } 317 318 if (RT_FAILURE(rc)) 319 RTMemFree(pThis->paGptEntries); 324 RTMemFree(pThis->paGptEntries); 320 325 } 321 326 else … … 324 329 else 325 330 rc = VERR_NOT_SUPPORTED; 326 327 if (RT_SUCCESS(rc))328 *phVolMgrFmt = pThis;329 else330 RTMemFree(pThis);331 331 } 332 RTMemFree(pThis); 332 333 } 333 334 else … … 348 349 349 350 pThis->pDisk = NULL; 350 memset(&pThis->HdrRev1, 0, sizeof(pThis->HdrRev1)); 351 RT_ZERO(pThis->HdrRev1); 352 351 353 RTMemFree(pThis->paGptEntries); 352 353 354 pThis->paGptEntries = NULL; 355 354 356 RTMemFree(pThis); 355 357 } … … 368 370 *pfUsed = false; 369 371 372 return VINF_SUCCESS; 373 } 374 375 /** @copydoc RTDVMFMTOPS::pfnQueryDiskUuid */ 376 static DECLCALLBACK(int) rtDvmFmtGptQueryDiskUuid(RTDVMFMT hVolMgrFmt, PRTUUID pUuid) 377 { 378 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 379 380 *pUuid = pThis->HdrRev1.DiskUuid; 370 381 return VINF_SUCCESS; 371 382 } … … 519 530 } 520 531 return false; 532 } 533 534 /** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */ 535 static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable) 536 { 537 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 538 PRTDVMFMTINTERNAL pVolMgr = pVol->pVolMgr; 539 *poffTable = RTDVM_GPT_LBA2BYTE(1, pVolMgr->pDisk); 540 *pcbTable = RTDVM_GPT_LBA2BYTE(pVolMgr->HdrRev1.u64LbaPartitionEntries, pVolMgr->pDisk) 541 + RT_ALIGN_Z(pVolMgr->HdrRev1.cPartitionEntries * pVolMgr->HdrRev1.cbPartitionEntry, pVolMgr->pDisk->cbSector) 542 - *poffTable; 543 return VINF_SUCCESS; 544 } 545 546 /** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */ 547 static DECLCALLBACK(uint32_t) rtDvmFmtGptVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex) 548 { 549 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 550 switch (enmIndex) 551 { 552 case RTDVMVOLIDX_USER_VISIBLE: 553 case RTDVMVOLIDX_ALL: 554 case RTDVMVOLIDX_LINUX: 555 return pVol->idxEntry + 1; 556 557 case RTDVMVOLIDX_IN_TABLE: 558 return pVol->idxEntry; 559 560 case RTDVMVOLIDX_32BIT_HACK: 561 case RTDVMVOLIDX_INVALID: 562 case RTDVMVOLIDX_END: 563 break; 564 /* no default! */ 565 } 566 AssertFailed(); 567 return UINT32_MAX; 568 } 569 570 /** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */ 571 static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty, 572 void *pvBuf, size_t cbBuf, size_t *pcbBuf) 573 { 574 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 575 switch (enmProperty) 576 { 577 case RTDVMVOLPROP_MBR_FIRST_CYLINDER: 578 case RTDVMVOLPROP_MBR_FIRST_HEAD: 579 case RTDVMVOLPROP_MBR_FIRST_SECTOR: 580 case RTDVMVOLPROP_MBR_LAST_CYLINDER: 581 case RTDVMVOLPROP_MBR_LAST_HEAD: 582 case RTDVMVOLPROP_MBR_LAST_SECTOR: 583 case RTDVMVOLPROP_MBR_TYPE: 584 return VERR_NOT_SUPPORTED; 585 586 case RTDVMVOLPROP_GPT_TYPE: 587 *pcbBuf = sizeof(RTUUID); 588 Assert(cbBuf >= *pcbBuf); 589 *(PRTUUID)pvBuf = pVol->pGptEntry->UuidType; 590 return VINF_SUCCESS; 591 592 case RTDVMVOLPROP_GPT_UUID: 593 *pcbBuf = sizeof(RTUUID); 594 Assert(cbBuf >= *pcbBuf); 595 *(PRTUUID)pvBuf = pVol->pGptEntry->UuidPartition; 596 return VINF_SUCCESS; 597 598 case RTDVMVOLPROP_INVALID: 599 case RTDVMVOLPROP_END: 600 case RTDVMVOLPROP_32BIT_HACK: 601 break; 602 /* not default! */ 603 } 604 AssertFailed(); 605 RT_NOREF(cbBuf); 606 return VERR_NOT_SUPPORTED; 521 607 } 522 608 … … 553 639 /* pfnQueryRangeUse */ 554 640 rtDvmFmtGptQueryRangeUse, 641 /* pfnQueryDiskUuid */ 642 rtDvmFmtGptQueryDiskUuid, 555 643 /* pfnGetValidVolumes */ 556 644 rtDvmFmtGptGetValidVolumes, … … 575 663 /* pfnVolumeIsRangeIntersecting */ 576 664 rtDvmFmtGptVolumeIsRangeIntersecting, 665 /* pfnVolumeQueryTableLocation */ 666 rtDvmFmtGptVolumeQueryTableLocation, 667 /* pfnVolumeGetIndex */ 668 rtDvmFmtGptVolumeGetIndex, 669 /* pfnVolumeQueryProp */ 670 rtDvmFmtGptVolumeQueryProp, 577 671 /* pfnVolumeRead */ 578 672 rtDvmFmtGptVolumeRead, -
trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp
r85124 r85877 37 37 #include <iprt/log.h> 38 38 #include <iprt/string.h> 39 #include <iprt/uuid.h> 39 40 #include "internal/dvm.h" 40 41 … … 52 53 /** Pointer to a MBR sector. */ 53 54 typedef struct RTDVMMBRSECTOR *PRTDVMMBRSECTOR; 55 56 57 /** The on-disk Cylinder/Head/Sector (CHS) info. */ 58 typedef struct MBRCHSADDR 59 { 60 uint8_t uHead; 61 uint8_t uSector : 6; 62 uint8_t uCylinderH : 2; 63 uint8_t uCylinderL; 64 } MBRCHSADDR; 65 AssertCompileSize(MBRCHSADDR, 3); 66 67 68 /** A decoded cylinder/head/sector address. */ 69 typedef struct RTDVMMBRCHSADDR 70 { 71 uint16_t uCylinder; 72 uint8_t uHead; 73 uint8_t uSector; 74 } RTDVMMBRCHSADDR; 75 54 76 55 77 /** … … 74 96 /** Bad entry. */ 75 97 bool fBad; 98 /** RTDVMVOLIDX_IN_TABLE - Zero-based index within the table in pSector. 99 * (Also the index into RTDVMMBRSECTOR::aEntries.) */ 100 uint8_t idxTable; 101 /** RTDVMVOLIDX_ALL - One-based index. All primary entries are included, 102 * whether they are used or not. In the extended table chain, only USED 103 * entries are counted (but we include RTDVMMBR_IS_EXTENDED entries). */ 104 uint8_t idxAll; 105 /** RTDVMVOLIDX_USER_VISIBLE - One-base index. Skips all unused entries 106 * and RTDVMMBR_IS_EXTENDED. */ 107 uint8_t idxVisible; 108 /** RTDVMVOLIDX_LINUX - One-based index following the /dev/sdaX scheme. */ 109 uint8_t idxLinux; 110 uint8_t bUnused; 111 /** The first CHS address of this partition */ 112 RTDVMMBRCHSADDR FirstChs; 113 /** The last CHS address of this partition */ 114 RTDVMMBRCHSADDR LastChs; 76 115 } RTDVMMBRENTRY; 77 116 /** Pointer to an MBR entry. */ … … 100 139 * fIsPrimary is @c true). UINT8_MAX if none. */ 101 140 uint8_t idxExtended; 141 #if ARCH_BITS == 64 142 uint32_t uAlignmentPadding; 143 #endif 102 144 /** The raw data. */ 103 uint8_t abData[ 512];145 uint8_t abData[RT_FLEXIBLE_ARRAY_NESTED]; 104 146 } RTDVMMBRSECTOR; 105 147 … … 114 156 * extended partition table entries. */ 115 157 RTLISTANCHOR PartitionHead; 158 /** The sector size to use when doing address calculation based on partition 159 * table sector addresses and counts. */ 160 uint32_t cbSector; 116 161 /** The total number of partitions, not counting extended ones. */ 117 162 uint32_t cPartitions; … … 181 226 }; 182 227 228 183 229 static DECLCALLBACK(int) rtDvmFmtMbrProbe(PCRTDVMDISK pDisk, uint32_t *puScore) 184 230 { 185 231 int rc = VINF_SUCCESS; 186 232 *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED; 187 if (pDisk->cbDisk > = 512)233 if (pDisk->cbDisk > RT_MAX(512, pDisk->cbSector)) 188 234 { 189 235 /* Read from the disk and check for the 0x55aa signature at the end. */ 190 uint8_t abMbr[512]; 191 rc = rtDvmDiskRead(pDisk, 0, &abMbr[0], sizeof(abMbr)); 192 if ( RT_SUCCESS(rc) 193 && abMbr[510] == 0x55 194 && abMbr[511] == 0xaa) 195 *puScore = RTDVM_MATCH_SCORE_SUPPORTED; /* Not perfect because GPTs have a protective MBR. */ 236 size_t cbAlignedSize = RT_MAX(512, pDisk->cbSector); 237 uint8_t *pbMbr = (uint8_t *)RTMemTmpAllocZ(cbAlignedSize); 238 if (pbMbr) 239 { 240 rc = rtDvmDiskRead(pDisk, 0, pbMbr, cbAlignedSize); 241 if ( RT_SUCCESS(rc) 242 && pbMbr[510] == 0x55 243 && pbMbr[511] == 0xaa) 244 *puScore = RTDVM_MATCH_SCORE_SUPPORTED; /* Not perfect because GPTs have a protective MBR. */ 245 /* @todo this could easily confuser a DOS, OS/2 or NT boot sector with a MBR... */ 246 RTMemTmpFree(pbMbr); 247 } 248 else 249 rc = VERR_NO_TMP_MEMORY; 196 250 } 197 251 … … 229 283 230 284 231 static int rtDvmFmtMbrReadExtended(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pPrimaryEntry) 285 /** 286 * Decodes the on-disk cylinder/head/sector info and stores it the 287 * destination structure. 288 */ 289 DECLINLINE(void) rtDvmFmtMbrDecodeChs(RTDVMMBRCHSADDR *pDst, uint8_t *pbRaw) 290 { 291 MBRCHSADDR *pRawChs = (MBRCHSADDR *)pbRaw; 292 pDst->uCylinder = RT_MAKE_U16(pRawChs->uCylinderL, pRawChs->uCylinderH); 293 pDst->uSector = pRawChs->uSector; 294 pDst->uHead = pRawChs->uHead; 295 } 296 297 298 static int rtDvmFmtMbrReadExtended(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pPrimaryEntry, 299 uint8_t *pidxAll, uint8_t *pidxVisible, uint8_t *pidxLinux) 232 300 { 233 301 uint64_t const cbExt = pPrimaryEntry->cbPart; … … 270 338 * Allocate a new sector entry and read the sector with the table. 271 339 */ 272 PRTDVMMBRSECTOR pNext = (PRTDVMMBRSECTOR)RTMemAllocZ(sizeof(*pNext)); 340 size_t const cbMbr = RT_MAX(512, pThis->pDisk->cbSector); 341 PRTDVMMBRSECTOR pNext = (PRTDVMMBRSECTOR)RTMemAllocZVar(RT_UOFFSETOF_DYN(RTDVMMBRSECTOR, abData[cbMbr])); 273 342 if (!pNext) 274 343 return VERR_NO_MEMORY; … … 280 349 pNext->idxExtended = UINT8_MAX; 281 350 282 int rc = rtDvmDiskRead(pThis->pDisk, pNext->offOnDisk, &pNext->abData[0], sizeof(pNext->abData)); 351 uint8_t *pabData = &pNext->abData[0]; 352 int rc = rtDvmDiskReadUnaligned(pThis->pDisk, pNext->offOnDisk, pabData, cbMbr); 283 353 if ( RT_FAILURE(rc) 284 || p Next->abData[510] != 0x55285 || p Next->abData[511] != 0xaa)354 || pabData[510] != 0x55 355 || pabData[511] != 0xaa) 286 356 { 287 357 if (RT_FAILURE(rc)) … … 289 359 else 290 360 LogRel(("rtDvmFmtMbrReadExtended: Extended partition table at sector %#RX64 does not have a valid DOS signature: %#x %#x\n", 291 offCurBegin, p Next->abData[510], pNext->abData[511]));361 offCurBegin, pabData[510], pabData[511])); 292 362 RTMemFree(pNext); 293 363 pCurEntry->fBad = true; … … 304 374 */ 305 375 PRTDVMMBRENTRY pEntry = &pNext->aEntries[0]; 306 uint8_t *pbMbrEntry = &p Next->abData[446];376 uint8_t *pbMbrEntry = &pabData[446]; 307 377 for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16) 308 378 { 379 pEntry->pSector = pNext; 380 pEntry->idxTable = (uint8_t)i; 381 RTListInit(&pEntry->ListEntry); 382 309 383 uint8_t const bType = pbMbrEntry[4]; 310 pEntry->pSector = pNext;311 RTListInit(&pEntry->ListEntry);312 384 if (bType != 0) 313 385 { 314 386 pEntry->bType = bType; 315 387 pEntry->fFlags = pbMbrEntry[0]; 316 pEntry->offPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08], 388 pEntry->idxAll = *pidxAll; 389 *pidxAll += 1; 390 391 rtDvmFmtMbrDecodeChs(&pEntry->FirstChs, &pbMbrEntry[1]); 392 rtDvmFmtMbrDecodeChs(&pEntry->LastChs, &pbMbrEntry[5]); 393 394 pEntry->offPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08 + 0], 317 395 pbMbrEntry[0x08 + 1], 318 396 pbMbrEntry[0x08 + 2], 319 397 pbMbrEntry[0x08 + 3]); 320 pEntry->offPart *= 512;321 pEntry->cbPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c ],398 pEntry->offPart *= pThis->cbSector; 399 pEntry->cbPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c + 0], 322 400 pbMbrEntry[0x0c + 1], 323 401 pbMbrEntry[0x0c + 2], 324 402 pbMbrEntry[0x0c + 3]); 325 pEntry->cbPart *= 512;403 pEntry->cbPart *= pThis->cbSector; 326 404 if (!RTDVMMBR_IS_EXTENDED(bType)) 327 405 { 328 pEntry->offPart += offCurBegin; 406 pEntry->offPart += offCurBegin; 407 pEntry->idxVisible = *pidxVisible; 408 *pidxVisible += 1; 409 pEntry->idxLinux = *pidxLinux; 410 *pidxLinux += 1; 411 329 412 pThis->cPartitions++; 330 413 RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry); … … 368 451 { 369 452 int rc; 370 PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL)); 453 size_t const cbMbr = RT_MAX(512, pDisk->cbSector); 454 PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZVar(RT_UOFFSETOF_DYN(RTDVMFMTINTERNAL, Primary.abData[cbMbr])); 371 455 if (pThis) 372 456 { … … 381 465 pThis->Primary.idxExtended = UINT8_MAX; 382 466 467 /* We'll use the sector size reported by the disk. 468 469 Though, giiven that the MBR was hardwired to 512 byte sectors, we probably 470 should do some probing when the sector size differs from 512, but that can 471 wait till there is a real need for it and we've got some semi reliable 472 heuristics for doing that. */ 473 pThis->cbSector = (uint32_t)pDisk->cbSector; 474 AssertLogRelMsgStmt( pThis->cbSector >= 512 475 && pThis->cbSector <= _64K, 476 ("cbSector=%#x\n", pThis->cbSector), 477 pThis->cbSector = 512); 478 383 479 /* 384 480 * Read the primary MBR. 385 481 */ 386 rc = rtDvmDiskRead(pDisk, 0, &pThis->Primary.abData[0], sizeof(pThis->Primary.abData)); 482 uint8_t *pabData = &pThis->Primary.abData[0]; 483 rc = rtDvmDiskRead(pDisk, 0, pabData, cbMbr); 387 484 if (RT_SUCCESS(rc)) 388 485 { 389 Assert(p This->Primary.abData[510] == 0x55 && pThis->Primary.abData[511] == 0xaa);486 Assert(pabData[510] == 0x55 && pabData[511] == 0xaa); 390 487 391 488 /* … … 393 490 */ 394 491 PRTDVMMBRENTRY pEntry = &pThis->Primary.aEntries[0]; 395 uint8_t *pbMbrEntry = &pThis->Primary.abData[446]; 492 uint8_t *pbMbrEntry = &pabData[446]; 493 uint8_t idxVisible = 1; 396 494 for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16) 397 495 { 398 pEntry->pSector = &pThis->Primary; 496 pEntry->pSector = &pThis->Primary; 497 pEntry->idxTable = (uint8_t)i; 399 498 RTListInit(&pEntry->ListEntry); 400 499 401 uint8_t const bType = pbMbrEntry[4];500 uint8_t const bType = pbMbrEntry[4]; 402 501 if (bType != 0) 403 502 { 503 pEntry->bType = bType; 504 pEntry->fFlags = pbMbrEntry[0]; 505 pEntry->idxAll = (uint8_t)(i + 1); 506 507 rtDvmFmtMbrDecodeChs(&pEntry->FirstChs, &pbMbrEntry[1]); 508 rtDvmFmtMbrDecodeChs(&pEntry->LastChs, &pbMbrEntry[5]); 509 404 510 pEntry->offPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08 + 0], 405 511 pbMbrEntry[0x08 + 1], 406 512 pbMbrEntry[0x08 + 2], 407 513 pbMbrEntry[0x08 + 3]); 408 pEntry->offPart *= 512;514 pEntry->offPart *= pThis->cbSector; 409 515 pEntry->cbPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c + 0], 410 516 pbMbrEntry[0x0c + 1], 411 517 pbMbrEntry[0x0c + 2], 412 518 pbMbrEntry[0x0c + 3]); 413 pEntry->cbPart *= 512; 414 pEntry->bType = bType; 415 pEntry->fFlags = pbMbrEntry[0]; 519 pEntry->cbPart *= pThis->cbSector; 416 520 if (!RTDVMMBR_IS_EXTENDED(bType)) 417 521 { 522 pEntry->idxVisible = idxVisible++; 523 pEntry->idxLinux = (uint8_t)(i + 1); 418 524 pThis->cPartitions++; 419 525 RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry); … … 439 545 */ 440 546 if (pThis->Primary.cExtended > 0) 547 { 548 uint8_t idxAll = 5; 549 uint8_t idxLinux = 5; 441 550 for (unsigned i = 0; i < 4; i++) 442 551 if (RTDVMMBR_IS_EXTENDED(pThis->Primary.aEntries[i].bType)) … … 444 553 if (pThis->Primary.idxExtended == UINT8_MAX) 445 554 pThis->Primary.idxExtended = (uint8_t)i; 446 rc = rtDvmFmtMbrReadExtended(pThis, &pThis->Primary.aEntries[i] );555 rc = rtDvmFmtMbrReadExtended(pThis, &pThis->Primary.aEntries[i], &idxAll, &idxVisible, &idxLinux); 447 556 if (RT_FAILURE(rc)) 448 557 break; 449 558 } 559 } 450 560 if (RT_SUCCESS(rc)) 451 561 { … … 453 563 return rc; 454 564 } 455 456 565 } 566 rtDvmFmtMbrDestroy(pThis); 457 567 } 458 568 else … … 465 575 { 466 576 int rc; 467 PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL)); 577 size_t const cbMbr = RT_MAX(512, pDisk->cbSector); 578 PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZVar(RT_UOFFSETOF_DYN(RTDVMFMTINTERNAL, Primary.abData[cbMbr])); 468 579 if (pThis) 469 580 { … … 479 590 480 591 /* Setup a new MBR and write it to the disk. */ 481 pThis->Primary.abData[510] = 0x55; 482 pThis->Primary.abData[511] = 0xaa; 483 rc = rtDvmDiskWrite(pDisk, 0, &pThis->Primary.abData[0], sizeof(pThis->Primary.abData)); 592 uint8_t *pabData = &pThis->Primary.abData[0]; 593 RT_BZERO(pabData, 512); 594 pabData[510] = 0x55; 595 pabData[511] = 0xaa; 596 rc = rtDvmDiskWrite(pDisk, 0, pabData, cbMbr); 484 597 if (RT_SUCCESS(rc)) 485 598 { … … 544 657 } 545 658 659 /** @copydoc RTDVMFMTOPS::pfnQueryDiskUuid */ 660 static DECLCALLBACK(int) rtDvmFmtMbrQueryDiskUuid(RTDVMFMT hVolMgrFmt, PRTUUID pUuid) 661 { 662 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 663 uint32_t idDisk = RT_MAKE_U32_FROM_U8(pThis->Primary.abData[440], 664 pThis->Primary.abData[441], 665 pThis->Primary.abData[442], 666 pThis->Primary.abData[443]); 667 if (idDisk != 0) 668 { 669 RTUuidClear(pUuid); 670 pUuid->Gen.u32TimeLow = idDisk; 671 return VINF_NOT_SUPPORTED; 672 } 673 return VERR_NOT_SUPPORTED; 674 } 675 546 676 static DECLCALLBACK(uint32_t) rtDvmFmtMbrGetValidVolumes(RTDVMFMT hVolMgrFmt) 547 677 { … … 668 798 } 669 799 return false; 800 } 801 802 /** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */ 803 static DECLCALLBACK(int) rtDvmFmtMbrVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable) 804 { 805 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 806 *poffTable = pVol->pEntry->pSector->offOnDisk; 807 *pcbTable = RT_MAX(512, pVol->pVolMgr->pDisk->cbSector); 808 return VINF_SUCCESS; 809 } 810 811 /** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */ 812 static DECLCALLBACK(uint32_t) rtDvmFmtMbrVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex) 813 { 814 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 815 switch (enmIndex) 816 { 817 case RTDVMVOLIDX_USER_VISIBLE: 818 return pVol->pEntry->idxVisible; 819 case RTDVMVOLIDX_ALL: 820 return pVol->pEntry->idxAll; 821 case RTDVMVOLIDX_IN_TABLE: 822 return pVol->pEntry->idxTable; 823 case RTDVMVOLIDX_LINUX: 824 return pVol->pEntry->idxLinux; 825 826 case RTDVMVOLIDX_INVALID: 827 case RTDVMVOLIDX_END: 828 case RTDVMVOLIDX_32BIT_HACK: 829 break; 830 /* no default! */ 831 } 832 return UINT32_MAX; 833 } 834 835 /** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */ 836 static DECLCALLBACK(int) rtDvmFmtMbrVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty, 837 void *pvBuf, size_t cbBuf, size_t *pcbBuf) 838 { 839 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 840 switch (enmProperty) 841 { 842 case RTDVMVOLPROP_MBR_FIRST_CYLINDER: 843 *pcbBuf = sizeof(uint16_t); 844 Assert(cbBuf >= *pcbBuf); 845 *(uint16_t *)pvBuf = pVol->pEntry->FirstChs.uCylinder; 846 return VINF_SUCCESS; 847 case RTDVMVOLPROP_MBR_LAST_CYLINDER: 848 *pcbBuf = sizeof(uint16_t); 849 Assert(cbBuf >= *pcbBuf); 850 *(uint16_t *)pvBuf = pVol->pEntry->LastChs.uCylinder; 851 return VINF_SUCCESS; 852 853 case RTDVMVOLPROP_MBR_FIRST_HEAD: 854 *pcbBuf = sizeof(uint8_t); 855 Assert(cbBuf >= *pcbBuf); 856 *(uint8_t *)pvBuf = pVol->pEntry->FirstChs.uHead; 857 return VINF_SUCCESS; 858 case RTDVMVOLPROP_MBR_LAST_HEAD: 859 *pcbBuf = sizeof(uint8_t); 860 Assert(cbBuf >= *pcbBuf); 861 *(uint8_t *)pvBuf = pVol->pEntry->LastChs.uHead; 862 return VINF_SUCCESS; 863 864 case RTDVMVOLPROP_MBR_FIRST_SECTOR: 865 *pcbBuf = sizeof(uint8_t); 866 Assert(cbBuf >= *pcbBuf); 867 *(uint8_t *)pvBuf = pVol->pEntry->FirstChs.uSector; 868 return VINF_SUCCESS; 869 case RTDVMVOLPROP_MBR_LAST_SECTOR: 870 *pcbBuf = sizeof(uint8_t); 871 Assert(cbBuf >= *pcbBuf); 872 *(uint8_t *)pvBuf = pVol->pEntry->LastChs.uSector; 873 return VINF_SUCCESS; 874 875 case RTDVMVOLPROP_MBR_TYPE: 876 *pcbBuf = sizeof(uint8_t); 877 Assert(cbBuf >= *pcbBuf); 878 *(uint8_t *)pvBuf = pVol->pEntry->bType; 879 return VINF_SUCCESS; 880 881 case RTDVMVOLPROP_GPT_TYPE: 882 case RTDVMVOLPROP_GPT_UUID: 883 return VERR_NOT_SUPPORTED; 884 885 case RTDVMVOLPROP_INVALID: 886 case RTDVMVOLPROP_END: 887 case RTDVMVOLPROP_32BIT_HACK: 888 break; 889 /* not default! */ 890 } 891 RT_NOREF(cbBuf); 892 AssertFailed(); 893 return VERR_NOT_SUPPORTED; 670 894 } 671 895 … … 702 926 /* pfnQueryRangeUse */ 703 927 rtDvmFmtMbrQueryRangeUse, 928 /* pfnQueryDiskUuid */ 929 rtDvmFmtMbrQueryDiskUuid, 704 930 /* pfnGetValidVolumes */ 705 931 rtDvmFmtMbrGetValidVolumes, … … 724 950 /* pfnVOlumeIsRangeIntersecting */ 725 951 rtDvmFmtMbrVolumeIsRangeIntersecting, 952 /* pfnVolumeQueryTableLocation */ 953 rtDvmFmtMbrVolumeQueryTableLocation, 954 /* pfnVolumeGetIndex */ 955 rtDvmFmtMbrVolumeGetIndex, 956 /* pfnVolumeQueryProp */ 957 rtDvmFmtMbrVolumeQueryProp, 726 958 /* pfnVolumeRead */ 727 959 rtDvmFmtMbrVolumeRead, -
trunk/src/VBox/Runtime/include/internal/dvm.h
r85124 r85877 138 138 139 139 /** 140 * Optional: Query the uuid of the current disk if applicable. 141 * 142 * @returns IPRT status code. 143 * @retval VERR_NOT_SUPPORTED if the partition scheme doesn't do UUIDs. 144 * @param hVolMgrFmt The format specific volume manager handle. 145 * @param pUuid Where to return the UUID. 146 */ 147 DECLCALLBACKMEMBER(int, pfnQueryDiskUuid,(RTDVMFMT hVolMgrFmt, PRTUUID pUuid)); 148 149 /** 140 150 * Gets the number of valid volumes in the map. 141 151 * … … 246 256 247 257 /** 258 * Queries the range of the partition table the volume belongs to on the underlying medium. 259 * 260 * @returns IPRT status code. 261 * @param hVolFmt The format specific volume handle. 262 * @param poffTable Where to return the byte offset on the underlying 263 * media of the (partition/volume/whatever) table. 264 * @param pcbTable Where to return the table size in bytes. This 265 * typically includes alignment padding. 266 * @sa RTDvmVolumeQueryTableLocation 267 */ 268 DECLCALLBACKMEMBER(int, pfnVolumeQueryTableLocation,(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffStart, uint64_t *poffLast)); 269 270 /** 271 * Gets the tiven index for the specified volume. 272 * 273 * @returns The requested index. UINT32_MAX on failure. 274 * @param hVolFmt The format specific volume handle. 275 * @param enmIndex The index to get. 276 * @sa RTDvmVolumeGetIndex 277 */ 278 DECLCALLBACKMEMBER(uint32_t, pfnVolumeGetIndex,(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex)); 279 280 /** 281 * Query a generic volume property. 282 * 283 * This is an extensible interface for retriving mostly format specific 284 * information, or information that's not commonly used. (It's modelled after 285 * RTLdrQueryPropEx.) 286 * 287 * @returns IPRT status code. 288 * @retval VERR_NOT_SUPPORTED if the property query isn't supported (either all 289 * or that specific property). The caller must handle this result. 290 * @retval VERR_NOT_FOUND is currently not returned, but intended for cases 291 * where it wasn't present in the tables. 292 * @retval VERR_INVALID_FUNCTION if the @a enmProperty value is wrong. 293 * @retval VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct 294 * size in @a *pcbRet. 295 * @retval VERR_BUFFER_OVERFLOW if the property doesn't have a fixed size 296 * buffer and the buffer isn't big enough. Correct size in @a *pcbRet. 297 * @retval VERR_INVALID_HANDLE if the handle is invalid. 298 * 299 * @param hVolFmt Handle to the volume. 300 * @param enmProperty The property to query. 301 * @param pvBuf Pointer to the input / output buffer. In most cases 302 * it's only used for returning data. 303 * @param cbBuf The size of the buffer. This is validated by the common 304 * code for all fixed typed & sized properties. The 305 * interger properties may have several supported sizes, in 306 * which case the user value is passed along as-is but it 307 * is okay to return a smaller amount of data. The common 308 * code will make upcast the data. 309 * @param pcbRet Where to return the amount of data returned. This must 310 * be set even for fixed type/sized data. 311 * @sa RTDvmVolumeQueryProp, RTDvmVolumeGetPropU64 312 */ 313 DECLCALLBACKMEMBER(int, pfnVolumeQueryProp,(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty, 314 void *pvBuf, size_t cbBuf, size_t *pcbBuf)); 315 316 /** 248 317 * Read data from the given volume. 249 318 * … … 300 369 * @param pvBuf Destination buffer. 301 370 * @param cbRead How much to read. 371 * @sa rtDvmDiskReadUnaligned 302 372 */ 303 373 DECLINLINE(int) rtDvmDiskRead(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead) … … 308 378 AssertReturn(off + cbRead <= pDisk->cbDisk, VERR_INVALID_PARAMETER); 309 379 380 /* Use RTVfsFileReadAt if these triggers: */ 381 Assert(!(cbRead % pDisk->cbSector)); 382 Assert(!(off % pDisk->cbSector)); 383 310 384 return RTVfsFileReadAt(pDisk->hVfsFile, off, pvBuf, cbRead, NULL /*pcbRead*/); 311 385 } 386 387 DECLHIDDEN(int) rtDvmDiskReadUnaligned(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead); 312 388 313 389 /** … … 327 403 AssertReturn(off + cbWrite <= pDisk->cbDisk, VERR_INVALID_PARAMETER); 328 404 405 /* Write RTVfsFileReadAt if these triggers: */ 406 Assert(!(cbWrite % pDisk->cbSector)); 407 Assert(!(off % pDisk->cbSector)); 408 329 409 return RTVfsFileWriteAt(pDisk->hVfsFile, off, pvBuf, cbWrite, NULL /*pcbWritten*/); 330 410 }
Note:
See TracChangeset
for help on using the changeset viewer.