Changeset 42860 in vbox for trunk/src/VBox
- Timestamp:
- Aug 17, 2012 9:04:41 AM (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp
r41245 r42860 92 92 typedef struct HOSTPARTITION 93 93 { 94 94 95 unsigned uIndex; 95 96 /** partition type */ … … 120 121 typedef struct HOSTPARTITIONS 121 122 { 123 /** partitioning type - MBR or GPT */ 124 PARTITIONING_TYPE uPartitioningType; 122 125 unsigned cPartitions; 123 126 HOSTPARTITION aPartitions[HOSTPARTITION_MAX]; … … 747 750 { 748 751 uint8_t aBuffer[512]; 752 uint8_t partitionTableHeader[512]; 753 uint32_t sector_size = 512; 754 uint64_t lastUsableLBA =0; 749 755 int rc; 756 757 PARTITIONING_TYPE partitioningType; 750 758 751 759 pPart->cPartitions = 0; 752 760 memset(pPart->aPartitions, '\0', sizeof(pPart->aPartitions)); 761 753 762 rc = RTFileReadAt(File, 0, &aBuffer, sizeof(aBuffer), NULL); 763 754 764 if (RT_FAILURE(rc)) 755 765 return rc; 756 if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) 757 return VERR_INVALID_PARAMETER; 758 759 unsigned uExtended = (unsigned)-1; 760 761 for (unsigned i = 0; i < 4; i++) 762 { 763 uint8_t *p = &aBuffer[0x1be + i * 16]; 764 if (p[4] == 0) 765 continue; 766 PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; 767 pCP->uIndex = i + 1; 768 pCP->uType = p[4]; 769 pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2); 770 pCP->uStartHead = p[1]; 771 pCP->uStartSector = p[2] & 0x3f; 772 pCP->uEndCylinder = (uint32_t)p[7] + ((uint32_t)(p[6] & 0xc0) << 2); 773 pCP->uEndHead = p[5]; 774 pCP->uEndSector = p[6] & 0x3f; 775 pCP->uStart = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 776 pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); 777 pCP->uPartDataStart = 0; /* will be filled out later properly. */ 778 pCP->cPartDataSectors = 0; 779 780 if (PARTTYPE_IS_EXTENDED(p[4])) 781 { 782 if (uExtended == (unsigned)-1) 783 uExtended = (unsigned)(pCP - pPart->aPartitions); 784 else 785 { 786 RTMsgError("More than one extended partition"); 766 767 if (aBuffer[450] == 0xEE)/* check the sign of the GPT disk*/ 768 { 769 partitioningType = GPT; 770 pPart->uPartitioningType = GPT;//partitioningType; 771 772 if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) 773 return VERR_INVALID_PARAMETER; 774 775 rc = RTFileReadAt(File, sector_size, &partitionTableHeader, sector_size, NULL); 776 if (RT_SUCCESS(rc)) 777 { 778 const char* l_ppth = (char*)partitionTableHeader; 779 rc = strncmp(l_ppth, "EFI PART", 8); 780 if(RT_FAILURE(rc)) 787 781 return VERR_INVALID_PARAMETER; 788 } 789 } 790 } 791 792 if (uExtended != (unsigned)-1) 793 { 794 unsigned uIndex = 5; 795 uint64_t uStart = pPart->aPartitions[uExtended].uStart; 796 uint64_t uOffset = 0; 797 if (!uStart) 798 { 799 RTMsgError("Inconsistency for logical partition start"); 782 783 /** @todo check GPT Version */ 784 785 uint64_t firstUsableLBA = RT_MAKE_U64_FROM_U8(partitionTableHeader[40], 786 partitionTableHeader[41], 787 partitionTableHeader[42], 788 partitionTableHeader[43], 789 partitionTableHeader[44], 790 partitionTableHeader[45], 791 partitionTableHeader[46], 792 partitionTableHeader[47] 793 ); 794 lastUsableLBA = RT_MAKE_U64_FROM_U8( partitionTableHeader[48], 795 partitionTableHeader[49], 796 partitionTableHeader[50], 797 partitionTableHeader[51], 798 partitionTableHeader[52], 799 partitionTableHeader[53], 800 partitionTableHeader[54], 801 partitionTableHeader[55] 802 ); 803 uint32_t partitionsNumber = RT_MAKE_U32_FROM_U8( partitionTableHeader[80], 804 partitionTableHeader[81], 805 partitionTableHeader[82], 806 partitionTableHeader[83] 807 ); 808 uint32_t partitionEntrySize = RT_MAKE_U32_FROM_U8( partitionTableHeader[84], 809 partitionTableHeader[85], 810 partitionTableHeader[86], 811 partitionTableHeader[87] 812 ); 813 814 uint32_t currentEntry = 0; 815 while(currentEntry<partitionsNumber) 816 { 817 uint8_t partitionEntry[128]; 818 819 /*partition entries begin from LBA2*/ 820 rc = RTFileReadAt(File, 1024 + currentEntry*partitionEntrySize, &partitionEntry, partitionEntrySize, NULL); 821 822 uint64_t start = RT_MAKE_U64_FROM_U8( partitionEntry[32], 823 partitionEntry[33], 824 partitionEntry[34], 825 partitionEntry[35], 826 partitionEntry[36], 827 partitionEntry[37], 828 partitionEntry[38], 829 partitionEntry[39] 830 ); 831 uint64_t end = RT_MAKE_U64_FROM_U8( partitionEntry[40], 832 partitionEntry[41], 833 partitionEntry[42], 834 partitionEntry[43], 835 partitionEntry[44], 836 partitionEntry[45], 837 partitionEntry[46], 838 partitionEntry[47] 839 ); 840 841 PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; 842 pCP->uIndex = currentEntry + 1; 843 pCP->uType = 0; 844 pCP->uStartCylinder = 0; 845 pCP->uStartHead = 0; 846 pCP->uStartSector = 0; 847 pCP->uEndCylinder = 0; 848 pCP->uEndHead = 0; 849 pCP->uEndSector = 0; 850 pCP->uPartDataStart = 0; /* will be filled out later properly. */ 851 pCP->cPartDataSectors = 0; 852 if(start==0 || end==0) 853 { 854 pCP->uIndex = 0; 855 --pPart->cPartitions; 856 break; 857 } 858 else{ 859 pCP->uStart = start; 860 pCP->uSize = (end +1) - start;/*+1 LBA because the last address is included*/ 861 } 862 863 ++currentEntry; 864 } 865 } 866 } 867 else 868 { 869 partitioningType = MBR; 870 pPart->uPartitioningType = MBR;//partitioningType; 871 872 if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) 800 873 return VERR_INVALID_PARAMETER; 801 } 802 803 do 804 { 805 rc = RTFileReadAt(File, (uStart + uOffset) * 512, &aBuffer, sizeof(aBuffer), NULL); 806 if (RT_FAILURE(rc)) 807 return rc; 808 809 if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) 810 { 811 RTMsgError("Logical partition without magic"); 812 return VERR_INVALID_PARAMETER; 813 } 814 uint8_t *p = &aBuffer[0x1be]; 815 874 875 unsigned uExtended = (unsigned)-1; 876 877 for (unsigned i = 0; i < 4; i++) 878 { 879 uint8_t *p = &aBuffer[0x1be + i * 16]; 816 880 if (p[4] == 0) 817 { 818 RTMsgError("Logical partition with type 0 encountered"); 819 return VERR_INVALID_PARAMETER; 820 } 821 881 continue; 822 882 PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; 823 pCP->uIndex = uIndex;883 pCP->uIndex = i + 1; 824 884 pCP->uType = p[4]; 825 885 pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2); … … 829 889 pCP->uEndHead = p[5]; 830 890 pCP->uEndSector = p[6] & 0x3f; 831 uint32_t uStartOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 832 if (!uStartOffset) 833 { 834 RTMsgError("Invalid partition start offset"); 891 pCP->uStart = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 892 pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); 893 pCP->uPartDataStart = 0; /* will be filled out later properly. */ 894 pCP->cPartDataSectors = 0; 895 896 if (PARTTYPE_IS_EXTENDED(p[4])) 897 { 898 if (uExtended == (unsigned)-1) 899 uExtended = (unsigned)(pCP - pPart->aPartitions); 900 else 901 { 902 RTMsgError("More than one extended partition"); 903 return VERR_INVALID_PARAMETER; 904 } 905 } 906 } 907 908 if (uExtended != (unsigned)-1) 909 { 910 unsigned uIndex = 5; 911 uint64_t uStart = pPart->aPartitions[uExtended].uStart; 912 uint64_t uOffset = 0; 913 if (!uStart) 914 { 915 RTMsgError("Inconsistency for logical partition start"); 835 916 return VERR_INVALID_PARAMETER; 836 917 } 837 pCP->uStart = uStart + uOffset + uStartOffset; 838 pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); 839 /* Fill out partitioning location info for EBR. */ 840 pCP->uPartDataStart = uStart + uOffset; 841 pCP->cPartDataSectors = uStartOffset; 842 p += 16; 843 if (p[4] == 0) 844 uExtended = (unsigned)-1; 845 else if (PARTTYPE_IS_EXTENDED(p[4])) 846 { 847 uExtended = uIndex++; 848 uOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 849 } 850 else 851 { 852 RTMsgError("Logical partition chain broken"); 853 return VERR_INVALID_PARAMETER; 854 } 855 } while (uExtended != (unsigned)-1); 856 } 918 919 do 920 { 921 rc = RTFileReadAt(File, (uStart + uOffset) * 512, &aBuffer, sizeof(aBuffer), NULL); 922 if (RT_FAILURE(rc)) 923 return rc; 924 925 if (aBuffer[510] != 0x55 || aBuffer[511] != 0xaa) 926 { 927 RTMsgError("Logical partition without magic"); 928 return VERR_INVALID_PARAMETER; 929 } 930 uint8_t *p = &aBuffer[0x1be]; 931 932 if (p[4] == 0) 933 { 934 RTMsgError("Logical partition with type 0 encountered"); 935 return VERR_INVALID_PARAMETER; 936 } 937 938 PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++]; 939 pCP->uIndex = uIndex; 940 pCP->uType = p[4]; 941 pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2); 942 pCP->uStartHead = p[1]; 943 pCP->uStartSector = p[2] & 0x3f; 944 pCP->uEndCylinder = (uint32_t)p[7] + ((uint32_t)(p[6] & 0xc0) << 2); 945 pCP->uEndHead = p[5]; 946 pCP->uEndSector = p[6] & 0x3f; 947 uint32_t uStartOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 948 if (!uStartOffset) 949 { 950 RTMsgError("Invalid partition start offset"); 951 return VERR_INVALID_PARAMETER; 952 } 953 pCP->uStart = uStart + uOffset + uStartOffset; 954 pCP->uSize = RT_MAKE_U32_FROM_U8(p[12], p[13], p[14], p[15]); 955 /* Fill out partitioning location info for EBR. */ 956 pCP->uPartDataStart = uStart + uOffset; 957 pCP->cPartDataSectors = uStartOffset; 958 p += 16; 959 if (p[4] == 0) 960 uExtended = (unsigned)-1; 961 else if (PARTTYPE_IS_EXTENDED(p[4])) 962 { 963 uExtended = uIndex++; 964 uOffset = RT_MAKE_U32_FROM_U8(p[8], p[9], p[10], p[11]); 965 } 966 else 967 { 968 RTMsgError("Logical partition chain broken"); 969 return VERR_INVALID_PARAMETER; 970 } 971 } while (uExtended != (unsigned)-1); 972 } 973 } 974 857 975 858 976 /* Sort partitions in ascending order of start sector, plus a trivial … … 892 1010 } 893 1011 894 /* Fill out partitioning location info for MBR . */1012 /* Fill out partitioning location info for MBR or GPT. */ 895 1013 pPart->aPartitions[0].uPartDataStart = 0; 896 1014 pPart->aPartitions[0].cPartDataSectors = pPart->aPartitions[0].uStart; 897 1015 898 /* Now do a some partition table consistency checking, to reject the most 899 * obvious garbage which can lead to trouble later. */ 900 uint64_t uPrevEnd = 0; 901 for (unsigned i = 0; i < pPart->cPartitions-1; i++) 902 { 903 if (pPart->aPartitions[i].cPartDataSectors) 904 uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors; 905 if (pPart->aPartitions[i].uStart < uPrevEnd) 906 { 907 RTMsgError("Overlapping partitions"); 908 return VERR_INVALID_PARAMETER; 909 } 910 if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType)) 911 uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize; 1016 /* Fill out partitioning location info for backup GPT. */ 1017 if(partitioningType == GPT) 1018 { 1019 pPart->aPartitions[pPart->cPartitions-1].uPartDataStart = lastUsableLBA+1; 1020 pPart->aPartitions[pPart->cPartitions-1].cPartDataSectors = 33; 1021 1022 /* Now do a some partition table consistency checking, to reject the most 1023 * obvious garbage which can lead to trouble later. */ 1024 uint64_t uPrevEnd = 0; 1025 for (unsigned i = 0; i < pPart->cPartitions; i++) 1026 { 1027 if (pPart->aPartitions[i].cPartDataSectors) 1028 uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors; 1029 if (pPart->aPartitions[i].uStart < uPrevEnd && 1030 pPart->cPartitions-1 != i) 1031 { 1032 RTMsgError("Overlapping GPT partitions"); 1033 return VERR_INVALID_PARAMETER; 1034 } 1035 } 1036 } 1037 else 1038 { 1039 /* Now do a some partition table consistency checking, to reject the most 1040 * obvious garbage which can lead to trouble later. */ 1041 uint64_t uPrevEnd = 0; 1042 for (unsigned i = 0; i < pPart->cPartitions; i++) 1043 { 1044 if (pPart->aPartitions[i].cPartDataSectors) 1045 uPrevEnd = pPart->aPartitions[i].uPartDataStart + pPart->aPartitions[i].cPartDataSectors; 1046 if (pPart->aPartitions[i].uStart < uPrevEnd) 1047 { 1048 RTMsgError("Overlapping MBR partitions"); 1049 return VERR_INVALID_PARAMETER; 1050 } 1051 if (!PARTTYPE_IS_EXTENDED(pPart->aPartitions[i].uType)) 1052 uPrevEnd = pPart->aPartitions[i].uStart + pPart->aPartitions[i].uSize; 1053 } 912 1054 } 913 1055 … … 1381 1523 goto out; 1382 1524 } 1525 1526 RawDescriptor.uPartitioningType = partitions.uPartitioningType; 1383 1527 1384 1528 for (unsigned i = 0; i < partitions.cPartitions; i++) … … 1560 1704 } 1561 1705 1562 /* Have a second go at MBR/EPT area clipping. Now that the data areas1706 /* Have a second go at MBR/EPT, GPT area clipping. Now that the data areas 1563 1707 * are sorted this is much easier to get 100% right. */ 1564 for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++) 1708 //for (unsigned i = 0; i < RawDescriptor.cPartDescs-1; i++) 1709 for (unsigned i = 0; i < RawDescriptor.cPartDescs; i++) 1565 1710 { 1566 1711 if (RawDescriptor.pPartDescs[i].pvPartitionData) … … 1569 1714 if (!RawDescriptor.pPartDescs[i].cbData) 1570 1715 { 1571 RTMsgError("MBR/EPT overlaps with data area"); 1572 vrc = VERR_INVALID_PARAMETER; 1573 goto out; 1716 if(RawDescriptor.uPartitioningType == MBR) 1717 { 1718 RTMsgError("MBR/EPT overlaps with data area"); 1719 vrc = VERR_INVALID_PARAMETER; 1720 goto out; 1721 } 1722 else 1723 { 1724 if(RawDescriptor.cPartDescs != i+1) 1725 { 1726 RTMsgError("GPT overlaps with data area"); 1727 vrc = VERR_INVALID_PARAMETER; 1728 goto out; 1729 } 1730 } 1574 1731 } 1575 1732 }
Note:
See TracChangeset
for help on using the changeset viewer.