xref: /onnv-gate/usr/src/lib/libparted/common/libparted/labels/bsd.c (revision 9663:ace9a2ac3683)
1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2 
3     libparted - a library for manipulating disk partitions
4     Copyright (C) 2000, 2001, 2007 Free Software Foundation, Inc.
5 
6     This program is free software; you can redistribute it and/or modify
7     it under the terms of the GNU General Public License as published by
8     the Free Software Foundation; either version 3 of the License, or
9     (at your option) any later version.
10 
11     This program is distributed in the hope that it will be useful,
12     but WITHOUT ANY WARRANTY; without even the implied warranty of
13     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14     GNU General Public License for more details.
15 
16     You should have received a copy of the GNU General Public License
17     along with this program.  If not, see <http://www.gnu.org/licenses/>.
18 
19     Contributor:  Matt Wilson <msw@redhat.com>
20 */
21 
22 #include <config.h>
23 
24 #include <parted/parted.h>
25 #include <parted/debug.h>
26 #include <parted/endian.h>
27 
28 #if ENABLE_NLS
29 #  include <libintl.h>
30 #  define _(String) dgettext (PACKAGE, String)
31 #else
32 #  define _(String) (String)
33 #endif /* ENABLE_NLS */
34 
35 /* struct's & #define's stolen from libfdisk, which probably came from
36  * Linux...
37  */
38 
39 #define BSD_DISKMAGIC	(0x82564557UL)	/* The disk magic number */
40 #define BSD_MAXPARTITIONS	8
41 #define BSD_FS_UNUSED		0	/* disklabel unused partition entry ID */
42 #define BSD_LABEL_OFFSET	64
43 
44 #define	BSD_DTYPE_SMD		1		/* SMD, XSMD; VAX hp/up */
45 #define	BSD_DTYPE_MSCP		2		/* MSCP */
46 #define	BSD_DTYPE_DEC		3		/* other DEC (rk, rl) */
47 #define	BSD_DTYPE_SCSI		4		/* SCSI */
48 #define	BSD_DTYPE_ESDI		5		/* ESDI interface */
49 #define	BSD_DTYPE_ST506		6		/* ST506 etc. */
50 #define	BSD_DTYPE_HPIB		7		/* CS/80 on HP-IB */
51 #define BSD_DTYPE_HPFL		8		/* HP Fiber-link */
52 #define	BSD_DTYPE_FLOPPY	10		/* floppy */
53 
54 #define	BSD_BBSIZE	8192		/* size of boot area, with label */
55 #define	BSD_SBSIZE	8192		/* max size of fs superblock */
56 
57 typedef struct _BSDRawPartition		BSDRawPartition;
58 typedef struct _BSDRawLabel		BSDRawLabel;
59 
60 #ifdef __sun
61 #define __attribute__(X)	/*nothing*/
62 #endif /* __sun */
63 
64 #ifdef __sun
65 #pragma pack(1)
66 #endif
67 struct _BSDRawPartition {		/* the partition table */
68 	uint32_t	p_size;		/* number of sectors in partition */
69 	uint32_t	p_offset;	/* starting sector */
70 	uint32_t	p_fsize;	/* file system basic fragment size */
71 	uint8_t		p_fstype;	/* file system type, see below */
72 	uint8_t		p_frag;		/* file system fragments per block */
73 	uint16_t	p_cpg;		/* file system cylinders per group */
74 } __attribute__((packed));
75 #ifdef __sun
76 #pragma pack()
77 #endif
78 
79 #ifdef __sun
80 #pragma pack(1)
81 #endif
82 struct _BSDRawLabel {
83 	uint32_t	d_magic;		/* the magic number */
84 	int16_t		d_type;			/* drive type */
85 	int16_t		d_subtype;		/* controller/d_type specific */
86 	int8_t		d_typename[16];		/* type name, e.g. "eagle" */
87 	int8_t		d_packname[16];		/* pack identifier */
88 	uint32_t	d_secsize;		/* # of bytes per sector */
89 	uint32_t	d_nsectors;		/* # of data sectors per track */
90 	uint32_t	d_ntracks;		/* # of tracks per cylinder */
91 	uint32_t	d_ncylinders;		/* # of data cylinders per unit */
92 	uint32_t	d_secpercyl;		/* # of data sectors per cylinder */
93 	uint32_t	d_secperunit;		/* # of data sectors per unit */
94 	uint16_t	d_sparespertrack;	/* # of spare sectors per track */
95 	uint16_t	d_sparespercyl;		/* # of spare sectors per cylinder */
96 	uint32_t	d_acylinders;		/* # of alt. cylinders per unit */
97 	uint16_t	d_rpm;			/* rotational speed */
98 	uint16_t	d_interleave;		/* hardware sector interleave */
99 	uint16_t	d_trackskew;		/* sector 0 skew, per track */
100 	uint16_t	d_cylskew;		/* sector 0 skew, per cylinder */
101 	uint32_t	d_headswitch;		/* head switch time, usec */
102 	uint32_t	d_trkseek;		/* track-to-track seek, usec */
103 	uint32_t	d_flags;		/* generic flags */
104 #define NDDATA 5
105 	uint32_t	d_drivedata[NDDATA];	/* drive-type specific information */
106 #define NSPARE 5
107 	uint32_t	d_spare[NSPARE];	/* reserved for future use */
108 	uint32_t	d_magic2;		/* the magic number (again) */
109 	uint16_t	d_checksum;		/* xor of data incl. partitions */
110 
111 	/* file system and partition information: */
112 	uint16_t	d_npartitions;		/* number of partitions in following */
113 	uint32_t	d_bbsize;		/* size of boot area at sn0, bytes */
114 	uint32_t	d_sbsize;		/* max size of fs superblock, bytes */
115 	BSDRawPartition d_partitions[BSD_MAXPARTITIONS];	/* actually may be more */
116 } __attribute__((packed));
117 #ifdef __sun
118 #pragma pack()
119 #endif
120 
121 typedef struct {
122 	char		boot_code [512];
123 } BSDDiskData;
124 
125 typedef struct {
126 	uint8_t		type;
127 } BSDPartitionData;
128 
129 static PedDiskType bsd_disk_type;
130 
131 /* XXX fixme: endian? */
132 static unsigned short
xbsd_dkcksum(BSDRawLabel * lp)133 xbsd_dkcksum (BSDRawLabel *lp) {
134 	unsigned short *start, *end;
135 	unsigned short sum = 0;
136 
137 	lp->d_checksum = 0;
138 	start = (u_short*) lp;
139 	end = (u_short*) &lp->d_partitions [
140 				PED_LE16_TO_CPU (lp->d_npartitions)];
141 	while (start < end)
142 		sum ^= *start++;
143 	return sum;
144 }
145 
146 /* XXX fixme: endian? */
147 static void
alpha_bootblock_checksum(char * boot)148 alpha_bootblock_checksum (char *boot) {
149 	uint64_t *dp, sum;
150 	int i;
151 
152 	dp = (uint64_t *)boot;
153 	sum = 0;
154 	for (i = 0; i < 63; i++)
155 		sum += dp[i];
156 	dp[63] = sum;
157 }
158 
159 
160 static int
bsd_probe(const PedDevice * dev)161 bsd_probe (const PedDevice *dev)
162 {
163 	char		boot[512];
164 	BSDRawLabel	*label;
165 
166 	PED_ASSERT (dev != NULL, return 0);
167 
168         if (dev->sector_size != 512)
169                 return 0;
170 
171 	if (!ped_device_read (dev, boot, 0, 1))
172 		return 0;
173 
174 	label = (BSDRawLabel *) (boot + BSD_LABEL_OFFSET);
175 
176 	alpha_bootblock_checksum(boot);
177 
178 	/* check magic */
179 	if (PED_LE32_TO_CPU (label->d_magic) != BSD_DISKMAGIC)
180 		return 0;
181 
182 	return 1;
183 }
184 
185 static PedDisk*
bsd_alloc(const PedDevice * dev)186 bsd_alloc (const PedDevice* dev)
187 {
188 	PedDisk*	disk;
189 	BSDDiskData*	bsd_specific;
190 	BSDRawLabel*	label;
191 
192 	PED_ASSERT(dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, return 0);
193 
194 	disk = _ped_disk_alloc ((PedDevice*)dev, &bsd_disk_type);
195 	if (!disk)
196 		goto error;
197 	disk->disk_specific = bsd_specific = ped_malloc (sizeof (BSDDiskData));
198 	if (!bsd_specific)
199 		goto error_free_disk;
200         /* Initialize the first byte to zero, so that the code in bsd_write
201            knows to call _probe_and_add_boot_code.  Initializing all of the
202            remaining buffer is a little wasteful, but the alternative is to
203            figure out why a block at offset 340 would otherwise be used
204            uninitialized.  */
205 	memset(bsd_specific->boot_code, 0, sizeof (bsd_specific->boot_code));
206 
207 	label = (BSDRawLabel*) (bsd_specific->boot_code + BSD_LABEL_OFFSET);
208 
209 	label->d_magic = PED_CPU_TO_LE32 (BSD_DISKMAGIC);
210 	label->d_type = PED_CPU_TO_LE16 (BSD_DTYPE_SCSI);
211 	label->d_flags = 0;
212 	label->d_secsize = PED_CPU_TO_LE16 (dev->sector_size);
213 	label->d_nsectors = PED_CPU_TO_LE32 (dev->bios_geom.sectors);
214 	label->d_ntracks = PED_CPU_TO_LE32 (dev->bios_geom.heads);
215 	label->d_ncylinders = PED_CPU_TO_LE32 (dev->bios_geom.cylinders);
216 	label->d_secpercyl = PED_CPU_TO_LE32 (dev->bios_geom.sectors
217 						* dev->bios_geom.heads);
218 	label->d_secperunit
219 		= PED_CPU_TO_LE32 (dev->bios_geom.sectors
220 				   * dev->bios_geom.heads
221 				   * dev->bios_geom.cylinders);
222 
223 	label->d_rpm = PED_CPU_TO_LE16 (3600);
224 	label->d_interleave = PED_CPU_TO_LE16 (1);;
225 	label->d_trackskew = 0;
226 	label->d_cylskew = 0;
227 	label->d_headswitch = 0;
228 	label->d_trkseek = 0;
229 
230 	label->d_magic2 = PED_CPU_TO_LE32 (BSD_DISKMAGIC);
231 	label->d_bbsize = PED_CPU_TO_LE32 (BSD_BBSIZE);
232 	label->d_sbsize = PED_CPU_TO_LE32 (BSD_SBSIZE);
233 
234 	label->d_npartitions = 0;
235 	label->d_checksum = xbsd_dkcksum (label);
236 	return disk;
237 
238 error_free_disk:
239 	ped_free (disk);
240 error:
241 	return NULL;
242 }
243 
244 static PedDisk*
bsd_duplicate(const PedDisk * disk)245 bsd_duplicate (const PedDisk* disk)
246 {
247 	PedDisk*	new_disk;
248 	BSDDiskData*	new_bsd_data;
249 	BSDDiskData*	old_bsd_data = (BSDDiskData*) disk->disk_specific;
250 
251 	new_disk = ped_disk_new_fresh (disk->dev, &bsd_disk_type);
252 	if (!new_disk)
253 		return NULL;
254 
255 	new_bsd_data = (BSDDiskData*) new_disk->disk_specific;
256 	memcpy (new_bsd_data->boot_code, old_bsd_data->boot_code, 512);
257 	return new_disk;
258 }
259 
260 static void
bsd_free(PedDisk * disk)261 bsd_free (PedDisk* disk)
262 {
263 	ped_free (disk->disk_specific);
264 	_ped_disk_free (disk);
265 }
266 
267 #ifndef DISCOVER_ONLY
268 static int
bsd_clobber(PedDevice * dev)269 bsd_clobber (PedDevice* dev)
270 {
271 	char		boot [512];
272 	BSDRawLabel*	label = (BSDRawLabel *) (boot + BSD_LABEL_OFFSET);
273 
274 	if (!ped_device_read (dev, boot, 0, 1))
275 		return 0;
276 	label->d_magic = 0;
277 	return ped_device_write (dev, (void*) boot, 0, 1);
278 }
279 #endif /* !DISCOVER_ONLY */
280 
281 static int
bsd_read(PedDisk * disk)282 bsd_read (PedDisk* disk)
283 {
284 	BSDDiskData*	bsd_specific = (BSDDiskData*) disk->disk_specific;
285 	BSDRawLabel*	label;
286 	int 		i;
287 
288 	ped_disk_delete_all (disk);
289 
290 	if (!ped_device_read (disk->dev, bsd_specific->boot_code, 0, 1))
291 		goto error;
292 	label = (BSDRawLabel *) (bsd_specific->boot_code + BSD_LABEL_OFFSET);
293 
294 	for (i = 1; i <= BSD_MAXPARTITIONS; i++) {
295 		PedPartition* 		part;
296 		BSDPartitionData*	bsd_part_data;
297 		PedSector		start;
298 		PedSector		end;
299 		PedConstraint*		constraint_exact;
300 
301 		if (!label->d_partitions[i - 1].p_size
302 		    || !label->d_partitions[i - 1].p_fstype)
303 			continue;
304 		start = PED_LE32_TO_CPU(label->d_partitions[i - 1].p_offset);
305 		end = PED_LE32_TO_CPU(label->d_partitions[i - 1].p_offset)
306 		      + PED_LE32_TO_CPU(label->d_partitions[i - 1].p_size) - 1;
307 		part = ped_partition_new (disk, 0, NULL, start, end);
308 		if (!part)
309 			goto error;
310 		bsd_part_data = part->disk_specific;
311 		bsd_part_data->type = label->d_partitions[i - 1].p_fstype;
312 		part->num = i;
313 		part->fs_type = ped_file_system_probe (&part->geom);
314 
315 		constraint_exact = ped_constraint_exact (&part->geom);
316 		if (!ped_disk_add_partition (disk, part, constraint_exact))
317 			goto error;
318 		ped_constraint_destroy (constraint_exact);
319 	}
320 
321 	return 1;
322 
323 error:
324 	return 0;
325 }
326 
327 static void
_probe_and_add_boot_code(const PedDisk * disk)328 _probe_and_add_boot_code (const PedDisk* disk)
329 {
330 	BSDDiskData*		bsd_specific;
331 	BSDRawLabel*		old_label;
332 	char			old_boot_code [512];
333 
334 	bsd_specific = (BSDDiskData*) disk->disk_specific;
335 	old_label = (BSDRawLabel*) (old_boot_code + BSD_LABEL_OFFSET);
336 
337 	if (!ped_device_read (disk->dev, old_boot_code, 0, 1))
338 		return;
339 	if (old_boot_code [0]
340 	    && old_label->d_magic == PED_CPU_TO_LE32 (BSD_DISKMAGIC))
341 		memcpy (bsd_specific->boot_code, old_boot_code, 512);
342 }
343 
344 #ifndef DISCOVER_ONLY
345 static int
bsd_write(const PedDisk * disk)346 bsd_write (const PedDisk* disk)
347 {
348 	BSDDiskData*		bsd_specific;
349 	BSDRawLabel*		label;
350 	BSDPartitionData*	bsd_data;
351 	PedPartition*		part;
352 	int			i;
353 	int			max_part = 0;
354 
355 	PED_ASSERT (disk != NULL, return 0);
356 	PED_ASSERT (disk->dev != NULL, return 0);
357 
358 	bsd_specific = (BSDDiskData*) disk->disk_specific;
359 	label = (BSDRawLabel *) (bsd_specific->boot_code + BSD_LABEL_OFFSET);
360 
361 	if (!bsd_specific->boot_code [0])
362 		_probe_and_add_boot_code (disk);
363 
364 	memset (label->d_partitions, 0,
365 		sizeof (BSDRawPartition) * BSD_MAXPARTITIONS);
366 
367 	for (i = 1; i <= BSD_MAXPARTITIONS; i++) {
368 		part = ped_disk_get_partition (disk, i);
369 		if (!part)
370 			continue;
371 		bsd_data = part->disk_specific;
372 		label->d_partitions[i - 1].p_fstype = bsd_data->type;
373 		label->d_partitions[i - 1].p_offset
374 			= PED_CPU_TO_LE32 (part->geom.start);
375 		label->d_partitions[i - 1].p_size
376 			= PED_CPU_TO_LE32 (part->geom.length);
377 		max_part = i;
378 	}
379 
380 	label->d_npartitions = PED_CPU_TO_LE16 (max_part) + 1;
381 	label->d_checksum = xbsd_dkcksum (label);
382 
383 	alpha_bootblock_checksum (bsd_specific->boot_code);
384 
385 	if (!ped_device_write (disk->dev, (void*) bsd_specific->boot_code,
386 			       0, 1))
387 		goto error;
388 	return ped_device_sync (disk->dev);
389 
390 error:
391 	return 0;
392 }
393 #endif /* !DISCOVER_ONLY */
394 
395 static PedPartition*
bsd_partition_new(const PedDisk * disk,PedPartitionType part_type,const PedFileSystemType * fs_type,PedSector start,PedSector end)396 bsd_partition_new (const PedDisk* disk, PedPartitionType part_type,
397 		   const PedFileSystemType* fs_type,
398 		   PedSector start, PedSector end)
399 {
400 	PedPartition*		part;
401 	BSDPartitionData*	bsd_data;
402 
403 	part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
404 	if (!part)
405 		goto error;
406 
407 	if (ped_partition_is_active (part)) {
408 		part->disk_specific
409 		       	= bsd_data = ped_malloc (sizeof (BSDPartitionData));
410 		if (!bsd_data)
411 			goto error_free_part;
412 		bsd_data->type = 0;
413 	} else {
414 		part->disk_specific = NULL;
415 	}
416 	return part;
417 
418 	ped_free (bsd_data);
419 error_free_part:
420 	ped_free (part);
421 error:
422 	return 0;
423 }
424 
425 static PedPartition*
bsd_partition_duplicate(const PedPartition * part)426 bsd_partition_duplicate (const PedPartition* part)
427 {
428 	PedPartition*		new_part;
429 	BSDPartitionData*	new_bsd_data;
430 	BSDPartitionData*	old_bsd_data;
431 
432 	new_part = ped_partition_new (part->disk, part->type,
433 				      part->fs_type, part->geom.start,
434 				      part->geom.end);
435 	if (!new_part)
436 		return NULL;
437 	new_part->num = part->num;
438 
439 	old_bsd_data = (BSDPartitionData*) part->disk_specific;
440 	new_bsd_data = (BSDPartitionData*) new_part->disk_specific;
441 	new_bsd_data->type = old_bsd_data->type;
442 	return new_part;
443 }
444 
445 static void
bsd_partition_destroy(PedPartition * part)446 bsd_partition_destroy (PedPartition* part)
447 {
448 	PED_ASSERT (part != NULL, return);
449 
450 	if (ped_partition_is_active (part))
451 		ped_free (part->disk_specific);
452 	_ped_partition_free (part);
453 }
454 
455 static int
bsd_partition_set_system(PedPartition * part,const PedFileSystemType * fs_type)456 bsd_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
457 {
458 	BSDPartitionData* bsd_data = part->disk_specific;
459 
460 	part->fs_type = fs_type;
461 
462 	if (!fs_type)
463 		bsd_data->type = 0x8;
464 	else if (!strcmp (fs_type->name, "linux-swap"))
465 		bsd_data->type = 0x1;
466 	else
467 		bsd_data->type = 0x8;
468 
469 	return 1;
470 }
471 
472 static int
bsd_partition_set_flag(PedPartition * part,PedPartitionFlag flag,int state)473 bsd_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
474 {
475 	/* no flags for bsd */
476 	return 0;
477 }
478 
479 static int
bsd_partition_get_flag(const PedPartition * part,PedPartitionFlag flag)480 bsd_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
481 {
482 	/* no flags for bsd */
483 	return 0;
484 }
485 
486 static int
bsd_partition_is_flag_available(const PedPartition * part,PedPartitionFlag flag)487 bsd_partition_is_flag_available (const PedPartition* part,
488 				 PedPartitionFlag flag)
489 {
490 	/* no flags for bsd */
491 	return 0;
492 }
493 
494 
495 static int
bsd_get_max_primary_partition_count(const PedDisk * disk)496 bsd_get_max_primary_partition_count (const PedDisk* disk)
497 {
498 	return BSD_MAXPARTITIONS;
499 }
500 
501 static PedConstraint*
_get_constraint(const PedDevice * dev)502 _get_constraint (const PedDevice* dev)
503 {
504 	PedGeometry	max;
505 
506 	ped_geometry_init (&max, dev, 1, dev->length - 1);
507 	return ped_constraint_new_from_max (&max);
508 }
509 
510 static int
bsd_partition_align(PedPartition * part,const PedConstraint * constraint)511 bsd_partition_align (PedPartition* part, const PedConstraint* constraint)
512 {
513 	if (_ped_partition_attempt_align (part, constraint,
514 					  _get_constraint (part->disk->dev)))
515 	       	return 1;
516 
517 #ifndef DISCOVER_ONLY
518 	ped_exception_throw (
519 		PED_EXCEPTION_ERROR,
520 		PED_EXCEPTION_CANCEL,
521 		_("Unable to satisfy all constraints on the partition."));
522 #endif
523 	return 0;
524 }
525 
526 static int
bsd_partition_enumerate(PedPartition * part)527 bsd_partition_enumerate (PedPartition* part)
528 {
529 	int i;
530 	PedPartition* p;
531 
532 	/* never change the partition numbers */
533 	if (part->num != -1)
534 		return 1;
535 	for (i = 1; i <= BSD_MAXPARTITIONS; i++) {
536 		p = ped_disk_get_partition (part->disk, i);
537 		if (!p) {
538 			part->num = i;
539 			return 1;
540 		}
541 	}
542 
543 	/* failed to allocate a number */
544 #ifndef DISCOVER_ONLY
545 	ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
546 			     _("Unable to allocate a bsd disklabel slot."));
547 #endif
548 	return 0;
549 }
550 
551 static int
bsd_alloc_metadata(PedDisk * disk)552 bsd_alloc_metadata (PedDisk* disk)
553 {
554 	PedPartition*		new_part;
555 	PedConstraint*		constraint_any = NULL;
556 
557 	PED_ASSERT (disk != NULL, goto error);
558 	PED_ASSERT (disk->dev != NULL, goto error);
559 
560 	constraint_any = ped_constraint_any (disk->dev);
561 
562 	/* allocate 1 sector for the disk label at the start */
563 	new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 0, 0);
564 	if (!new_part)
565 		goto error;
566 
567 	if (!ped_disk_add_partition (disk, new_part, constraint_any)) {
568 		ped_partition_destroy (new_part);
569 		goto error;
570 	}
571 
572 	ped_constraint_destroy (constraint_any);
573 	return 1;
574 error:
575 	ped_constraint_destroy (constraint_any);
576 	return 0;
577 }
578 
579 static PedDiskOps bsd_disk_ops = {
580 	.probe =		bsd_probe,
581 #ifndef DISCOVER_ONLY
582 	.clobber =		bsd_clobber,
583 #else
584 	.clobber =		NULL,
585 #endif
586 	.alloc =		bsd_alloc,
587 	.duplicate =		bsd_duplicate,
588 	.free =			bsd_free,
589 	.read =			bsd_read,
590 #ifndef DISCOVER_ONLY
591 	.write =		bsd_write,
592 #else
593 	.write =		NULL,
594 #endif
595 
596 	.partition_new =	bsd_partition_new,
597 	.partition_duplicate =	bsd_partition_duplicate,
598 	.partition_destroy =	bsd_partition_destroy,
599 	.partition_set_system =	bsd_partition_set_system,
600 	.partition_set_flag =	bsd_partition_set_flag,
601 	.partition_get_flag =	bsd_partition_get_flag,
602 	.partition_is_flag_available =	bsd_partition_is_flag_available,
603 	.partition_set_name =	NULL,
604 	.partition_get_name =	NULL,
605 	.partition_align =	bsd_partition_align,
606 	.partition_enumerate =	bsd_partition_enumerate,
607 
608 	.alloc_metadata =	bsd_alloc_metadata,
609 	.get_max_primary_partition_count =
610 				bsd_get_max_primary_partition_count
611 };
612 
613 static PedDiskType bsd_disk_type = {
614 	.next =			NULL,
615 	.name =			"bsd",
616 	.ops =			&bsd_disk_ops,
617 	.features =		0
618 };
619 
620 void
ped_disk_bsd_init()621 ped_disk_bsd_init ()
622 {
623 	PED_ASSERT (sizeof (BSDRawPartition) == 16, return);
624 	PED_ASSERT (sizeof (BSDRawLabel) == 276, return);
625 
626 	ped_disk_type_register (&bsd_disk_type);
627 }
628 
629 void
ped_disk_bsd_done()630 ped_disk_bsd_done ()
631 {
632 	ped_disk_type_unregister (&bsd_disk_type);
633 }
634