Index: /trunk/include/iprt/dvm.h
===================================================================
--- /trunk/include/iprt/dvm.h	(revision 85876)
+++ /trunk/include/iprt/dvm.h	(revision 85877)
@@ -241,4 +241,21 @@
 
 /**
+ * Gets the UUID of the disk if applicable.
+ *
+ * Disks using the MBR format may return the 32-bit disk identity in the
+ * u32TimeLow field and set the rest to zero.
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if the partition scheme doesn't do UUIDs.
+ * @retval  VINF_NOT_SUPPORTED if non-UUID disk ID is returned.
+ * @param   hVolMgr     The volume manager handle.
+ * @param   pUuid       Where to return the UUID.
+ *
+ * @todo It's quite possible this should be turned into a map-level edition of
+ *       RTDvmVolumeQueryProp...
+ */
+RTDECL(int) RTDvmMapQueryDiskUuid(RTDVM hVolMgr, PRTUUID pUuid);
+
+/**
  * Gets the number of valid partitions in the map.
  *
@@ -355,5 +372,5 @@
 
 /**
- * Queries the range of the given volume on the underyling medium.
+ * Queries the range of the given volume on the underlying medium.
  *
  * @returns IPRT status code.
@@ -361,7 +378,148 @@
  * @param   hVol            The volume handle.
  * @param   poffStart       Where to store the start offset in bytes on the underlying medium.
- * @param   poffEnd         Where to store the end offset in bytes on the underlying medium (inclusive).
- */
-RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffEnd);
+ * @param   poffLast        Where to store the last offset in bytes on the underlying medium (inclusive).
+ */
+RTDECL(int) RTDvmVolumeQueryRange(RTDVMVOLUME hVol, uint64_t *poffStart, uint64_t *poffLast);
+
+/**
+ * Returns the partition/whatever table location of the volume.
+ *
+ * For volume format with a single table, like GPT and BSD-labels, it will
+ * return the location of that table.  Though for GPT, the fake MBR will not be
+ * included.
+ *
+ * For logical (extended) MBR-style volumes, this will return the location of
+ * the extended partition table.  For primary volumes the MBR location is
+ * returned.  The special MBR case is why this operation is done on the volume
+ * rather than the volume manager.
+ *
+ * Using RTDvmVolumeGetIndex with RTDVMVOLIDX_IN_PART_TABLE should get you
+ * the index in the table returned by this function.
+ *
+ * @returns IPRT status code.
+ * @param   hVol            The volume handle.
+ * @param   poffTable       Where to return the byte offset on the underlying
+ *                          media of the (partition/volume/whatever) table.
+ * @param   pcbTable        Where to return the table size in bytes.  (This does
+ *                          not include any alignment padding or such, just
+ *                          padding up to sector/block size.)
+ */
+RTDECL(int) RTDvmVolumeQueryTableLocation(RTDVMVOLUME hVol, uint64_t *poffTable, uint64_t *pcbTable);
+
+/**
+ * RTDvmVolumeGetIndex indexes.
+ */
+typedef enum RTDVMVOLIDX
+{
+    /** Invalid zero value. */
+    RTDVMVOLIDX_INVALID = 0,
+    /** Only consider user visible ones, i.e. don't count MBR extended partition
+     *  entries and such like. */
+    RTDVMVOLIDX_USER_VISIBLE,
+    /** Index when all volumes, user visible, hidden, special, whatever ones are
+     * included.
+     *
+     * For MBR this is 1-based index where all primary entires are included whether
+     * in use or not.  Only non-empty entries in extended tables are counted, though
+     * the forward link is included. */
+    RTDVMVOLIDX_ALL,
+    /** The raw index within the partition/volume/whatever table.  This have a kind
+     *  of special meaning to MBR, where there are multiple tables. */
+    RTDVMVOLIDX_IN_TABLE,
+    /** Follows the linux /dev/sdaX convention as closely as absolutely possible. */
+    RTDVMVOLIDX_LINUX,
+    /** End of valid indexes. */
+    RTDVMVOLIDX_END,
+    /** Make sure the type is 32-bit.   */
+    RTDVMVOLIDX_32BIT_HACK = 0x7fffffff
+} RTDVMVOLIDX;
+
+/**
+ * Gets the tiven index for the specified volume.
+ *
+ * @returns The requested index, UINT32_MAX on failure.
+ * @param   hVol            The volume handle.
+ * @param   enmIndex        Which kind of index to get for the volume.
+ */
+RTDECL(uint32_t) RTDvmVolumeGetIndex(RTDVMVOLUME hVol, RTDVMVOLIDX enmIndex);
+
+/**
+ * Volume properties queriable via RTDvmVolumeQueryProp.
+ *
+ * @note Integer values can typically be queried in multiple sizes.  This is
+ *       handled by the frontend code.  The format specific backends only
+ *       have to handle the smallest allowed size.
+ */
+typedef enum RTDVMVOLPROP
+{
+    /** Customary invalid zero value. */
+    RTDVMVOLPROP_INVALID = 0,
+    /** unsigned[16,32,64]:     MBR first cylinder (0-based, CHS). */
+    RTDVMVOLPROP_MBR_FIRST_CYLINDER,
+    /** unsigned[8,16,32,64]:   MBR first head (0-based, CHS). */
+    RTDVMVOLPROP_MBR_FIRST_HEAD,
+    /** unsigned[8,16,32,64]:   MBR first sector (1-based, CHS). */
+    RTDVMVOLPROP_MBR_FIRST_SECTOR,
+    /** unsigned[16,32,64]:     MBR last cylinder (0-based, CHS). */
+    RTDVMVOLPROP_MBR_LAST_CYLINDER,
+    /** unsigned[8,16,32,64]:   MBR last head (0-based, CHS). */
+    RTDVMVOLPROP_MBR_LAST_HEAD,
+    /** unsigned[8,16,32,64]:   MBR last sector (1-based, CHS). */
+    RTDVMVOLPROP_MBR_LAST_SECTOR,
+    /** unsigned[8,16,32,64]:   MBR partition type. */
+    RTDVMVOLPROP_MBR_TYPE,
+    /** RTUUID:                 GPT volume type. */
+    RTDVMVOLPROP_GPT_TYPE,
+    /** RTUUID:                 GPT volume UUID. */
+    RTDVMVOLPROP_GPT_UUID,
+    /** End of valid values. */
+    RTDVMVOLPROP_END,
+    /** Make sure the type is 32-bit. */
+    RTDVMVOLPROP_32BIT_HACK = 0x7fffffff
+} RTDVMVOLPROP;
+
+/**
+ * Query a generic volume property.
+ *
+ * This is an extensible interface for retriving mostly format specific
+ * information, or information that's not commonly used.  (It's modelled after
+ * RTLdrQueryPropEx.)
+ *
+ * @returns IPRT status code.
+ * @retval  VERR_NOT_SUPPORTED if the property query isn't supported (either all
+ *          or that specific property).  The caller  must  handle this result.
+ * @retval  VERR_NOT_FOUND is currently not returned, but intended for cases
+ *          where it wasn't present in the tables.
+ * @retval  VERR_INVALID_FUNCTION if the @a enmProperty value is wrong.
+ * @retval  VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct
+ *          size in @a *pcbRet.
+ * @retval  VERR_BUFFER_OVERFLOW if the property doesn't have a fixed size
+ *          buffer and the buffer isn't big enough. Correct size in @a *pcbRet.
+ * @retval  VERR_INVALID_HANDLE if the handle is invalid.
+ * @param   hVol        Handle to the volume.
+ * @param   enmProperty The property to query.
+ * @param   pvBuf       Pointer to the input / output buffer.  In most cases
+ *                      it's only used for returning data.
+ * @param   cbBuf       The size of the buffer.
+ * @param   pcbRet      Where to return the amount of data returned.  On
+ *                      buffer size errors, this is set to the correct size.
+ *                      Optional.
+ * @sa      RTDvmVolumeGetPropU64
+ */
+RTDECL(int) RTDvmVolumeQueryProp(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, void *pvBuf, size_t cbBuf, size_t *pcbBuf);
+
+/**
+ * Wrapper around RTDvmVolumeQueryProp for simplifying getting unimportant
+ * integer properties.
+ *
+ * @returns The property value if supported and found, the default value if not.
+ *          Errors other than VERR_NOT_SUPPORTED and VERR_NOT_FOUND are
+ *          asserted.
+ * @param   hVol        Handle to the volume.
+ * @param   enmProperty The property to query.
+ * @param   uDefault    The value to return on error.
+ * @sa      RTDvmVolumeQueryProp
+ */
+RTDECL(uint64_t) RTDvmVolumeGetPropU64(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, uint64_t uDefault);
 
 /**
Index: /trunk/include/iprt/mangling.h
===================================================================
--- /trunk/include/iprt/mangling.h	(revision 85876)
+++ /trunk/include/iprt/mangling.h	(revision 85877)
@@ -833,8 +833,13 @@
 # define RTDvmMapQueryFirstVolume                       RT_MANGLER(RTDvmMapQueryFirstVolume)
 # define RTDvmMapQueryNextVolume                        RT_MANGLER(RTDvmMapQueryNextVolume)
+# define RTDvmMapQueryDiskUuid                          RT_MANGLER(RTDvmMapQueryDiskUuid)
 # define RTDvmVolumeRetain                              RT_MANGLER(RTDvmVolumeRetain)
 # define RTDvmVolumeRelease                             RT_MANGLER(RTDvmVolumeRelease)
+# define RTDvmVolumeGetIndex                            RT_MANGLER(RTDvmVolumeGetIndex)
+# define RTDvmVolumeGetPropU64                          RT_MANGLER(RTDvmVolumeGetPropU64)
 # define RTDvmVolumeGetSize                             RT_MANGLER(RTDvmVolumeGetSize)
 # define RTDvmVolumeQueryName                           RT_MANGLER(RTDvmVolumeQueryName)
+# define RTDvmVolumeQueryProp                           RT_MANGLER(RTDvmVolumeQueryProp)
+# define RTDvmVolumeQueryTableLocation                  RT_MANGLER(RTDvmVolumeQueryTableLocation)
 # define RTDvmVolumeGetType                             RT_MANGLER(RTDvmVolumeGetType)
 # define RTDvmVolumeGetFlags                            RT_MANGLER(RTDvmVolumeGetFlags)
Index: /trunk/src/VBox/Runtime/common/dvm/dvm.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvm.cpp	(revision 85876)
+++ /trunk/src/VBox/Runtime/common/dvm/dvm.cpp	(revision 85877)
@@ -146,4 +146,40 @@
 
 /**
+ * Read from the disk at the given offset, neither the offset nor the size is
+ * necessary sector aligned.
+ *
+ * @returns IPRT status code.
+ * @param   pDisk    The disk descriptor to read from.
+ * @param   off      Start offset.
+ * @param   pvBuf    Destination buffer.
+ * @param   cbRead   How much to read.
+ */
+DECLHIDDEN(int) rtDvmDiskReadUnaligned(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead)
+{
+    size_t const cbSector = (size_t)pDisk->cbSector;
+    size_t const offDelta = off    % cbSector;
+    size_t const cbDelta  = cbRead % cbSector;
+    if (!cbDelta && !offDelta)
+        return rtDvmDiskRead(pDisk, off, pvBuf, cbRead);
+
+    int rc;
+    size_t cbExtra = offDelta + (cbDelta ? cbSector - cbDelta: 0);
+    uint8_t *pbTmpBuf = (uint8_t *)RTMemTmpAlloc(cbRead + cbExtra);
+    if (pbTmpBuf)
+    {
+        rc = rtDvmDiskRead(pDisk, off - offDelta, pbTmpBuf, cbRead + cbExtra);
+        if (RT_SUCCESS(rc))
+            memcpy(pvBuf, &pbTmpBuf[offDelta], cbRead);
+        else
+            RT_BZERO(pvBuf, cbRead);
+        RTMemTmpFree(pbTmpBuf);
+    }
+    else
+        rc = VERR_NO_TMP_MEMORY;
+    return rc;
+}
+
+
+/**
  * Creates a new volume.
  *
@@ -424,4 +460,17 @@
 
     return pThis->pDvmFmtOps->enmFormat;
+}
+
+RTDECL(int) RTDvmMapQueryDiskUuid(RTDVM hVolMgr, PRTUUID pUuid)
+{
+    PRTDVMINTERNAL pThis = hVolMgr;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTDVM_MAGIC, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->hVolMgrFmt != NIL_RTDVMFMT, VERR_INVALID_HANDLE);
+    AssertPtrReturn(pUuid, VERR_INVALID_POINTER);
+
+    if (pThis->pDvmFmtOps->pfnQueryDiskUuid)
+        return pThis->pDvmFmtOps->pfnQueryDiskUuid(pThis->hVolMgrFmt, pUuid);
+    return VERR_NOT_SUPPORTED;
 }
 
@@ -670,4 +719,134 @@
 }
 
+RTDECL(int) RTDvmVolumeQueryTableLocation(RTDVMVOLUME hVol, uint64_t *poffTable, uint64_t *pcbTable)
+{
+    PRTDVMVOLUMEINTERNAL pThis = hVol;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
+    AssertPtrReturn(poffTable, VERR_INVALID_POINTER);
+    AssertPtrReturn(pcbTable, VERR_INVALID_POINTER);
+
+    return pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryTableLocation(pThis->hVolFmt, poffTable, pcbTable);
+}
+
+RTDECL(uint32_t) RTDvmVolumeGetIndex(RTDVMVOLUME hVol, RTDVMVOLIDX enmIndex)
+{
+    PRTDVMVOLUMEINTERNAL pThis = hVol;
+    AssertPtrReturn(pThis, UINT32_MAX);
+    AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, UINT32_MAX);
+    AssertReturn(enmIndex > RTDVMVOLIDX_INVALID && enmIndex < RTDVMVOLIDX_END, UINT32_MAX);
+
+    return pThis->pVolMgr->pDvmFmtOps->pfnVolumeGetIndex(pThis->hVolFmt, enmIndex);
+}
+
+/**
+ * Helper for RTDvmVolumeQueryProp.
+ */
+static void rtDvmReturnInteger(void *pvDst, size_t cbDst, PRTUINT64U pSrc, size_t cbSrc)
+{
+    /* Read the source: */
+    uint64_t uSrc;
+    switch (cbSrc)
+    {
+        case sizeof(uint8_t):  uSrc = (uint8_t)pSrc->Words.w0; break;
+        case sizeof(uint16_t): uSrc = pSrc->Words.w0; break;
+        case sizeof(uint32_t): uSrc = pSrc->s.Lo; break;
+        default: AssertFailed(); RT_FALL_THROUGH();
+        case sizeof(uint64_t): uSrc = pSrc->u; break;
+    }
+
+    /* Write the destination: */
+    switch (cbDst)
+    {
+        default: AssertFailed(); RT_FALL_THROUGH();
+        case sizeof(uint8_t):  *(uint8_t  *)pvDst = (uint8_t)uSrc; break;
+        case sizeof(uint16_t): *(uint16_t *)pvDst = (uint16_t)uSrc; break;
+        case sizeof(uint32_t): *(uint32_t *)pvDst = (uint32_t)uSrc; break;
+        case sizeof(uint64_t): *(uint64_t *)pvDst = uSrc; break;
+    }
+}
+
+RTDECL(int) RTDvmVolumeQueryProp(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, void *pvBuf, size_t cbBuf, size_t *pcbBuf)
+{
+    PRTDVMVOLUMEINTERNAL pThis = hVol;
+    AssertPtrReturn(pThis, VERR_INVALID_HANDLE);
+    AssertReturn(pThis->u32Magic == RTDVMVOLUME_MAGIC, VERR_INVALID_HANDLE);
+    size_t cbBufFallback = 0;
+    if (pcbBuf == NULL)
+        pcbBuf = &cbBufFallback;
+    AssertReturnStmt(enmProperty > RTDVMVOLPROP_INVALID && enmProperty < RTDVMVOLPROP_END, *pcbBuf = 0, VERR_INVALID_FUNCTION);
+
+    switch (enmProperty)
+    {
+        /* 8, 16, 32 or 64 bit sized integers: */
+        case RTDVMVOLPROP_MBR_FIRST_HEAD:
+        case RTDVMVOLPROP_MBR_FIRST_SECTOR:
+        case RTDVMVOLPROP_MBR_LAST_HEAD:
+        case RTDVMVOLPROP_MBR_LAST_SECTOR:
+        case RTDVMVOLPROP_MBR_TYPE:
+        {
+            *pcbBuf = sizeof(uint8_t);
+            AssertReturn(   cbBuf == sizeof(uint8_t)
+                         || cbBuf == sizeof(uint16_t)
+                         || cbBuf == sizeof(uint32_t)
+                         || cbBuf == sizeof(uint64_t), VERR_INVALID_PARAMETER);
+            AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+
+            RTUINT64U Union64 = {0};
+            int rc = pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryProp(pThis->hVolFmt, enmProperty, &Union64, cbBuf, pcbBuf);
+            rtDvmReturnInteger(pvBuf, cbBuf, &Union64, *pcbBuf);
+            return rc;
+        }
+
+        /* 16, 32 or 64 bit sized integers: */
+        case RTDVMVOLPROP_MBR_FIRST_CYLINDER:
+        case RTDVMVOLPROP_MBR_LAST_CYLINDER:
+        {
+            *pcbBuf = sizeof(uint16_t);
+            AssertReturn(   cbBuf == sizeof(uint16_t)
+                         || cbBuf == sizeof(uint32_t)
+                         || cbBuf == sizeof(uint64_t), VERR_INVALID_PARAMETER);
+            AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+
+            RTUINT64U Union64 = {0};
+            int rc = pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryProp(pThis->hVolFmt, enmProperty, &Union64, cbBuf, pcbBuf);
+            rtDvmReturnInteger(pvBuf, cbBuf, &Union64, *pcbBuf);
+            return rc;
+        }
+
+        /* RTUUIDs: */
+        case RTDVMVOLPROP_GPT_TYPE:
+        case RTDVMVOLPROP_GPT_UUID:
+        {
+            *pcbBuf = sizeof(RTUUID);
+            AssertReturn(cbBuf == sizeof(RTUUID), VERR_INVALID_PARAMETER);
+            AssertPtrReturn(pvBuf, VERR_INVALID_POINTER);
+
+            RTUUID Uuid = RTUUID_INITIALIZE_NULL;
+            int rc = pThis->pVolMgr->pDvmFmtOps->pfnVolumeQueryProp(pThis->hVolFmt, enmProperty, &Uuid, sizeof(RTUUID), pcbBuf);
+            memcpy(pvBuf, &Uuid, sizeof(Uuid));
+            return rc;
+        }
+
+        case RTDVMVOLPROP_INVALID:
+        case RTDVMVOLPROP_END:
+        case RTDVMVOLPROP_32BIT_HACK:
+            break;
+        /* No default case! */
+    }
+    AssertFailed();
+    return VERR_NOT_SUPPORTED;
+}
+
+RTDECL(uint64_t) RTDvmVolumeGetPropU64(RTDVMVOLUME hVol, RTDVMVOLPROP enmProperty, uint64_t uDefault)
+{
+    uint64_t uValue = uDefault;
+    int rc = RTDvmVolumeQueryProp(hVol, enmProperty, &uValue, sizeof(uValue), NULL);
+    if (RT_SUCCESS(rc))
+        return uValue;
+    AssertMsg(rc == VERR_NOT_SUPPORTED || rc == VERR_NOT_FOUND, ("%Rrc enmProperty=%d\n", rc, enmProperty));
+    return uDefault;
+}
+
 RTDECL(int) RTDvmVolumeRead(RTDVMVOLUME hVol, uint64_t off, void *pvBuf, size_t cbRead)
 {
Index: /trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp	(revision 85876)
+++ /trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp	(revision 85877)
@@ -53,5 +53,4 @@
  * A BSD disk label partition.
  */
-#pragma pack(1)
 typedef struct BsdLabelPartition
 {
@@ -69,5 +68,4 @@
     uint16_t             cFsCylPerGroup;
 } BsdLabelPartition;
-#pragma pack()
 AssertCompileSize(BsdLabelPartition, 16);
 /** Pointer to a BSD disklabel partition structure. */
@@ -77,5 +75,4 @@
  * On disk BSD label structure.
  */
-#pragma pack(1)
 typedef struct BsdLabel
 {
@@ -139,5 +136,4 @@
     BsdLabelPartition    aPartitions[RTDVM_BSDLBL_MAX_PARTITIONS];
 } BsdLabel;
-#pragma pack()
 AssertCompileSize(BsdLabel, 148 + RTDVM_BSDLBL_MAX_PARTITIONS * 16);
 /** Pointer to a BSD disklabel structure. */
@@ -285,5 +281,5 @@
     {
         /* Read from the disk and check for the disk label structure. */
-        rc = rtDvmDiskRead(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &DiskLabel, sizeof(BsdLabel));
+        rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &DiskLabel, sizeof(BsdLabel));
         if (   RT_SUCCESS(rc)
             && rtDvmFmtBsdLblDiskLabelDecode(&DiskLabel))
@@ -305,5 +301,5 @@
 
         /* Read from the disk and check for the disk label structure. */
-        rc = rtDvmDiskRead(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &pThis->DiskLabel, sizeof(BsdLabel));
+        rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &pThis->DiskLabel, sizeof(BsdLabel));
         if (   RT_SUCCESS(rc)
             && rtDvmFmtBsdLblDiskLabelDecode(&pThis->DiskLabel))
