VirtualBox

Changeset 85877 in vbox


Ignore:
Timestamp:
Aug 24, 2020 5:03:23 PM (4 years ago)
Author:
vboxsync
Message:

Main: bugref:9224: DVM API changes

Location:
trunk
Files:
7 edited

Legend:

Unmodified
Added
Removed
  • trunk/include/iprt/dvm.h

    r85121 r85877  
    241241
    242242/**
     243 * Gets the UUID of the disk if applicable.
     244 *
     245 * Disks using the MBR format may return the 32-bit disk identity in the
     246 * u32TimeLow field and set the rest to zero.
     247 *
     248 * @returns IPRT status code.
     249 * @retval  VERR_NOT_SUPPORTED if the partition scheme doesn't do UUIDs.
     250 * @retval  VINF_NOT_SUPPORTED if non-UUID disk ID is returned.
     251 * @param   hVolMgr     The volume manager handle.
     252 * @param   pUuid       Where to return the UUID.
     253 *
     254 * @todo It's quite possible this should be turned into a map-level edition of
     255 *       RTDvmVolumeQueryProp...
     256 */
     257RTDECL(int) RTDvmMapQueryDiskUuid(RTDVM hVolMgr, PRTUUID pUuid);
     258
     259/**
    243260 * Gets the number of valid partitions in the map.
    244261 *
     
    355372
    356373/**
    357  * Queries the range of the given volume on the underyling medium.
     374 * Queries the range of the given volume on the underlying medium.
    358375 *
    359376 * @returns IPRT status code.
     
    361378 * @param   hVol            The volume handle.
    362379 * @param   poffStart       Where to store the start offset in bytes on the underlying medium.
    363  * @param   poffEnd         Where to store the end offset in bytes on the underlying medium (inclusive).
    364  */
    365 RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffEnd);
     380 * @param   poffLast        Where to store the last offset in bytes on the underlying medium (inclusive).
     381 */
     382RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffLast);
     383
     384/**
     385 * Returns the partition/whatever table location of the volume.
     386 *
     387 * For volume format with a single table, like GPT and BSD-labels, it will
     388 * return the location of that table.  Though for GPT, the fake MBR will not be
     389 * included.
     390 *
     391 * For logical (extended) MBR-style volumes, this will return the location of
     392 * the extended partition table.  For primary volumes the MBR location is
     393 * returned.  The special MBR case is why this operation is done on the volume
     394 * rather than the volume manager.
     395 *
     396 * Using RTDvmVolumeGetIndex with RTDVMVOLIDX_IN_PART_TABLE should get you
     397 * the index in the table returned by this function.
     398 *
     399 * @returns IPRT status code.
     400 * @param   hVol            The volume handle.
     401 * @param   poffTable       Where to return the byte offset on the underlying
     402 *                          media of the (partition/volume/whatever) table.
     403 * @param   pcbTable        Where to return the table size in bytes.  (This does
     404 *                          not include any alignment padding or such, just
     405 *                          padding up to sector/block size.)
     406 */
     407RTDECL(int) RTDvmVolumeQueryTableLocation(RTDVMVOLUME hVol, uint64_t *poffTable, uint64_t *pcbTable);
     408
     409/**
     410 * RTDvmVolumeGetIndex indexes.
     411 */
     412typedef enum RTDVMVOLIDX
     413{
     414    /** Invalid zero value. */
     415    RTDVMVOLIDX_INVALID = 0,
     416    /** Only consider user visible ones, i.e. don't count MBR extended partition
     417     *  entries and such like. */
     418    RTDVMVOLIDX_USER_VISIBLE,
     419    /** Index when all volumes, user visible, hidden, special, whatever ones are
     420     * included.
     421     *
     422     * For MBR this is 1-based index where all primary entires are included whether
     423     * in use or not.  Only non-empty entries in extended tables are counted, though
     424     * the forward link is included. */
     425    RTDVMVOLIDX_ALL,
     426    /** The raw index within the partition/volume/whatever table.  This have a kind
     427     *  of special meaning to MBR, where there are multiple tables. */
     428    RTDVMVOLIDX_IN_TABLE,
     429    /** Follows the linux /dev/sdaX convention as closely as absolutely possible. */
     430    RTDVMVOLIDX_LINUX,
     431    /** End of valid indexes. */
     432    RTDVMVOLIDX_END,
     433    /** Make sure the type is 32-bit.   */
     434    RTDVMVOLIDX_32BIT_HACK = 0x7fffffff
     435} RTDVMVOLIDX;
     436
     437/**
     438 * Gets the tiven index for the specified volume.
     439 *
     440 * @returns The requested index, UINT32_MAX on failure.
     441 * @param   hVol            The volume handle.
     442 * @param   enmIndex        Which kind of index to get for the volume.
     443 */
     444RTDECL(uint32_t) RTDvmVolumeGetIndex(RTDVMVOLUME hVol, RTDVMVOLIDX enmIndex);
     445
     446/**
     447 * Volume properties queriable via RTDvmVolumeQueryProp.
     448 *
     449 * @note Integer values can typically be queried in multiple sizes.  This is
     450 *       handled by the frontend code.  The format specific backends only
     451 *       have to handle the smallest allowed size.
     452 */
     453typedef enum RTDVMVOLPROP
     454{
     455    /** Customary invalid zero value. */
     456    RTDVMVOLPROP_INVALID = 0,
     457    /** unsigned[16,32,64]:     MBR first cylinder (0-based, CHS). */
     458    RTDVMVOLPROP_MBR_FIRST_CYLINDER,
     459    /** unsigned[8,16,32,64]:   MBR first head (0-based, CHS). */
     460    RTDVMVOLPROP_MBR_FIRST_HEAD,
     461    /** unsigned[8,16,32,64]:   MBR first sector (1-based, CHS). */
     462    RTDVMVOLPROP_MBR_FIRST_SECTOR,
     463    /** unsigned[16,32,64]:     MBR last cylinder (0-based, CHS). */
     464    RTDVMVOLPROP_MBR_LAST_CYLINDER,
     465    /** unsigned[8,16,32,64]:   MBR last head (0-based, CHS). */
     466    RTDVMVOLPROP_MBR_LAST_HEAD,
     467    /** unsigned[8,16,32,64]:   MBR last sector (1-based, CHS). */
     468    RTDVMVOLPROP_MBR_LAST_SECTOR,
     469    /** unsigned[8,16,32,64]:   MBR partition type. */
     470    RTDVMVOLPROP_MBR_TYPE,
     471    /** RTUUID:                 GPT volume type. */
     472    RTDVMVOLPROP_GPT_TYPE,
     473    /** RTUUID:                 GPT volume UUID. */
     474    RTDVMVOLPROP_GPT_UUID,
     475    /** End of valid values. */
     476    RTDVMVOLPROP_END,
     477    /** Make sure the type is 32-bit. */
     478    RTDVMVOLPROP_32BIT_HACK = 0x7fffffff
     479} RTDVMVOLPROP;
     480
     481/**
     482 * Query a generic volume property.
     483 *
     484 * This is an extensible interface for retriving mostly format specific
     485 * information, or information that's not commonly used.  (It's modelled after
     486 * RTLdrQueryPropEx.)
     487 *
     488 * @returns IPRT status code.
     489 * @retval  VERR_NOT_SUPPORTED if the property query isn't supported (either all
     490 *          or that specific property).  The caller  must  handle this result.
     491 * @retval  VERR_NOT_FOUND is currently not returned, but intended for cases
     492 *          where it wasn't present in the tables.
     493 * @retval  VERR_INVALID_FUNCTION if the @a enmProperty value is wrong.
     494 * @retval  VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct
     495 *          size in @a *pcbRet.
     496 * @retval  VERR_BUFFER_OVERFLOW if the property doesn't have a fixed size
     497 *          buffer and the buffer isn't big enough. Correct size in @a *pcbRet.
     498 * @retval  VERR_INVALID_HANDLE if the handle is invalid.
     499 * @param   hVol        Handle to the volume.
     500 * @param   enmProperty The property to query.
     501 * @param   pvBuf       Pointer to the input / output buffer.  In most cases
     502 *                      it's only used for returning data.
     503 * @param   cbBuf       The size of the buffer.
     504 * @param   pcbRet      Where to return the amount of data returned.  On
     505 *                      buffer size errors, this is set to the correct size.
     506 *                      Optional.
     507 * @sa      RTDvmVolumeGetPropU64
     508 */
     509RTDECL(int) RTDvmVolumeQueryProp(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, void *pvBuf, size_t cbBuf, size_t *pcbBuf);
     510
     511/**
     512 * Wrapper around RTDvmVolumeQueryProp for simplifying getting unimportant
     513 * integer properties.
     514 *
     515 * @returns The property value if supported and found, the default value if not.
     516 *          Errors other than VERR_NOT_SUPPORTED and VERR_NOT_FOUND are
     517 *          asserted.
     518 * @param   hVol        Handle to the volume.
     519 * @param   enmProperty The property to query.
     520 * @param   uDefault    The value to return on error.
     521 * @sa      RTDvmVolumeQueryProp
     522 */
     523RTDECL(uint64_t) RTDvmVolumeGetPropU64(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, uint64_t uDefault);
    366524
    367525/**
  • trunk/include/iprt/mangling.h

    r85875 r85877  
    833833# define RTDvmMapQueryFirstVolume                       RT_MANGLER(RTDvmMapQueryFirstVolume)
    834834# define RTDvmMapQueryNextVolume                        RT_MANGLER(RTDvmMapQueryNextVolume)
     835# define RTDvmMapQueryDiskUuid                          RT_MANGLER(RTDvmMapQueryDiskUuid)
    835836# define RTDvmVolumeRetain                              RT_MANGLER(RTDvmVolumeRetain)
    836837# define RTDvmVolumeRelease                             RT_MANGLER(RTDvmVolumeRelease)
     838# define RTDvmVolumeGetIndex                            RT_MANGLER(RTDvmVolumeGetIndex)
     839# define RTDvmVolumeGetPropU64                          RT_MANGLER(RTDvmVolumeGetPropU64)
    837840# define RTDvmVolumeGetSize                             RT_MANGLER(RTDvmVolumeGetSize)
    838841# define RTDvmVolumeQueryName                           RT_MANGLER(RTDvmVolumeQueryName)
     842# define RTDvmVolumeQueryProp                           RT_MANGLER(RTDvmVolumeQueryProp)
     843# define RTDvmVolumeQueryTableLocation                  RT_MANGLER(RTDvmVolumeQueryTableLocation)
    839844# define RTDvmVolumeGetType                             RT_MANGLER(RTDvmVolumeGetType)
    840845# define RTDvmVolumeGetFlags                            RT_MANGLER(RTDvmVolumeGetFlags)
  • trunk/src/VBox/Runtime/common/dvm/dvm.cpp

    r85126 r85877  
    146146
    147147/**
     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 */
     157DECLHIDDEN(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/**
    148184 * Creates a new volume.
    149185 *
     
    424460
    425461    return pThis->pDvmFmtOps->enmFormat;
     462}
     463
     464RTDECL(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;
    426475}
    427476
     
    670719}
    671720
     721RTDECL(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
     732RTDECL(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 */
     745static 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
     769RTDECL(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
     841RTDECL(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
    672851RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
    673852{
  • trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp

    r85124 r85877  
    5353 * A BSD disk label partition.
    5454 */
    55 #pragma pack(1)
    5655typedef struct BsdLabelPartition
    5756{
     
    6968    uint16_t             cFsCylPerGroup;
    7069} BsdLabelPartition;
    71 #pragma pack()
    7270AssertCompileSize(BsdLabelPartition, 16);
    7371/** Pointer to a BSD disklabel partition structure. */
     
    7775 * On disk BSD label structure.
    7876 */
    79 #pragma pack(1)
    8077typedef struct BsdLabel
    8178{
     
    139136    BsdLabelPartition    aPartitions[RTDVM_BSDLBL_MAX_PARTITIONS];
    140137} BsdLabel;
    141 #pragma pack()
    142138AssertCompileSize(BsdLabel, 148 + RTDVM_BSDLBL_MAX_PARTITIONS * 16);
    143139/** Pointer to a BSD disklabel structure. */
     
    285281    {
    286282        /* 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));
    288284        if (   RT_SUCCESS(rc)
    289285            && rtDvmFmtBsdLblDiskLabelDecode(&DiskLabel))
     
    305301
    306302        /* 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));
    308304        if (   RT_SUCCESS(rc)
    309305            && rtDvmFmtBsdLblDiskLabelDecode(&pThis->DiskLabel))
     
    340336    pThis->pDisk       = NULL;
    341337    pThis->cPartitions = 0;
    342     memset(&pThis->DiskLabel, 0, sizeof(BsdLabel));
     338    RT_ZERO(pThis->DiskLabel);
    343339    RTMemFree(pThis);
    344340}
     
    507503
    508504    return fIntersect;
     505}
     506
     507/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
     508static 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 */
     517static 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 */
     540static 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;
    509564}
    510565
     
    541596    /* pfnQueryRangeUse */
    542597    rtDvmFmtBsdLblQueryRangeUse,
     598    /* pfnQueryDiskUuid */
     599    NULL,
    543600    /* pfnGetValidVolumes */
    544601    rtDvmFmtBsdLblGetValidVolumes,
     
    563620    /* pfnVolumeIsRangeIntersecting */
    564621    rtDvmFmtBsdLblVolumeIsRangeIntersecting,
     622    /* pfnVolumeQueryTableLocation */
     623    rtDvmFmtBsdLblVolumeQueryTableLocation,
     624    /* pfnVolumeGetIndex */
     625    rtDvmFmtBsdLblVolumeGetIndex,
     626    /* pfnVolumeQueryProp */
     627    rtDvmFmtBsdLblVolumeQueryProp,
    565628    /* pfnVolumeRead */
    566629    rtDvmFmtBsdLblVolumeRead,
  • trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp

    r85124 r85877  
    252252    {
    253253        /* 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));
    255255        if (   RT_SUCCESS(rc)
    256256            && !strncmp(&Hdr.abSignature[0], RTDVM_GPT_SIGNATURE, RT_ELEMENTS(Hdr.abSignature))
     
    275275
    276276        /* 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));
    278278        if (RT_SUCCESS(rc))
    279279        {
     
    293293            if (pThis->HdrRev1.cbPartitionEntry == sizeof(GPTENTRY))
    294294            {
    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);
    296297                if (pThis->paGptEntries)
    297298                {
    298299                    rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(pThis->HdrRev1.u64LbaPartitionEntries, pDisk),
    299                                      pThis->paGptEntries, pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry);
     300                                       pThis->paGptEntries, cbAlignedGptEntries);
    300301                    if (RT_SUCCESS(rc))
    301302                    {
     
    314315                                pThis->cPartitions++;
    315316                            }
     317
     318                        if (RT_SUCCESS(rc))
     319                        {
     320                            *phVolMgrFmt = pThis;
     321                            return rc;
     322                        }
    316323                    }
    317 
    318                     if (RT_FAILURE(rc))
    319                         RTMemFree(pThis->paGptEntries);
     324                    RTMemFree(pThis->paGptEntries);
    320325                }
    321326                else
     
    324329            else
    325330                rc = VERR_NOT_SUPPORTED;
    326 
    327             if (RT_SUCCESS(rc))
    328                 *phVolMgrFmt = pThis;
    329             else
    330                 RTMemFree(pThis);
    331331        }
     332        RTMemFree(pThis);
    332333    }
    333334    else
     
    348349
    349350    pThis->pDisk = NULL;
    350     memset(&pThis->HdrRev1, 0, sizeof(pThis->HdrRev1));
     351    RT_ZERO(pThis->HdrRev1);
     352
    351353    RTMemFree(pThis->paGptEntries);
    352 
    353354    pThis->paGptEntries = NULL;
     355
    354356    RTMemFree(pThis);
    355357}
     
    368370        *pfUsed = false;
    369371
     372    return VINF_SUCCESS;
     373}
     374
     375/** @copydoc RTDVMFMTOPS::pfnQueryDiskUuid */
     376static DECLCALLBACK(int) rtDvmFmtGptQueryDiskUuid(RTDVMFMT hVolMgrFmt, PRTUUID pUuid)
     377{
     378    PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
     379
     380    *pUuid = pThis->HdrRev1.DiskUuid;
    370381    return VINF_SUCCESS;
    371382}
     
    519530    }
    520531    return false;
     532}
     533
     534/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
     535static 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 */
     547static 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 */
     571static 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;
    521607}
    522608
     
    553639    /* pfnQueryRangeUse */
    554640    rtDvmFmtGptQueryRangeUse,
     641    /* pfnQueryDiskUuid */
     642    rtDvmFmtGptQueryDiskUuid,
    555643    /* pfnGetValidVolumes */
    556644    rtDvmFmtGptGetValidVolumes,
     
    575663    /* pfnVolumeIsRangeIntersecting */
    576664    rtDvmFmtGptVolumeIsRangeIntersecting,
     665    /* pfnVolumeQueryTableLocation */
     666    rtDvmFmtGptVolumeQueryTableLocation,
     667    /* pfnVolumeGetIndex */
     668    rtDvmFmtGptVolumeGetIndex,
     669    /* pfnVolumeQueryProp */
     670    rtDvmFmtGptVolumeQueryProp,
    577671    /* pfnVolumeRead */
    578672    rtDvmFmtGptVolumeRead,
  • trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp

    r85124 r85877  
    3737#include <iprt/log.h>
    3838#include <iprt/string.h>
     39#include <iprt/uuid.h>
    3940#include "internal/dvm.h"
    4041
     
    5253/** Pointer to a MBR sector. */
    5354typedef struct RTDVMMBRSECTOR *PRTDVMMBRSECTOR;
     55
     56
     57/** The on-disk Cylinder/Head/Sector (CHS) info. */
     58typedef struct MBRCHSADDR
     59{
     60    uint8_t uHead;
     61    uint8_t uSector : 6;
     62    uint8_t uCylinderH : 2;
     63    uint8_t uCylinderL;
     64} MBRCHSADDR;
     65AssertCompileSize(MBRCHSADDR, 3);
     66
     67
     68/** A decoded cylinder/head/sector address. */
     69typedef struct RTDVMMBRCHSADDR
     70{
     71    uint16_t uCylinder;
     72    uint8_t  uHead;
     73    uint8_t  uSector;
     74} RTDVMMBRCHSADDR;
     75
    5476
    5577/**
     
    7496    /** Bad entry. */
    7597    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;
    76115} RTDVMMBRENTRY;
    77116/** Pointer to an MBR entry. */
     
    100139     *  fIsPrimary is @c true). UINT8_MAX if none. */
    101140    uint8_t             idxExtended;
     141#if ARCH_BITS == 64
     142    uint32_t            uAlignmentPadding;
     143#endif
    102144    /** The raw data. */
    103     uint8_t             abData[512];
     145    uint8_t             abData[RT_FLEXIBLE_ARRAY_NESTED];
    104146} RTDVMMBRSECTOR;
    105147
     
    114156     *  extended partition table entries. */
    115157    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;
    116161    /** The total number of partitions, not counting extended ones. */
    117162    uint32_t            cPartitions;
     
    181226};
    182227
     228
    183229static DECLCALLBACK(int) rtDvmFmtMbrProbe(PCRTDVMDISK pDisk, uint32_t *puScore)
    184230{
    185231    int rc = VINF_SUCCESS;
    186232    *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED;
    187     if (pDisk->cbDisk >= 512)
     233    if (pDisk->cbDisk > RT_MAX(512, pDisk->cbSector))
    188234    {
    189235        /* 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;
    196250    }
    197251
     
    229283
    230284
    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 */
     289DECLINLINE(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
     298static int rtDvmFmtMbrReadExtended(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pPrimaryEntry,
     299                                   uint8_t *pidxAll, uint8_t *pidxVisible, uint8_t *pidxLinux)
    232300{
    233301    uint64_t const  cbExt       = pPrimaryEntry->cbPart;
     
    270338         * Allocate a new sector entry and read the sector with the table.
    271339         */
    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]));
    273342        if (!pNext)
    274343            return VERR_NO_MEMORY;
     
    280349        pNext->idxExtended  = UINT8_MAX;
    281350
    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);
    283353        if (   RT_FAILURE(rc)
    284             || pNext->abData[510] != 0x55
    285             || pNext->abData[511] != 0xaa)
     354            || pabData[510] != 0x55
     355            || pabData[511] != 0xaa)
    286356        {
    287357            if (RT_FAILURE(rc))
     
    289359            else
    290360                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]));
     361                        offCurBegin, pabData[510], pabData[511]));
    292362            RTMemFree(pNext);
    293363            pCurEntry->fBad = true;
     
    304374         */
    305375        PRTDVMMBRENTRY pEntry     = &pNext->aEntries[0];
    306         uint8_t       *pbMbrEntry = &pNext->abData[446];
     376        uint8_t       *pbMbrEntry = &pabData[446];
    307377        for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16)
    308378        {
     379            pEntry->pSector  = pNext;
     380            pEntry->idxTable = (uint8_t)i;
     381            RTListInit(&pEntry->ListEntry);
     382
    309383            uint8_t const bType  = pbMbrEntry[4];
    310             pEntry->pSector = pNext;
    311             RTListInit(&pEntry->ListEntry);
    312384            if (bType != 0)
    313385            {
    314386                pEntry->bType    = bType;
    315387                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],
    317395                                                       pbMbrEntry[0x08 + 1],
    318396                                                       pbMbrEntry[0x08 + 2],
    319397                                                       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],
    322400                                                       pbMbrEntry[0x0c + 1],
    323401                                                       pbMbrEntry[0x0c + 2],
    324402                                                       pbMbrEntry[0x0c + 3]);
    325                 pEntry->cbPart  *= 512;
     403                pEntry->cbPart  *= pThis->cbSector;
    326404                if (!RTDVMMBR_IS_EXTENDED(bType))
    327405                {
    328                     pEntry->offPart += offCurBegin;
     406                    pEntry->offPart    += offCurBegin;
     407                    pEntry->idxVisible  = *pidxVisible;
     408                    *pidxVisible += 1;
     409                    pEntry->idxLinux    = *pidxLinux;
     410                    *pidxLinux += 1;
     411
    329412                    pThis->cPartitions++;
    330413                    RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry);
     
    368451{
    369452    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]));
    371455    if (pThis)
    372456    {
     
    381465        pThis->Primary.idxExtended   = UINT8_MAX;
    382466
     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
    383479        /*
    384480         * Read the primary MBR.
    385481         */
    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);
    387484        if (RT_SUCCESS(rc))
    388485        {
    389             Assert(pThis->Primary.abData[510] == 0x55 && pThis->Primary.abData[511] == 0xaa);
     486            Assert(pabData[510] == 0x55 && pabData[511] == 0xaa);
    390487
    391488            /*
     
    393490             */
    394491            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;
    396494            for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16)
    397495            {
    398                 pEntry->pSector = &pThis->Primary;
     496                pEntry->pSector  = &pThis->Primary;
     497                pEntry->idxTable = (uint8_t)i;
    399498                RTListInit(&pEntry->ListEntry);
    400499
    401                 uint8_t const bType = pbMbrEntry[4];
     500                uint8_t const bType  = pbMbrEntry[4];
    402501                if (bType != 0)
    403502                {
     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
    404510                    pEntry->offPart  = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08 + 0],
    405511                                                           pbMbrEntry[0x08 + 1],
    406512                                                           pbMbrEntry[0x08 + 2],
    407513                                                           pbMbrEntry[0x08 + 3]);
    408                     pEntry->offPart *= 512;
     514                    pEntry->offPart *= pThis->cbSector;
    409515                    pEntry->cbPart   = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c + 0],
    410516                                                           pbMbrEntry[0x0c + 1],
    411517                                                           pbMbrEntry[0x0c + 2],
    412518                                                           pbMbrEntry[0x0c + 3]);
    413                     pEntry->cbPart  *= 512;
    414                     pEntry->bType    = bType;
    415                     pEntry->fFlags   = pbMbrEntry[0];
     519                    pEntry->cbPart  *= pThis->cbSector;
    416520                    if (!RTDVMMBR_IS_EXTENDED(bType))
    417521                    {
     522                        pEntry->idxVisible = idxVisible++;
     523                        pEntry->idxLinux   = (uint8_t)(i + 1);
    418524                        pThis->cPartitions++;
    419525                        RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry);
     
    439545             */
    440546            if (pThis->Primary.cExtended > 0)
     547            {
     548                uint8_t idxAll   = 5;
     549                uint8_t idxLinux = 5;
    441550                for (unsigned i = 0; i < 4; i++)
    442551                    if (RTDVMMBR_IS_EXTENDED(pThis->Primary.aEntries[i].bType))
     
    444553                        if (pThis->Primary.idxExtended == UINT8_MAX)
    445554                            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);
    447556                        if (RT_FAILURE(rc))
    448557                            break;
    449558                    }
     559            }
    450560            if (RT_SUCCESS(rc))
    451561            {
     
    453563                return rc;
    454564            }
    455 
    456565        }
     566        rtDvmFmtMbrDestroy(pThis);
    457567    }
    458568    else
     
    465575{
    466576    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]));
    468579    if (pThis)
    469580    {
     
    479590
    480591        /* 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);
    484597        if (RT_SUCCESS(rc))
    485598        {
     
    544657}
    545658
     659/** @copydoc RTDVMFMTOPS::pfnQueryDiskUuid */
     660static 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
    546676static DECLCALLBACK(uint32_t) rtDvmFmtMbrGetValidVolumes(RTDVMFMT hVolMgrFmt)
    547677{
     
    668798    }
    669799    return false;
     800}
     801
     802/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
     803static 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 */
     812static 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 */
     836static 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;
    670894}
    671895
     
    702926    /* pfnQueryRangeUse */
    703927    rtDvmFmtMbrQueryRangeUse,
     928    /* pfnQueryDiskUuid */
     929    rtDvmFmtMbrQueryDiskUuid,
    704930    /* pfnGetValidVolumes */
    705931    rtDvmFmtMbrGetValidVolumes,
     
    724950    /* pfnVOlumeIsRangeIntersecting */
    725951    rtDvmFmtMbrVolumeIsRangeIntersecting,
     952    /* pfnVolumeQueryTableLocation */
     953    rtDvmFmtMbrVolumeQueryTableLocation,
     954    /* pfnVolumeGetIndex */
     955    rtDvmFmtMbrVolumeGetIndex,
     956    /* pfnVolumeQueryProp */
     957    rtDvmFmtMbrVolumeQueryProp,
    726958    /* pfnVolumeRead */
    727959    rtDvmFmtMbrVolumeRead,
  • trunk/src/VBox/Runtime/include/internal/dvm.h

    r85124 r85877  
    138138
    139139    /**
     140     * Optional: Query the uuid of the current disk if applicable.
     141     *
     142     * @returns IPRT status code.
     143     * @retval  VERR_NOT_SUPPORTED if the partition scheme doesn't do UUIDs.
     144     * @param   hVolMgrFmt      The format specific volume manager handle.
     145     * @param   pUuid           Where to return the UUID.
     146     */
     147    DECLCALLBACKMEMBER(int, pfnQueryDiskUuid,(RTDVMFMT hVolMgrFmt, PRTUUID pUuid));
     148
     149    /**
    140150     * Gets the number of valid volumes in the map.
    141151     *
     
    246256
    247257    /**
     258     * Queries the range of the partition table the volume belongs to on the underlying medium.
     259     *
     260     * @returns IPRT status code.
     261     * @param   hVolFmt         The format specific volume handle.
     262     * @param   poffTable       Where to return the byte offset on the underlying
     263     *                          media of the (partition/volume/whatever) table.
     264     * @param   pcbTable        Where to return the table size in bytes.  This
     265     *                          typically includes alignment padding.
     266     * @sa RTDvmVolumeQueryTableLocation
     267     */
     268    DECLCALLBACKMEMBER(int, pfnVolumeQueryTableLocation,(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffStart, uint64_t *poffLast));
     269
     270    /**
     271     * Gets the tiven index for the specified volume.
     272     *
     273     * @returns The requested index. UINT32_MAX on failure.
     274     * @param   hVolFmt         The format specific volume handle.
     275     * @param   enmIndex        The index to get.
     276     * @sa RTDvmVolumeGetIndex
     277     */
     278    DECLCALLBACKMEMBER(uint32_t, pfnVolumeGetIndex,(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex));
     279
     280    /**
     281     * Query a generic volume property.
     282     *
     283     * This is an extensible interface for retriving mostly format specific
     284     * information, or information that's not commonly used.  (It's modelled after
     285     * RTLdrQueryPropEx.)
     286     *
     287     * @returns IPRT status code.
     288     * @retval  VERR_NOT_SUPPORTED if the property query isn't supported (either all
     289     *          or that specific property).  The caller  must  handle this result.
     290     * @retval  VERR_NOT_FOUND is currently not returned, but intended for cases
     291     *          where it wasn't present in the tables.
     292     * @retval  VERR_INVALID_FUNCTION if the @a enmProperty value is wrong.
     293     * @retval  VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct
     294     *          size in @a *pcbRet.
     295     * @retval  VERR_BUFFER_OVERFLOW if the property doesn't have a fixed size
     296     *          buffer and the buffer isn't big enough. Correct size in @a *pcbRet.
     297     * @retval  VERR_INVALID_HANDLE if the handle is invalid.
     298     *
     299     * @param   hVolFmt     Handle to the volume.
     300     * @param   enmProperty The property to query.
     301     * @param   pvBuf       Pointer to the input / output buffer.  In most cases
     302     *                      it's only used for returning data.
     303     * @param   cbBuf       The size of the buffer.  This is validated by the common
     304     *                      code for all fixed typed & sized properties.  The
     305     *                      interger properties may have several supported sizes, in
     306     *                      which case the user value is passed along as-is but it
     307     *                      is okay to return a smaller amount of data.  The common
     308     *                      code will make upcast the data.
     309     * @param   pcbRet      Where to return the amount of data returned.  This must
     310     *                      be set even for fixed type/sized data.
     311     * @sa RTDvmVolumeQueryProp, RTDvmVolumeGetPropU64
     312     */
     313    DECLCALLBACKMEMBER(int, pfnVolumeQueryProp,(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
     314                                                void *pvBuf, size_t cbBuf, size_t *pcbBuf));
     315
     316    /**
    248317     * Read data from the given volume.
    249318     *
     
    300369 * @param   pvBuf    Destination buffer.
    301370 * @param   cbRead   How much to read.
     371 * @sa      rtDvmDiskReadUnaligned
    302372 */
    303373DECLINLINE(int) rtDvmDiskRead(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead)
     
    308378    AssertReturn(off + cbRead <= pDisk->cbDisk, VERR_INVALID_PARAMETER);
    309379
     380    /* Use RTVfsFileReadAt if these triggers: */
     381    Assert(!(cbRead % pDisk->cbSector));
     382    Assert(!(off    % pDisk->cbSector));
     383
    310384    return RTVfsFileReadAt(pDisk->hVfsFile, off, pvBuf, cbRead, NULL /*pcbRead*/);
    311385}
     386
     387DECLHIDDEN(int) rtDvmDiskReadUnaligned(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead);
    312388
    313389/**
     
    327403    AssertReturn(off + cbWrite <= pDisk->cbDisk, VERR_INVALID_PARAMETER);
    328404
     405    /* Write RTVfsFileReadAt if these triggers: */
     406    Assert(!(cbWrite % pDisk->cbSector));
     407    Assert(!(off     % pDisk->cbSector));
     408
    329409    return RTVfsFileWriteAt(pDisk->hVfsFile, off, pvBuf, cbWrite, NULL /*pcbWritten*/);
    330410}
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