Changeset 85877 in vbox for trunk/src/VBox/Runtime/common/dvm
- Timestamp:
- Aug 24, 2020 5:03:23 PM (5 years ago)
- svn:sync-xref-src-repo-rev:
- 140048
- Location:
- trunk/src/VBox/Runtime/common/dvm
- Files:
-
- 4 edited
Legend:
- Unmodified
- Added
- Removed
-
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,
Note:
See TracChangeset
for help on using the changeset viewer.