@@ -340,5 +336,5 @@
     pThis->pDisk       = NULL;
     pThis->cPartitions = 0;
-    memset(&pThis->DiskLabel, 0, sizeof(BsdLabel));
+    RT_ZERO(pThis->DiskLabel);
     RTMemFree(pThis);
 }
@@ -507,4 +503,63 @@
 
     return fIntersect;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
+static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    *poffTable = RTDVM_BSDLBL_LBA2BYTE(1, pVol->pVolMgr->pDisk);
+    *pcbTable  = RT_ALIGN_Z(sizeof(BsdLabel), pVol->pVolMgr->pDisk->cbSector);
+    return VINF_SUCCESS;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */
+static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    switch (enmIndex)
+    {
+        case RTDVMVOLIDX_USER_VISIBLE:
+        case RTDVMVOLIDX_ALL:
+        case RTDVMVOLIDX_LINUX:
+            return pVol->idxEntry + 1;
+        case RTDVMVOLIDX_IN_TABLE:
+            return pVol->idxEntry;
+
+        case RTDVMVOLIDX_INVALID:
+        case RTDVMVOLIDX_END:
+        case RTDVMVOLIDX_32BIT_HACK:
+            break;
+        /* no default! */
+    }
+    AssertFailed();
+    return UINT32_MAX;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */
+static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
+                                                       void *pvBuf, size_t cbBuf, size_t *pcbBuf)
+{
+    switch (enmProperty)
+    {
+        case RTDVMVOLPROP_MBR_FIRST_CYLINDER:
+        case RTDVMVOLPROP_MBR_FIRST_HEAD:
+        case RTDVMVOLPROP_MBR_FIRST_SECTOR:
+        case RTDVMVOLPROP_MBR_LAST_CYLINDER:
+        case RTDVMVOLPROP_MBR_LAST_HEAD:
+        case RTDVMVOLPROP_MBR_LAST_SECTOR:
+        case RTDVMVOLPROP_MBR_TYPE:
+        case RTDVMVOLPROP_GPT_TYPE:
+        case RTDVMVOLPROP_GPT_UUID:
+            return VERR_NOT_SUPPORTED;
+
+        case RTDVMVOLPROP_INVALID:
+        case RTDVMVOLPROP_END:
+        case RTDVMVOLPROP_32BIT_HACK:
+            break;
+        /* no default! */
+    }
+    RT_NOREF(hVolFmt, pvBuf, cbBuf, pcbBuf);
+    return VERR_NOT_SUPPORTED;
 }
 
