VirtualBox

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

Last change on this file since 98103 was 98103, checked in by vboxsync, 17 months ago

Copyright year updates by scm.

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

© 2023 Oracle
ContactPrivacy policyTerms of Use