VirtualBox

source: vbox/trunk/src/VBox/Runtime/common/dvm/dvmbsdlabel.cpp@ 95841

Last change on this file since 95841 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 23.6 KB
Line 
1/* $Id: dvmbsdlabel.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * IPRT Disk Volume Management API (DVM) - BSD disklabel format backend.
4 */
5
6/*
7 * Copyright (C) 2011-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 *
17 * The contents of this file may alternatively be used under the terms
18 * of the Common Development and Distribution License Version 1.0
19 * (CDDL) only, as it comes in the "COPYING.CDDL" file of the
20 * VirtualBox OSE distribution, in which case the provisions of the
21 * CDDL are applicable instead of those of the GPL.
22 *
23 * You may elect to license modified versions of this file under the
24 * terms and conditions of either the GPL or the CDDL or both.
25 */
26
27#include <iprt/types.h>
28#include <iprt/assert.h>
29#include <iprt/mem.h>
30#include <iprt/dvm.h>
31#include <iprt/string.h>
32#include <iprt/asm.h>
33#include "internal/dvm.h"
34
35
36/*********************************************************************************************************************************
37* Structures and Typedefs *
38*********************************************************************************************************************************/
39
40/*
41 * Below are the on disk structures of a bsd disklabel as found in
42 * /usr/include/sys/disklabel.h from a FreeBSD system.
43 *
44 * Everything is stored in little endian on the disk.
45 */
46
47/** BSD disklabel magic. */
48#define RTDVM_BSDLBL_MAGIC UINT32_C(0x82564557)
49/** Maximum number of partitions in the label. */
50#define RTDVM_BSDLBL_MAX_PARTITIONS 8
51
52/**
53 * A BSD disk label partition.
54 */
55typedef struct BsdLabelPartition
56{
57 /** Number of sectors in the partition. */
58 uint32_t cSectors;
59 /** Start sector. */
60 uint32_t offSectorStart;
61 /** Filesystem fragment size. */
62 uint32_t cbFsFragment;
63 /** Filesystem type. */
64 uint8_t bFsType;
65 /** Filesystem fragments per block. */
66 uint8_t cFsFragmentsPerBlock;
67 /** Filesystem cylinders per group. */
68 uint16_t cFsCylPerGroup;
69} BsdLabelPartition;
70AssertCompileSize(BsdLabelPartition, 16);
71/** Pointer to a BSD disklabel partition structure. */
72typedef BsdLabelPartition *PBsdLabelPartition;
73
74/**
75 * On disk BSD label structure.
76 */
77typedef struct BsdLabel
78{
79 /** Magic identifying the BSD disk label. */
80 uint32_t u32Magic;
81 /** Drive type */
82 uint16_t u16DriveType;
83 /** Subtype depending on the drive type above. */
84 uint16_t u16SubType;
85 /** Type name. */
86 uint8_t abTypeName[16];
87 /** Pack identifier. */
88 uint8_t abPackName[16];
89 /** Number of bytes per sector. */
90 uint32_t cbSector;
91 /** Number of sectors per track. */
92 uint32_t cSectorsPerTrack;
93 /** Number of tracks per cylinder. */
94 uint32_t cTracksPerCylinder;
95 /** Number of data cylinders pre unit. */
96 uint32_t cDataCylindersPerUnit;
97 /** Number of data sectors per cylinder. */
98 uint32_t cDataSectorsPerCylinder;
99 /** Number of data sectors per unit (unit as in disk drive?). */
100 uint32_t cSectorsPerUnit;
101 /** Number of spare sectors per track. */
102 uint16_t cSpareSectorsPerTrack;
103 /** Number of spare sectors per cylinder. */
104 uint16_t cSpareSectorsPerCylinder;
105 /** Number of alternate cylinders per unit. */
106 uint32_t cSpareCylindersPerUnit;
107 /** Rotational speed of the disk drive in rotations per minute. */
108 uint16_t cRotationsPerMinute;
109 /** Sector interleave. */
110 uint16_t uSectorInterleave;
111 /** Sector 0 skew, per track. */
112 uint16_t uSectorSkewPerTrack;
113 /** Sector 0 skew, per cylinder. */
114 uint16_t uSectorSkewPerCylinder;
115 /** Head switch time in us. */
116 uint32_t usHeadSwitch;
117 /** Time of a track-to-track seek in us. */
118 uint32_t usTrackSeek;
119 /** Flags. */
120 uint32_t fFlags;
121 /** Drive type sepcific information. */
122 uint32_t au32DriveData[5];
123 /** Reserved. */
124 uint32_t au32Reserved[5];
125 /** The magic number again. */
126 uint32_t u32Magic2;
127 /** Checksum (xor of the whole structure). */
128 uint16_t u16ChkSum;
129 /** Number of partitions in the array. */
130 uint16_t cPartitions;
131 /** Boot area size in bytes. */
132 uint32_t cbBootArea;
133 /** Maximum size of the filesystem super block. */
134 uint32_t cbFsSuperBlock;
135 /** The partition array. */
136 BsdLabelPartition aPartitions[RTDVM_BSDLBL_MAX_PARTITIONS];
137} BsdLabel;
138AssertCompileSize(BsdLabel, 148 + RTDVM_BSDLBL_MAX_PARTITIONS * 16);
139/** Pointer to a BSD disklabel structure. */
140typedef BsdLabel *PBsdLabel;
141
142/**
143 * BSD disk label volume manager data.
144 */
145typedef struct RTDVMFMTINTERNAL
146{
147 /** Pointer to the underlying disk. */
148 PCRTDVMDISK pDisk;
149 /** Number of used partitions. */
150 uint32_t cPartitions;
151 /** Saved BSD disklabel structure. */
152 BsdLabel DiskLabel;
153} RTDVMFMTINTERNAL;
154/** Pointer to the MBR volume manager. */
155typedef RTDVMFMTINTERNAL *PRTDVMFMTINTERNAL;
156
157/**
158 * MBR volume data.
159 */
160typedef struct RTDVMVOLUMEFMTINTERNAL
161{
162 /** Pointer to the volume manager. */
163 PRTDVMFMTINTERNAL pVolMgr;
164 /** Partition table entry index. */
165 uint32_t idxEntry;
166 /** Start offset of the volume. */
167 uint64_t offStart;
168 /** Size of the volume. */
169 uint64_t cbVolume;
170 /** Pointer to the raw partition table entry. */
171 PBsdLabelPartition pBsdPartitionEntry;
172} RTDVMVOLUMEFMTINTERNAL;
173/** Pointer to an MBR volume. */
174typedef RTDVMVOLUMEFMTINTERNAL *PRTDVMVOLUMEFMTINTERNAL;
175
176/** Converts a LBA number to the byte offset. */
177#define RTDVM_BSDLBL_LBA2BYTE(lba, disk) ((lba) * (disk)->cbSector)
178/** Converts a Byte offset to the LBA number. */
179#define RTDVM_BSDLBL_BYTE2LBA(lba, disk) ((lba) / (disk)->cbSector)
180
181/**
182 * Calculates the checksum of the entire bsd disklabel structure.
183 *
184 * @returns The checksum.
185 * @param pBsdLabel BSD disklabel to get the checksum for.
186 */
187static uint16_t rtDvmFmtBsdLblDiskLabelChkSum(PBsdLabel pBsdLabel)
188{
189 uint16_t uChkSum = 0;
190 uint16_t *pCurr = (uint16_t *)pBsdLabel;
191 uint16_t *pEnd = (uint16_t *)&pBsdLabel->aPartitions[pBsdLabel->cPartitions];
192
193 while (pCurr < pEnd)
194 uChkSum ^= *pCurr++;
195
196 return uChkSum;
197}
198
199/**
200 * Converts a partition entry to the host endianness.
201 *
202 * @returns nothing.
203 * @param pPartition The partition to decode.
204 */
205static void rtDvmFmtBsdLblDiskLabelDecodePartition(PBsdLabelPartition pPartition)
206{
207 pPartition->cSectors = RT_LE2H_U32(pPartition->cSectors);
208 pPartition->offSectorStart = RT_LE2H_U32(pPartition->offSectorStart);
209 pPartition->cbFsFragment = RT_LE2H_U32(pPartition->cbFsFragment);
210 pPartition->cFsCylPerGroup = RT_LE2H_U16(pPartition->cFsCylPerGroup);
211}
212
213/**
214 * Converts the on disk BSD label to the host endianness.
215 *
216 * @returns Whether the given label structure is a valid BSD disklabel.
217 * @param pBsdLabel Pointer to the BSD disklabel to decode.
218 */
219static bool rtDvmFmtBsdLblDiskLabelDecode(PBsdLabel pBsdLabel)
220{
221 pBsdLabel->u32Magic = RT_LE2H_U32(pBsdLabel->u32Magic);
222 pBsdLabel->u16DriveType = RT_LE2H_U16(pBsdLabel->u16DriveType);
223 pBsdLabel->u16SubType = RT_LE2H_U16(pBsdLabel->u16SubType);
224 pBsdLabel->cbSector = RT_LE2H_U32(pBsdLabel->cbSector);
225 pBsdLabel->cSectorsPerTrack = RT_LE2H_U32(pBsdLabel->cSectorsPerTrack);
226 pBsdLabel->cTracksPerCylinder = RT_LE2H_U32(pBsdLabel->cTracksPerCylinder);
227 pBsdLabel->cDataCylindersPerUnit = RT_LE2H_U32(pBsdLabel->cDataCylindersPerUnit);
228 pBsdLabel->cDataSectorsPerCylinder = RT_LE2H_U32(pBsdLabel->cDataSectorsPerCylinder);
229 pBsdLabel->cSectorsPerUnit = RT_LE2H_U32(pBsdLabel->cSectorsPerUnit);
230 pBsdLabel->cSpareSectorsPerTrack = RT_LE2H_U16(pBsdLabel->cSpareSectorsPerTrack);
231 pBsdLabel->cSpareSectorsPerCylinder = RT_LE2H_U16(pBsdLabel->cSpareSectorsPerCylinder);
232 pBsdLabel->cSpareCylindersPerUnit = RT_LE2H_U32(pBsdLabel->cSpareCylindersPerUnit);
233 pBsdLabel->cRotationsPerMinute = RT_LE2H_U16(pBsdLabel->cRotationsPerMinute);
234 pBsdLabel->uSectorInterleave = RT_LE2H_U16(pBsdLabel->uSectorInterleave);
235 pBsdLabel->uSectorSkewPerTrack = RT_LE2H_U16(pBsdLabel->uSectorSkewPerTrack);
236 pBsdLabel->uSectorSkewPerCylinder = RT_LE2H_U16(pBsdLabel->uSectorSkewPerCylinder);
237 pBsdLabel->usHeadSwitch = RT_LE2H_U16(pBsdLabel->usHeadSwitch);
238 pBsdLabel->usTrackSeek = RT_LE2H_U16(pBsdLabel->usTrackSeek);
239 pBsdLabel->fFlags = RT_LE2H_U32(pBsdLabel->fFlags);
240
241 for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->au32DriveData); i++)
242 pBsdLabel->au32DriveData[i] = RT_LE2H_U32(pBsdLabel->au32DriveData[i]);
243 for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->au32Reserved); i++)
244 pBsdLabel->au32Reserved[i] = RT_LE2H_U32(pBsdLabel->au32Reserved[i]);
245
246 pBsdLabel->u32Magic2 = RT_LE2H_U32(pBsdLabel->u32Magic2);
247 pBsdLabel->u16ChkSum = RT_LE2H_U16(pBsdLabel->u16ChkSum);
248 pBsdLabel->cPartitions = RT_LE2H_U16(pBsdLabel->cPartitions);
249 pBsdLabel->cbBootArea = RT_LE2H_U32(pBsdLabel->cbBootArea);
250 pBsdLabel->cbFsSuperBlock = RT_LE2H_U32(pBsdLabel->cbFsSuperBlock);
251
252 /* Check the magics now. */
253 if ( pBsdLabel->u32Magic != RTDVM_BSDLBL_MAGIC
254 || pBsdLabel->u32Magic2 != RTDVM_BSDLBL_MAGIC
255 || pBsdLabel->cPartitions != RTDVM_BSDLBL_MAX_PARTITIONS)
256 return false;
257
258 /* Convert the partitions array. */
259 for (unsigned i = 0; i < RT_ELEMENTS(pBsdLabel->aPartitions); i++)
260 rtDvmFmtBsdLblDiskLabelDecodePartition(&pBsdLabel->aPartitions[i]);
261
262 /* Check the checksum now. */
263 uint16_t u16ChkSumSaved = pBsdLabel->u16ChkSum;
264
265 pBsdLabel->u16ChkSum = 0;
266 if (u16ChkSumSaved != rtDvmFmtBsdLblDiskLabelChkSum(pBsdLabel))
267 return false;
268
269 pBsdLabel->u16ChkSum = u16ChkSumSaved;
270 return true;
271}
272
273static DECLCALLBACK(int) rtDvmFmtBsdLblProbe(PCRTDVMDISK pDisk, uint32_t *puScore)
274{
275 BsdLabel DiskLabel;
276 int rc = VINF_SUCCESS;
277
278 *puScore = RTDVM_MATCH_SCORE_UNSUPPORTED;
279
280 if (pDisk->cbDisk >= sizeof(BsdLabel))
281 {
282 /* Read from the disk and check for the disk label structure. */
283 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &DiskLabel, sizeof(BsdLabel));
284 if ( RT_SUCCESS(rc)
285 && rtDvmFmtBsdLblDiskLabelDecode(&DiskLabel))
286 *puScore = RTDVM_MATCH_SCORE_PERFECT;
287 }
288 return rc;
289}
290
291static DECLCALLBACK(int) rtDvmFmtBsdLblOpen(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
292{
293 int rc = VINF_SUCCESS;
294 PRTDVMFMTINTERNAL pThis = NULL;
295
296 pThis = (PRTDVMFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMFMTINTERNAL));
297 if (pThis)
298 {
299 pThis->pDisk = pDisk;
300 pThis->cPartitions = 0;
301
302 /* Read from the disk and check for the disk label structure. */
303 rc = rtDvmDiskReadUnaligned(pDisk, RTDVM_BSDLBL_LBA2BYTE(1, pDisk), &pThis->DiskLabel, sizeof(BsdLabel));
304 if ( RT_SUCCESS(rc)
305 && rtDvmFmtBsdLblDiskLabelDecode(&pThis->DiskLabel))
306 {
307 /* Count number of used entries. */
308 for (unsigned i = 0; i < pThis->DiskLabel.cPartitions; i++)
309 if (pThis->DiskLabel.aPartitions[i].cSectors)
310 pThis->cPartitions++;
311
312 *phVolMgrFmt = pThis;
313 }
314 else
315 {
316 RTMemFree(pThis);
317 rc = VERR_INVALID_MAGIC;
318 }
319 }
320 else
321 rc = VERR_NO_MEMORY;
322
323 return rc;
324}
325
326static DECLCALLBACK(int) rtDvmFmtBsdLblInitialize(PCRTDVMDISK pDisk, PRTDVMFMT phVolMgrFmt)
327{
328 NOREF(pDisk); NOREF(phVolMgrFmt);
329 return VERR_NOT_IMPLEMENTED;
330}
331
332static DECLCALLBACK(void) rtDvmFmtBsdLblClose(RTDVMFMT hVolMgrFmt)
333{
334 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
335
336 pThis->pDisk = NULL;
337 pThis->cPartitions = 0;
338 RT_ZERO(pThis->DiskLabel);
339 RTMemFree(pThis);
340}
341
342static DECLCALLBACK(int) rtDvmFmtBsdLblQueryRangeUse(RTDVMFMT hVolMgrFmt,
343 uint64_t off, uint64_t cbRange,
344 bool *pfUsed)
345{
346 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
347
348 NOREF(cbRange);
349
350 if (off <= RTDVM_BSDLBL_LBA2BYTE(1, pThis->pDisk))
351 *pfUsed = true;
352 else
353 *pfUsed = false;
354
355 return VINF_SUCCESS;
356}
357
358static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblGetValidVolumes(RTDVMFMT hVolMgrFmt)
359{
360 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
361 return pThis->cPartitions;
362}
363
364static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblGetMaxVolumes(RTDVMFMT hVolMgrFmt)
365{
366 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
367 return pThis->DiskLabel.cPartitions;
368}
369
370/**
371 * Creates a new volume.
372 *
373 * @returns IPRT status code.
374 * @param pThis The MBR volume manager data.
375 * @param pbBsdLblEntry The raw MBR entry data.
376 * @param idx The index in the partition table.
377 * @param phVolFmt Where to store the volume data on success.
378 */
379static int rtDvmFmtBsdLblVolumeCreate(PRTDVMFMTINTERNAL pThis, PBsdLabelPartition pBsdPartitionEntry,
380 uint32_t idx, PRTDVMVOLUMEFMT phVolFmt)
381{
382 int rc = VINF_SUCCESS;
383 PRTDVMVOLUMEFMTINTERNAL pVol = (PRTDVMVOLUMEFMTINTERNAL)RTMemAllocZ(sizeof(RTDVMVOLUMEFMTINTERNAL));
384
385 if (pVol)
386 {
387 pVol->pVolMgr = pThis;
388 pVol->idxEntry = idx;
389 pVol->pBsdPartitionEntry = pBsdPartitionEntry;
390 pVol->offStart = (uint64_t)pBsdPartitionEntry->offSectorStart * pThis->DiskLabel.cbSector;
391 pVol->cbVolume = (uint64_t)pBsdPartitionEntry->cSectors * pThis->DiskLabel.cbSector;
392
393 *phVolFmt = pVol;
394 }
395 else
396 rc = VERR_NO_MEMORY;
397
398 return rc;
399}
400
401static DECLCALLBACK(int) rtDvmFmtBsdLblQueryFirstVolume(RTDVMFMT hVolMgrFmt, PRTDVMVOLUMEFMT phVolFmt)
402{
403 int rc = VINF_SUCCESS;
404 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
405
406 if (pThis->cPartitions != 0)
407 {
408 /* Search for the first non empty entry. */
409 for (unsigned i = 0; i < pThis->DiskLabel.cPartitions; i++)
410 {
411 if (pThis->DiskLabel.aPartitions[i].cSectors)
412 {
413 rc = rtDvmFmtBsdLblVolumeCreate(pThis, &pThis->DiskLabel.aPartitions[i], i, phVolFmt);
414 break;
415 }
416 }
417 }
418 else
419 rc = VERR_DVM_MAP_EMPTY;
420
421 return rc;
422}
423
424static DECLCALLBACK(int) rtDvmFmtBsdLblQueryNextVolume(RTDVMFMT hVolMgrFmt, RTDVMVOLUMEFMT hVolFmt, PRTDVMVOLUMEFMT phVolFmtNext)
425{
426 int rc = VERR_DVM_MAP_NO_VOLUME;
427 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
428 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
429 PBsdLabelPartition pBsdPartitionEntry = pVol->pBsdPartitionEntry + 1;
430
431 for (unsigned i = pVol->idxEntry + 1; i < pThis->DiskLabel.cPartitions; i++)
432 {
433 if (pBsdPartitionEntry->cSectors)
434 {
435 rc = rtDvmFmtBsdLblVolumeCreate(pThis, pBsdPartitionEntry, i, phVolFmtNext);
436 break;
437 }
438 pBsdPartitionEntry++;
439 }
440
441 return rc;
442}
443
444/** @copydoc RTDVMFMTOPS::pfnQueryTableLocations */
445static DECLCALLBACK(int) rtDvmFmtBsdLblQueryTableLocations(RTDVMFMT hVolMgrFmt, uint32_t fFlags, PRTDVMTABLELOCATION paLocations,
446 size_t cLocations, size_t *pcActual)
447{
448 PRTDVMFMTINTERNAL pThis = hVolMgrFmt;
449
450 /*
451 * The MBR if requested.
452 */
453 int rc = VINF_SUCCESS;
454 size_t iLoc = 0;
455 if (fFlags & RTDVMMAPQTABLOC_F_INCLUDE_LEGACY)
456 {
457 if (cLocations > 0)
458 {
459 paLocations[iLoc].off = 0;
460 paLocations[iLoc].cb = RTDVM_BSDLBL_LBA2BYTE(1, pThis->pDisk);
461 paLocations[iLoc].cbPadding = 0;
462 }
463 else
464 rc = VERR_BUFFER_OVERFLOW;
465 iLoc++;
466 }
467
468 /*
469 * The BSD lable.
470 */
471 if (cLocations > iLoc)
472 {
473 paLocations[iLoc].off = RTDVM_BSDLBL_LBA2BYTE(1, pThis->pDisk);
474 paLocations[iLoc].cb = (sizeof(BsdLabel) + pThis->pDisk->cbSector - 1) / pThis->pDisk->cbSector * pThis->pDisk->cbSector;
475
476 uint32_t offFirstSector = pThis->pDisk->cbDisk / pThis->pDisk->cbSector;
477 for (unsigned i = 0; i < pThis->DiskLabel.cPartitions; i++)
478 if ( pThis->DiskLabel.aPartitions[i].cSectors
479 && pThis->DiskLabel.aPartitions[i].offSectorStart < offFirstSector)
480 offFirstSector = pThis->DiskLabel.aPartitions[i].offSectorStart;
481
482 uint64_t offEnd = paLocations[iLoc].off + paLocations[iLoc].cb;
483 paLocations[iLoc].cbPadding = (uint64_t)offFirstSector * pThis->DiskLabel.cbSector;
484 if (paLocations[iLoc].cbPadding > offEnd)
485 paLocations[iLoc].cbPadding -= offEnd;
486 else
487 AssertFailedStmt(paLocations[iLoc].cbPadding = 0);
488 }
489 else
490 rc = VERR_BUFFER_OVERFLOW;
491 iLoc++;
492
493 /*
494 * Return values.
495 */
496 if (pcActual)
497 *pcActual = iLoc;
498 else if (cLocations != iLoc && RT_SUCCESS(rc))
499 {
500 RT_BZERO(&paLocations[iLoc], (cLocations - iLoc) * sizeof(paLocations[0]));
501 rc = VERR_BUFFER_UNDERFLOW;
502 }
503 return rc;
504}
505
506static DECLCALLBACK(void) rtDvmFmtBsdLblVolumeClose(RTDVMVOLUMEFMT hVolFmt)
507{
508 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
509
510 pVol->pVolMgr = NULL;
511 pVol->offStart = 0;
512 pVol->cbVolume = 0;
513 pVol->pBsdPartitionEntry = NULL;
514
515 RTMemFree(pVol);
516}
517
518static DECLCALLBACK(uint64_t) rtDvmFmtBsdLblVolumeGetSize(RTDVMVOLUMEFMT hVolFmt)
519{
520 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
521
522 return pVol->cbVolume;
523}
524
525static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryName(RTDVMVOLUMEFMT hVolFmt, char **ppszVolName)
526{
527 NOREF(hVolFmt); NOREF(ppszVolName);
528 return VERR_NOT_SUPPORTED;
529}
530
531static DECLCALLBACK(RTDVMVOLTYPE) rtDvmFmtBsdLblVolumeGetType(RTDVMVOLUMEFMT hVolFmt)
532{
533 NOREF(hVolFmt);
534 return RTDVMVOLTYPE_UNKNOWN;
535}
536
537static DECLCALLBACK(uint64_t) rtDvmFmtBsdLblVolumeGetFlags(RTDVMVOLUMEFMT hVolFmt)
538{
539 NOREF(hVolFmt);
540 return DVMVOLUME_F_CONTIGUOUS;
541}
542
543static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryRange(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffStart, uint64_t *poffLast)
544{
545 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
546 *poffStart = pVol->offStart;
547 *poffLast = pVol->offStart + pVol->cbVolume - 1;
548 return VINF_SUCCESS;
549}
550
551static DECLCALLBACK(bool) rtDvmFmtBsdLblVolumeIsRangeIntersecting(RTDVMVOLUMEFMT hVolFmt,
552 uint64_t offStart, size_t cbRange,
553 uint64_t *poffVol,
554 uint64_t *pcbIntersect)
555{
556 bool fIntersect = false;
557 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
558
559 if (RTDVM_RANGE_IS_INTERSECTING(pVol->offStart, pVol->cbVolume, offStart))
560 {
561 fIntersect = true;
562 *poffVol = offStart - pVol->offStart;
563 *pcbIntersect = RT_MIN(cbRange, pVol->offStart + pVol->cbVolume - offStart);
564 }
565
566 return fIntersect;
567}
568
569/** @copydoc RTDVMFMTOPS::pfnVolumeQueryTableLocation */
570static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryTableLocation(RTDVMVOLUMEFMT hVolFmt, uint64_t *poffTable, uint64_t *pcbTable)
571{
572 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
573 *poffTable = RTDVM_BSDLBL_LBA2BYTE(1, pVol->pVolMgr->pDisk);
574 *pcbTable = RT_ALIGN_Z(sizeof(BsdLabel), pVol->pVolMgr->pDisk->cbSector);
575 return VINF_SUCCESS;
576}
577
578/** @copydoc RTDVMFMTOPS::pfnVolumeGetIndex */
579static DECLCALLBACK(uint32_t) rtDvmFmtBsdLblVolumeGetIndex(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLIDX enmIndex)
580{
581 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
582 switch (enmIndex)
583 {
584 case RTDVMVOLIDX_USER_VISIBLE:
585 case RTDVMVOLIDX_ALL:
586 case RTDVMVOLIDX_LINUX:
587 return pVol->idxEntry + 1;
588 case RTDVMVOLIDX_IN_TABLE:
589 return pVol->idxEntry;
590
591 case RTDVMVOLIDX_INVALID:
592 case RTDVMVOLIDX_HOST:
593 case RTDVMVOLIDX_END:
594 case RTDVMVOLIDX_32BIT_HACK:
595 break;
596 /* no default! */
597 }
598 AssertFailed();
599 return UINT32_MAX;
600}
601
602/** @copydoc RTDVMFMTOPS::pfnVolumeQueryProp */
603static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeQueryProp(RTDVMVOLUMEFMT hVolFmt, RTDVMVOLPROP enmProperty,
604 void *pvBuf, size_t cbBuf, size_t *pcbBuf)
605{
606 switch (enmProperty)
607 {
608 case RTDVMVOLPROP_MBR_FIRST_CYLINDER:
609 case RTDVMVOLPROP_MBR_FIRST_HEAD:
610 case RTDVMVOLPROP_MBR_FIRST_SECTOR:
611 case RTDVMVOLPROP_MBR_LAST_CYLINDER:
612 case RTDVMVOLPROP_MBR_LAST_HEAD:
613 case RTDVMVOLPROP_MBR_LAST_SECTOR:
614 case RTDVMVOLPROP_MBR_TYPE:
615 case RTDVMVOLPROP_GPT_TYPE:
616 case RTDVMVOLPROP_GPT_UUID:
617 return VERR_NOT_SUPPORTED;
618
619 case RTDVMVOLPROP_INVALID:
620 case RTDVMVOLPROP_END:
621 case RTDVMVOLPROP_32BIT_HACK:
622 break;
623 /* no default! */
624 }
625 RT_NOREF(hVolFmt, pvBuf, cbBuf, pcbBuf);
626 return VERR_NOT_SUPPORTED;
627}
628
629static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeRead(RTDVMVOLUMEFMT hVolFmt, uint64_t off, void *pvBuf, size_t cbRead)
630{
631 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
632 AssertReturn(off + cbRead <= pVol->cbVolume, VERR_INVALID_PARAMETER);
633
634 return rtDvmDiskRead(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbRead);
635}
636
637static DECLCALLBACK(int) rtDvmFmtBsdLblVolumeWrite(RTDVMVOLUMEFMT hVolFmt, uint64_t off, const void *pvBuf, size_t cbWrite)
638{
639 PRTDVMVOLUMEFMTINTERNAL pVol = hVolFmt;
640 AssertReturn(off + cbWrite <= pVol->cbVolume, VERR_INVALID_PARAMETER);
641
642 return rtDvmDiskWrite(pVol->pVolMgr->pDisk, pVol->offStart + off, pvBuf, cbWrite);
643}
644
645DECL_HIDDEN_CONST(const RTDVMFMTOPS) g_rtDvmFmtBsdLbl =
646{
647 /* pcszFmt */
648 "BsdLabel",
649 /* enmFormat, */
650 RTDVMFORMATTYPE_BSD_LABEL,
651 /* pfnProbe */
652 rtDvmFmtBsdLblProbe,
653 /* pfnOpen */
654 rtDvmFmtBsdLblOpen,
655 /* pfnInitialize */
656 rtDvmFmtBsdLblInitialize,
657 /* pfnClose */
658 rtDvmFmtBsdLblClose,
659 /* pfnQueryRangeUse */
660 rtDvmFmtBsdLblQueryRangeUse,
661 /* pfnQueryDiskUuid */
662 NULL,
663 /* pfnGetValidVolumes */
664 rtDvmFmtBsdLblGetValidVolumes,
665 /* pfnGetMaxVolumes */
666 rtDvmFmtBsdLblGetMaxVolumes,
667 /* pfnQueryFirstVolume */
668 rtDvmFmtBsdLblQueryFirstVolume,
669 /* pfnQueryNextVolume */
670 rtDvmFmtBsdLblQueryNextVolume,
671 /* pfnQueryTableLocations */
672 rtDvmFmtBsdLblQueryTableLocations,
673 /* pfnVolumeClose */
674 rtDvmFmtBsdLblVolumeClose,
675 /* pfnVolumeGetSize */
676 rtDvmFmtBsdLblVolumeGetSize,
677 /* pfnVolumeQueryName */
678 rtDvmFmtBsdLblVolumeQueryName,
679 /* pfnVolumeGetType */
680 rtDvmFmtBsdLblVolumeGetType,
681 /* pfnVolumeGetFlags */
682 rtDvmFmtBsdLblVolumeGetFlags,
683 /* pfnVolumeQueryRange */
684 rtDvmFmtBsdLblVolumeQueryRange,
685 /* pfnVolumeIsRangeIntersecting */
686 rtDvmFmtBsdLblVolumeIsRangeIntersecting,
687 /* pfnVolumeQueryTableLocation */
688 rtDvmFmtBsdLblVolumeQueryTableLocation,
689 /* pfnVolumeGetIndex */
690 rtDvmFmtBsdLblVolumeGetIndex,
691 /* pfnVolumeQueryProp */
692 rtDvmFmtBsdLblVolumeQueryProp,
693 /* pfnVolumeRead */
694 rtDvmFmtBsdLblVolumeRead,
695 /* pfnVolumeWrite */
696 rtDvmFmtBsdLblVolumeWrite
697};
698
Note: See TracBrowser for help on using the repository browser.

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