@@ -541,4 +596,6 @@
     /* pfnQueryRangeUse */
     rtDvmFmtBsdLblQueryRangeUse,
+    /* pfnQueryDiskUuid */
+    NULL,
     /* pfnGetValidVolumes */
     rtDvmFmtBsdLblGetValidVolumes,
@@ -563,4 +620,10 @@
     /* pfnVolumeIsRangeIntersecting */
     rtDvmFmtBsdLblVolumeIsRangeIntersecting,
+    /* pfnVolumeQueryTableLocation */
+    rtDvmFmtBsdLblVolumeQueryTableLocation,
+    /* pfnVolumeGetIndex */
+    rtDvmFmtBsdLblVolumeGetIndex,
+    /* pfnVolumeQueryProp */
+    rtDvmFmtBsdLblVolumeQueryProp,
     /* pfnVolumeRead */
     rtDvmFmtBsdLblVolumeRead,
Index: /trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp	(revision 85876)
+++ /trunk/src/VBox/Runtime/common/dvm/dvmgpt.cpp	(revision 85877)
@@ -252,5 +252,5 @@
     {
         /* Read from the disk and check for the signature. */
-        rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &Hdr, sizeof(GPTHDR));
+        rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &Hdr, sizeof(GPTHDR));
         if (   RT_SUCCESS(rc)
             && !strncmp(&Hdr.abSignature[0], RTDVM_GPT_SIGNATURE, RT_ELEMENTS(Hdr.abSignature))
@@ -275,5 +275,5 @@
 
         /* Read the complete GPT header and convert to host endianess. */
-        rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &pThis->HdrRev1, sizeof(pThis->HdrRev1));
+        rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_GPT_LBA2BYTE(1, pDisk), &pThis->HdrRev1, sizeof(pThis->HdrRev1));
         if (RT_SUCCESS(rc))
         {
@@ -293,9 +293,10 @@
             if (pThis->HdrRev1.cbPartitionEntry == sizeof(GPTENTRY))
             {
-                pThis->paGptEntries = (PGPTENTRY)RTMemAllocZ(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry);
+                size_t cbAlignedGptEntries = RT_ALIGN_Z(pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry, pDisk->cbSector);
+                pThis->paGptEntries = (PGPTENTRY)RTMemAllocZ(cbAlignedGptEntries);
                 if (pThis->paGptEntries)
                 {
                     rc = rtDvmDiskRead(pDisk, RTDVM_GPT_LBA2BYTE(pThis->HdrRev1.u64LbaPartitionEntries, pDisk),
-                                     pThis->paGptEntries, pThis->HdrRev1.cPartitionEntries * pThis->HdrRev1.cbPartitionEntry);
+                                       pThis->paGptEntries, cbAlignedGptEntries);
                     if (RT_SUCCESS(rc))
                     {
@@ -314,8 +315,12 @@
                                 pThis->cPartitions++;
                             }
+
+                        if (RT_SUCCESS(rc))
+                        {
+                            *phVolMgrFmt = pThis;
+                            return rc;
+                        }
                     }
-
-                    if (RT_FAILURE(rc))
-                        RTMemFree(pThis->paGptEntries);
+                    RTMemFree(pThis->paGptEntries);
                 }
                 else
