VirtualBox

Changeset 42860 in vbox for trunk/src/VBox


Ignore:
Timestamp:
Aug 17, 2012 9:04:41 AM (12 years ago)
Author:
vboxsync
Message:

Frontends/VBoxManage: GPT partitioning for raw partition access has been imlemented. (See issue 4116 on xtracker)

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Frontends/VBoxManage/VBoxInternalManage.cpp

    r41245 r42860  
    9292typedef struct HOSTPARTITION
    9393{
     94
    9495    unsigned        uIndex;
    9596    /** partition type */
     
    120121typedef struct HOSTPARTITIONS
    121122{
     123    /** partitioning type - MBR or GPT */
     124    PARTITIONING_TYPE uPartitioningType;
    122125    unsigned        cPartitions;
    123126    HOSTPARTITION   aPartitions[HOSTPARTITION_MAX];
     
    747750{
    748751    uint8_t aBuffer[512];
     752    uint8_t partitionTableHeader[512];
     753    uint32_t sector_size = 512;
     754    uint64_t lastUsableLBA =0;
    749755    int rc;
     756
     757    PARTITIONING_TYPE partitioningType;
    750758
    751759    pPart->cPartitions = 0;
    752760    memset(pPart->aPartitions, '\0', sizeof(pPart->aPartitions));
     761
    753762    rc = RTFileReadAt(File, 0, &aBuffer, sizeof(aBuffer), NULL);
     763
    754764    if (RT_FAILURE(rc))
    755765        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))
    787781                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)
    800873            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];
    816880            if (p[4] == 0)
    817             {
    818                 RTMsgError("Logical partition with type 0 encountered");
    819                 return VERR_INVALID_PARAMETER;
    820             }
    821 
     881                continue;
    822882            PHOSTPARTITION pCP = &pPart->aPartitions[pPart->cPartitions++];
    823             pCP->uIndex = uIndex;
     883            pCP->uIndex = i + 1;
    824884            pCP->uType = p[4];
    825885            pCP->uStartCylinder = (uint32_t)p[3] + ((uint32_t)(p[2] & 0xc0) << 2);
     
    829889            pCP->uEndHead = p[5];
    830890            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");
    835916                return VERR_INVALID_PARAMETER;
    836917            }
    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
    857975
    858976    /* Sort partitions in ascending order of start sector, plus a trivial
     
    8921010    }
    8931011
    894     /* Fill out partitioning location info for MBR. */
     1012    /* Fill out partitioning location info for MBR or GPT. */
    8951013    pPart->aPartitions[0].uPartDataStart = 0;
    8961014    pPart->aPartitions[0].cPartDataSectors = pPart->aPartitions[0].uStart;
    8971015
    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        }
    9121054    }
    9131055
     
    13811523            goto out;
    13821524        }
     1525
     1526        RawDescriptor.uPartitioningType = partitions.uPartitioningType;
    13831527
    13841528        for (unsigned i = 0; i < partitions.cPartitions; i++)
     
    15601704        }
    15611705
    1562         /* Have a second go at MBR/EPT area clipping. Now that the data areas
     1706        /* Have a second go at MBR/EPT, GPT area clipping. Now that the data areas
    15631707         * 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++)
    15651710        {
    15661711            if (RawDescriptor.pPartDescs[i].pvPartitionData)
     
    15691714                if (!RawDescriptor.pPartDescs[i].cbData)
    15701715                {
    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                    }
    15741731                }
    15751732            }
Note: See TracChangeset for help on using the changeset viewer.

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