2 libparted - a library for manipulating disk partitions
3 Copyright (C) 2000, 2002, 2004, 2007 Free Software Foundation, Inc.
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
22 #include <parted/parted.h>
23 #include <parted/debug.h>
24 #include <parted/endian.h>
28 # define _(String) dgettext (PACKAGE, String)
30 # define _(String) (String)
31 #endif /* ENABLE_NLS */
33 /* struct's hacked from Linux source: fs/partitions/mac.h
34 * I believe it was originally written by Paul Mackerras (from comments in
38 * http://developer.apple.com/documentation/mac/Devices/Devices-126.html
39 * http://developer.apple.com/documentation/mac/Devices/Devices-121.html
40 * http://devworld.apple.com/technotes/tn/tn1189.html
43 * Apple_Bootstrap new-world (HFS) boot partition
44 * Apple_partition_map partition map (table)
45 * Apple_Driver device driver
46 * Apple_Driver43 SCSI Manager 4.3 device driver
47 * Apple_MFS original Macintosh File System
48 * Apple_HFS Hierarchical File System (and +)
49 * Apple_HFSX HFS+ with case sensitivity and more
50 * Apple_UNIX_SVR2 UNIX file system (UFS?)
51 * Apple_PRODOS ProDOS file system
52 * Apple_Free unused space
54 * Apple_Void padding for iso9660
55 * Apple_Extra an unused partition map entry
65 * partition volume or partition
68 * * All space must be accounted for, except block 0 (driver block) and
69 * block 1-X (the partition map: i.e. lots of MacRawPartitions)
71 * * It's really hard to grow/shrink the number of MacRawPartition
72 * entries in the partition map, because the first partition starts
73 * immediately after the partition map. When we can move the start of
74 * HFS and ext2 partitions, this problem will disappear ;-)
77 #define MAC_PARTITION_MAGIC_1 0x5453 /* old */
78 #define MAC_PARTITION_MAGIC_2 0x504d
79 #define MAC_DISK_MAGIC 0x4552
81 #define MAC_STATUS_BOOTABLE 8 /* partition is bootable */
83 typedef struct _MacRawPartition MacRawPartition;
84 typedef struct _MacRawDisk MacRawDisk;
85 typedef struct _MacDeviceDriver MacDeviceDriver;
86 typedef struct _MacPartitionData MacPartitionData;
87 typedef struct _MacDiskData MacDiskData;
89 struct __attribute__ ((packed)) _MacRawPartition {
90 uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
92 uint32_t map_count; /* # blocks in partition map */
93 uint32_t start_block; /* absolute starting block # of partition */
94 uint32_t block_count; /* number of blocks in partition */
95 char name[32]; /* partition name */
96 char type[32]; /* string type description */
97 uint32_t data_start; /* rel block # of first data block */
98 uint32_t data_count; /* number of data blocks */
99 uint32_t status; /* partition status bits */
105 uint32_t boot_entry2;
107 char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
112 /* Driver descriptor structure, in block 0 */
113 struct __attribute__ ((packed)) _MacRawDisk {
114 uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
115 uint16_t block_size; /* physical sector size */
116 uint32_t block_count; /* size of device in blocks */
117 uint16_t dev_type; /* reserved */
118 uint16_t dev_id; /* reserved */
119 uint32_t data; /* reserved */
120 uint16_t driver_count; /* # of driver descriptor entries */
121 uint8_t driverlist[488];/* info about available drivers */
122 uint16_t padding[3]; /* pad to 512 bytes */
125 struct __attribute__ ((packed)) _MacDeviceDriver {
126 uint32_t block; /* startblock in MacRawDisk->block_size units */
127 uint16_t size; /* size in 512 byte units */
128 uint16_t type; /* operating system type (MacOS = 1) */
131 struct _MacPartitionData {
132 char volume_name[33]; /* eg: "Games" */
133 char system_name[33]; /* eg: "Apple_Unix_SVR2" */
134 char processor_name[17];
144 PedSector data_region_length;
145 PedSector boot_region_length;
147 uint32_t boot_base_address;
148 uint32_t boot_entry_address;
149 uint32_t boot_checksum;
155 struct _MacDiskData {
156 int ghost_size; /* sectors per "driver" block */
157 int part_map_entry_count; /* # entries (incl. ghost) */
158 int part_map_entry_num; /* partition map location */
160 int active_part_entry_count; /* # real partitions */
161 int free_part_entry_count; /* # free space */
162 int last_part_entry_num; /* last entry number */
164 uint16_t block_size; /* physical sector size */
165 uint16_t driver_count;
166 MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */
169 static PedDiskType mac_disk_type;
172 _check_signature (MacRawDisk* raw_disk)
174 if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
178 return ped_exception_throw (
180 PED_EXCEPTION_IGNORE_CANCEL,
181 _("Invalid signature %x for Mac disk labels."),
182 (int) PED_BE16_TO_CPU (raw_disk->signature))
183 == PED_EXCEPTION_IGNORE;
191 _rawpart_check_signature (MacRawPartition* raw_part)
193 int sig = (int) PED_BE16_TO_CPU (raw_part->signature);
194 return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
198 mac_probe (const PedDevice * dev)
202 PED_ASSERT (dev != NULL, return 0);
204 if (dev->sector_size != 512)
207 if (!ped_device_read (dev, &buf, 0, 1))
210 return _check_signature (&buf);
214 _disk_add_part_map_entry (PedDisk* disk, int warn)
216 MacDiskData* mac_disk_data = disk->disk_specific;
217 PedPartition* new_part;
218 MacPartitionData* mac_part_data;
219 PedSector part_map_size;
220 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
222 #ifndef DISCOVER_ONLY
223 if (warn && ped_exception_throw (
225 PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
226 _("Partition map has no partition map entry!"))
227 != PED_EXCEPTION_FIX)
229 #endif /* !DISCOVER_ONLY */
232 = ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
233 if (part_map_size == 0)
236 new_part = ped_partition_new (disk, 0, NULL, 1, part_map_size - 1);
240 mac_part_data = new_part->disk_specific;
241 strcpy (mac_part_data->volume_name, "Apple");
242 strcpy (mac_part_data->system_name, "Apple_partition_map");
244 if (!ped_disk_add_partition (disk, new_part, constraint_any))
245 goto error_destroy_new_part;
247 mac_disk_data->part_map_entry_num = new_part->num;
248 mac_disk_data->part_map_entry_count
249 = new_part->geom.end - mac_disk_data->ghost_size;
250 ped_constraint_destroy (constraint_any);
253 error_destroy_new_part:
254 ped_partition_destroy (new_part);
256 ped_constraint_destroy (constraint_any);
261 mac_alloc (const PedDevice* dev)
264 MacDiskData* mac_disk_data;
266 PED_ASSERT (dev != NULL, return NULL);
268 #ifndef DISCOVER_ONLY
269 if (dev->length < 256) {
270 ped_exception_throw (
272 PED_EXCEPTION_CANCEL,
273 _("%s is too small for a Mac disk label!"),
279 disk = _ped_disk_alloc (dev, &mac_disk_type);
283 mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
285 goto error_free_disk;
286 disk->disk_specific = mac_disk_data;
287 mac_disk_data->ghost_size = disk->dev->sector_size / 512;
288 mac_disk_data->active_part_entry_count = 0;
289 mac_disk_data->free_part_entry_count = 1;
290 mac_disk_data->last_part_entry_num = 1;
291 mac_disk_data->block_size = 0;
292 mac_disk_data->driver_count = 0;
293 memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
295 if (!_disk_add_part_map_entry (disk, 0))
296 goto error_free_disk;
300 _ped_disk_free (disk);
306 mac_duplicate (const PedDisk* disk)
309 MacDiskData* new_mac_data;
310 MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific;
311 PedPartition* partition_map;
313 new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type);
317 new_mac_data = (MacDiskData*) new_disk->disk_specific;
319 /* remove the partition map partition - it will be duplicated
322 partition_map = ped_disk_get_partition_by_sector (new_disk, 1);
323 PED_ASSERT (partition_map != NULL, return 0);
324 ped_disk_remove_partition (new_disk, partition_map);
326 /* ugly, but C is ugly :p */
327 memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
330 _ped_disk_free (new_disk);
336 mac_free (PedDisk* disk)
338 MacDiskData* mac_disk_data = disk->disk_specific;
340 _ped_disk_free (disk);
341 ped_free (mac_disk_data);
344 #ifndef DISCOVER_ONLY
346 _clobber_part_map (PedDevice* dev)
348 MacRawPartition raw_part;
351 for (sector=1; 1; sector++) {
352 if (!ped_device_read (dev, &raw_part, sector, 1))
354 if (!_rawpart_check_signature (&raw_part))
356 memset (&raw_part, 0, 512);
357 if (!ped_device_write (dev, &raw_part, sector, 1))
363 mac_clobber (PedDevice* dev)
367 if (!ped_device_read (dev, &raw_disk, 0, 1))
369 if (!_check_signature (&raw_disk))
371 memset (&raw_disk, 0, 512);
372 if (!ped_device_write (dev, &raw_disk, 0, 1))
375 return _clobber_part_map (dev);
377 #endif /* !DISCOVER_ONLY */
380 _rawpart_cmp_type (MacRawPartition* raw_part, char* type)
382 return strncasecmp (raw_part->type, type, 32) == 0;
386 _rawpart_cmp_name (MacRawPartition* raw_part, char* name)
388 return strncasecmp (raw_part->name, name, 32) == 0;
392 _rawpart_is_partition_map (MacRawPartition* raw_part)
394 return _rawpart_cmp_type (raw_part, "Apple_partition_map");
398 strncasestr (const char* haystack, const char* needle, int n)
400 int needle_size = strlen (needle);
403 for (i = 0; haystack[i] && i < n - needle_size; i++) {
404 if (strncasecmp (haystack + i, needle, needle_size) == 0)
412 _rawpart_is_boot (MacRawPartition* raw_part)
414 if (!strcasecmp(raw_part->type, "Apple_Bootstrap"))
417 if (!strcasecmp(raw_part->type, "Apple_Boot"))
424 _rawpart_is_driver (MacRawPartition* raw_part)
426 if (strncmp (raw_part->type, "Apple_", 6) != 0)
428 if (!strncasestr (raw_part->type, "driver", 32))
434 _rawpart_has_driver (MacRawPartition* raw_part, MacDiskData* mac_disk_data)
436 MacDeviceDriver *driverlist;
438 uint32_t driver_bs, driver_be, part_be;
440 driverlist = &mac_disk_data->driverlist[0];
441 bsz = mac_disk_data->block_size / 512;
442 for (i = 0; i < mac_disk_data->driver_count; i++) {
443 driver_bs = driverlist->block * bsz;
444 driver_be = driver_bs + driverlist->size;
445 part_be = raw_part->start_block + raw_part->block_count;
446 if (driver_bs >= raw_part->start_block && driver_be <= part_be)
454 _rawpart_is_root (MacRawPartition* raw_part)
456 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
458 if (strcmp (raw_part->name, "root") != 0)
464 _rawpart_is_swap (MacRawPartition* raw_part)
466 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
468 if (strcmp (raw_part->name, "swap") != 0)
474 _rawpart_is_lvm (MacRawPartition* raw_part)
476 if (strcmp (raw_part->type, "Linux_LVM") != 0)
482 _rawpart_is_raid (MacRawPartition* raw_part)
484 if (strcmp (raw_part->type, "Linux_RAID") != 0)
490 _rawpart_is_void (MacRawPartition* raw_part)
492 return _rawpart_cmp_type (raw_part, "Apple_Void");
495 /* returns 1 if the raw_part represents a partition that is "unused space", or
496 * doesn't represent a partition at all. NOTE: some people make Apple_Free
497 * partitions with MacOS, because they can't select another type. So, if the
498 * name is anything other than "Extra" or "", it is treated as a "real"
502 _rawpart_is_active (MacRawPartition* raw_part)
504 if (_rawpart_cmp_type (raw_part, "Apple_Free")
505 && (_rawpart_cmp_name (raw_part, "Extra")
506 || _rawpart_cmp_name (raw_part, "")))
508 if (_rawpart_cmp_type (raw_part, "Apple_Void"))
510 if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
512 if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
519 _rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
521 MacDiskData* mac_disk_data;
523 MacPartitionData* mac_part_data;
524 PedSector block_size;
525 PedSector start, length;
527 if (!_rawpart_check_signature (raw_part)) {
528 #ifndef DISCOVER_ONLY
529 if (ped_exception_throw (
530 PED_EXCEPTION_WARNING,
531 PED_EXCEPTION_IGNORE_CANCEL,
532 _("Partition %d has an invalid signature %x."),
534 (int) PED_BE16_TO_CPU (raw_part->signature))
535 != PED_EXCEPTION_IGNORE)
540 mac_disk_data = (MacDiskData*) disk->disk_specific;
541 block_size = disk->dev->sector_size / 512;
543 start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
544 length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
546 #ifndef DISCOVER_ONLY
547 ped_exception_throw (
549 PED_EXCEPTION_CANCEL,
550 _("Partition %d has an invalid length of 0 bytes!"),
555 part = ped_partition_new (disk, 0, NULL, start, start + length - 1);
559 mac_part_data = part->disk_specific;
561 strncpy (mac_part_data->volume_name, raw_part->name, 32);
562 strncpy (mac_part_data->system_name, raw_part->type, 32);
563 strncpy (mac_part_data->processor_name, raw_part->processor, 16);
565 mac_part_data->is_boot = _rawpart_is_boot (raw_part);
566 mac_part_data->is_driver = _rawpart_is_driver (raw_part);
567 if (mac_part_data->is_driver)
568 mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
569 mac_part_data->is_root = _rawpart_is_root (raw_part);
570 mac_part_data->is_swap = _rawpart_is_swap (raw_part);
571 mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
572 mac_part_data->is_raid = _rawpart_is_raid (raw_part);
575 #ifndef DISCOVER_ONLY
576 if (raw_part->data_start) {
577 ped_exception_throw (
579 PED_EXCEPTION_CANCEL,
580 _("The data region doesn't start at the start "
581 "of the partition."));
582 goto error_destroy_part;
584 #endif /* !DISCOVER_ONLY */
585 mac_part_data->data_region_length
586 = PED_BE32_TO_CPU (raw_part->data_count) * block_size;
588 /* boot region - we have no idea what this is for, but Mac OSX
589 * seems to put garbage here, and doesn't pay any attention to
590 * it afterwards. [clausen, dan burcaw]
593 if (raw_part->boot_start) {
594 ped_exception_throw (
596 PED_EXCEPTION_CANCEL,
597 _("The boot region doesn't start at the start "
598 "of the partition."));
599 goto error_destroy_part;
602 mac_part_data->boot_region_length
603 = PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
605 #ifndef DISCOVER_ONLY
606 if (mac_part_data->has_driver) {
607 if (mac_part_data->boot_region_length < part->geom.length) {
608 if (ped_exception_throw (
610 PED_EXCEPTION_IGNORE_CANCEL,
611 _("The partition's boot region doesn't occupy "
612 "the entire partition."))
613 != PED_EXCEPTION_IGNORE)
614 goto error_destroy_part;
617 if (mac_part_data->data_region_length < part->geom.length &&
618 !mac_part_data->is_boot) {
619 if (ped_exception_throw (
621 PED_EXCEPTION_IGNORE_CANCEL,
622 _("The partition's data region doesn't occupy "
623 "the entire partition."))
624 != PED_EXCEPTION_IGNORE)
625 goto error_destroy_part;
628 #endif /* !DISCOVER_ONLY */
630 mac_part_data->boot_base_address
631 = PED_BE32_TO_CPU (raw_part->boot_load);
632 mac_part_data->boot_entry_address
633 = PED_BE32_TO_CPU (raw_part->boot_entry);
634 mac_part_data->boot_checksum
635 = PED_BE32_TO_CPU (raw_part->boot_cksum);
637 mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
638 mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
643 ped_partition_destroy (part);
648 /* looks at the partition map size field in a mac raw partition, and calculates
649 * what the size of the partition map should be, from it
652 _rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
654 MacDiskData* mac_disk_data = disk->disk_specific;
655 PedSector sector_size = disk->dev->sector_size / 512;
656 PedSector part_map_start;
657 PedSector part_map_end;
659 part_map_start = mac_disk_data->ghost_size;
660 part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
662 return part_map_end - part_map_start + 1;
666 _disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
668 PedSector block_size;
670 if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
671 #ifndef DISCOVER_ONLY
672 ped_exception_throw (
674 PED_EXCEPTION_CANCEL,
675 _("Weird block size on device descriptor: %d bytes is "
676 "not divisible by 512."),
677 (int) PED_BE16_TO_CPU (raw_disk->block_size));
682 block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
683 if (block_size != disk->dev->sector_size / 512) {
684 #ifndef DISCOVER_ONLY
685 if (ped_exception_throw (
686 PED_EXCEPTION_WARNING,
687 PED_EXCEPTION_IGNORE_CANCEL,
688 _("The driver descriptor says the physical block size "
689 "is %d bytes, but Linux says it is %d bytes."),
690 (int) block_size * 512,
691 (int) disk->dev->sector_size)
692 != PED_EXCEPTION_IGNORE)
695 disk->dev->sector_size = block_size * 512;
704 /* Tries to figure out the block size used by the drivers, for the ghost
705 * partitioning scheme. Ghost partitioning works like this: the OpenFirmware
706 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
707 * perhaps, some other number?). To remain compatible, the partition map
708 * only has "real" partition map entries on ghost-aligned block numbers (and
709 * the others are padded with Apple_Void partitions). This function tries
710 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
711 * doesn't always equal 2048!!!)
714 _disk_analyse_ghost_size (PedDisk* disk)
716 MacDiskData* mac_disk_data = disk->disk_specific;
717 MacRawPartition raw_part;
720 for (i = 1; i < 64; i *= 2) {
721 if (!ped_device_read (disk->dev, &raw_part, i, 1))
723 if (_rawpart_check_signature (&raw_part)
724 && !_rawpart_is_void (&raw_part)) {
725 mac_disk_data->ghost_size = i;
726 PED_ASSERT (i <= disk->dev->sector_size / 512,
732 #ifndef DISCOVER_ONLY
733 ped_exception_throw (
735 PED_EXCEPTION_CANCEL,
736 _("No valid partition map found."));
742 mac_read (PedDisk* disk)
745 MacRawPartition raw_part;
746 MacDiskData* mac_disk_data;
749 PedSector ghost_size;
750 PedConstraint* constraint_exact;
751 int last_part_entry_num = 0;
753 PED_ASSERT (disk != NULL, return 0);
755 mac_disk_data = disk->disk_specific;
756 mac_disk_data->part_map_entry_num = 0; /* 0 == none */
758 if (!ped_device_read (disk->dev, &raw_disk, 0, 1))
760 if (!_check_signature (&raw_disk))
763 if (!_disk_analyse_block_size (disk, &raw_disk))
765 if (!_disk_analyse_ghost_size (disk))
767 ghost_size = mac_disk_data->ghost_size;
769 if (!ped_disk_delete_all (disk))
772 if (raw_disk.driver_count && raw_disk.driver_count < 62) {
773 memcpy(&mac_disk_data->driverlist[0], &raw_disk.driverlist[0],
774 sizeof(mac_disk_data->driverlist));
775 mac_disk_data->driver_count = raw_disk.driver_count;
776 mac_disk_data->block_size = raw_disk.block_size;
779 for (num=1; num==1 || num <= last_part_entry_num; num++) {
780 if (!ped_device_read (disk->dev, &raw_part,
781 num * ghost_size, 1))
782 goto error_delete_all;
784 if (!_rawpart_check_signature (&raw_part))
789 = _rawpart_get_partmap_size (&raw_part, disk);
790 if (_rawpart_get_partmap_size (&raw_part, disk)
791 != last_part_entry_num) {
792 if (ped_exception_throw (
794 PED_EXCEPTION_IGNORE_CANCEL,
795 _("Conflicting partition map entry sizes! "
796 "Entry 1 says it is %d, but entry %d says "
799 _rawpart_get_partmap_size (&raw_part, disk))
800 != PED_EXCEPTION_IGNORE)
801 goto error_delete_all;
804 if (!_rawpart_is_active (&raw_part))
807 part = _rawpart_analyse (&raw_part, disk, num);
809 goto error_delete_all;
811 part->fs_type = ped_file_system_probe (&part->geom);
812 constraint_exact = ped_constraint_exact (&part->geom);
813 if (!ped_disk_add_partition (disk, part, constraint_exact))
814 goto error_delete_all;
815 ped_constraint_destroy (constraint_exact);
817 if (_rawpart_is_partition_map (&raw_part)) {
818 if (mac_disk_data->part_map_entry_num
819 && ped_exception_throw (
821 PED_EXCEPTION_IGNORE_CANCEL,
822 _("Weird! There are 2 partitions "
824 != PED_EXCEPTION_IGNORE)
825 goto error_delete_all;
827 mac_disk_data->part_map_entry_num = num;
828 mac_disk_data->part_map_entry_count
829 = part->geom.end - ghost_size + 1;
833 if (!mac_disk_data->part_map_entry_num) {
834 if (!_disk_add_part_map_entry (disk, 1))
835 goto error_delete_all;
836 ped_disk_commit_to_dev (disk);
841 ped_disk_delete_all (disk);
846 #ifndef DISCOVER_ONLY
847 /* The Ghost partition: is a blank entry, used to pad out each block (where
848 * there physical block size > 512 bytes). This is because OpenFirmware uses
849 * 512 byte blocks, but device drivers Think Different TM, with a different
850 * lbock size, so we need to do this to avoid a clash (!)
853 _pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
855 MacDiskData* mac_disk_data = disk->disk_specific;
856 MacRawPartition ghost_entry;
859 memset (&ghost_entry, 0, sizeof (ghost_entry));
860 ghost_entry.signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
861 strcpy (ghost_entry.type, "Apple_Void");
862 ghost_entry.map_count
863 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
865 for (i=0; i < mac_disk_data->ghost_size - 1; i++)
866 memcpy (&part_map [i + (num - 1) * mac_disk_data->ghost_size],
867 &ghost_entry, sizeof (MacRawPartition));
873 _update_driver_count (MacRawPartition* part_map_entry,
874 MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
876 uint16_t i, count_orig, count_cur, bsz;
877 uint32_t driver_bs, driver_be, part_be;
879 bsz = mac_disk_data->block_size / 512;
880 count_cur = mac_driverdata->driver_count;
881 count_orig = mac_disk_data->driver_count;
882 for (i = 0; i < count_orig; i++) {
883 driver_bs = mac_disk_data->driverlist[i].block * bsz;
884 driver_be = driver_bs + mac_disk_data->driverlist[i].size;
885 part_be = part_map_entry->start_block + part_map_entry->block_count;
886 if (driver_bs >= part_map_entry->start_block
887 && driver_be <= part_be) {
888 mac_driverdata->driverlist[count_cur].block
889 = mac_disk_data->driverlist[i].block;
890 mac_driverdata->driverlist[count_cur].size
891 = mac_disk_data->driverlist[i].size;
892 mac_driverdata->driverlist[count_cur].type
893 = mac_disk_data->driverlist[i].type;
894 mac_driverdata->driver_count++;
901 _generate_raw_part (PedDisk* disk, PedPartition* part,
902 MacRawPartition* part_map, MacDiskData *mac_driverdata)
904 MacDiskData* mac_disk_data;
905 MacPartitionData* mac_part_data;
906 MacRawPartition* part_map_entry;
907 PedSector block_size = disk->dev->sector_size / 512;
909 PED_ASSERT (part->num > 0, goto error);
911 mac_disk_data = disk->disk_specific;
912 mac_part_data = part->disk_specific;
914 part_map_entry = &part_map [part->num * mac_disk_data->ghost_size - 1];
916 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
917 part_map_entry->map_count
918 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
919 part_map_entry->start_block
920 = PED_CPU_TO_BE32 (part->geom.start / block_size);
921 part_map_entry->block_count
922 = PED_CPU_TO_BE32 (part->geom.length / block_size);
923 strcpy (part_map_entry->name, mac_part_data->volume_name);
924 strcpy (part_map_entry->type, mac_part_data->system_name);
926 if (mac_part_data->is_driver) {
927 mac_part_data->boot_region_length = part->geom.length;
928 if (mac_part_data->has_driver)
929 _update_driver_count(part_map_entry, mac_driverdata,
932 mac_part_data->data_region_length = part->geom.length;
933 part_map_entry->data_count = PED_CPU_TO_BE32 (
934 mac_part_data->data_region_length / block_size);
935 part_map_entry->boot_count = PED_CPU_TO_BE32 (
936 mac_part_data->boot_region_length / block_size);
937 part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
938 part_map_entry->driver_sig
939 = PED_CPU_TO_BE32 (mac_part_data->driver_sig);
941 part_map_entry->boot_load =
942 PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
943 part_map_entry->boot_entry =
944 PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
945 part_map_entry->boot_cksum =
946 PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
948 strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
950 if (!_pad_raw_part (disk, part->num, part_map))
960 _generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
961 MacRawPartition* part_map)
963 MacDiskData* mac_disk_data = disk->disk_specific;
964 MacRawPartition* part_map_entry;
965 PedSector block_size = disk->dev->sector_size / 512;
967 PED_ASSERT (num > 0, goto error);
969 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
971 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
972 part_map_entry->map_count
973 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
974 part_map_entry->start_block
975 = PED_CPU_TO_BE32 (geom->start / block_size);
976 part_map_entry->block_count
977 = PED_CPU_TO_BE32 (geom->length / block_size);
978 strcpy (part_map_entry->name, "Extra");
979 strcpy (part_map_entry->type, "Apple_Free");
981 part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
982 part_map_entry->status = 0;
983 part_map_entry->driver_sig = 0;
985 if (!_pad_raw_part (disk, num, part_map))
995 _generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
997 MacDiskData* mac_disk_data = disk->disk_specific;
998 MacRawPartition* part_map_entry;
1000 PED_ASSERT (num > 0, return 0);
1002 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
1003 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
1004 part_map_entry->map_count
1005 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
1006 strcpy (part_map_entry->type, "Apple_Void");
1008 return _pad_raw_part (disk, num, part_map);
1011 /* returns the first empty entry in the partition map */
1013 _get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map)
1015 MacDiskData* mac_disk_data = disk->disk_specific;
1018 for (i=1; i <= mac_disk_data->last_part_entry_num; i++) {
1019 if (!part_map[i * mac_disk_data->ghost_size - 1].signature)
1027 write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
1029 PedDevice* dev = disk->dev;
1030 MacRawDisk raw_disk;
1032 if (!ped_device_read (dev, &raw_disk, 0, 1))
1035 raw_disk.signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
1036 raw_disk.block_size = PED_CPU_TO_BE16 (dev->sector_size);
1037 raw_disk.block_count
1038 = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
1040 raw_disk.driver_count = mac_driverdata->driver_count;
1041 memcpy(&raw_disk.driverlist[0], &mac_driverdata->driverlist[0],
1042 sizeof(raw_disk.driverlist));
1044 return ped_device_write (dev, &raw_disk, 0, 1);
1048 mac_write (PedDisk* disk)
1050 MacRawPartition* part_map;
1051 MacDiskData* mac_disk_data;
1052 MacDiskData* mac_driverdata; /* updated driver list */
1056 PED_ASSERT (disk != NULL, return 0);
1057 PED_ASSERT (disk->disk_specific != NULL, return 0);
1058 PED_ASSERT (disk->dev != NULL, return 0);
1059 PED_ASSERT (!disk->update_mode, return 0);
1061 mac_disk_data = disk->disk_specific;
1063 if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
1064 if (!_disk_add_part_map_entry (disk, 1))
1068 mac_driverdata = ped_malloc(sizeof(MacDiskData));
1069 if (!mac_driverdata)
1071 memset (mac_driverdata, 0, sizeof(MacDiskData));
1073 part_map = (MacRawPartition*)
1074 ped_malloc (mac_disk_data->part_map_entry_count * 512);
1076 goto error_free_driverdata;
1077 memset (part_map, 0, mac_disk_data->part_map_entry_count * 512);
1079 /* write (to memory) the "real" partitions */
1080 for (part = ped_disk_next_partition (disk, NULL); part;
1081 part = ped_disk_next_partition (disk, part)) {
1082 if (!ped_partition_is_active (part))
1084 if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
1085 goto error_free_part_map;
1088 /* write the "free space" partitions */
1089 for (part = ped_disk_next_partition (disk, NULL); part;
1090 part = ped_disk_next_partition (disk, part)) {
1091 if (part->type != PED_PARTITION_FREESPACE)
1093 num = _get_first_empty_part_entry (disk, part_map);
1094 if (!_generate_raw_freespace_part (disk, &part->geom, num,
1096 goto error_free_part_map;
1099 /* write the "void" (empty) partitions */
1100 for (num = _get_first_empty_part_entry (disk, part_map); num;
1101 num = _get_first_empty_part_entry (disk, part_map))
1102 _generate_empty_part (disk, num, part_map);
1105 if (!ped_device_write (disk->dev, part_map, 1,
1106 mac_disk_data->part_map_entry_count))
1107 goto error_free_part_map;
1108 ped_free (part_map);
1109 return write_block_zero (disk, mac_driverdata);
1111 error_free_part_map:
1112 ped_free (part_map);
1113 error_free_driverdata:
1114 ped_free (mac_driverdata);
1118 #endif /* !DISCOVER_ONLY */
1120 static PedPartition*
1122 const PedDisk* disk, PedPartitionType part_type,
1123 const PedFileSystemType* fs_type, PedSector start, PedSector end)
1126 MacPartitionData* mac_data;
1128 part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1132 if (ped_partition_is_active (part)) {
1134 = mac_data = ped_malloc (sizeof (MacPartitionData));
1136 goto error_free_part;
1138 memset (mac_data, 0, sizeof (MacPartitionData));
1139 strcpy (mac_data->volume_name, "untitled");
1141 part->disk_specific = NULL;
1145 ped_free (mac_data);
1152 static PedPartition*
1153 mac_partition_duplicate (const PedPartition* part)
1155 PedPartition* new_part;
1156 MacPartitionData* new_mac_data;
1157 MacPartitionData* old_mac_data;
1159 new_part = ped_partition_new (part->disk, part->type,
1160 part->fs_type, part->geom.start,
1164 new_part->num = part->num;
1166 old_mac_data = (MacPartitionData*) part->disk_specific;
1167 new_mac_data = (MacPartitionData*) new_part->disk_specific;
1169 /* ugly, but C is ugly :p */
1170 memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
1175 mac_partition_destroy (PedPartition* part)
1177 PED_ASSERT (part != NULL, return);
1179 if (ped_partition_is_active (part))
1180 ped_free (part->disk_specific);
1185 mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1187 MacPartitionData* mac_data = part->disk_specific;
1189 part->fs_type = fs_type;
1191 if (fs_type && !strcmp (fs_type->name, "linux-swap"))
1192 ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1194 if (mac_data->is_boot) {
1195 strcpy (mac_data->system_name, "Apple_Bootstrap");
1196 mac_data->status = 0x33;
1200 if (fs_type && (!strcmp (fs_type->name, "hfs")
1201 || !strcmp (fs_type->name, "hfs+"))) {
1202 strcpy (mac_data->system_name, "Apple_HFS");
1203 mac_data->status |= 0x7f;
1204 } else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
1205 strcpy (mac_data->system_name, "Apple_HFSX");
1206 mac_data->status |= 0x7f;
1208 strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
1209 mac_data->status = 0x33;
1216 mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1218 MacPartitionData* mac_data;
1220 PED_ASSERT (part != NULL, return 0);
1221 PED_ASSERT (part->disk_specific != NULL, return 0);
1223 mac_data = part->disk_specific;
1226 case PED_PARTITION_BOOT:
1227 mac_data->is_boot = state;
1230 return mac_partition_set_system (part, part->fs_type);
1233 strcpy (mac_data->system_name, "Apple_Bootstrap");
1234 mac_data->status = 0x33;
1238 case PED_PARTITION_ROOT:
1240 strcpy (mac_data->volume_name, "root");
1241 mac_data->is_swap = 0;
1243 if (mac_data->is_root)
1244 strcpy (mac_data->volume_name, "untitled");
1246 mac_data->is_root = state;
1249 case PED_PARTITION_SWAP:
1251 strcpy (mac_data->volume_name, "swap");
1252 mac_data->is_root = 0;
1254 if (mac_data->is_swap)
1255 strcpy (mac_data->volume_name, "untitled");
1257 mac_data->is_swap = state;
1260 case PED_PARTITION_LVM:
1262 strcpy (mac_data->system_name, "Linux_LVM");
1263 mac_data->is_lvm = state;
1265 if (mac_data->is_lvm)
1266 mac_partition_set_system (part, part->fs_type);
1270 case PED_PARTITION_RAID:
1272 strcpy (mac_data->system_name, "Linux_RAID");
1273 mac_data->is_raid = state;
1275 if (mac_data->is_raid)
1276 mac_partition_set_system (part, part->fs_type);
1286 mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1288 MacPartitionData* mac_data;
1290 PED_ASSERT (part != NULL, return 0);
1291 PED_ASSERT (part->disk_specific != NULL, return 0);
1293 mac_data = part->disk_specific;
1295 case PED_PARTITION_BOOT:
1296 return mac_data->is_boot;
1298 case PED_PARTITION_ROOT:
1299 return mac_data->is_root;
1301 case PED_PARTITION_SWAP:
1302 return mac_data->is_swap;
1304 case PED_PARTITION_LVM:
1305 return mac_data->is_lvm;
1307 case PED_PARTITION_RAID:
1308 return mac_data->is_raid;
1316 mac_partition_is_flag_available (
1317 const PedPartition* part, PedPartitionFlag flag)
1320 case PED_PARTITION_BOOT:
1321 case PED_PARTITION_ROOT:
1322 case PED_PARTITION_SWAP:
1323 case PED_PARTITION_LVM:
1324 case PED_PARTITION_RAID:
1333 mac_partition_set_name (PedPartition* part, const char* name)
1335 MacPartitionData* mac_data;
1338 PED_ASSERT (part != NULL, return);
1339 PED_ASSERT (part->disk_specific != NULL, return);
1340 mac_data = part->disk_specific;
1342 #ifndef DISCOVER_ONLY
1343 if (mac_data->is_root || mac_data->is_swap) {
1344 if (ped_exception_throw (
1345 PED_EXCEPTION_WARNING,
1346 PED_EXCEPTION_IGNORE_CANCEL,
1347 _("Changing the name of a root or swap partition "
1348 "will prevent Linux from recognising it as such."))
1349 != PED_EXCEPTION_IGNORE)
1351 mac_data->is_root = mac_data->is_swap = 0;
1355 strncpy (mac_data->volume_name, name, 32);
1356 mac_data->volume_name [32] = 0;
1357 for (i = strlen (mac_data->volume_name) - 1;
1358 mac_data->volume_name[i] == ' '; i--)
1359 mac_data->volume_name [i] = 0;
1363 mac_partition_get_name (const PedPartition* part)
1365 MacPartitionData* mac_data;
1367 PED_ASSERT (part != NULL, return NULL);
1368 PED_ASSERT (part->disk_specific != NULL, return NULL);
1369 mac_data = part->disk_specific;
1371 return mac_data->volume_name;
1374 static PedConstraint*
1375 _primary_constraint (PedDisk* disk)
1377 PedAlignment start_align;
1378 PedAlignment end_align;
1379 PedGeometry max_geom;
1380 PedSector sector_size;
1382 sector_size = disk->dev->sector_size / 512;
1384 if (!ped_alignment_init (&start_align, 0, sector_size))
1386 if (!ped_alignment_init (&end_align, -1, sector_size))
1388 if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1391 return ped_constraint_new (&start_align, &end_align, &max_geom,
1392 &max_geom, 1, disk->dev->length);
1396 mac_partition_align (PedPartition* part, const PedConstraint* constraint)
1398 PED_ASSERT (part != NULL, return 0);
1400 if (_ped_partition_attempt_align (part, constraint,
1401 _primary_constraint (part->disk)))
1404 #ifndef DISCOVER_ONLY
1405 ped_exception_throw (
1406 PED_EXCEPTION_ERROR,
1407 PED_EXCEPTION_CANCEL,
1408 _("Unable to satisfy all constraints on the partition."));
1414 mac_partition_enumerate (PedPartition* part)
1417 MacDiskData* mac_disk_data;
1421 PED_ASSERT (part != NULL, return 0);
1422 PED_ASSERT (part->disk != NULL, return 0);
1425 mac_disk_data = (MacDiskData*) disk->disk_specific;
1427 max_part_count = ped_disk_get_max_primary_partition_count (disk);
1429 if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
1432 for (i = 1; i <= max_part_count; i++) {
1433 if (!ped_disk_get_partition (disk, i)) {
1439 #ifndef DISCOVER_ONLY
1440 ped_exception_throw (
1441 PED_EXCEPTION_ERROR,
1442 PED_EXCEPTION_CANCEL,
1443 _("Can't add another partition -- the partition map is too "
1451 _disk_count_partitions (PedDisk* disk)
1453 MacDiskData* mac_disk_data = disk->disk_specific;
1454 PedPartition* part = NULL;
1455 PedPartition* last = NULL;
1457 PED_ASSERT (disk->update_mode, return 0);
1459 mac_disk_data->active_part_entry_count = 0;
1460 mac_disk_data->free_part_entry_count = 0;
1461 mac_disk_data->last_part_entry_num = 0;
1463 /* subtle: we only care about free space after the partition map.
1464 * the partition map is an "active" partition, BTW... */
1465 for (part = ped_disk_next_partition (disk, part); part;
1466 part = ped_disk_next_partition (disk, part)) {
1467 if (!ped_partition_is_active (part))
1470 mac_disk_data->active_part_entry_count++;
1471 if (last && last->geom.end + 1 < part->geom.start)
1472 mac_disk_data->free_part_entry_count++;
1473 mac_disk_data->last_part_entry_num
1474 = PED_MAX (mac_disk_data->last_part_entry_num,
1480 if (last && last->geom.end < disk->dev->length - 1)
1481 mac_disk_data->free_part_entry_count++;
1483 mac_disk_data->last_part_entry_num
1484 = PED_MAX (mac_disk_data->last_part_entry_num,
1485 mac_disk_data->active_part_entry_count
1486 + mac_disk_data->free_part_entry_count);
1491 add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
1493 PedPartition* new_part;
1494 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
1496 PED_ASSERT (disk != NULL, return 0);
1498 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1502 if (!ped_disk_add_partition (disk, new_part, constraint_any))
1503 goto error_destroy_new_part;
1505 ped_constraint_destroy (constraint_any);
1508 error_destroy_new_part:
1509 ped_partition_destroy (new_part);
1511 ped_constraint_destroy (constraint_any);
1516 mac_alloc_metadata (PedDisk* disk)
1518 MacDiskData* mac_disk_data;
1520 PED_ASSERT (disk != NULL, return 0);
1521 PED_ASSERT (disk->disk_specific != NULL, return 0);
1522 PED_ASSERT (disk->dev != NULL, return 0);
1524 mac_disk_data = disk->disk_specific;
1526 if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
1529 /* hack: this seems to be a good place, to update the partition map
1530 * entry count, since mac_alloc_metadata() gets called during
1531 * _disk_pop_update_mode()
1533 return _disk_count_partitions (disk);
1537 mac_get_max_primary_partition_count (const PedDisk* disk)
1539 MacDiskData* mac_disk_data = disk->disk_specific;
1540 PedPartition* part_map_partition;
1542 part_map_partition = ped_disk_get_partition (disk,
1543 mac_disk_data->part_map_entry_num);
1545 /* HACK: if we haven't found the partition map partition (yet),
1548 if (!part_map_partition) {
1549 mac_disk_data->part_map_entry_num = 0;
1553 /* HACK: since Mac labels need an entry for free-space regions, we
1554 * must allow half plus 1 entries for free-space partitions. I hate
1555 * this, but things get REALLY complicated, otherwise.
1556 * (I'm prepared to complicate things later, but I want to get
1557 * everything working, first)
1559 return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
1560 - mac_disk_data->free_part_entry_count + 1;
1563 static PedDiskOps mac_disk_ops = {
1565 #ifndef DISCOVER_ONLY
1566 clobber: mac_clobber,
1571 duplicate: mac_duplicate,
1574 #ifndef DISCOVER_ONLY
1575 /* FIXME: remove this cast, once mac_write is fixed not to
1576 modify its *DISK parameter. */
1577 write: (int (*) (const PedDisk*)) mac_write,
1582 partition_new: mac_partition_new,
1583 partition_duplicate: mac_partition_duplicate,
1584 partition_destroy: mac_partition_destroy,
1585 partition_set_system: mac_partition_set_system,
1586 partition_set_flag: mac_partition_set_flag,
1587 partition_get_flag: mac_partition_get_flag,
1588 partition_is_flag_available: mac_partition_is_flag_available,
1589 partition_set_name: mac_partition_set_name,
1590 partition_get_name: mac_partition_get_name,
1591 partition_align: mac_partition_align,
1592 partition_enumerate: mac_partition_enumerate,
1594 alloc_metadata: mac_alloc_metadata,
1595 get_max_primary_partition_count:
1596 mac_get_max_primary_partition_count
1599 static PedDiskType mac_disk_type = {
1603 features: PED_DISK_TYPE_PARTITION_NAME
1607 ped_disk_mac_init ()
1609 PED_ASSERT (sizeof (MacRawPartition) == 512, return);
1610 PED_ASSERT (sizeof (MacRawDisk) == 512, return);
1612 ped_disk_type_register (&mac_disk_type);
1616 ped_disk_mac_done ()
1618 ped_disk_type_unregister (&mac_disk_type);