@@ -324,10 +329,6 @@
             else
                 rc = VERR_NOT_SUPPORTED;
-
-            if (RT_SUCCESS(rc))
-                *phVolMgrFmt = pThis;
-            else
-                RTMemFree(pThis);
         }
+        RTMemFree(pThis);
     }
     else
@@ -348,8 +349,9 @@
 
     pThis->pDisk = NULL;
-    memset(&pThis->HdrRev1, 0, sizeof(pThis->HdrRev1));
+    RT_ZERO(pThis->HdrRev1);
+
     RTMemFree(pThis->paGptEntries);
-
     pThis->paGptEntries = NULL;
+
     RTMemFree(pThis);
 }
@@ -368,4 +370,13 @@
         *pfUsed = false;
 
+    return VINF_SUCCESS;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnQueryDiskUuid */
+static DECLCALLBACK(int) rtDvmFmtGptQueryDiskUuid(RTDVMFMT hVolMgrFmt, PRTUUID pUuid)
+{
+    PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
+
+    *pUuid = pThis->HdrRev1.DiskUuid;
     return VINF_SUCCESS;
 }
@@ -519,4 +530,79 @@
     }
     return false;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
+static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    PRTDVMFMTINTERNAL pVolMgr = pVol->pVolMgr;
+    *poffTable = RTDVM_GPT_LBA2BYTE(1, pVolMgr->pDisk);
+    *pcbTable  = RTDVM_GPT_LBA2BYTE(pVolMgr->HdrRev1.u64LbaPartitionEntries, pVolMgr->pDisk)
+               + RT_ALIGN_Z(pVolMgr->HdrRev1.cPartitionEntries * pVolMgr->HdrRev1.cbPartitionEntry, pVolMgr->pDisk->cbSector)
+               - *poffTable;
+    return VINF_SUCCESS;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */
+static DECLCALLBACK(uint32_t) rtDvmFmtGptVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    switch (enmIndex)
+    {
+        case RTDVMVOLIDX_USER_VISIBLE:
+        case RTDVMVOLIDX_ALL:
+        case RTDVMVOLIDX_LINUX:
+            return pVol->idxEntry + 1;
+
+        case RTDVMVOLIDX_IN_TABLE:
+            return pVol->idxEntry;
+
+        case RTDVMVOLIDX_32BIT_HACK:
+        case RTDVMVOLIDX_INVALID:
+        case RTDVMVOLIDX_END:
+            break;
+        /* no default! */
+    }
+    AssertFailed();
+    return UINT32_MAX;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */
+static DECLCALLBACK(int) rtDvmFmtGptVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
+                                                    void *pvBuf, size_t cbBuf, size_t *pcbBuf)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    switch (enmProperty)
+    {
+        case RTDVMVOLPROP_MBR_FIRST_CYLINDER:
+        case RTDVMVOLPROP_MBR_FIRST_HEAD:
+        case RTDVMVOLPROP_MBR_FIRST_SECTOR:
+        case RTDVMVOLPROP_MBR_LAST_CYLINDER:
+        case RTDVMVOLPROP_MBR_LAST_HEAD:
+        case RTDVMVOLPROP_MBR_LAST_SECTOR:
+        case RTDVMVOLPROP_MBR_TYPE:
+            return VERR_NOT_SUPPORTED;
+
+        case RTDVMVOLPROP_GPT_TYPE:
+            *pcbBuf = sizeof(RTUUID);
+            Assert(cbBuf >= *pcbBuf);
+            *(PRTUUID)pvBuf = pVol->pGptEntry->UuidType;
+            return VINF_SUCCESS;
+
+        case RTDVMVOLPROP_GPT_UUID:
+            *pcbBuf = sizeof(RTUUID);
+            Assert(cbBuf >= *pcbBuf);
+            *(PRTUUID)pvBuf = pVol->pGptEntry->UuidPartition;
+            return VINF_SUCCESS;
+
+        case RTDVMVOLPROP_INVALID:
+        case RTDVMVOLPROP_END:
+        case RTDVMVOLPROP_32BIT_HACK:
+            break;
+        /* not default! */
+    }
+    AssertFailed();
+    RT_NOREF(cbBuf);
+    return VERR_NOT_SUPPORTED;
 }
 
