- Timestamp:
- Nov 10, 2017 6:40:38 PM (7 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/Runtime/common/dvm/dvmmbr.cpp
r69618 r69651 29 29 * Header Files * 30 30 *********************************************************************************************************************************/ 31 #define LOG_GROUP RTLOGGROUP_FS 31 32 #include <iprt/types.h> 32 33 #include <iprt/assert.h> 33 34 #include <iprt/mem.h> 34 35 #include <iprt/dvm.h> 36 #include <iprt/list.h> 37 #include <iprt/log.h> 35 38 #include <iprt/string.h> 36 39 #include "internal/dvm.h" 40 41 42 /********************************************************************************************************************************* 43 * Defined Constants And Macros * 44 *********************************************************************************************************************************/ 45 /** Checks if the partition type is an extended partition container. */ 46 #define RTDVMMBR_IS_EXTENDED(a_bType) ((a_bType) == 0x05 || (a_bType) == 0x0f) 37 47 38 48 … … 40 50 * Structures and Typedefs * 41 51 *********************************************************************************************************************************/ 52 /** Pointer to a MBR sector. */ 53 typedef struct RTDVMMBRSECTOR *PRTDVMMBRSECTOR; 54 55 /** 56 * MBR entry. 57 */ 58 typedef struct RTDVMMBRENTRY 59 { 60 /** Our entry in the in-use partition entry list (RTDVMMBRENTRY). */ 61 RTLISTNODE ListEntry; 62 /** Pointer to the MBR sector containing this entry. */ 63 PRTDVMMBRSECTOR pSector; 64 /** Pointer to the next sector in the extended partition table chain. */ 65 PRTDVMMBRSECTOR pChain; 66 /** The byte offset of the start of the partition (relative to disk). */ 67 uint64_t offPart; 68 /** Number of bytes for this partition. */ 69 uint64_t cbPart; 70 /** The partition/filesystem type. */ 71 uint8_t bType; 72 /** The partition flags. */ 73 uint8_t fFlags; 74 /** Bad entry. */ 75 bool fBad; 76 } RTDVMMBRENTRY; 77 /** Pointer to an MBR entry. */ 78 typedef RTDVMMBRENTRY *PRTDVMMBRENTRY; 79 80 /** 81 * A MBR sector. 82 */ 83 typedef struct RTDVMMBRSECTOR 84 { 85 /** Internal representation of the entries. */ 86 RTDVMMBRENTRY aEntries[4]; 87 /** The byte offset of this MBR sector (relative to disk). 88 * We keep this for detecting cycles now, but it will be needed if we start 89 * updating the partition table at some point. */ 90 uint64_t offOnDisk; 91 /** Pointer to the previous sector if this isn't a primary one. */ 92 PRTDVMMBRENTRY pPrevSector; 93 /** Set if this is the primary MBR, cleared if an extended. */ 94 bool fIsPrimary; 95 /** Number of used entries. */ 96 uint8_t cUsed; 97 /** Number of extended entries. */ 98 uint8_t cExtended; 99 /** The extended entry we're following (we only follow one, except when 100 * fIsPrimary is @c true). UINT8_MAX if none. */ 101 uint8_t idxExtended; 102 /** The raw data. */ 103 uint8_t abData[512]; 104 } RTDVMMBRSECTOR; 42 105 43 106 /** … … 47 110 { 48 111 /** Pointer to the underlying disk. */ 49 PCRTDVMDISK pDisk; 50 /** Number of initialized partitions. */ 51 uint32_t cPartitions; 52 /** The raw MBR data. */ 53 uint8_t abMbr[512]; 112 PCRTDVMDISK pDisk; 113 /** Head of the list of in-use RTDVMMBRENTRY structures. This excludes 114 * extended partition table entries. */ 115 RTLISTANCHOR PartitionHead; 116 /** The total number of partitions, not counting extended ones. */ 117 uint32_t cPartitions; 118 /** The actual primary MBR sector. */ 119 RTDVMMBRSECTOR Primary; 54 120 } RTDVMFMTINTERNAL; 55 121 /** Pointer to the MBR volume manager. */ … … 62 128 { 63 129 /** Pointer to the volume manager. */ 64 PRTDVMFMTINTERNAL pVolMgr; 65 /** Partition table entry index. */ 66 uint32_t idxEntry; 67 /** Start offset of the volume. */ 68 uint64_t offStart; 69 /** Size of the volume. */ 70 uint64_t cbVolume; 71 /** Pointer to the raw partition table entry. */ 72 uint8_t *pbMbrEntry; 130 PRTDVMFMTINTERNAL pVolMgr; 131 /** The MBR entry. */ 132 PRTDVMMBRENTRY pEntry; 73 133 } RTDVMVOLUMEFMTINTERNAL; 74 134 /** Pointer to an MBR volume. */ 75 135 typedef RTDVMVOLUMEFMTINTERNAL *PRTDVMVOLUMEFMTINTERNAL; 76 77 /**78 * MBR FS type to DVM volume type mapping entry.79 */80 81 typedef struct RTDVMMBRFS2VOLTYPE82 {83 /** MBR FS Id. */84 uint8_t bFsId;85 /** DVM volume type. */86 RTDVMVOLTYPE enmVolType;87 } RTDVMMBRFS2VOLTYPE;88 /** Pointer to a MBR FS Type to volume type mapping entry. */89 typedef RTDVMMBRFS2VOLTYPE *PRTDVMMBRFS2VOLTYPE;90 136 91 137 … … 96 142 * Mapping of FS types to DVM volume types. 97 143 * 98 * From http://www.win.tue.nl/~aeb/partitions/partition_types-1.html 99 */ 100 static const RTDVMMBRFS2VOLTYPE g_aFs2DvmVolTypes[] = 144 * @see https://en.wikipedia.org/wiki/Partition_type 145 * @see http://www.win.tue.nl/~aeb/partitions/partition_types-1.html 146 */ 147 static const struct RTDVMMBRFS2VOLTYPE 148 { 149 /** MBR FS Id. */ 150 uint8_t bFsId; 151 /** DVM volume type. */ 152 RTDVMVOLTYPE enmVolType; 153 } g_aFs2DvmVolTypes[] = 101 154 { 102 155 { 0x01, RTDVMVOLTYPE_FAT12 }, … … 131 184 { 132 185 int rc = VINF_SUCCESS; 133 uint8_t abMbr[512];134 135 186 *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED; 136 137 187 if (pDisk->cbDisk >= 512) 138 188 { 139 189 /* Read from the disk and check for the 0x55aa signature at the end. */ 190 uint8_t abMbr[512]; 140 191 rc = rtDvmDiskRead(pDisk, 0, &abMbr[0], sizeof(abMbr)); 141 192 if ( RT_SUCCESS(rc) … … 148 199 } 149 200 201 202 static void rtDvmFmtMbrDestroy(PRTDVMFMTINTERNAL pThis) 203 { 204 /* 205 * Delete chains of extended partitions. 206 */ 207 for (unsigned i = 0; i < 4; i++) 208 { 209 PRTDVMMBRSECTOR pCur = pThis->Primary.aEntries[i].pChain; 210 while (pCur) 211 { 212 PRTDVMMBRSECTOR pNext = pCur->idxExtended != UINT8_MAX ? pCur->aEntries[pCur->idxExtended].pChain : NULL; 213 214 RT_ZERO(pCur->aEntries); 215 pCur->pPrevSector = NULL; 216 RTMemFree(pCur); 217 218 pCur = pNext; 219 } 220 } 221 222 /* 223 * Now kill this. 224 */ 225 pThis->pDisk = NULL; 226 RT_ZERO(pThis->Primary.aEntries); 227 RTMemFree(pThis); 228 } 229 230 231 static int rtDvmFmtMbrReadExtended(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pPrimaryEntry) 232 { 233 uint32_t const cbExt = pPrimaryEntry->cbPart; 234 uint64_t const offExtBegin = pPrimaryEntry->offPart; 235 236 uint64_t offCurBegin = offExtBegin; 237 PRTDVMMBRENTRY pCurEntry = pPrimaryEntry; 238 for (unsigned cTables = 1; ; cTables++) 239 { 240 /* 241 * Do some sanity checking. 242 */ 243 /* Check the address of the partition table. */ 244 if (offCurBegin - offExtBegin >= cbExt) 245 { 246 LogRel(("rtDvmFmtMbrReadExtended: offCurBegin=%#RX64 is outside the extended partition: %#RX64..%#RX64 (LB %#RX64)\n", 247 offCurBegin, offExtBegin, offExtBegin + cbExt - 1, cbExt)); 248 pCurEntry->fBad = true; 249 return -VERR_OUT_OF_RANGE; 250 } 251 252 /* Limit the chain length. */ 253 if (cTables > 64) 254 { 255 LogRel(("rtDvmFmtMbrReadExtended: offCurBegin=%#RX64 is the %uth table, we stop here.\n", offCurBegin, cTables)); 256 pCurEntry->fBad = true; 257 return -VERR_TOO_MANY_SYMLINKS; 258 } 259 260 /* Check for obvious cycles. */ 261 for (PRTDVMMBRENTRY pPrev = pCurEntry->pSector->pPrevSector; pPrev != NULL; pPrev = pPrev->pSector->pPrevSector) 262 if (pPrev->offPart == offCurBegin) 263 { 264 LogRel(("rtDvmFmtMbrReadExtended: Cycle! We've seen offCurBegin=%#RX64 before\n", offCurBegin)); 265 pCurEntry->fBad = true; 266 return -VERR_TOO_MANY_SYMLINKS; 267 } 268 269 /* 270 * Allocate a new sector entry and read the sector with the table. 271 */ 272 PRTDVMMBRSECTOR pNext = (PRTDVMMBRSECTOR)RTMemAllocZ(sizeof(*pNext)); 273 if (!pNext) 274 return VERR_NO_MEMORY; 275 pNext->offOnDisk = offCurBegin; 276 pNext->pPrevSector = pCurEntry; 277 //pNext->fIsPrimary = false; 278 //pNext->cUsed = 0; 279 //pNext->cExtended = 0; 280 pNext->idxExtended = UINT8_MAX; 281 282 int rc = rtDvmDiskRead(pThis->pDisk, pNext->offOnDisk, &pNext->abData[0], sizeof(pNext->abData)); 283 if ( RT_FAILURE(rc) 284 || pNext->abData[510] != 0x55 285 || pNext->abData[511] != 0xaa) 286 { 287 if (RT_FAILURE(rc)) 288 LogRel(("rtDvmFmtMbrReadExtended: Error reading extended partition table at sector %#RX64: %Rrc\n", offCurBegin, rc)); 289 else 290 LogRel(("rtDvmFmtMbrReadExtended: Extended partition table at sector %#RX64 does not have a valid DOS signature: %#x %#x\n", 291 offCurBegin, pNext->abData[510], pNext->abData[511])); 292 RTMemFree(pNext); 293 pCurEntry->fBad = true; 294 return rc; 295 } 296 pCurEntry->pChain = pNext; 297 298 /* 299 * Process the table, taking down the first forward entry. 300 * 301 * As noted in the caller of this function, we only deal with one extended 302 * partition entry at this level since noone really ever put more than one 303 * here anyway. 304 */ 305 PRTDVMMBRENTRY pEntry = &pNext->aEntries[0]; 306 uint8_t *pbMbrEntry = &pNext->abData[446]; 307 for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16) 308 { 309 uint8_t const bType = pbMbrEntry[4]; 310 pEntry->pSector = pNext; 311 RTListInit(&pEntry->ListEntry); 312 if (bType != 0) 313 { 314 pEntry->bType = bType; 315 pEntry->fFlags = pbMbrEntry[0]; 316 pEntry->offPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08], 317 pbMbrEntry[0x08 + 1], 318 pbMbrEntry[0x08 + 2], 319 pbMbrEntry[0x08 + 3]); 320 pEntry->offPart *= 512; 321 pEntry->cbPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c], 322 pbMbrEntry[0x0c + 1], 323 pbMbrEntry[0x0c + 2], 324 pbMbrEntry[0x0c + 3]); 325 pEntry->cbPart *= 512; 326 if (!RTDVMMBR_IS_EXTENDED(bType)) 327 { 328 pEntry->offPart += offCurBegin; 329 pThis->cPartitions++; 330 RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry); 331 Log2(("rtDvmFmtMbrReadExtended: %#012RX64::%u: vol%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n", 332 offCurBegin, i, pThis->cPartitions - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart)); 333 } 334 else 335 { 336 pEntry->offPart += offExtBegin; 337 pNext->cExtended++; 338 if (pNext->idxExtended == UINT8_MAX) 339 pNext->idxExtended = (uint8_t)i; 340 else 341 { 342 pEntry->fBad = true; 343 LogRel(("rtDvmFmtMbrReadExtended: Warning! Both #%u and #%u are extended partition table entries! Only following the former\n", 344 i, pNext->idxExtended)); 345 } 346 Log2(("rtDvmFmtMbrReadExtended: %#012RX64::%u: ext%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n", 347 offCurBegin, i, pNext->cExtended - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart)); 348 } 349 pNext->cUsed++; 350 351 } 352 /* else: unused */ 353 } 354 355 /* 356 * We're done if we didn't find any extended partition table entry. 357 * Otherwise, advance to the next one. 358 */ 359 if (!pNext->cExtended) 360 return VINF_SUCCESS; 361 pCurEntry = &pNext->aEntries[pNext->idxExtended]; 362 offCurBegin = pCurEntry->offPart; 363 } 364 } 365 366 150 367 static DECLCALLBACK(int) rtDvmFmtMbrOpen(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt) 151 368 { 152 int rc = VINF_SUCCESS; 153 PRTDVMFMTINTERNAL pThis = NULL; 154 155 pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL)); 369 int rc; 370 PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL)); 156 371 if (pThis) 157 372 { 158 pThis->pDisk = pDisk; 159 pThis->cPartitions = 0; 160 161 /* Read the MBR and count the valid partition entries. */ 162 rc = rtDvmDiskRead(pDisk, 0, &pThis->abMbr[0], sizeof(pThis->abMbr)); 373 pThis->pDisk = pDisk; 374 //pThis->cPartitions = 0; 375 RTListInit(&pThis->PartitionHead); 376 //pThis->Primary.offOnDisk = 0; 377 //pThis->Primary.pPrevSector = NULL; 378 pThis->Primary.fIsPrimary = true; 379 //pThis->Primary.cUsed = 0; 380 //pThis->Primary.cExtended = 0; 381 pThis->Primary.idxExtended = UINT8_MAX; 382 383 /* 384 * Read the primary MBR. 385 */ 386 rc = rtDvmDiskRead(pDisk, 0, &pThis->Primary.abData[0], sizeof(pThis->Primary.abData)); 163 387 if (RT_SUCCESS(rc)) 164 388 { 165 uint8_t *pbMbrEntry = &pThis->abMbr[446]; 166 167 Assert(pThis->abMbr[510] == 0x55 && pThis->abMbr[511] == 0xaa); 168 169 for (unsigned i = 0; i < 4; i++) 389 Assert(pThis->Primary.abData[510] == 0x55 && pThis->Primary.abData[511] == 0xaa); 390 391 /* 392 * Setup basic data for the 4 entries. 393 */ 394 PRTDVMMBRENTRY pEntry = &pThis->Primary.aEntries[0]; 395 uint8_t *pbMbrEntry = &pThis->Primary.abData[446]; 396 for (unsigned i = 0; i < 4; i++, pEntry++, pbMbrEntry += 16) 170 397 { 171 /* The entry is unused if the type contains 0x00. */ 172 if (pbMbrEntry[4] != 0x00) 173 pThis->cPartitions++; 174 175 pbMbrEntry += 16; 398 pEntry->pSector = &pThis->Primary; 399 RTListInit(&pEntry->ListEntry); 400 401 uint8_t const bType = pbMbrEntry[4]; 402 if (bType != 0) 403 { 404 pEntry->offPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x08 + 0], 405 pbMbrEntry[0x08 + 1], 406 pbMbrEntry[0x08 + 2], 407 pbMbrEntry[0x08 + 3]); 408 pEntry->offPart *= 512; 409 pEntry->cbPart = RT_MAKE_U32_FROM_U8(pbMbrEntry[0x0c + 0], 410 pbMbrEntry[0x0c + 1], 411 pbMbrEntry[0x0c + 2], 412 pbMbrEntry[0x0c + 3]); 413 pEntry->cbPart *= 512; 414 pEntry->bType = bType; 415 pEntry->fFlags = pbMbrEntry[0]; 416 if (!RTDVMMBR_IS_EXTENDED(bType)) 417 { 418 pThis->cPartitions++; 419 RTListAppend(&pThis->PartitionHead, &pEntry->ListEntry); 420 Log2(("rtDvmFmtMbrOpen: %u: vol%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n", 421 i, pThis->cPartitions - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart)); 422 } 423 else 424 { 425 pThis->Primary.cExtended++; 426 Log2(("rtDvmFmtMbrOpen: %u: ext%u bType=%#04x fFlags=%#04x offPart=%#012RX64 cbPart=%#012RX64\n", 427 i, pThis->Primary.cExtended - 1, pEntry->bType, pEntry->fFlags, pEntry->offPart, pEntry->cbPart)); 428 } 429 pThis->Primary.cUsed++; 430 } 431 /* else: unused */ 176 432 } 177 433 178 *phVolMgrFmt = pThis; 434 /* 435 * Now read any extended partitions. Since it's no big deal for us, we allow 436 * the primary partition table to have more than one extended partition. However 437 * in the extended tables we only allow a single forward link to avoid having to 438 * deal with recursion. 439 */ 440 if (pThis->Primary.cExtended > 0) 441 for (unsigned i = 0; i < 4; i++) 442 if (RTDVMMBR_IS_EXTENDED(pThis->Primary.aEntries[i].bType)) 443 { 444 if (pThis->Primary.idxExtended == UINT8_MAX) 445 pThis->Primary.idxExtended = (uint8_t)i; 446 rc = rtDvmFmtMbrReadExtended(pThis, &pThis->Primary.aEntries[i]); 447 if (RT_FAILURE(rc)) 448 break; 449 } 450 if (RT_SUCCESS(rc)) 451 { 452 *phVolMgrFmt = pThis; 453 return rc; 454 } 455 179 456 } 180 457 } … … 187 464 static DECLCALLBACK(int) rtDvmFmtMbrInitialize(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt) 188 465 { 189 int rc = VINF_SUCCESS; 190 PRTDVMFMTINTERNAL pThis = NULL; 191 192 pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL)); 466 int rc; 467 PRTDVMFMTINTERNAL pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL)); 193 468 if (pThis) 194 469 { 470 pThis->pDisk = pDisk; 471 //pThis->cPartitions = 0; 472 RTListInit(&pThis->PartitionHead); 473 //pThis->Primary.offOnDisk = 0 474 //pThis->Primary.pPrevSector = NULL; 475 pThis->Primary.fIsPrimary = true; 476 //pThis->Primary.cUsed = 0; 477 //pThis->Primary.cExtended = 0; 478 pThis->Primary.idxExtended = UINT8_MAX; 479 195 480 /* Setup a new MBR and write it to the disk. */ 196 memset(&pThis->abMbr[0], 0, sizeof(pThis->abMbr)); 197 pThis->abMbr[510] = 0x55; 198 pThis->abMbr[511] = 0xaa; 199 200 rc = rtDvmDiskWrite(pDisk, 0, &pThis->abMbr[0], sizeof(pThis->abMbr)); 201 481 pThis->Primary.abData[510] = 0x55; 482 pThis->Primary.abData[511] = 0xaa; 483 rc = rtDvmDiskWrite(pDisk, 0, &pThis->Primary.abData[0], sizeof(pThis->Primary.abData)); 202 484 if (RT_SUCCESS(rc)) 203 485 { 204 pThis->pDisk = pDisk; 205 pThis->cPartitions = 0; 486 pThis->pDisk = pDisk; 206 487 *phVolMgrFmt = pThis; 207 488 } … … 217 498 static DECLCALLBACK(void) rtDvmFmtMbrClose(RTDVMFMT hVolMgrFmt) 218 499 { 219 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 220 221 pThis->pDisk = NULL; 222 pThis->cPartitions = 0; 223 memset(&pThis->abMbr[0], 0, sizeof(pThis->abMbr)); 224 RTMemFree(pThis); 500 rtDvmFmtMbrDestroy(hVolMgrFmt); 225 501 } 226 502 … … 254 530 * 255 531 * @returns IPRT status code. 256 * @param pThis The MBR volume manager data. 257 * @param pbMbrEntry The raw MBR entry data. 258 * @param idx The index in the partition table. 259 * @param phVolFmt Where to store the volume data on success. 260 */ 261 static int rtDvmFmtMbrVolumeCreate(PRTDVMFMTINTERNAL pThis, uint8_t *pbMbrEntry, 262 uint32_t idx, PRTDVMVOLUMEFMT phVolFmt) 263 { 264 int rc = VINF_SUCCESS; 532 * @param pThis The MBR volume manager data. 533 * @param pEntry The MBR entry to create a volume handle for. 534 * @param phVolFmt Where to store the volume data on success. 535 */ 536 static int rtDvmFmtMbrVolumeCreate(PRTDVMFMTINTERNAL pThis, PRTDVMMBRENTRY pEntry, PRTDVMVOLUMEFMT phVolFmt) 537 { 265 538 PRTDVMVOLUMEFMTINTERNAL pVol = (PRTDVMVOLUMEFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEFMTINTERNAL)); 266 267 539 if (pVol) 268 540 { 269 541 pVol->pVolMgr = pThis; 270 pVol->idxEntry = idx; 271 pVol->pbMbrEntry = pbMbrEntry; 272 pVol->offStart = *(uint32_t *)&pbMbrEntry[0x08] * pThis->pDisk->cbSector; 273 pVol->cbVolume = *(uint32_t *)&pbMbrEntry[0x0c] * pThis->pDisk->cbSector; 274 542 pVol->pEntry = pEntry; 275 543 *phVolFmt = pVol; 276 } 277 else 278 rc = VERR_NO_MEMORY; 279 280 return rc; 544 return VINF_SUCCESS; 545 } 546 return VERR_NO_MEMORY; 281 547 } 282 548 283 549 static DECLCALLBACK(int) rtDvmFmtMbrQueryFirstVolume(RTDVMFMT hVolMgrFmt, PRTDVMVOLUMEFMT phVolFmt) 284 550 { 285 int rc = VINF_SUCCESS;286 551 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 287 288 552 if (pThis->cPartitions != 0) 289 { 290 uint8_t *pbMbrEntry = &pThis->abMbr[446]; 291 292 /* Search for the first non empty entry. */ 293 for (unsigned i = 0; i < 4; i++) 294 { 295 if (pbMbrEntry[0x04] != 0x00) 296 { 297 rc = rtDvmFmtMbrVolumeCreate(pThis, pbMbrEntry, i, phVolFmt); 298 break; 299 } 300 pbMbrEntry += 16; 301 } 302 } 303 else 304 rc = VERR_DVM_MAP_EMPTY; 305 306 return rc; 553 return rtDvmFmtMbrVolumeCreate(pThis, RTListGetFirst(&pThis->PartitionHead, RTDVMMBRENTRY, ListEntry), phVolFmt); 554 return VERR_DVM_MAP_EMPTY; 307 555 } 308 556 309 557 static DECLCALLBACK(int) rtDvmFmtMbrQueryNextVolume(RTDVMFMT hVolMgrFmt, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUMEFMT phVolFmtNext) 310 558 { 311 int rc = VERR_DVM_MAP_NO_VOLUME; 312 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 559 PRTDVMFMTINTERNAL pThis = hVolMgrFmt; 560 PRTDVMVOLUMEFMTINTERNAL pCurVol = hVolFmt; 561 if (pCurVol) 562 { 563 PRTDVMMBRENTRY pNextEntry = RTListGetNext(&pThis->PartitionHead, pCurVol->pEntry, RTDVMMBRENTRY, ListEntry); 564 if (pNextEntry) 565 return rtDvmFmtMbrVolumeCreate(pThis, pNextEntry, phVolFmtNext); 566 return VERR_DVM_MAP_NO_VOLUME; 567 } 568 if (pThis->cPartitions != 0) 569 return rtDvmFmtMbrVolumeCreate(pThis, RTListGetFirst(&pThis->PartitionHead, RTDVMMBRENTRY, ListEntry), phVolFmtNext); 570 return VERR_DVM_MAP_EMPTY; 571 } 572 573 static DECLCALLBACK(void) rtDvmFmtMbrVolumeClose(RTDVMVOLUMEFMT hVolFmt) 574 { 313 575 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 314 uint8_t *pbMbrEntry = pVol->pbMbrEntry + 16; 315 316 for (unsigned i = pVol->idxEntry + 1; i < 4; i++) 317 { 318 if (pbMbrEntry[0x04] != 0x00) 319 { 320 rc = rtDvmFmtMbrVolumeCreate(pThis, pbMbrEntry, i, phVolFmtNext); 321 break; 322 } 323 pbMbrEntry += 16; 324 } 325 326 return rc; 327 } 328 329 static DECLCALLBACK(void) rtDvmFmtMbrVolumeClose(RTDVMVOLUMEFMT hVolFmt) 576 577 pVol->pVolMgr = NULL; 578 pVol->pEntry = NULL; 579 580 RTMemFree(pVol); 581 } 582 583 static DECLCALLBACK(uint64_t) rtDvmFmtMbrVolumeGetSize(RTDVMVOLUMEFMT hVolFmt) 330 584 { 331 585 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 332 586 333 pVol->pVolMgr = NULL; 334 pVol->offStart = 0; 335 pVol->cbVolume = 0; 336 pVol->pbMbrEntry = NULL; 337 338 RTMemFree(pVol); 339 } 340 341 static DECLCALLBACK(uint64_t) rtDvmFmtMbrVolumeGetSize(RTDVMVOLUMEFMT hVolFmt) 342 { 343 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 344 345 return pVol->cbVolume; 587 return pVol->pEntry->cbPart; 346 588 } 347 589 … … 354 596 static DECLCALLBACK(RTDVMVOLTYPE) rtDvmFmtMbrVolumeGetType(RTDVMVOLUMEFMT hVolFmt) 355 597 { 356 RTDVMVOLTYPE enmVolType = RTDVMVOLTYPE_UNKNOWN;357 598 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 358 599 600 uint8_t const bType = pVol->pEntry->bType; 359 601 for (unsigned i = 0; i < RT_ELEMENTS(g_aFs2DvmVolTypes); i++) 360 if (pVol->pbMbrEntry[0x04] == g_aFs2DvmVolTypes[i].bFsId) 361 { 362 enmVolType = g_aFs2DvmVolTypes[i].enmVolType; 363 break; 364 } 365 366 return enmVolType; 602 if (g_aFs2DvmVolTypes[i].bFsId == bType) 603 return g_aFs2DvmVolTypes[i].enmVolType; 604 605 return RTDVMVOLTYPE_UNKNOWN; 367 606 } 368 607 369 608 static DECLCALLBACK(uint64_t) rtDvmFmtMbrVolumeGetFlags(RTDVMVOLUMEFMT hVolFmt) 370 609 { 610 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 611 371 612 uint64_t fFlags = 0; 372 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 373 374 if (pVol->pbMbrEntry[0x00] & 0x80) 613 if (pVol->pEntry->bType & 0x80) 375 614 fFlags |= DVMVOLUME_FLAGS_BOOTABLE | DVMVOLUME_FLAGS_ACTIVE; 376 615 … … 383 622 uint64_t *pcbIntersect) 384 623 { 385 bool fIntersect = false;386 624 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 387 625 388 if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart)) 389 { 390 fIntersect = true; 391 *poffVol = offStart - pVol->offStart; 392 *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart); 393 } 394 395 return fIntersect; 626 if (RTDVM_RANGE_IS_INTERSECTING(pVol->pEntry->offPart, pVol->pEntry->cbPart, offStart)) 627 { 628 *poffVol = offStart - pVol->pEntry->offPart; 629 *pcbIntersect = RT_MIN(cbRange, pVol->pEntry->offPart + pVol->pEntry->cbPart - offStart); 630 return true; 631 } 632 return false; 396 633 } 397 634 … … 399 636 { 400 637 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 401 AssertReturn(off + cbRead <= pVol-> cbVolume, VERR_INVALID_PARAMETER);402 403 return rtDvmDiskRead(pVol->pVolMgr->pDisk, pVol-> offStart + off, pvBuf, cbRead);638 AssertReturn(off + cbRead <= pVol->pEntry->cbPart, VERR_INVALID_PARAMETER); 639 640 return rtDvmDiskRead(pVol->pVolMgr->pDisk, pVol->pEntry->offPart + off, pvBuf, cbRead); 404 641 } 405 642 … … 407 644 { 408 645 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt; 409 AssertReturn(off + cbWrite <= pVol-> cbVolume, VERR_INVALID_PARAMETER);410 411 return rtDvmDiskWrite(pVol->pVolMgr->pDisk, pVol-> offStart + off, pvBuf, cbWrite);646 AssertReturn(off + cbWrite <= pVol->pEntry->cbPart, VERR_INVALID_PARAMETER); 647 648 return rtDvmDiskWrite(pVol->pVolMgr->pDisk, pVol->pEntry->offPart + off, pvBuf, cbWrite); 412 649 } 413 650
Note:
See TracChangeset
for help on using the changeset viewer.