2 libparted - a library for manipulating disk partitions
3 Copyright (C) 2000, 2002, 2004, 2007-2009 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 3 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, see <http://www.gnu.org/licenses/>.
21 #include <parted/parted.h>
22 #include <parted/debug.h>
23 #include <parted/endian.h>
28 # define _(String) dgettext (PACKAGE, String)
30 # define _(String) (String)
31 #endif /* ENABLE_NLS */
36 /* struct's hacked from Linux source: fs/partitions/mac.h
37 * I believe it was originally written by Paul Mackerras (from comments in
41 * http://developer.apple.com/documentation/mac/Devices/Devices-126.html
42 * http://developer.apple.com/documentation/mac/Devices/Devices-121.html
43 * http://devworld.apple.com/technotes/tn/tn1189.html
46 * Apple_Bootstrap new-world (HFS) boot partition
47 * Apple_partition_map partition map (table)
48 * Apple_Driver device driver
49 * Apple_Driver43 SCSI Manager 4.3 device driver
50 * Apple_MFS original Macintosh File System
51 * Apple_HFS Hierarchical File System (and +)
52 * Apple_HFSX HFS+ with case sensitivity and more
53 * Apple_UNIX_SVR2 UNIX file system (UFS?)
54 * Apple_PRODOS ProDOS file system
55 * Apple_Free unused space
57 * Apple_Void padding for iso9660
58 * Apple_Extra an unused partition map entry
68 * partition volume or partition
71 * * All space must be accounted for, except block 0 (driver block) and
72 * block 1-X (the partition map: i.e. lots of MacRawPartitions)
74 * * It's really hard to grow/shrink the number of MacRawPartition
75 * entries in the partition map, because the first partition starts
76 * immediately after the partition map. When we can move the start of
77 * HFS and ext2 partitions, this problem will disappear ;-)
80 #define MAC_PARTITION_MAGIC_1 0x5453 /* old */
81 #define MAC_PARTITION_MAGIC_2 0x504d
82 #define MAC_DISK_MAGIC 0x4552
84 #define MAC_STATUS_BOOTABLE 8 /* partition is bootable */
86 typedef struct _MacRawPartition MacRawPartition;
87 typedef struct _MacRawDisk MacRawDisk;
88 typedef struct _MacDeviceDriver MacDeviceDriver;
89 typedef struct _MacPartitionData MacPartitionData;
90 typedef struct _MacDiskData MacDiskData;
92 struct __attribute__ ((packed)) _MacRawPartition {
93 uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
95 uint32_t map_count; /* # blocks in partition map */
96 uint32_t start_block; /* absolute starting block # of partition */
97 uint32_t block_count; /* number of blocks in partition */
98 char name[32]; /* partition name */
99 char type[32]; /* string type description */
100 uint32_t data_start; /* rel block # of first data block */
101 uint32_t data_count; /* number of data blocks */
102 uint32_t status; /* partition status bits */
108 uint32_t boot_entry2;
110 char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
115 /* Driver descriptor structure, in block 0 */
116 struct __attribute__ ((packed)) _MacRawDisk {
117 uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
118 uint16_t block_size; /* physical sector size */
119 uint32_t block_count; /* size of device in blocks */
120 uint16_t dev_type; /* reserved */
121 uint16_t dev_id; /* reserved */
122 uint32_t data; /* reserved */
123 uint16_t driver_count; /* # of driver descriptor entries */
124 uint8_t driverlist[488];/* info about available drivers */
125 uint16_t padding[3]; /* pad to 512 bytes */
128 struct __attribute__ ((packed)) _MacDeviceDriver {
129 uint32_t block; /* startblock in MacRawDisk->block_size units */
130 uint16_t size; /* size in 512 byte units */
131 uint16_t type; /* operating system type (MacOS = 1) */
134 struct _MacPartitionData {
135 char volume_name[33]; /* eg: "Games" */
136 char system_name[33]; /* eg: "Apple_Unix_SVR2" */
137 char processor_name[17];
147 PedSector data_region_length;
148 PedSector boot_region_length;
150 uint32_t boot_base_address;
151 uint32_t boot_entry_address;
152 uint32_t boot_checksum;
158 struct _MacDiskData {
159 int ghost_size; /* sectors per "driver" block */
160 int part_map_entry_count; /* # entries (incl. ghost) */
161 int part_map_entry_num; /* partition map location */
163 int active_part_entry_count; /* # real partitions */
164 int free_part_entry_count; /* # free space */
165 int last_part_entry_num; /* last entry number */
167 uint16_t block_size; /* physical sector size */
168 uint16_t driver_count;
169 MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */
172 static PedDiskType mac_disk_type;
175 _check_signature (MacRawDisk const *raw_disk)
177 if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
181 return ped_exception_throw (
183 PED_EXCEPTION_IGNORE_CANCEL,
184 _("Invalid signature %x for Mac disk labels."),
185 (int) PED_BE16_TO_CPU (raw_disk->signature))
186 == PED_EXCEPTION_IGNORE;
194 _rawpart_check_signature (MacRawPartition* raw_part)
196 int sig = (int) PED_BE16_TO_CPU (raw_part->signature);
197 return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
201 mac_probe (const PedDevice * dev)
203 PED_ASSERT (dev != NULL, return 0);
205 if (dev->sector_size < sizeof (MacRawDisk))
209 if (!ptt_read_sector (dev, 0, &label))
212 int valid = _check_signature (label);
219 _disk_add_part_map_entry (PedDisk* disk, int warn)
221 MacDiskData* mac_disk_data = disk->disk_specific;
222 PedPartition* new_part;
223 MacPartitionData* mac_part_data;
224 PedSector part_map_size;
225 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
227 #ifndef DISCOVER_ONLY
228 if (warn && ped_exception_throw (
230 PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
231 _("Partition map has no partition map entry!"))
232 != PED_EXCEPTION_FIX)
234 #endif /* !DISCOVER_ONLY */
237 = ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
238 if (part_map_size == 0)
241 new_part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
242 1, part_map_size - 1);
246 mac_part_data = new_part->disk_specific;
247 strcpy (mac_part_data->volume_name, "Apple");
248 strcpy (mac_part_data->system_name, "Apple_partition_map");
250 if (!ped_disk_add_partition (disk, new_part, constraint_any))
251 goto error_destroy_new_part;
253 mac_disk_data->part_map_entry_num = new_part->num;
254 mac_disk_data->part_map_entry_count
255 = new_part->geom.end - mac_disk_data->ghost_size;
256 ped_constraint_destroy (constraint_any);
259 error_destroy_new_part:
260 ped_partition_destroy (new_part);
262 ped_constraint_destroy (constraint_any);
267 mac_alloc (const PedDevice* dev)
270 MacDiskData* mac_disk_data;
272 PED_ASSERT (dev != NULL, return NULL);
274 #ifndef DISCOVER_ONLY
275 if (dev->length < 256) {
276 ped_exception_throw (
278 PED_EXCEPTION_CANCEL,
279 _("%s is too small for a Mac disk label!"),
285 disk = _ped_disk_alloc (dev, &mac_disk_type);
289 mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
291 goto error_free_disk;
292 disk->disk_specific = mac_disk_data;
293 mac_disk_data->ghost_size = disk->dev->sector_size / 512;
294 mac_disk_data->active_part_entry_count = 0;
295 mac_disk_data->free_part_entry_count = 1;
296 mac_disk_data->last_part_entry_num = 1;
297 mac_disk_data->block_size = 0;
298 mac_disk_data->driver_count = 0;
299 memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
301 if (!_disk_add_part_map_entry (disk, 0))
302 goto error_free_disk;
306 _ped_disk_free (disk);
312 mac_duplicate (const PedDisk* disk)
315 MacDiskData* new_mac_data;
316 MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific;
317 PedPartition* partition_map;
319 new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type);
323 new_mac_data = (MacDiskData*) new_disk->disk_specific;
325 /* remove the partition map partition - it will be duplicated
328 partition_map = ped_disk_get_partition_by_sector (new_disk, 1);
329 PED_ASSERT (partition_map != NULL, return 0);
330 ped_disk_remove_partition (new_disk, partition_map);
332 /* ugly, but C is ugly :p */
333 memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
338 mac_free (PedDisk* disk)
340 MacDiskData* mac_disk_data = disk->disk_specific;
342 _ped_disk_free (disk);
343 free (mac_disk_data);
346 #ifndef DISCOVER_ONLY
348 _clobber_part_map (PedDevice* dev)
350 void *buf = ped_malloc (dev->sector_size);
356 for (sector=1; 1; sector++) {
357 if (!ped_device_read (dev, buf, sector, 1)) {
361 if (!_rawpart_check_signature (buf)) {
365 memset (buf, 0, dev->sector_size);
366 if (!ped_device_write (dev, buf, sector, 1)) {
376 mac_clobber (PedDevice* dev)
379 if (!ptt_read_sector (dev, 0, &buf))
382 if (!_check_signature (buf)) {
387 memset (buf, 0, dev->sector_size);
388 bool ok = ped_device_write (dev, buf, 0, 1);
393 return _clobber_part_map (dev);
395 #endif /* !DISCOVER_ONLY */
398 _rawpart_cmp_type (const MacRawPartition* raw_part, const char* type)
400 return strncasecmp (raw_part->type, type, 32) == 0;
404 _rawpart_cmp_name (const MacRawPartition* raw_part, const char* name)
406 return strncasecmp (raw_part->name, name, 32) == 0;
410 _rawpart_is_partition_map (const MacRawPartition* raw_part)
412 return _rawpart_cmp_type (raw_part, "Apple_partition_map");
416 strncasestr (const char* haystack, const char* needle, int n)
418 int needle_size = strlen (needle);
421 for (i = 0; haystack[i] && i < n - needle_size; i++) {
422 if (strncasecmp (haystack + i, needle, needle_size) == 0)
430 _rawpart_is_boot (const MacRawPartition* raw_part)
432 if (!strcasecmp(raw_part->type, "Apple_Bootstrap"))
435 if (!strcasecmp(raw_part->type, "Apple_Boot"))
442 _rawpart_is_driver (const MacRawPartition* raw_part)
444 if (strncmp (raw_part->type, "Apple_", 6) != 0)
446 if (!strncasestr (raw_part->type, "driver", 32))
452 _rawpart_has_driver (const MacRawPartition* raw_part, MacDiskData* mac_disk_data)
454 MacDeviceDriver *driverlist;
456 uint32_t driver_bs, driver_be, part_be;
458 driverlist = &mac_disk_data->driverlist[0];
459 bsz = mac_disk_data->block_size / 512;
460 for (i = 0; i < mac_disk_data->driver_count; i++) {
461 driver_bs = driverlist->block * bsz;
462 driver_be = driver_bs + driverlist->size;
463 part_be = raw_part->start_block + raw_part->block_count;
464 if (driver_bs >= raw_part->start_block && driver_be <= part_be)
472 _rawpart_is_root (MacRawPartition* raw_part)
474 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
476 if (strcmp (raw_part->name, "root") != 0)
482 _rawpart_is_swap (MacRawPartition* raw_part)
484 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
486 if (strcmp (raw_part->name, "swap") != 0)
492 _rawpart_is_lvm (MacRawPartition* raw_part)
494 if (strcmp (raw_part->type, "Linux_LVM") != 0)
500 _rawpart_is_raid (MacRawPartition* raw_part)
502 if (strcmp (raw_part->type, "Linux_RAID") != 0)
508 _rawpart_is_void (MacRawPartition* raw_part)
510 return _rawpart_cmp_type (raw_part, "Apple_Void");
513 /* returns 1 if the raw_part represents a partition that is "unused space", or
514 * doesn't represent a partition at all. NOTE: some people make Apple_Free
515 * partitions with MacOS, because they can't select another type. So, if the
516 * name is anything other than "Extra" or "", it is treated as a "real"
520 _rawpart_is_active (MacRawPartition* raw_part)
522 if (_rawpart_cmp_type (raw_part, "Apple_Free")
523 && (_rawpart_cmp_name (raw_part, "Extra")
524 || _rawpart_cmp_name (raw_part, "")))
526 if (_rawpart_cmp_type (raw_part, "Apple_Void"))
528 if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
530 if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
537 _rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
539 MacDiskData* mac_disk_data;
541 MacPartitionData* mac_part_data;
542 PedSector block_size;
543 PedSector start, length;
545 if (!_rawpart_check_signature (raw_part)) {
546 #ifndef DISCOVER_ONLY
547 if (ped_exception_throw (
548 PED_EXCEPTION_WARNING,
549 PED_EXCEPTION_IGNORE_CANCEL,
550 _("Partition %d has an invalid signature %x."),
552 (int) PED_BE16_TO_CPU (raw_part->signature))
553 != PED_EXCEPTION_IGNORE)
558 mac_disk_data = (MacDiskData*) disk->disk_specific;
559 block_size = disk->dev->sector_size / 512;
561 start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
562 length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
564 #ifndef DISCOVER_ONLY
565 ped_exception_throw (
567 PED_EXCEPTION_CANCEL,
568 _("Partition %d has an invalid length of 0 bytes!"),
573 part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
574 start, start + length - 1);
578 mac_part_data = part->disk_specific;
580 strncpy (mac_part_data->volume_name, raw_part->name, 32);
581 strncpy (mac_part_data->system_name, raw_part->type, 32);
582 strncpy (mac_part_data->processor_name, raw_part->processor, 16);
584 mac_part_data->is_boot = _rawpart_is_boot (raw_part);
585 mac_part_data->is_driver = _rawpart_is_driver (raw_part);
586 if (mac_part_data->is_driver)
587 mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
588 mac_part_data->is_root = _rawpart_is_root (raw_part);
589 mac_part_data->is_swap = _rawpart_is_swap (raw_part);
590 mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
591 mac_part_data->is_raid = _rawpart_is_raid (raw_part);
594 #ifndef DISCOVER_ONLY
595 if (raw_part->data_start) {
596 ped_exception_throw (
598 PED_EXCEPTION_CANCEL,
599 _("The data region doesn't start at the start "
600 "of the partition."));
601 goto error_destroy_part;
603 #endif /* !DISCOVER_ONLY */
604 mac_part_data->data_region_length
605 = PED_BE32_TO_CPU (raw_part->data_count) * block_size;
607 /* boot region - we have no idea what this is for, but Mac OSX
608 * seems to put garbage here, and doesn't pay any attention to
609 * it afterwards. [clausen, dan burcaw]
612 if (raw_part->boot_start) {
613 ped_exception_throw (
615 PED_EXCEPTION_CANCEL,
616 _("The boot region doesn't start at the start "
617 "of the partition."));
618 goto error_destroy_part;
621 mac_part_data->boot_region_length
622 = PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
624 #ifndef DISCOVER_ONLY
625 if (mac_part_data->has_driver) {
626 if (mac_part_data->boot_region_length < part->geom.length) {
627 if (ped_exception_throw (
629 PED_EXCEPTION_IGNORE_CANCEL,
630 _("The partition's boot region doesn't occupy "
631 "the entire partition."))
632 != PED_EXCEPTION_IGNORE)
633 goto error_destroy_part;
636 if (mac_part_data->data_region_length < part->geom.length &&
637 !mac_part_data->is_boot) {
638 if (ped_exception_throw (
640 PED_EXCEPTION_IGNORE_CANCEL,
641 _("The partition's data region doesn't occupy "
642 "the entire partition."))
643 != PED_EXCEPTION_IGNORE)
644 goto error_destroy_part;
647 #endif /* !DISCOVER_ONLY */
649 mac_part_data->boot_base_address
650 = PED_BE32_TO_CPU (raw_part->boot_load);
651 mac_part_data->boot_entry_address
652 = PED_BE32_TO_CPU (raw_part->boot_entry);
653 mac_part_data->boot_checksum
654 = PED_BE32_TO_CPU (raw_part->boot_cksum);
656 mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
657 mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
662 ped_partition_destroy (part);
667 /* looks at the partition map size field in a mac raw partition, and calculates
668 * what the size of the partition map should be, from it
671 _rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
673 MacDiskData* mac_disk_data = disk->disk_specific;
674 PedSector sector_size = disk->dev->sector_size / 512;
675 PedSector part_map_start;
676 PedSector part_map_end;
678 part_map_start = mac_disk_data->ghost_size;
679 part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
681 return part_map_end - part_map_start + 1;
685 _disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
687 PedSector block_size;
689 if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
690 #ifndef DISCOVER_ONLY
691 ped_exception_throw (
693 PED_EXCEPTION_CANCEL,
694 _("Weird block size on device descriptor: %d bytes is "
695 "not divisible by 512."),
696 (int) PED_BE16_TO_CPU (raw_disk->block_size));
701 block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
702 if (block_size != disk->dev->sector_size / 512) {
703 #ifndef DISCOVER_ONLY
704 if (ped_exception_throw (
705 PED_EXCEPTION_WARNING,
706 PED_EXCEPTION_IGNORE_CANCEL,
707 _("The driver descriptor says the physical block size "
708 "is %d bytes, but Linux says it is %d bytes."),
709 (int) block_size * 512,
710 (int) disk->dev->sector_size)
711 != PED_EXCEPTION_IGNORE)
714 disk->dev->sector_size = block_size * 512;
723 /* Tries to figure out the block size used by the drivers, for the ghost
724 * partitioning scheme. Ghost partitioning works like this: the OpenFirmware
725 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
726 * perhaps, some other number?). To remain compatible, the partition map
727 * only has "real" partition map entries on ghost-aligned block numbers (and
728 * the others are padded with Apple_Void partitions). This function tries
729 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
730 * doesn't always equal 2048!!!)
733 _disk_analyse_ghost_size (PedDisk* disk)
735 MacDiskData* mac_disk_data = disk->disk_specific;
737 void *buf = ped_malloc (disk->dev->sector_size);
743 for (i = 1; i < 64; i *= 2) {
744 if (!ped_device_read (disk->dev, buf, i, 1))
746 if (_rawpart_check_signature (buf)
747 && !_rawpart_is_void (buf)) {
748 mac_disk_data->ghost_size = i;
749 PED_ASSERT (i <= disk->dev->sector_size / 512, break);
756 #ifndef DISCOVER_ONLY
758 ped_exception_throw (
760 PED_EXCEPTION_CANCEL,
761 _("No valid partition map found."));
767 mac_read (PedDisk* disk)
769 MacDiskData* mac_disk_data;
772 PedSector ghost_size;
773 PedConstraint* constraint_exact;
774 int last_part_entry_num = 0;
776 PED_ASSERT (disk != NULL, return 0);
778 mac_disk_data = disk->disk_specific;
779 mac_disk_data->part_map_entry_num = 0; /* 0 == none */
782 if (!ptt_read_sector (disk->dev, 0, &buf))
785 MacRawDisk *raw_disk = (MacRawDisk *) buf;
787 if (!_check_signature (raw_disk))
790 if (!_disk_analyse_block_size (disk, raw_disk))
792 if (!_disk_analyse_ghost_size (disk))
794 ghost_size = mac_disk_data->ghost_size;
796 if (!ped_disk_delete_all (disk))
799 if (raw_disk->driver_count && raw_disk->driver_count < 62) {
800 memcpy(&mac_disk_data->driverlist[0], &raw_disk->driverlist[0],
801 sizeof(mac_disk_data->driverlist));
802 mac_disk_data->driver_count = raw_disk->driver_count;
803 mac_disk_data->block_size = raw_disk->block_size;
806 for (num=1; num==1 || num <= last_part_entry_num; num++) {
807 void *raw_part = buf;
808 if (!ped_device_read (disk->dev, raw_part,
809 num * ghost_size, 1))
810 goto error_delete_all;
812 if (!_rawpart_check_signature (raw_part))
817 = _rawpart_get_partmap_size (raw_part, disk);
818 if (_rawpart_get_partmap_size (raw_part, disk)
819 != last_part_entry_num) {
820 if (ped_exception_throw (
822 PED_EXCEPTION_IGNORE_CANCEL,
823 _("Conflicting partition map entry sizes! "
824 "Entry 1 says it is %d, but entry %d says "
827 _rawpart_get_partmap_size (raw_part, disk))
828 != PED_EXCEPTION_IGNORE)
829 goto error_delete_all;
832 if (!_rawpart_is_active (raw_part))
835 part = _rawpart_analyse (raw_part, disk, num);
837 goto error_delete_all;
839 part->fs_type = ped_file_system_probe (&part->geom);
840 constraint_exact = ped_constraint_exact (&part->geom);
841 if (!ped_disk_add_partition (disk, part, constraint_exact))
842 goto error_delete_all;
843 ped_constraint_destroy (constraint_exact);
845 if (_rawpart_is_partition_map (raw_part)) {
846 if (mac_disk_data->part_map_entry_num
847 && ped_exception_throw (
849 PED_EXCEPTION_IGNORE_CANCEL,
850 _("Weird! There are 2 partitions "
852 != PED_EXCEPTION_IGNORE)
853 goto error_delete_all;
855 mac_disk_data->part_map_entry_num = num;
856 mac_disk_data->part_map_entry_count
857 = part->geom.end - ghost_size + 1;
861 if (!mac_disk_data->part_map_entry_num) {
862 if (!_disk_add_part_map_entry (disk, 1))
863 goto error_delete_all;
864 ped_disk_commit_to_dev (disk);
870 ped_disk_delete_all (disk);
876 #ifndef DISCOVER_ONLY
877 /* The Ghost partition: is a blank entry, used to pad out each block (where
878 * there physical block size > 512 bytes). This is because OpenFirmware uses
879 * 512 byte blocks, but device drivers Think Different TM, with a different
880 * lbock size, so we need to do this to avoid a clash (!)
883 _pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
885 MacDiskData* mac_disk_data = disk->disk_specific;
888 size_t ss = disk->dev->sector_size;
889 void *buf = ped_calloc (ss);
893 MacRawPartition *ghost_entry = buf;
894 ghost_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
895 strcpy (ghost_entry->type, "Apple_Void");
896 ghost_entry->map_count
897 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
899 for (i=0; i < mac_disk_data->ghost_size - 1; i++) {
900 PedSector idx = i + (num - 1) * mac_disk_data->ghost_size;
901 memcpy ((char*)part_map + idx * ss, ghost_entry, ss);
909 _update_driver_count (MacRawPartition* part_map_entry,
910 MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
912 uint16_t i, count_orig, count_cur, bsz;
913 uint32_t driver_bs, driver_be, part_be;
915 bsz = mac_disk_data->block_size / 512;
916 count_cur = mac_driverdata->driver_count;
917 count_orig = mac_disk_data->driver_count;
918 for (i = 0; i < count_orig; i++) {
919 driver_bs = mac_disk_data->driverlist[i].block * bsz;
920 driver_be = driver_bs + mac_disk_data->driverlist[i].size;
921 part_be = part_map_entry->start_block + part_map_entry->block_count;
922 if (driver_bs >= part_map_entry->start_block
923 && driver_be <= part_be) {
924 mac_driverdata->driverlist[count_cur].block
925 = mac_disk_data->driverlist[i].block;
926 mac_driverdata->driverlist[count_cur].size
927 = mac_disk_data->driverlist[i].size;
928 mac_driverdata->driverlist[count_cur].type
929 = mac_disk_data->driverlist[i].type;
930 mac_driverdata->driver_count++;
936 static MacRawPartition *
937 get_pme (MacRawPartition const *part_map, PedSector i, PedDisk const *disk)
939 MacDiskData const *mac_disk_data = disk->disk_specific;
940 PedSector idx = i * mac_disk_data->ghost_size - 1;
941 return (MacRawPartition *) ((char*)part_map
942 + idx * disk->dev->sector_size);
945 /* Initialize the disk->dev->sector_size bytes of part_map[part->num]. */
947 _generate_raw_part (PedDisk* disk, PedPartition* part,
948 MacRawPartition* part_map, MacDiskData *mac_driverdata)
950 MacDiskData* mac_disk_data;
951 MacPartitionData* mac_part_data;
952 PedSector block_size = disk->dev->sector_size / 512;
954 PED_ASSERT (part->num > 0, goto error);
956 mac_disk_data = disk->disk_specific;
957 mac_part_data = part->disk_specific;
959 MacRawPartition *part_map_entry = get_pme (part_map, part->num, disk);
960 memset (part_map_entry, 0, disk->dev->sector_size);
962 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
963 part_map_entry->map_count
964 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
965 part_map_entry->start_block
966 = PED_CPU_TO_BE32 (part->geom.start / block_size);
967 part_map_entry->block_count
968 = PED_CPU_TO_BE32 (part->geom.length / block_size);
969 strcpy (part_map_entry->name, mac_part_data->volume_name);
970 strcpy (part_map_entry->type, mac_part_data->system_name);
972 if (mac_part_data->is_driver) {
973 mac_part_data->boot_region_length = part->geom.length;
974 if (mac_part_data->has_driver)
975 _update_driver_count(part_map_entry, mac_driverdata,
978 mac_part_data->data_region_length = part->geom.length;
979 part_map_entry->data_count = PED_CPU_TO_BE32 (
980 mac_part_data->data_region_length / block_size);
981 part_map_entry->boot_count = PED_CPU_TO_BE32 (
982 mac_part_data->boot_region_length / block_size);
983 part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
984 part_map_entry->driver_sig
985 = PED_CPU_TO_BE32 (mac_part_data->driver_sig);
987 part_map_entry->boot_load =
988 PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
989 part_map_entry->boot_entry =
990 PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
991 part_map_entry->boot_cksum =
992 PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
994 strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
996 if (!_pad_raw_part (disk, part->num, part_map))
1006 _generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
1007 MacRawPartition* part_map)
1009 MacDiskData* mac_disk_data = disk->disk_specific;
1010 PedSector block_size = disk->dev->sector_size / 512;
1012 PED_ASSERT (num > 0, goto error);
1014 MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
1016 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
1017 part_map_entry->map_count
1018 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
1019 part_map_entry->start_block
1020 = PED_CPU_TO_BE32 (geom->start / block_size);
1021 part_map_entry->block_count
1022 = PED_CPU_TO_BE32 (geom->length / block_size);
1023 strcpy (part_map_entry->name, "Extra");
1024 strcpy (part_map_entry->type, "Apple_Free");
1026 part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
1027 part_map_entry->status = 0;
1028 part_map_entry->driver_sig = 0;
1030 if (!_pad_raw_part (disk, num, part_map))
1040 _generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
1042 MacDiskData* mac_disk_data = disk->disk_specific;
1044 PED_ASSERT (num > 0, return 0);
1046 MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
1047 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
1048 part_map_entry->map_count
1049 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
1050 strcpy (part_map_entry->type, "Apple_Void");
1052 return _pad_raw_part (disk, num, part_map);
1055 /* returns the first empty entry in the partition map */
1057 _get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map)
1059 MacDiskData* mac_disk_data = disk->disk_specific;
1062 for (i=1; i <= mac_disk_data->last_part_entry_num; i++) {
1063 MacRawPartition *part_map_entry = get_pme (part_map, i, disk);
1064 if (!part_map_entry->signature)
1072 write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
1074 PedDevice* dev = disk->dev;
1076 if (!ptt_read_sector (dev, 0, &s0))
1078 MacRawDisk *raw_disk = (MacRawDisk *) s0;
1080 raw_disk->signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
1081 raw_disk->block_size = PED_CPU_TO_BE16 (dev->sector_size);
1082 raw_disk->block_count
1083 = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
1085 raw_disk->driver_count = mac_driverdata->driver_count;
1086 memcpy(&raw_disk->driverlist[0], &mac_driverdata->driverlist[0],
1087 sizeof(raw_disk->driverlist));
1089 return ped_device_write (dev, raw_disk, 0, 1);
1093 mac_write (PedDisk* disk)
1095 MacRawPartition* part_map;
1096 MacDiskData* mac_disk_data;
1097 MacDiskData* mac_driverdata; /* updated driver list */
1101 PED_ASSERT (disk != NULL, return 0);
1102 PED_ASSERT (disk->disk_specific != NULL, return 0);
1103 PED_ASSERT (disk->dev != NULL, return 0);
1104 PED_ASSERT (!disk->update_mode, return 0);
1106 mac_disk_data = disk->disk_specific;
1108 if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
1109 if (!_disk_add_part_map_entry (disk, 1))
1113 mac_driverdata = ped_malloc(sizeof(MacDiskData));
1114 if (!mac_driverdata)
1116 memset (mac_driverdata, 0, sizeof(MacDiskData));
1118 size_t pmap_bytes = (mac_disk_data->part_map_entry_count
1119 * mac_disk_data->ghost_size
1120 * disk->dev->sector_size);
1121 part_map = (MacRawPartition*) ped_calloc (pmap_bytes);
1123 goto error_free_driverdata;
1125 /* write (to memory) the "real" partitions */
1126 for (part = ped_disk_next_partition (disk, NULL); part;
1127 part = ped_disk_next_partition (disk, part)) {
1128 if (!ped_partition_is_active (part))
1130 if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
1131 goto error_free_part_map;
1134 /* write the "free space" partitions */
1135 for (part = ped_disk_next_partition (disk, NULL); part;
1136 part = ped_disk_next_partition (disk, part)) {
1137 if (part->type != PED_PARTITION_FREESPACE)
1139 num = _get_first_empty_part_entry (disk, part_map);
1140 if (!_generate_raw_freespace_part (disk, &part->geom, num,
1142 goto error_free_part_map;
1145 /* write the "void" (empty) partitions */
1146 for (num = _get_first_empty_part_entry (disk, part_map); num;
1147 num = _get_first_empty_part_entry (disk, part_map))
1148 _generate_empty_part (disk, num, part_map);
1151 if (!ped_device_write (disk->dev, part_map, 1,
1152 mac_disk_data->part_map_entry_count))
1153 goto error_free_part_map;
1155 return write_block_zero (disk, mac_driverdata);
1157 error_free_part_map:
1159 error_free_driverdata:
1160 free (mac_driverdata);
1164 #endif /* !DISCOVER_ONLY */
1166 static PedPartition*
1168 const PedDisk* disk, PedPartitionType part_type,
1169 const PedFileSystemType* fs_type, PedSector start, PedSector end)
1172 MacPartitionData* mac_data;
1174 part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1178 if (ped_partition_is_active (part)) {
1180 = mac_data = ped_malloc (sizeof (MacPartitionData));
1182 goto error_free_part;
1184 memset (mac_data, 0, sizeof (MacPartitionData));
1185 strcpy (mac_data->volume_name, "untitled");
1187 part->disk_specific = NULL;
1197 static PedPartition*
1198 mac_partition_duplicate (const PedPartition* part)
1200 PedPartition* new_part;
1201 MacPartitionData* new_mac_data;
1202 MacPartitionData* old_mac_data;
1204 new_part = ped_partition_new (part->disk, part->type,
1205 part->fs_type, part->geom.start,
1209 new_part->num = part->num;
1211 old_mac_data = (MacPartitionData*) part->disk_specific;
1212 new_mac_data = (MacPartitionData*) new_part->disk_specific;
1214 /* ugly, but C is ugly :p */
1215 memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
1220 mac_partition_destroy (PedPartition* part)
1222 PED_ASSERT (part != NULL, return);
1224 if (ped_partition_is_active (part))
1225 free (part->disk_specific);
1230 mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1232 MacPartitionData* mac_data = part->disk_specific;
1234 part->fs_type = fs_type;
1236 if (fs_type && is_linux_swap (fs_type->name))
1237 ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1239 if (mac_data->is_boot) {
1240 strcpy (mac_data->system_name, "Apple_Bootstrap");
1241 mac_data->status = 0x33;
1245 if (fs_type && (!strcmp (fs_type->name, "hfs")
1246 || !strcmp (fs_type->name, "hfs+"))) {
1247 strcpy (mac_data->system_name, "Apple_HFS");
1248 mac_data->status |= 0x7f;
1249 } else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
1250 strcpy (mac_data->system_name, "Apple_HFSX");
1251 mac_data->status |= 0x7f;
1253 strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
1254 mac_data->status = 0x33;
1261 mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1263 MacPartitionData* mac_data;
1265 PED_ASSERT (part != NULL, return 0);
1266 PED_ASSERT (part->disk_specific != NULL, return 0);
1268 mac_data = part->disk_specific;
1271 case PED_PARTITION_BOOT:
1272 mac_data->is_boot = state;
1275 return mac_partition_set_system (part, part->fs_type);
1278 strcpy (mac_data->system_name, "Apple_Bootstrap");
1279 mac_data->status = 0x33;
1283 case PED_PARTITION_ROOT:
1285 strcpy (mac_data->volume_name, "root");
1286 mac_data->is_swap = 0;
1288 if (mac_data->is_root)
1289 strcpy (mac_data->volume_name, "untitled");
1291 mac_data->is_root = state;
1294 case PED_PARTITION_SWAP:
1296 strcpy (mac_data->volume_name, "swap");
1297 mac_data->is_root = 0;
1299 if (mac_data->is_swap)
1300 strcpy (mac_data->volume_name, "untitled");
1302 mac_data->is_swap = state;
1305 case PED_PARTITION_LVM:
1307 strcpy (mac_data->system_name, "Linux_LVM");
1308 mac_data->is_lvm = state;
1310 if (mac_data->is_lvm)
1311 mac_partition_set_system (part, part->fs_type);
1315 case PED_PARTITION_RAID:
1317 strcpy (mac_data->system_name, "Linux_RAID");
1318 mac_data->is_raid = state;
1320 if (mac_data->is_raid)
1321 mac_partition_set_system (part, part->fs_type);
1331 mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1333 MacPartitionData* mac_data;
1335 PED_ASSERT (part != NULL, return 0);
1336 PED_ASSERT (part->disk_specific != NULL, return 0);
1338 mac_data = part->disk_specific;
1340 case PED_PARTITION_BOOT:
1341 return mac_data->is_boot;
1343 case PED_PARTITION_ROOT:
1344 return mac_data->is_root;
1346 case PED_PARTITION_SWAP:
1347 return mac_data->is_swap;
1349 case PED_PARTITION_LVM:
1350 return mac_data->is_lvm;
1352 case PED_PARTITION_RAID:
1353 return mac_data->is_raid;
1361 mac_partition_is_flag_available (
1362 const PedPartition* part, PedPartitionFlag flag)
1365 case PED_PARTITION_BOOT:
1366 case PED_PARTITION_ROOT:
1367 case PED_PARTITION_SWAP:
1368 case PED_PARTITION_LVM:
1369 case PED_PARTITION_RAID:
1378 mac_partition_set_name (PedPartition* part, const char* name)
1380 MacPartitionData* mac_data;
1383 PED_ASSERT (part != NULL, return);
1384 PED_ASSERT (part->disk_specific != NULL, return);
1385 mac_data = part->disk_specific;
1387 #ifndef DISCOVER_ONLY
1388 if (mac_data->is_root || mac_data->is_swap) {
1389 if (ped_exception_throw (
1390 PED_EXCEPTION_WARNING,
1391 PED_EXCEPTION_IGNORE_CANCEL,
1392 _("Changing the name of a root or swap partition "
1393 "will prevent Linux from recognising it as such."))
1394 != PED_EXCEPTION_IGNORE)
1396 mac_data->is_root = mac_data->is_swap = 0;
1400 strncpy (mac_data->volume_name, name, 32);
1401 mac_data->volume_name [32] = 0;
1402 for (i = strlen (mac_data->volume_name) - 1;
1403 mac_data->volume_name[i] == ' '; i--)
1404 mac_data->volume_name [i] = 0;
1408 mac_partition_get_name (const PedPartition* part)
1410 MacPartitionData* mac_data;
1412 PED_ASSERT (part != NULL, return NULL);
1413 PED_ASSERT (part->disk_specific != NULL, return NULL);
1414 mac_data = part->disk_specific;
1416 return mac_data->volume_name;
1419 static PedConstraint*
1420 _primary_constraint (PedDisk* disk)
1422 PedAlignment start_align;
1423 PedAlignment end_align;
1424 PedGeometry max_geom;
1425 PedSector sector_size;
1427 sector_size = disk->dev->sector_size / 512;
1429 if (!ped_alignment_init (&start_align, 0, sector_size))
1431 if (!ped_alignment_init (&end_align, -1, sector_size))
1433 if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1436 return ped_constraint_new (&start_align, &end_align, &max_geom,
1437 &max_geom, 1, disk->dev->length);
1441 mac_partition_align (PedPartition* part, const PedConstraint* constraint)
1443 PED_ASSERT (part != NULL, return 0);
1445 if (_ped_partition_attempt_align (part, constraint,
1446 _primary_constraint (part->disk)))
1449 #ifndef DISCOVER_ONLY
1450 ped_exception_throw (
1451 PED_EXCEPTION_ERROR,
1452 PED_EXCEPTION_CANCEL,
1453 _("Unable to satisfy all constraints on the partition."));
1459 mac_partition_enumerate (PedPartition* part)
1462 MacDiskData* mac_disk_data;
1466 PED_ASSERT (part != NULL, return 0);
1467 PED_ASSERT (part->disk != NULL, return 0);
1470 mac_disk_data = (MacDiskData*) disk->disk_specific;
1472 max_part_count = ped_disk_get_max_primary_partition_count (disk);
1474 if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
1477 for (i = 1; i <= max_part_count; i++) {
1478 if (!ped_disk_get_partition (disk, i)) {
1484 #ifndef DISCOVER_ONLY
1485 ped_exception_throw (
1486 PED_EXCEPTION_ERROR,
1487 PED_EXCEPTION_CANCEL,
1488 _("Can't add another partition -- the partition map is too "
1496 _disk_count_partitions (PedDisk* disk)
1498 MacDiskData* mac_disk_data = disk->disk_specific;
1499 PedPartition* part = NULL;
1500 PedPartition* last = NULL;
1502 PED_ASSERT (disk->update_mode, return 0);
1504 mac_disk_data->active_part_entry_count = 0;
1505 mac_disk_data->free_part_entry_count = 0;
1506 mac_disk_data->last_part_entry_num = 0;
1508 /* subtle: we only care about free space after the partition map.
1509 * the partition map is an "active" partition, BTW... */
1510 for (part = ped_disk_next_partition (disk, part); part;
1511 part = ped_disk_next_partition (disk, part)) {
1512 if (!ped_partition_is_active (part))
1515 mac_disk_data->active_part_entry_count++;
1516 if (last && last->geom.end + 1 < part->geom.start)
1517 mac_disk_data->free_part_entry_count++;
1518 mac_disk_data->last_part_entry_num
1519 = PED_MAX (mac_disk_data->last_part_entry_num,
1525 if (last && last->geom.end < disk->dev->length - 1)
1526 mac_disk_data->free_part_entry_count++;
1528 mac_disk_data->last_part_entry_num
1529 = PED_MAX (mac_disk_data->last_part_entry_num,
1530 mac_disk_data->active_part_entry_count
1531 + mac_disk_data->free_part_entry_count);
1536 add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
1538 PedPartition* new_part;
1539 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
1541 PED_ASSERT (disk != NULL, return 0);
1543 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1547 if (!ped_disk_add_partition (disk, new_part, constraint_any))
1548 goto error_destroy_new_part;
1550 ped_constraint_destroy (constraint_any);
1553 error_destroy_new_part:
1554 ped_partition_destroy (new_part);
1556 ped_constraint_destroy (constraint_any);
1561 mac_alloc_metadata (PedDisk* disk)
1563 MacDiskData* mac_disk_data;
1565 PED_ASSERT (disk != NULL, return 0);
1566 PED_ASSERT (disk->disk_specific != NULL, return 0);
1567 PED_ASSERT (disk->dev != NULL, return 0);
1569 mac_disk_data = disk->disk_specific;
1571 if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
1574 /* hack: this seems to be a good place, to update the partition map
1575 * entry count, since mac_alloc_metadata() gets called during
1576 * _disk_pop_update_mode()
1578 return _disk_count_partitions (disk);
1582 mac_get_max_primary_partition_count (const PedDisk* disk)
1584 MacDiskData* mac_disk_data = disk->disk_specific;
1585 PedPartition* part_map_partition;
1587 part_map_partition = ped_disk_get_partition (disk,
1588 mac_disk_data->part_map_entry_num);
1590 /* HACK: if we haven't found the partition map partition (yet),
1593 if (!part_map_partition) {
1594 mac_disk_data->part_map_entry_num = 0;
1598 /* HACK: since Mac labels need an entry for free-space regions, we
1599 * must allow half plus 1 entries for free-space partitions. I hate
1600 * this, but things get REALLY complicated, otherwise.
1601 * (I'm prepared to complicate things later, but I want to get
1602 * everything working, first)
1604 return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
1605 - mac_disk_data->free_part_entry_count + 1;
1609 mac_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
1615 static PedDiskOps mac_disk_ops = {
1617 #ifndef DISCOVER_ONLY
1618 clobber: mac_clobber,
1623 duplicate: mac_duplicate,
1626 #ifndef DISCOVER_ONLY
1627 /* FIXME: remove this cast, once mac_write is fixed not to
1628 modify its *DISK parameter. */
1629 write: (int (*) (const PedDisk*)) mac_write,
1634 partition_new: mac_partition_new,
1635 partition_duplicate: mac_partition_duplicate,
1636 partition_destroy: mac_partition_destroy,
1637 partition_set_system: mac_partition_set_system,
1638 partition_set_flag: mac_partition_set_flag,
1639 partition_get_flag: mac_partition_get_flag,
1640 partition_is_flag_available: mac_partition_is_flag_available,
1641 partition_set_name: mac_partition_set_name,
1642 partition_get_name: mac_partition_get_name,
1643 partition_align: mac_partition_align,
1644 partition_enumerate: mac_partition_enumerate,
1646 alloc_metadata: mac_alloc_metadata,
1647 get_max_primary_partition_count:
1648 mac_get_max_primary_partition_count,
1649 get_max_supported_partition_count:
1650 mac_get_max_supported_partition_count
1653 static PedDiskType mac_disk_type = {
1657 features: PED_DISK_TYPE_PARTITION_NAME
1661 ped_disk_mac_init ()
1663 PED_ASSERT (sizeof (MacRawPartition) == 512, return);
1664 PED_ASSERT (sizeof (MacRawDisk) == 512, return);
1666 ped_disk_type_register (&mac_disk_type);
1670 ped_disk_mac_done ()
1672 ped_disk_type_unregister (&mac_disk_type);