@@ -553,4 +639,6 @@
     /* pfnQueryRangeUse */
     rtDvmFmtGptQueryRangeUse,
+    /* pfnQueryDiskUuid */
+    rtDvmFmtGptQueryDiskUuid,
     /* pfnGetValidVolumes */
     rtDvmFmtGptGetValidVolumes,
@@ -575,4 +663,10 @@
     /* pfnVolumeIsRangeIntersecting */
     rtDvmFmtGptVolumeIsRangeIntersecting,
+    /* pfnVolumeQueryTableLocation */
+    rtDvmFmtGptVolumeQueryTableLocation,
+    /* pfnVolumeGetIndex */
+    rtDvmFmtGptVolumeGetIndex,
+    /* pfnVolumeQueryProp */
+    rtDvmFmtGptVolumeQueryProp,
     /* pfnVolumeRead */
     rtDvmFmtGptVolumeRead,
Index: /trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp
===================================================================
--- /trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp	(revision 85876)
+++ /trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp	(revision 85877)
@@ -37,4 +37,5 @@
 #include <iprt/log.h>
 #include <iprt/string.h>
+#include <iprt/uuid.h>
 #include "internal/dvm.h"
 
@@ -52,4 +53,25 @@
 /** Pointer to a MBR sector. */
 typedef struct RTDVMMBRSECTOR *PRTDVMMBRSECTOR;
+
+
+/** The on-disk Cylinder/Head/Sector (CHS) info. */
+typedef struct MBRCHSADDR
+{
+    uint8_t uHead;
+    uint8_t uSector : 6;
+    uint8_t uCylinderH : 2;
+    uint8_t uCylinderL;
+} MBRCHSADDR;
+AssertCompileSize(MBRCHSADDR, 3);
+
+
+/** A decoded cylinder/head/sector address. */
+typedef struct RTDVMMBRCHSADDR
+{
+    uint16_t uCylinder;
+    uint8_t  uHead;
+    uint8_t  uSector;
+} RTDVMMBRCHSADDR;
+
 
 /**
@@ -74,4 +96,21 @@
     /** Bad entry. */
     bool                fBad;
+    /** RTDVMVOLIDX_IN_TABLE - Zero-based index within the table in pSector.
+     * (Also the index into RTDVMMBRSECTOR::aEntries.) */
+    uint8_t             idxTable;
+    /** RTDVMVOLIDX_ALL - One-based index.  All primary entries are included,
+     *  whether they are used or not.  In the extended table chain, only USED
+     *  entries are counted (but we include RTDVMMBR_IS_EXTENDED entries). */
+    uint8_t             idxAll;
+    /** RTDVMVOLIDX_USER_VISIBLE - One-base index.  Skips all unused entries
+     *  and RTDVMMBR_IS_EXTENDED. */
+    uint8_t             idxVisible;
+    /** RTDVMVOLIDX_LINUX - One-based index following the /dev/sdaX scheme. */
+    uint8_t             idxLinux;
+    uint8_t             bUnused;
+    /** The first CHS address of this partition */
+    RTDVMMBRCHSADDR     FirstChs;
+    /** The last CHS address of this partition */
+    RTDVMMBRCHSADDR     LastChs;
 } RTDVMMBRENTRY;
 /** Pointer to an MBR entry. */
@@ -100,6 +139,9 @@
      *  fIsPrimary is @c true). UINT8_MAX if none. */
     uint8_t             idxExtended;
+#if ARCH_BITS == 64
+    uint32_t            uAlignmentPadding;
+#endif
     /** The raw data. */
-    uint8_t             abData[512];
+    uint8_t             abData[RT_FLEXIBLE_ARRAY_NESTED];
 } RTDVMMBRSECTOR;
 
@@ -114,4 +156,7 @@
      *  extended partition table entries. */
     RTLISTANCHOR        PartitionHead;
+    /** The sector size to use when doing address calculation based on partition
+     *  table sector addresses and counts. */
+    uint32_t            cbSector;
     /** The total number of partitions, not counting extended ones. */
     uint32_t            cPartitions;
@@ -181,17 +226,26 @@
 };
 
