VirtualBox

Changeset 69651 in vbox for trunk


Ignore:
Timestamp:
Nov 10, 2017 6:40:38 PM (7 years ago)
Author:
vboxsync
Message:

dvmmbr.cpp: support for extended and logical partitions.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp

    r69618 r69651  
    2929*   Header Files                                                                                                                 *
    3030*********************************************************************************************************************************/
     31#define LOG_GROUP RTLOGGROUP_FS
    3132#include <iprt/types.h>
    3233#include <iprt/assert.h>
    3334#include <iprt/mem.h>
    3435#include <iprt/dvm.h>
     36#include <iprt/list.h>
     37#include <iprt/log.h>
    3538#include <iprt/string.h>
    3639#include "internal/dvm.h"
     40
     41
     42/*********************************************************************************************************************************
     43*   Defined Constants And Macros                                                                                                 *
     44*********************************************************************************************************************************/
     45/** Checks if the partition type is an extended partition container. */
     46#define RTDVMMBR_IS_EXTENDED(a_bType) ((a_bType) == 0x05 || (a_bType) == 0x0f)
    3747
    3848
     
    4050*   Structures and Typedefs                                                                                                      *
    4151*********************************************************************************************************************************/
     52/** Pointer to a MBR sector. */
     53typedef struct RTDVMMBRSECTOR *PRTDVMMBRSECTOR;
     54
     55/**
     56 * MBR entry.
     57 */
     58typedef struct RTDVMMBRENTRY
     59{
     60    /** Our entry in the in-use partition entry list (RTDVMMBRENTRY). */
     61    RTLISTNODE          ListEntry;
     62    /** Pointer to the MBR sector containing this entry. */
     63    PRTDVMMBRSECTOR     pSector;
     64    /** Pointer to the next sector in the extended partition table chain. */
     65    PRTDVMMBRSECTOR     pChain;
     66    /** The byte offset of the start of the partition (relative to disk). */
     67    uint64_t            offPart;
     68    /** Number of bytes for this partition. */
     69    uint64_t            cbPart;
     70    /** The partition/filesystem type. */
     71    uint8_t             bType;
     72    /** The partition flags. */
     73    uint8_t             fFlags;
     74    /** Bad entry. */
     75    bool                fBad;
     76} RTDVMMBRENTRY;
     77/** Pointer to an MBR entry. */
     78typedef RTDVMMBRENTRY *PRTDVMMBRENTRY;
     79
     80/**
     81 * A MBR sector.
     82 */
     83typedef struct RTDVMMBRSECTOR
     84{
     85    /** Internal representation of the entries. */
     86    RTDVMMBRENTRY       aEntries[4];
     87    /** The byte offset of this MBR sector (relative to disk).
     88     * We keep this for detecting cycles now, but it will be needed if we start
     89     * updating the partition table at some point. */
     90    uint64_t            offOnDisk;
     91    /** Pointer to the previous sector if this isn't a primary one. */
     92    PRTDVMMBRENTRY      pPrevSector;
     93    /** Set if this is the primary MBR, cleared if an extended. */
     94    bool                fIsPrimary;
     95    /** Number of used entries. */
     96    uint8_t             cUsed;
     97    /** Number of extended entries. */
     98    uint8_t             cExtended;
     99    /** The extended entry we're following (we only follow one, except when
     100     *  fIsPrimary is @c true). UINT8_MAX if none. */
     101    uint8_t             idxExtended;
     102    /** The raw data. */
     103    uint8_t             abData[512];
     104} RTDVMMBRSECTOR;
    42105
    43106/**
     
    47110{
    48111    /** Pointer to the underlying disk. */
    49     PCRTDVMDISK     pDisk;
    50     /** Number of initialized partitions. */
    51     uint32_t        cPartitions;
    52     /** The raw MBR data. */
    53     uint8_t         abMbr[512];
     112    PCRTDVMDISK         pDisk;
     113    /** Head of the list of in-use RTDVMMBRENTRY structures.  This excludes
     114     *  extended partition table entries. */
     115    RTLISTANCHOR        PartitionHead;
     116    /** The total number of partitions, not counting extended ones. */
     117    uint32_t            cPartitions;
     118    /** The actual primary MBR sector. */
     119    RTDVMMBRSECTOR      Primary;
    54120} RTDVMFMTINTERNAL;
    55121/** Pointer to the MBR volume manager. */
     
    62128{
    63129    /** Pointer to the volume manager. */
    64     PRTDVMFMTINTERNAL pVolMgr;
    65     /** Partition table entry index. */
    66     uint32_t          idxEntry;
    67     /** Start offset of the volume. */
    68     uint64_t          offStart;
    69     /** Size of the volume. */
    70     uint64_t          cbVolume;
    71     /** Pointer to the raw partition table entry. */
    72     uint8_t          *pbMbrEntry;
     130    PRTDVMFMTINTERNAL   pVolMgr;
     131    /** The MBR entry.    */
     132    PRTDVMMBRENTRY      pEntry;
    73133} RTDVMVOLUMEFMTINTERNAL;
    74134/** Pointer to an MBR volume. */
    75135typedef RTDVMVOLUMEFMTINTERNAL *PRTDVMVOLUMEFMTINTERNAL;
    76 
    77 /**
    78  * MBR FS type to DVM volume type mapping entry.
    79  */
    80 
    81 typedef struct RTDVMMBRFS2VOLTYPE
    82 {
    83     /** MBR FS Id. */
    84     uint8_t           bFsId;
    85     /** DVM volume type. */
    86     RTDVMVOLTYPE      enmVolType;
    87 } RTDVMMBRFS2VOLTYPE;
    88 /** Pointer to a MBR FS Type to volume type mapping entry. */
    89 typedef RTDVMMBRFS2VOLTYPE *PRTDVMMBRFS2VOLTYPE;
    90136
    91137
     
    96142 * Mapping of FS types to DVM volume types.
    97143 *
    98  * From http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
    99  */
    100 static const RTDVMMBRFS2VOLTYPE g_aFs2DvmVolTypes[] =
     144 * @see https://en.wikipedia.org/wiki/Partition_type
     145 * @see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html
     146 */
     147static const struct RTDVMMBRFS2VOLTYPE
     148{
     149    /** MBR FS Id. */
     150    uint8_t             bFsId;
     151    /** DVM volume type. */
     152    RTDVMVOLTYPE        enmVolType;
     153} g_aFs2DvmVolTypes[] =
    101154{
    102155    { 0x01, RTDVMVOLTYPE_FAT12 },
     
    131184{
    132185    int rc = VINF_SUCCESS;
    133     uint8_t abMbr[512];
    134 
    135186    *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED;
    136 
    137187    if (pDisk->cbDisk >= 512)
    138188    {
    139189        /* Read from the disk and check for the 0x55aa signature at the end. */
     190        uint8_t abMbr[512];
    140191        rc = rtDvmDiskRead(pDisk, 0, &abMbr[0], sizeof(abMbr));
    141192        if (   RT_SUCCESS(rc)
     
    148199}
    149200
     201
     202static void rtDvmFmtMbrDestroy(PRTDVMFMTINTERNAL pThis)
     203{
     204    /*
     205     * Delete chains of extended partitions.
     206     */
     207    for (unsigned i = 0; i < 4; i++)
     208    {
     209        PRTDVMMBRSECTOR pCur = pThis->Primary.aEntries[i].pChain;
     210        while (pCur)
     211        {
     212            PRTDVMMBRSECTOR pNext = pCur->idxExtended != UINT8_MAX ? pCur->aEntries[pCur->idxExtended].pChain : NULL;
     213
     214            RT_ZERO(pCur->aEntries);
     215            pCur->pPrevSector = NULL;
     216            RTMemFree(pCur);
     217
     218            pCur = pNext;
     219        }
     220    }
     221
     222    /*
     223     * Now kill this.
     224     */
     225    pThis->pDisk = NULL;
     226    RT_ZERO(pThis->Primary.aEntries);
     227    RTMemFree(pThis);
     228}
     229
     230
     231static int rtDvmFmtMbrReadExtended(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pPrimaryEntry)
     232{
     233    uint32_t const  cbExt       = pPrimaryEntry->cbPart;
     234    uint64_t const  offExtBegin = pPrimaryEntry->offPart;
     235
     236    uint64_t        offCurBegin = offExtBegin;
     237    PRTDVMMBRENTRY  pCurEntry   = pPrimaryEntry;
     238    for (unsigned cTables = 1; ; cTables++)
     239    {
     240        /*
     241         * Do some sanity checking.
     242         */
     243        /* Check the address of the partition table. */
     244        if (offCurBegin - offExtBegin >= cbExt)
     245        {
     246            LogRel(("rtDvmFmtMbrReadExtended: offCurBegin=%#RX64 is outside the extended partition: %#RX64..%#RX64 (LB %#RX64)\n",
     247                    offCurBegin, offExtBegin, offExtBegin + cbExt - 1, cbExt));
     248            pCurEntry->fBad = true;
     249            return -VERR_OUT_OF_RANGE;
     250        }
     251
     252        /* Limit the chain length. */
     253        if (cTables > 64)
     254        {
     255            LogRel(("rtDvmFmtMbrReadExtended: offCurBegin=%#RX64 is the %uth table, we stop here.\n", offCurBegin, cTables));
     256            pCurEntry->fBad = true;
     257            return -VERR_TOO_MANY_SYMLINKS;
     258        }
     259
     260        /* Check for obvious cycles. */
     261        for (PRTDVMMBRENTRY pPrev = pCurEntry->pSector->pPrevSector; pPrev != NULL; pPrev = pPrev->pSector->pPrevSector)
     262            if (pPrev->offPart == offCurBegin)
     263            {
     264                LogRel(("rtDvmFmtMbrReadExtended: Cycle! We've seen offCurBegin=%#RX64 before\n", offCurBegin));
     265                pCurEntry->fBad = true;
     266                return -VERR_TOO_MANY_SYMLINKS;
     267            }
     268
     269        /*
     270         * Allocate a new sector entry and read the sector with the table.
     271         */
     272        PRTDVMMBRSECTOR pNext = (PRTDVMMBRSECTOR)RTMemAllocZ(sizeof(*pNext));
     273        if (!pNext)
     274            return VERR_NO_MEMORY;
     275        pNext->offOnDisk    = offCurBegin;
     276        pNext->pPrevSector  = pCurEntry;
     277        //pNext->fIsPrimary = false;
     278        //pNext->cUsed      = 0;
     279        //pNext->cExtended  = 0;
     280        pNext->idxExtended  = UINT8_MAX;
     281
     282        int rc = rtDvmDiskRead(pThis->pDisk, pNext->offOnDisk, &pNext->abData[0], sizeof(pNext->abData));
     283        if (   RT_FAILURE(rc)
     284            || pNext->abData[510] != 0x55
     285            || pNext->abData[511] != 0xaa)
     286        {
     287            if (RT_FAILURE(rc))
     288                LogRel(("rtDvmFmtMbrReadExtended: Error reading extended partition table at sector %#RX64: %Rrc\n", offCurBegin, rc));
     289            else
     290                LogRel(("rtDvmFmtMbrReadExtended: Extended partition table at sector %#RX64 does not have a valid DOS signature: %#x %#x\n",
     291                        offCurBegin, pNext->abData[510], pNext->abData[511]));
     292            RTMemFree(pNext);
     293            pCurEntry->fBad = true;
     294            return rc;
     295        }
     296        pCurEntry->pChain = pNext;
     297
     298        /*
     299         * Process the table, taking down the first forward entry.
     300         *
     301         * As noted in the caller of this function, we only deal with one extended
     302         * partition entry at this level since noone really ever put more than one
     303         * here anyway.
     304         */
     305        PRTDVMMBRENTRY pEntry     = &pNext->aEntries[0];
     306        uint8_t       *pbMbrEntry = &pNext->abData[446];
     307        for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16)
     308        {
     309            uint8_t const bType  = pbMbrEntry[4];
     310            pEntry->pSector = pNext;
     311            RTListInit(&pEntry->ListEntry);
     312            if (bType != 0)
     313            {
     314                pEntry->bType    = bType;
     315                pEntry->fFlags   = pbMbrEntry[0];
     316                pEntry->offPart  = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08],
     317                                                       pbMbrEntry[0x08 + 1],
     318                                                       pbMbrEntry[0x08 + 2],
     319                                                       pbMbrEntry[0x08 + 3]);
     320                pEntry->offPart *= 512;
     321                pEntry->cbPart   = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c],
     322                                                       pbMbrEntry[0x0c + 1],
     323                                                       pbMbrEntry[0x0c + 2],
     324                                                       pbMbrEntry[0x0c + 3]);
     325                pEntry->cbPart  *= 512;
     326                if (!RTDVMMBR_IS_EXTENDED(bType))
     327                {
     328                    pEntry->offPart += offCurBegin;
     329                    pThis->cPartitions++;
     330                    RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry);
     331                    Log2(("rtDvmFmtMbrReadExtended: %#012RX64::%u: vol%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n",
     332                          offCurBegin, i, pThis->cPartitions - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart));
     333                }
     334                else
     335                {
     336                    pEntry->offPart += offExtBegin;
     337                    pNext->cExtended++;
     338                    if (pNext->idxExtended == UINT8_MAX)
     339                        pNext->idxExtended = (uint8_t)i;
     340                    else
     341                    {
     342                        pEntry->fBad = true;
     343                        LogRel(("rtDvmFmtMbrReadExtended: Warning! Both #%u and #%u are extended partition table entries! Only following the former\n",
     344                                i, pNext->idxExtended));
     345                    }
     346                    Log2(("rtDvmFmtMbrReadExtended: %#012RX64::%u: ext%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n",
     347                          offCurBegin, i, pNext->cExtended - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart));
     348                }
     349                pNext->cUsed++;
     350
     351            }
     352            /* else: unused */
     353        }
     354
     355        /*
     356         * We're done if we didn't find any extended partition table entry.
     357         * Otherwise, advance to the next one.
     358         */
     359        if (!pNext->cExtended)
     360            return VINF_SUCCESS;
     361        pCurEntry   = &pNext->aEntries[pNext->idxExtended];
     362        offCurBegin = pCurEntry->offPart;
     363    }
     364}
     365
     366
    150367static DECLCALLBACK(int) rtDvmFmtMbrOpen(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
    151368{
    152     int rc = VINF_SUCCESS;
    153     PRTDVMFMTINTERNAL pThis = NULL;
    154 
    155     pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
     369    int rc;
     370    PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
    156371    if (pThis)
    157372    {
    158         pThis->pDisk       = pDisk;
    159         pThis->cPartitions = 0;
    160 
    161         /* Read the MBR and count the valid partition entries. */
    162         rc = rtDvmDiskRead(pDisk, 0, &pThis->abMbr[0], sizeof(pThis->abMbr));
     373        pThis->pDisk            = pDisk;
     374        //pThis->cPartitions    = 0;
     375        RTListInit(&pThis->PartitionHead);
     376        //pThis->Primary.offOnDisk   = 0;
     377        //pThis->Primary.pPrevSector = NULL;
     378        pThis->Primary.fIsPrimary    = true;
     379        //pThis->Primary.cUsed       = 0;
     380        //pThis->Primary.cExtended   = 0;
     381        pThis->Primary.idxExtended   = UINT8_MAX;
     382
     383        /*
     384         * Read the primary MBR.
     385         */
     386        rc = rtDvmDiskRead(pDisk, 0, &pThis->Primary.abData[0], sizeof(pThis->Primary.abData));
    163387        if (RT_SUCCESS(rc))
    164388        {
    165             uint8_t *pbMbrEntry = &pThis->abMbr[446];
    166 
    167             Assert(pThis->abMbr[510] == 0x55 && pThis->abMbr[511] == 0xaa);
    168 
    169             for (unsigned i = 0; i < 4; i++)
     389            Assert(pThis->Primary.abData[510] == 0x55 && pThis->Primary.abData[511] == 0xaa);
     390
     391            /*
     392             * Setup basic data for the 4 entries.
     393             */
     394            PRTDVMMBRENTRY pEntry     = &pThis->Primary.aEntries[0];
     395            uint8_t       *pbMbrEntry = &pThis->Primary.abData[446];
     396            for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16)
    170397            {
    171                 /* The entry is unused if the type contains 0x00. */
    172                 if (pbMbrEntry[4] != 0x00)
    173                     pThis->cPartitions++;
    174 
    175                 pbMbrEntry += 16;
     398                pEntry->pSector = &pThis->Primary;
     399                RTListInit(&pEntry->ListEntry);
     400
     401                uint8_t const bType = pbMbrEntry[4];
     402                if (bType != 0)
     403                {
     404                    pEntry->offPart  = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08 + 0],
     405                                                           pbMbrEntry[0x08 + 1],
     406                                                           pbMbrEntry[0x08 + 2],
     407                                                           pbMbrEntry[0x08 + 3]);
     408                    pEntry->offPart *= 512;
     409                    pEntry->cbPart   = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c + 0],
     410                                                           pbMbrEntry[0x0c + 1],
     411                                                           pbMbrEntry[0x0c + 2],
     412                                                           pbMbrEntry[0x0c + 3]);
     413                    pEntry->cbPart  *= 512;
     414                    pEntry->bType    = bType;
     415                    pEntry->fFlags   = pbMbrEntry[0];
     416                    if (!RTDVMMBR_IS_EXTENDED(bType))
     417                    {
     418                        pThis->cPartitions++;
     419                        RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry);
     420                        Log2(("rtDvmFmtMbrOpen: %u: vol%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n",
     421                              i, pThis->cPartitions - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart));
     422                    }
     423                    else
     424                    {
     425                        pThis->Primary.cExtended++;
     426                        Log2(("rtDvmFmtMbrOpen: %u: ext%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n",
     427                              i, pThis->Primary.cExtended - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart));
     428                    }
     429                    pThis->Primary.cUsed++;
     430                }
     431                /* else: unused */
    176432            }
    177433
    178             *phVolMgrFmt = pThis;
     434            /*
     435             * Now read any extended partitions.  Since it's no big deal for us, we allow
     436             * the primary partition table to have more than one extended partition.  However
     437             * in the extended tables we only allow a single forward link to avoid having to
     438             * deal with recursion.
     439             */
     440            if (pThis->Primary.cExtended > 0)
     441                for (unsigned i = 0; i < 4; i++)
     442                    if (RTDVMMBR_IS_EXTENDED(pThis->Primary.aEntries[i].bType))
     443                    {
     444                        if (pThis->Primary.idxExtended == UINT8_MAX)
     445                            pThis->Primary.idxExtended = (uint8_t)i;
     446                        rc = rtDvmFmtMbrReadExtended(pThis, &pThis->Primary.aEntries[i]);
     447                        if (RT_FAILURE(rc))
     448                            break;
     449                    }
     450            if (RT_SUCCESS(rc))
     451            {
     452                *phVolMgrFmt = pThis;
     453                return rc;
     454            }
     455
    179456        }
    180457    }
     
    187464static DECLCALLBACK(int) rtDvmFmtMbrInitialize(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
    188465{
    189     int rc = VINF_SUCCESS;
    190     PRTDVMFMTINTERNAL pThis = NULL;
    191 
    192     pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
     466    int rc;
     467    PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
    193468    if (pThis)
    194469    {
     470        pThis->pDisk            = pDisk;
     471        //pThis->cPartitions    = 0;
     472        RTListInit(&pThis->PartitionHead);
     473        //pThis->Primary.offOnDisk   = 0
     474        //pThis->Primary.pPrevSector = NULL;
     475        pThis->Primary.fIsPrimary    = true;
     476        //pThis->Primary.cUsed       = 0;
     477        //pThis->Primary.cExtended   = 0;
     478        pThis->Primary.idxExtended   = UINT8_MAX;
     479
    195480        /* Setup a new MBR and write it to the disk. */
    196         memset(&pThis->abMbr[0], 0, sizeof(pThis->abMbr));
    197         pThis->abMbr[510] = 0x55;
    198         pThis->abMbr[511] = 0xaa;
    199 
    200         rc = rtDvmDiskWrite(pDisk, 0, &pThis->abMbr[0], sizeof(pThis->abMbr));
    201 
     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));
    202484        if (RT_SUCCESS(rc))
    203485        {
    204             pThis->pDisk       = pDisk;
    205             pThis->cPartitions = 0;
     486            pThis->pDisk = pDisk;
    206487            *phVolMgrFmt = pThis;
    207488        }
     
    217498static DECLCALLBACK(void) rtDvmFmtMbrClose(RTDVMFMT hVolMgrFmt)
    218499{
    219     PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
    220 
    221     pThis->pDisk       = NULL;
    222     pThis->cPartitions = 0;
    223     memset(&pThis->abMbr[0], 0, sizeof(pThis->abMbr));
    224     RTMemFree(pThis);
     500    rtDvmFmtMbrDestroy(hVolMgrFmt);
    225501}
    226502
     
    254530 *
    255531 * @returns IPRT status code.
    256  * @param   pThis         The MBR volume manager data.
    257  * @param   pbMbrEntry    The raw MBR entry data.
    258  * @param   idx           The index in the partition table.
    259  * @param   phVolFmt      Where to store the volume data on success.
    260  */
    261 static int rtDvmFmtMbrVolumeCreate(PRTDVMFMTINTERNAL pThis, uint8_t *pbMbrEntry,
    262                                  uint32_t idx, PRTDVMVOLUMEFMT phVolFmt)
    263 {
    264     int rc = VINF_SUCCESS;
     532 * @param   pThis       The MBR volume manager data.
     533 * @param   pEntry      The MBR entry to create a volume handle for.
     534 * @param   phVolFmt    Where to store the volume data on success.
     535 */
     536static int rtDvmFmtMbrVolumeCreate(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pEntry, PRTDVMVOLUMEFMT phVolFmt)
     537{
    265538    PRTDVMVOLUMEFMTINTERNAL pVol = (PRTDVMVOLUMEFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEFMTINTERNAL));
    266 
    267539    if (pVol)
    268540    {
    269541        pVol->pVolMgr    = pThis;
    270         pVol->idxEntry   = idx;
    271         pVol->pbMbrEntry = pbMbrEntry;
    272         pVol->offStart   = *(uint32_t *)&pbMbrEntry[0x08] * pThis->pDisk->cbSector;
    273         pVol->cbVolume   = *(uint32_t *)&pbMbrEntry[0x0c] * pThis->pDisk->cbSector;
    274 
     542        pVol->pEntry     = pEntry;
    275543        *phVolFmt = pVol;
    276     }
    277     else
    278         rc = VERR_NO_MEMORY;
    279 
    280     return rc;
     544        return VINF_SUCCESS;
     545    }
     546    return VERR_NO_MEMORY;
    281547}
    282548
    283549static DECLCALLBACK(int) rtDvmFmtMbrQueryFirstVolume(RTDVMFMT hVolMgrFmt, PRTDVMVOLUMEFMT phVolFmt)
    284550{
    285     int rc = VINF_SUCCESS;
    286551    PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
    287 
    288552    if (pThis->cPartitions != 0)
    289     {
    290         uint8_t *pbMbrEntry = &pThis->abMbr[446];
    291 
    292         /* Search for the first non empty entry. */
    293         for (unsigned i = 0; i < 4; i++)
    294         {
    295             if (pbMbrEntry[0x04] != 0x00)
    296             {
    297                 rc = rtDvmFmtMbrVolumeCreate(pThis, pbMbrEntry, i, phVolFmt);
    298                 break;
    299             }
    300             pbMbrEntry += 16;
    301         }
    302     }
    303     else
    304         rc = VERR_DVM_MAP_EMPTY;
    305 
    306     return rc;
     553        return rtDvmFmtMbrVolumeCreate(pThis, RTListGetFirst(&pThis->PartitionHead, RTDVMMBRENTRY, ListEntry), phVolFmt);
     554    return VERR_DVM_MAP_EMPTY;
    307555}
    308556
    309557static DECLCALLBACK(int) rtDvmFmtMbrQueryNextVolume(RTDVMFMT hVolMgrFmt, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUMEFMT phVolFmtNext)
    310558{
    311     int rc = VERR_DVM_MAP_NO_VOLUME;
    312     PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
     559    PRTDVMFMTINTERNAL       pThis   = hVolMgrFmt;
     560    PRTDVMVOLUMEFMTINTERNAL pCurVol = hVolFmt;
     561    if (pCurVol)
     562    {
     563        PRTDVMMBRENTRY pNextEntry = RTListGetNext(&pThis->PartitionHead, pCurVol->pEntry, RTDVMMBRENTRY, ListEntry);
     564        if (pNextEntry)
     565            return rtDvmFmtMbrVolumeCreate(pThis, pNextEntry, phVolFmtNext);
     566        return VERR_DVM_MAP_NO_VOLUME;
     567    }
     568    if (pThis->cPartitions != 0)
     569        return rtDvmFmtMbrVolumeCreate(pThis, RTListGetFirst(&pThis->PartitionHead, RTDVMMBRENTRY, ListEntry), phVolFmtNext);
     570    return VERR_DVM_MAP_EMPTY;
     571}
     572
     573static DECLCALLBACK(void) rtDvmFmtMbrVolumeClose(RTDVMVOLUMEFMT hVolFmt)
     574{
    313575    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    314     uint8_t *pbMbrEntry = pVol->pbMbrEntry + 16;
    315 
    316     for (unsigned i = pVol->idxEntry + 1; i < 4; i++)
    317     {
    318         if (pbMbrEntry[0x04] != 0x00)
    319         {
    320             rc = rtDvmFmtMbrVolumeCreate(pThis, pbMbrEntry, i, phVolFmtNext);
    321             break;
    322         }
    323         pbMbrEntry += 16;
    324     }
    325 
    326     return rc;
    327 }
    328 
    329 static DECLCALLBACK(void) rtDvmFmtMbrVolumeClose(RTDVMVOLUMEFMT hVolFmt)
     576
     577    pVol->pVolMgr    = NULL;
     578    pVol->pEntry     = NULL;
     579
     580    RTMemFree(pVol);
     581}
     582
     583static DECLCALLBACK(uint64_t) rtDvmFmtMbrVolumeGetSize(RTDVMVOLUMEFMT hVolFmt)
    330584{
    331585    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    332586
    333     pVol->pVolMgr    = NULL;
    334     pVol->offStart   = 0;
    335     pVol->cbVolume   = 0;
    336     pVol->pbMbrEntry = NULL;
    337 
    338     RTMemFree(pVol);
    339 }
    340 
    341 static DECLCALLBACK(uint64_t) rtDvmFmtMbrVolumeGetSize(RTDVMVOLUMEFMT hVolFmt)
    342 {
    343     PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    344 
    345     return pVol->cbVolume;
     587    return pVol->pEntry->cbPart;
    346588}
    347589
     
    354596static DECLCALLBACK(RTDVMVOLTYPE) rtDvmFmtMbrVolumeGetType(RTDVMVOLUMEFMT hVolFmt)
    355597{
    356     RTDVMVOLTYPE enmVolType = RTDVMVOLTYPE_UNKNOWN;
    357598    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    358599
     600    uint8_t const bType = pVol->pEntry->bType;
    359601    for (unsigned i = 0; i < RT_ELEMENTS(g_aFs2DvmVolTypes); i++)
    360         if (pVol->pbMbrEntry[0x04] == g_aFs2DvmVolTypes[i].bFsId)
    361         {
    362             enmVolType = g_aFs2DvmVolTypes[i].enmVolType;
    363             break;
    364         }
    365 
    366     return enmVolType;
     602        if (g_aFs2DvmVolTypes[i].bFsId == bType)
     603            return g_aFs2DvmVolTypes[i].enmVolType;
     604
     605    return RTDVMVOLTYPE_UNKNOWN;
    367606}
    368607
    369608static DECLCALLBACK(uint64_t) rtDvmFmtMbrVolumeGetFlags(RTDVMVOLUMEFMT hVolFmt)
    370609{
     610    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
     611
    371612    uint64_t fFlags = 0;
    372     PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    373 
    374     if (pVol->pbMbrEntry[0x00] & 0x80)
     613    if (pVol->pEntry->bType & 0x80)
    375614        fFlags |= DVMVOLUME_FLAGS_BOOTABLE | DVMVOLUME_FLAGS_ACTIVE;
    376615
     
    383622                                                               uint64_t *pcbIntersect)
    384623{
    385     bool fIntersect = false;
    386624    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    387625
    388     if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart))
    389     {
    390         fIntersect    = true;
    391         *poffVol      = offStart - pVol->offStart;
    392         *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart);
    393     }
    394 
    395     return fIntersect;
     626    if (RTDVM_RANGE_IS_INTERSECTING(pVol->pEntry->offPart, pVol->pEntry->cbPart, offStart))
     627    {
     628        *poffVol      = offStart - pVol->pEntry->offPart;
     629        *pcbIntersect = RT_MIN(cbRange, pVol->pEntry->offPart + pVol->pEntry->cbPart - offStart);
     630        return true;
     631    }
     632    return false;
    396633}
    397634
     
    399636{
    400637    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    401     AssertReturn(off + cbRead <= pVol->cbVolume, VERR_INVALID_PARAMETER);
    402 
    403     return rtDvmDiskRead(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbRead);
     638    AssertReturn(off + cbRead <= pVol->pEntry->cbPart, VERR_INVALID_PARAMETER);
     639
     640    return rtDvmDiskRead(pVol->pVolMgr->pDisk, pVol->pEntry->offPart + off, pvBuf, cbRead);
    404641}
    405642
     
    407644{
    408645    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
    409     AssertReturn(off + cbWrite <= pVol->cbVolume, VERR_INVALID_PARAMETER);
    410 
    411     return rtDvmDiskWrite(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbWrite);
     646    AssertReturn(off + cbWrite <= pVol->pEntry->cbPart, VERR_INVALID_PARAMETER);
     647
     648    return rtDvmDiskWrite(pVol->pVolMgr->pDisk, pVol->pEntry->offPart + off, pvBuf, cbWrite);
    412649}
    413650
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