+
 static DECLCALLBACK(int) rtDvmFmtMbrProbe(PCRTDVMDISK pDisk, uint32_t *puScore)
 {
     int rc = VINF_SUCCESS;
     *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED;
-    if (pDisk->cbDisk >= 512)
+    if (pDisk->cbDisk > RT_MAX(512, pDisk->cbSector))
     {
         /* Read from the disk and check for the 0x55aa signature at the end. */
-        uint8_t abMbr[512];
-        rc = rtDvmDiskRead(pDisk, 0, &abMbr[0], sizeof(abMbr));
-        if (   RT_SUCCESS(rc)
-            && abMbr[510] == 0x55
-            && abMbr[511] == 0xaa)
-            *puScore = RTDVM_MATCH_SCORE_SUPPORTED; /* Not perfect because GPTs have a protective MBR. */
+        size_t cbAlignedSize = RT_MAX(512, pDisk->cbSector);
+        uint8_t *pbMbr = (uint8_t *)RTMemTmpAllocZ(cbAlignedSize);
+        if (pbMbr)
+        {
+            rc = rtDvmDiskRead(pDisk, 0, pbMbr, cbAlignedSize);
+            if (   RT_SUCCESS(rc)
+                && pbMbr[510] == 0x55
+                && pbMbr[511] == 0xaa)
+                *puScore = RTDVM_MATCH_SCORE_SUPPORTED; /* Not perfect because GPTs have a protective MBR. */
+            /* @todo this could easily confuser a DOS, OS/2 or NT boot sector with a MBR... */
+            RTMemTmpFree(pbMbr);
+        }
+        else
+            rc = VERR_NO_TMP_MEMORY;
     }
 
@@ -229,5 +283,19 @@
 
 
-static int rtDvmFmtMbrReadExtended(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pPrimaryEntry)
+/**
+ * Decodes the on-disk cylinder/head/sector info and stores it the
+ * destination structure.
+ */
+DECLINLINE(void) rtDvmFmtMbrDecodeChs(RTDVMMBRCHSADDR *pDst, uint8_t *pbRaw)
+{
+    MBRCHSADDR *pRawChs = (MBRCHSADDR *)pbRaw;
+    pDst->uCylinder = RT_MAKE_U16(pRawChs->uCylinderL, pRawChs->uCylinderH);
+    pDst->uSector   = pRawChs->uSector;
+    pDst->uHead     = pRawChs->uHead;
+}
+
+
+static int rtDvmFmtMbrReadExtended(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pPrimaryEntry,
+                                   uint8_t *pidxAll, uint8_t *pidxVisible, uint8_t *pidxLinux)
 {
     uint64_t const  cbExt       = pPrimaryEntry->cbPart;
@@ -270,5 +338,6 @@
          * Allocate a new sector entry and read the sector with the table.
          */
-        PRTDVMMBRSECTOR pNext = (PRTDVMMBRSECTOR)RTMemAllocZ(sizeof(*pNext));
+        size_t const    cbMbr = RT_MAX(512, pThis->pDisk->cbSector);
+        PRTDVMMBRSECTOR pNext = (PRTDVMMBRSECTOR)RTMemAllocZVar(RT_UOFFSETOF_DYN(RTDVMMBRSECTOR, abData[cbMbr]));
         if (!pNext)
             return VERR_NO_MEMORY;
@@ -280,8 +349,9 @@
         pNext->idxExtended  = UINT8_MAX;
 
-        int rc = rtDvmDiskRead(pThis->pDisk, pNext->offOnDisk, &pNext->abData[0], sizeof(pNext->abData));
+        uint8_t *pabData = &pNext->abData[0];
+        int rc = rtDvmDiskReadUnaligned(pThis->pDisk, pNext->offOnDisk, pabData, cbMbr);
         if (   RT_FAILURE(rc)
-            || pNext->abData[510] != 0x55
-            || pNext->abData[511] != 0xaa)
+            || pabData[510] != 0x55
+            || pabData[511] != 0xaa)
         {
             if (RT_FAILURE(rc))
@@ -289,5 +359,5 @@
             else
                 LogRel(("rtDvmFmtMbrReadExtended: Extended partition table at sector %#RX64 does not have a valid DOS signature: %#x %#x\n",
-                        offCurBegin, pNext->abData[510], pNext->abData[511]));
+                        offCurBegin, pabData[510], pabData[511]));
             RTMemFree(pNext);
             pCurEntry->fBad = true;
@@ -304,27 +374,40 @@
          */
         PRTDVMMBRENTRY pEntry     = &pNext->aEntries[0];
-        uint8_t       *pbMbrEntry = &pNext->abData[446];
+        uint8_t       *pbMbrEntry = &pabData[446];
         for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16)
         {
+            pEntry->pSector  = pNext;
+            pEntry->idxTable = (uint8_t)i;
+            RTListInit(&pEntry->ListEntry);
+
             uint8_t const bType  = pbMbrEntry[4];
-            pEntry->pSector = pNext;
-            RTListInit(&pEntry->ListEntry);
             if (bType != 0)
             {
                 pEntry->bType    = bType;
                 pEntry->fFlags   = pbMbrEntry[0];
-                pEntry->offPart  = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08],
+                pEntry->idxAll   = *pidxAll;
+                *pidxAll += 1;
+
+                rtDvmFmtMbrDecodeChs(&pEntry->FirstChs, &pbMbrEntry[1]);
+                rtDvmFmtMbrDecodeChs(&pEntry->LastChs,  &pbMbrEntry[5]);
+
+                pEntry->offPart  = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08 + 0],
                                                        pbMbrEntry[0x08 + 1],
                                                        pbMbrEntry[0x08 + 2],
                                                        pbMbrEntry[0x08 + 3]);
-                pEntry->offPart *= 512;
-                pEntry->cbPart   = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c],
+                pEntry->offPart *= pThis->cbSector;
+                pEntry->cbPart   = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c + 0],
                                                        pbMbrEntry[0x0c + 1],
                                                        pbMbrEntry[0x0c + 2],
                                                        pbMbrEntry[0x0c + 3]);
-                pEntry->cbPart  *= 512;
+                pEntry->cbPart  *= pThis->cbSector;
                 if (!RTDVMMBR_IS_EXTENDED(bType))
                 {
-                    pEntry->offPart += offCurBegin;
+                    pEntry->offPart    += offCurBegin;
+                    pEntry->idxVisible  = *pidxVisible;
+                    *pidxVisible += 1;
+                    pEntry->idxLinux    = *pidxLinux;
+                    *pidxLinux += 1;
+
                     pThis->cPartitions++;
                     RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry);
@@ -368,5 +451,6 @@
 {
     int rc;
-    PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
+    size_t const      cbMbr = RT_MAX(512, pDisk->cbSector);
+    PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZVar(RT_UOFFSETOF_DYN(RTDVMFMTINTERNAL, Primary.abData[cbMbr]));
     if (pThis)
     {
@@ -381,11 +465,24 @@
         pThis->Primary.idxExtended   = UINT8_MAX;
 
+        /* We'll use the sector size reported by the disk.
+
+           Though, giiven that the MBR was hardwired to 512 byte sectors, we probably
+           should do some probing when the sector size differs from 512, but that can
+           wait till there is a real need for it and we've got some semi reliable
+           heuristics for doing that. */
+        pThis->cbSector = (uint32_t)pDisk->cbSector;
+        AssertLogRelMsgStmt(   pThis->cbSector >= 512
+                            && pThis->cbSector <= _64K,
+                            ("cbSector=%#x\n", pThis->cbSector),
+                            pThis->cbSector = 512);
+
         /*
          * Read the primary MBR.
          */
-        rc = rtDvmDiskRead(pDisk, 0, &pThis->Primary.abData[0], sizeof(pThis->Primary.abData));
+        uint8_t *pabData = &pThis->Primary.abData[0];
+        rc = rtDvmDiskRead(pDisk, 0, pabData, cbMbr);
         if (RT_SUCCESS(rc))
         {
-            Assert(pThis->Primary.abData[510] == 0x55 && pThis->Primary.abData[511] == 0xaa);
+            Assert(pabData[510] == 0x55 && pabData[511] == 0xaa);
 
             /*
@@ -393,27 +490,36 @@
              */
             PRTDVMMBRENTRY pEntry     = &pThis->Primary.aEntries[0];
-            uint8_t       *pbMbrEntry = &pThis->Primary.abData[446];
+            uint8_t       *pbMbrEntry = &pabData[446];
+            uint8_t        idxVisible = 1;
             for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16)
             {
-                pEntry->pSector = &pThis->Primary;
+                pEntry->pSector  = &pThis->Primary;
+                pEntry->idxTable = (uint8_t)i;
                 RTListInit(&pEntry->ListEntry);
 
-                uint8_t const bType = pbMbrEntry[4];
+                uint8_t const bType  = pbMbrEntry[4];
                 if (bType != 0)
                 {
+                    pEntry->bType    = bType;
+                    pEntry->fFlags   = pbMbrEntry[0];
+                    pEntry->idxAll   = (uint8_t)(i + 1);
+
+                    rtDvmFmtMbrDecodeChs(&pEntry->FirstChs, &pbMbrEntry[1]);
+                    rtDvmFmtMbrDecodeChs(&pEntry->LastChs,  &pbMbrEntry[5]);
+
                     pEntry->offPart  = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08 + 0],
                                                            pbMbrEntry[0x08 + 1],
                                                            pbMbrEntry[0x08 + 2],
                                                            pbMbrEntry[0x08 + 3]);
-                    pEntry->offPart *= 512;
+                    pEntry->offPart *= pThis->cbSector;
                     pEntry->cbPart   = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c + 0],
                                                            pbMbrEntry[0x0c + 1],
                                                            pbMbrEntry[0x0c + 2],
                                                            pbMbrEntry[0x0c + 3]);
-                    pEntry->cbPart  *= 512;
-                    pEntry->bType    = bType;
-                    pEntry->fFlags   = pbMbrEntry[0];
+                    pEntry->cbPart  *= pThis->cbSector;
                     if (!RTDVMMBR_IS_EXTENDED(bType))
                     {
+                        pEntry->idxVisible = idxVisible++;
+                        pEntry->idxLinux   = (uint8_t)(i + 1);
                         pThis->cPartitions++;
                         RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry);
@@ -439,4 +545,7 @@
              */
             if (pThis->Primary.cExtended > 0)
+            {
+                uint8_t idxAll   = 5;
+                uint8_t idxLinux = 5;
                 for (unsigned i = 0; i < 4; i++)
                     if (RTDVMMBR_IS_EXTENDED(pThis->Primary.aEntries[i].bType))
@@ -444,8 +553,9 @@
                         if (pThis->Primary.idxExtended == UINT8_MAX)
                             pThis->Primary.idxExtended = (uint8_t)i;
-                        rc = rtDvmFmtMbrReadExtended(pThis, &pThis->Primary.aEntries[i]);
+                        rc = rtDvmFmtMbrReadExtended(pThis, &pThis->Primary.aEntries[i], &idxAll, &idxVisible, &idxLinux);
                         if (RT_FAILURE(rc))
                             break;
                     }
+            }
             if (RT_SUCCESS(rc))
             {
@@ -453,6 +563,6 @@
                 return rc;
             }
-
         }
+        rtDvmFmtMbrDestroy(pThis);
     }
     else
@@ -465,5 +575,6 @@
 {
     int rc;
-    PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
+    size_t const cbMbr = RT_MAX(512, pDisk->cbSector);
+    PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZVar(RT_UOFFSETOF_DYN(RTDVMFMTINTERNAL, Primary.abData[cbMbr]));
     if (pThis)
     {
@@ -479,7 +590,9 @@
 
         /* Setup a new MBR and write it to the disk. */
-        pThis->Primary.abData[510] = 0x55;
-        pThis->Primary.abData[511] = 0xaa;
-        rc = rtDvmDiskWrite(pDisk, 0, &pThis->Primary.abData[0], sizeof(pThis->Primary.abData));
+        uint8_t *pabData = &pThis->Primary.abData[0];
+        RT_BZERO(pabData, 512);
+        pabData[510] = 0x55;
+        pabData[511] = 0xaa;
+        rc = rtDvmDiskWrite(pDisk, 0, pabData, cbMbr);
         if (RT_SUCCESS(rc))
         {
@@ -544,4 +657,21 @@
 }
 
+/** @copydoc RTDVMFMTOPS::pfnQueryDiskUuid */
+static DECLCALLBACK(int) rtDvmFmtMbrQueryDiskUuid(RTDVMFMT hVolMgrFmt, PRTUUID pUuid)
+{
+    PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
+    uint32_t idDisk = RT_MAKE_U32_FROM_U8(pThis->Primary.abData[440],
+                                          pThis->Primary.abData[441],
+                                          pThis->Primary.abData[442],
+                                          pThis->Primary.abData[443]);
+    if (idDisk != 0)
+    {
+        RTUuidClear(pUuid);
+        pUuid->Gen.u32TimeLow = idDisk;
+        return VINF_NOT_SUPPORTED;
+    }
+    return VERR_NOT_SUPPORTED;
+}
+
 static DECLCALLBACK(uint32_t) rtDvmFmtMbrGetValidVolumes(RTDVMFMT hVolMgrFmt)
 {
@@ -668,4 +798,98 @@
     }
     return false;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
+static DECLCALLBACK(int) rtDvmFmtMbrVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    *poffTable = pVol->pEntry->pSector->offOnDisk;
+    *pcbTable  = RT_MAX(512, pVol->pVolMgr->pDisk->cbSector);
+    return VINF_SUCCESS;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */
+static DECLCALLBACK(uint32_t) rtDvmFmtMbrVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    switch (enmIndex)
+    {
+        case RTDVMVOLIDX_USER_VISIBLE:
+            return pVol->pEntry->idxVisible;
+        case RTDVMVOLIDX_ALL:
+            return pVol->pEntry->idxAll;
+        case RTDVMVOLIDX_IN_TABLE:
+            return pVol->pEntry->idxTable;
+        case RTDVMVOLIDX_LINUX:
+            return pVol->pEntry->idxLinux;
+
+        case RTDVMVOLIDX_INVALID:
+        case RTDVMVOLIDX_END:
+        case RTDVMVOLIDX_32BIT_HACK:
+            break;
+        /* no default! */
+    }
+    return UINT32_MAX;
+}
+
+/** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */
+static DECLCALLBACK(int) rtDvmFmtMbrVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
+                                                    void *pvBuf, size_t cbBuf, size_t *pcbBuf)
+{
+    PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
+    switch (enmProperty)
+    {
+        case RTDVMVOLPROP_MBR_FIRST_CYLINDER:
+            *pcbBuf = sizeof(uint16_t);
+            Assert(cbBuf >= *pcbBuf);
+            *(uint16_t *)pvBuf = pVol->pEntry->FirstChs.uCylinder;
+            return VINF_SUCCESS;
+        case RTDVMVOLPROP_MBR_LAST_CYLINDER:
+            *pcbBuf = sizeof(uint16_t);
+            Assert(cbBuf >= *pcbBuf);
+            *(uint16_t *)pvBuf = pVol->pEntry->LastChs.uCylinder;
+            return VINF_SUCCESS;
+
+        case RTDVMVOLPROP_MBR_FIRST_HEAD:
+            *pcbBuf = sizeof(uint8_t);
+            Assert(cbBuf >= *pcbBuf);
+            *(uint8_t *)pvBuf = pVol->pEntry->FirstChs.uHead;
+            return VINF_SUCCESS;
+        case RTDVMVOLPROP_MBR_LAST_HEAD:
+            *pcbBuf = sizeof(uint8_t);
+            Assert(cbBuf >= *pcbBuf);
+            *(uint8_t *)pvBuf = pVol->pEntry->LastChs.uHead;
+            return VINF_SUCCESS;
+
+        case RTDVMVOLPROP_MBR_FIRST_SECTOR:
+            *pcbBuf = sizeof(uint8_t);
+            Assert(cbBuf >= *pcbBuf);
+            *(uint8_t *)pvBuf = pVol->pEntry->FirstChs.uSector;
+            return VINF_SUCCESS;
+        case RTDVMVOLPROP_MBR_LAST_SECTOR:
+            *pcbBuf = sizeof(uint8_t);
+            Assert(cbBuf >= *pcbBuf);
+            *(uint8_t *)pvBuf = pVol->pEntry->LastChs.uSector;
+            return VINF_SUCCESS;
+
+        case RTDVMVOLPROP_MBR_TYPE:
+            *pcbBuf = sizeof(uint8_t);
+            Assert(cbBuf >= *pcbBuf);
+            *(uint8_t *)pvBuf = pVol->pEntry->bType;
+            return VINF_SUCCESS;
+
+        case RTDVMVOLPROP_GPT_TYPE:
+        case RTDVMVOLPROP_GPT_UUID:
+            return VERR_NOT_SUPPORTED;
+
+        case RTDVMVOLPROP_INVALID:
+        case RTDVMVOLPROP_END:
+        case RTDVMVOLPROP_32BIT_HACK:
+            break;
+        /* not default! */
+    }
+    RT_NOREF(cbBuf);
+    AssertFailed();
+    return VERR_NOT_SUPPORTED;
 }
 
@@ -702,4 +926,6 @@
     /* pfnQueryRangeUse */
     rtDvmFmtMbrQueryRangeUse,
+    /* pfnQueryDiskUuid */
+    rtDvmFmtMbrQueryDiskUuid,
     /* pfnGetValidVolumes */
     rtDvmFmtMbrGetValidVolumes,
@@ -724,4 +950,10 @@
     /* pfnVOlumeIsRangeIntersecting */
     rtDvmFmtMbrVolumeIsRangeIntersecting,
+    /* pfnVolumeQueryTableLocation */
+    rtDvmFmtMbrVolumeQueryTableLocation,
+    /* pfnVolumeGetIndex */
+    rtDvmFmtMbrVolumeGetIndex,
+    /* pfnVolumeQueryProp */
+    rtDvmFmtMbrVolumeQueryProp,
     /* pfnVolumeRead */
     rtDvmFmtMbrVolumeRead,
Index: /trunk/src/VBox/Runtime/include/internal/dvm.h
===================================================================
--- /trunk/src/VBox/Runtime/include/internal/dvm.h	(revision 85876)
+++ /trunk/src/VBox/Runtime/include/internal/dvm.h	(revision 85877)
@@ -138,4 +138,14 @@
 
     /**
+     * Optional: Query the uuid of the current disk if applicable.
+     *
+     * @returns IPRT status code.
+     * @retval  VERR_NOT_SUPPORTED if the partition scheme doesn't do UUIDs.
+     * @param   hVolMgrFmt      The format specific volume manager handle.
+     * @param   pUuid           Where to return the UUID.
+     */
+    DECLCALLBACKMEMBER(int, pfnQueryDiskUuid,(RTDVMFMT hVolMgrFmt, PRTUUID pUuid));
+
+    /**
      * Gets the number of valid volumes in the map.
      *
@@ -246,4 +256,63 @@
 
     /**
+     * Queries the range of the partition table the volume belongs to on the underlying medium.
+     *
+     * @returns IPRT status code.
+     * @param   hVolFmt         The format specific volume handle.
+     * @param   poffTable       Where to return the byte offset on the underlying
+     *                          media of the (partition/volume/whatever) table.
+     * @param   pcbTable        Where to return the table size in bytes.  This
+     *                          typically includes alignment padding.
+     * @sa RTDvmVolumeQueryTableLocation
+     */
+    DECLCALLBACKMEMBER(int, pfnVolumeQueryTableLocation,(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffStart, uint64_t *poffLast));
+
+    /**
+     * Gets the tiven index for the specified volume.
+     *
+     * @returns The requested index. UINT32_MAX on failure.
+     * @param   hVolFmt         The format specific volume handle.
+     * @param   enmIndex        The index to get.
+     * @sa RTDvmVolumeGetIndex
+     */
+    DECLCALLBACKMEMBER(uint32_t, pfnVolumeGetIndex,(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex));
+
+    /**
+     * Query a generic volume property.
+     *
+     * This is an extensible interface for retriving mostly format specific
+     * information, or information that's not commonly used.  (It's modelled after
+     * RTLdrQueryPropEx.)
+     *
+     * @returns IPRT status code.
+     * @retval  VERR_NOT_SUPPORTED if the property query isn't supported (either all
+     *          or that specific property).  The caller  must  handle this result.
+     * @retval  VERR_NOT_FOUND is currently not returned, but intended for cases
+     *          where it wasn't present in the tables.
+     * @retval  VERR_INVALID_FUNCTION if the @a enmProperty value is wrong.
+     * @retval  VERR_INVALID_PARAMETER if the fixed buffer size is wrong. Correct
+     *          size in @a *pcbRet.
+     * @retval  VERR_BUFFER_OVERFLOW if the property doesn't have a fixed size
+     *          buffer and the buffer isn't big enough. Correct size in @a *pcbRet.
+     * @retval  VERR_INVALID_HANDLE if the handle is invalid.
+     *
+     * @param   hVolFmt     Handle to the volume.
+     * @param   enmProperty The property to query.
+     * @param   pvBuf       Pointer to the input / output buffer.  In most cases
+     *                      it's only used for returning data.
+     * @param   cbBuf       The size of the buffer.  This is validated by the common
+     *                      code for all fixed typed & sized properties.  The
+     *                      interger properties may have several supported sizes, in
+     *                      which case the user value is passed along as-is but it
+     *                      is okay to return a smaller amount of data.  The common
+     *                      code will make upcast the data.
+     * @param   pcbRet      Where to return the amount of data returned.  This must
+     *                      be set even for fixed type/sized data.
+     * @sa RTDvmVolumeQueryProp, RTDvmVolumeGetPropU64
+     */
+    DECLCALLBACKMEMBER(int, pfnVolumeQueryProp,(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
+                                                void *pvBuf, size_t cbBuf, size_t *pcbBuf));
+
+    /**
      * Read data from the given volume.
      *
@@ -300,4 +369,5 @@
  * @param   pvBuf    Destination buffer.
  * @param   cbRead   How much to read.
+ * @sa      rtDvmDiskReadUnaligned
  */
 DECLINLINE(int) rtDvmDiskRead(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead)
@@ -308,6 +378,12 @@
     AssertReturn(off + cbRead <= pDisk->cbDisk, VERR_INVALID_PARAMETER);
 
+    /* Use RTVfsFileReadAt if these triggers: */
+    Assert(!(cbRead % pDisk->cbSector));
+    Assert(!(off    % pDisk->cbSector));
+
     return RTVfsFileReadAt(pDisk->hVfsFile, off, pvBuf, cbRead, NULL /*pcbRead*/);
 }
+
+DECLHIDDEN(int) rtDvmDiskReadUnaligned(PCRTDVMDISK pDisk, uint64_t off, void *pvBuf, size_t cbRead);
 
 /**
@@ -327,4 +403,8 @@
     AssertReturn(off + cbWrite <= pDisk->cbDisk, VERR_INVALID_PARAMETER);
 
+    /* Write RTVfsFileReadAt if these triggers: */
+    Assert(!(cbWrite % pDisk->cbSector));
+    Assert(!(off     % pDisk->cbSector));
+
     return RTVfsFileWriteAt(pDisk->hVfsFile, off, pvBuf, cbWrite, NULL /*pcbWritten*/);
 }
