2 libparted - a library for manipulating disk partitions
3 Copyright (C) 2000, 2002, 2004, 2007-2010 Free Software Foundation,
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.
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.
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/>.
22 #include <parted/parted.h>
23 #include <parted/debug.h>
24 #include <parted/endian.h>
29 # define _(String) dgettext (PACKAGE, String)
31 # define _(String) (String)
32 #endif /* ENABLE_NLS */
37 /* struct's hacked from Linux source: fs/partitions/mac.h
38 * I believe it was originally written by Paul Mackerras (from comments in
42 * http://developer.apple.com/documentation/mac/Devices/Devices-126.html
43 * http://developer.apple.com/documentation/mac/Devices/Devices-121.html
44 * http://devworld.apple.com/technotes/tn/tn1189.html
47 * Apple_Bootstrap new-world (HFS) boot partition
48 * Apple_partition_map partition map (table)
49 * Apple_Driver device driver
50 * Apple_Driver43 SCSI Manager 4.3 device driver
51 * Apple_MFS original Macintosh File System
52 * Apple_HFS Hierarchical File System (and +)
53 * Apple_HFSX HFS+ with case sensitivity and more
54 * Apple_UNIX_SVR2 UNIX file system (UFS?)
55 * Apple_PRODOS ProDOS file system
56 * Apple_Free unused space
58 * Apple_Void padding for iso9660
59 * Apple_Extra an unused partition map entry
69 * partition volume or partition
72 * * All space must be accounted for, except block 0 (driver block) and
73 * block 1-X (the partition map: i.e. lots of MacRawPartitions)
75 * * It's really hard to grow/shrink the number of MacRawPartition
76 * entries in the partition map, because the first partition starts
77 * immediately after the partition map. When we can move the start of
78 * HFS and ext2 partitions, this problem will disappear ;-)
81 #define MAC_PARTITION_MAGIC_1 0x5453 /* old */
82 #define MAC_PARTITION_MAGIC_2 0x504d
83 #define MAC_DISK_MAGIC 0x4552
85 #define MAC_STATUS_BOOTABLE 8 /* partition is bootable */
87 typedef struct _MacRawPartition MacRawPartition;
88 typedef struct _MacRawDisk MacRawDisk;
89 typedef struct _MacDeviceDriver MacDeviceDriver;
90 typedef struct _MacPartitionData MacPartitionData;
91 typedef struct _MacDiskData MacDiskData;
93 struct __attribute__ ((packed)) _MacRawPartition {
94 uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
96 uint32_t map_count; /* # blocks in partition map */
97 uint32_t start_block; /* absolute starting block # of partition */
98 uint32_t block_count; /* number of blocks in partition */
99 char name[32]; /* partition name */
100 char type[32]; /* string type description */
101 uint32_t data_start; /* rel block # of first data block */
102 uint32_t data_count; /* number of data blocks */
103 uint32_t status; /* partition status bits */
109 uint32_t boot_entry2;
111 char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
116 /* Driver descriptor structure, in block 0 */
117 struct __attribute__ ((packed)) _MacRawDisk {
118 uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
119 uint16_t block_size; /* physical sector size */
120 uint32_t block_count; /* size of device in blocks */
121 uint16_t dev_type; /* reserved */
122 uint16_t dev_id; /* reserved */
123 uint32_t data; /* reserved */
124 uint16_t driver_count; /* # of driver descriptor entries */
125 uint8_t driverlist[488];/* info about available drivers */
126 uint16_t padding[3]; /* pad to 512 bytes */
129 struct __attribute__ ((packed)) _MacDeviceDriver {
130 uint32_t block; /* startblock in MacRawDisk->block_size units */
131 uint16_t size; /* size in 512 byte units */
132 uint16_t type; /* operating system type (MacOS = 1) */
135 struct _MacPartitionData {
136 char volume_name[33]; /* eg: "Games" */
137 char system_name[33]; /* eg: "Apple_Unix_SVR2" */
138 char processor_name[17];
148 PedSector data_region_length;
149 PedSector boot_region_length;
151 uint32_t boot_base_address;
152 uint32_t boot_entry_address;
153 uint32_t boot_checksum;
159 struct _MacDiskData {
160 int ghost_size; /* sectors per "driver" block */
161 int part_map_entry_count; /* # entries (incl. ghost) */
162 int part_map_entry_num; /* partition map location */
164 int active_part_entry_count; /* # real partitions */
165 int free_part_entry_count; /* # free space */
166 int last_part_entry_num; /* last entry number */
168 uint16_t block_size; /* physical sector size */
169 uint16_t driver_count;
170 MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */
173 static PedDiskType mac_disk_type;
176 _check_signature (MacRawDisk const *raw_disk)
178 if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
182 return ped_exception_throw (
184 PED_EXCEPTION_IGNORE_CANCEL,
185 _("Invalid signature %x for Mac disk labels."),
186 (int) PED_BE16_TO_CPU (raw_disk->signature))
187 == PED_EXCEPTION_IGNORE;
195 _rawpart_check_signature (MacRawPartition* raw_part)
197 int sig = (int) PED_BE16_TO_CPU (raw_part->signature);
198 return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
202 mac_probe (const PedDevice * dev)
204 PED_ASSERT (dev != NULL, return 0);
206 if (dev->sector_size < sizeof (MacRawDisk))
210 if (!ptt_read_sector (dev, 0, &label))
213 int valid = _check_signature (label);
220 _disk_add_part_map_entry (PedDisk* disk, int warn)
222 MacDiskData* mac_disk_data = disk->disk_specific;
223 PedPartition* new_part;
224 MacPartitionData* mac_part_data;
225 PedSector part_map_size;
226 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
228 #ifndef DISCOVER_ONLY
229 if (warn && ped_exception_throw (
231 PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
232 _("Partition map has no partition map entry!"))
233 != PED_EXCEPTION_FIX)
235 #endif /* !DISCOVER_ONLY */
238 = ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
239 if (part_map_size == 0)
242 new_part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
243 1, part_map_size - 1);
247 mac_part_data = new_part->disk_specific;
248 strcpy (mac_part_data->volume_name, "Apple");
249 strcpy (mac_part_data->system_name, "Apple_partition_map");
251 if (!ped_disk_add_partition (disk, new_part, constraint_any))
252 goto error_destroy_new_part;
254 mac_disk_data->part_map_entry_num = new_part->num;
255 mac_disk_data->part_map_entry_count
256 = new_part->geom.end - mac_disk_data->ghost_size;
257 ped_constraint_destroy (constraint_any);
260 error_destroy_new_part:
261 ped_partition_destroy (new_part);
263 ped_constraint_destroy (constraint_any);
268 mac_alloc (const PedDevice* dev)
271 MacDiskData* mac_disk_data;
273 PED_ASSERT (dev != NULL, return NULL);
275 #ifndef DISCOVER_ONLY
276 if (dev->length < 256) {
277 ped_exception_throw (
279 PED_EXCEPTION_CANCEL,
280 _("%s is too small for a Mac disk label!"),
286 disk = _ped_disk_alloc (dev, &mac_disk_type);
290 mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
292 goto error_free_disk;
293 disk->disk_specific = mac_disk_data;
294 mac_disk_data->ghost_size = disk->dev->sector_size / 512;
295 mac_disk_data->active_part_entry_count = 0;
296 mac_disk_data->free_part_entry_count = 1;
297 mac_disk_data->last_part_entry_num = 1;
298 mac_disk_data->block_size = 0;
299 mac_disk_data->driver_count = 0;
300 memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
302 if (!_disk_add_part_map_entry (disk, 0))
303 goto error_free_disk;
307 _ped_disk_free (disk);
313 mac_duplicate (const PedDisk* disk)
316 MacDiskData* new_mac_data;
317 MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific;
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 PedSector first_part_map_sector = old_mac_data->ghost_size;
329 PedPartition *partition_map
330 = ped_disk_get_partition_by_sector (new_disk, first_part_map_sector);
331 PED_ASSERT (partition_map != NULL, return 0);
333 /* ped_disk_remove_partition may be used only to delete a "normal"
334 partition. Trying to delete at least "freespace" or "metadata"
335 partitions leads to a violation of assumptions in
336 ped_disk_remove_partition, since it calls _disk_push_update_mode,
337 which destroys all "freespace" and "metadata" partitions, and
338 depends on that destruction not freeing its PART parameter. */
339 PED_ASSERT (partition_map->type == PED_PARTITION_NORMAL, return 0);
340 ped_disk_remove_partition (new_disk, partition_map);
342 /* ugly, but C is ugly :p */
343 memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
348 mac_free (PedDisk* disk)
350 MacDiskData* mac_disk_data = disk->disk_specific;
352 _ped_disk_free (disk);
353 free (mac_disk_data);
356 #ifndef DISCOVER_ONLY
358 _clobber_part_map (PedDevice* dev)
360 void *buf = ped_malloc (dev->sector_size);
366 for (sector=1; 1; sector++) {
367 if (!ped_device_read (dev, buf, sector, 1)) {
371 if (!_rawpart_check_signature (buf)) {
375 memset (buf, 0, dev->sector_size);
376 if (!ped_device_write (dev, buf, sector, 1)) {
386 mac_clobber (PedDevice* dev)
389 if (!ptt_read_sector (dev, 0, &buf))
392 if (!_check_signature (buf)) {
397 memset (buf, 0, dev->sector_size);
398 int ok = ped_device_write (dev, buf, 0, 1);
403 return _clobber_part_map (dev);
405 #endif /* !DISCOVER_ONLY */
408 _rawpart_cmp_type (const MacRawPartition* raw_part, const char* type)
410 return strncasecmp (raw_part->type, type, 32) == 0;
414 _rawpart_cmp_name (const MacRawPartition* raw_part, const char* name)
416 return strncasecmp (raw_part->name, name, 32) == 0;
420 _rawpart_is_partition_map (const MacRawPartition* raw_part)
422 return _rawpart_cmp_type (raw_part, "Apple_partition_map");
426 strncasestr (const char* haystack, const char* needle, int n)
428 int needle_size = strlen (needle);
431 for (i = 0; haystack[i] && i < n - needle_size; i++) {
432 if (strncasecmp (haystack + i, needle, needle_size) == 0)
440 _rawpart_is_boot (const MacRawPartition* raw_part)
442 if (!strcasecmp(raw_part->type, "Apple_Bootstrap"))
445 if (!strcasecmp(raw_part->type, "Apple_Boot"))
452 _rawpart_is_driver (const MacRawPartition* raw_part)
454 if (strncmp (raw_part->type, "Apple_", 6) != 0)
456 if (!strncasestr (raw_part->type, "driver", 32))
462 _rawpart_has_driver (const MacRawPartition* raw_part, MacDiskData* mac_disk_data)
464 MacDeviceDriver *driverlist;
466 uint32_t driver_bs, driver_be, part_be;
468 driverlist = &mac_disk_data->driverlist[0];
469 bsz = mac_disk_data->block_size / 512;
470 for (i = 0; i < mac_disk_data->driver_count; i++) {
471 driver_bs = driverlist->block * bsz;
472 driver_be = driver_bs + driverlist->size;
473 part_be = raw_part->start_block + raw_part->block_count;
474 if (driver_bs >= raw_part->start_block && driver_be <= part_be)
482 _rawpart_is_root (MacRawPartition* raw_part)
484 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
486 if (strcmp (raw_part->name, "root") != 0)
492 _rawpart_is_swap (MacRawPartition* raw_part)
494 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
496 if (strcmp (raw_part->name, "swap") != 0)
502 _rawpart_is_lvm (MacRawPartition* raw_part)
504 if (strcmp (raw_part->type, "Linux_LVM") != 0)
510 _rawpart_is_raid (MacRawPartition* raw_part)
512 if (strcmp (raw_part->type, "Linux_RAID") != 0)
518 _rawpart_is_void (MacRawPartition* raw_part)
520 return _rawpart_cmp_type (raw_part, "Apple_Void");
523 /* returns 1 if the raw_part represents a partition that is "unused space", or
524 * doesn't represent a partition at all. NOTE: some people make Apple_Free
525 * partitions with MacOS, because they can't select another type. So, if the
526 * name is anything other than "Extra" or "", it is treated as a "real"
530 _rawpart_is_active (MacRawPartition* raw_part)
532 if (_rawpart_cmp_type (raw_part, "Apple_Free")
533 && (_rawpart_cmp_name (raw_part, "Extra")
534 || _rawpart_cmp_name (raw_part, "")))
536 if (_rawpart_cmp_type (raw_part, "Apple_Void"))
538 if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
540 if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
547 _rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
549 MacDiskData* mac_disk_data;
551 MacPartitionData* mac_part_data;
552 PedSector block_size;
553 PedSector start, length;
555 if (!_rawpart_check_signature (raw_part)) {
556 #ifndef DISCOVER_ONLY
557 if (ped_exception_throw (
558 PED_EXCEPTION_WARNING,
559 PED_EXCEPTION_IGNORE_CANCEL,
560 _("Partition %d has an invalid signature %x."),
562 (int) PED_BE16_TO_CPU (raw_part->signature))
563 != PED_EXCEPTION_IGNORE)
568 mac_disk_data = (MacDiskData*) disk->disk_specific;
569 block_size = disk->dev->sector_size / 512;
571 start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
572 length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
574 #ifndef DISCOVER_ONLY
575 ped_exception_throw (
577 PED_EXCEPTION_CANCEL,
578 _("Partition %d has an invalid length of 0 bytes!"),
583 part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
584 start, start + length - 1);
588 mac_part_data = part->disk_specific;
590 strncpy (mac_part_data->volume_name, raw_part->name, 32);
591 strncpy (mac_part_data->system_name, raw_part->type, 32);
592 strncpy (mac_part_data->processor_name, raw_part->processor, 16);
594 mac_part_data->is_boot = _rawpart_is_boot (raw_part);
595 mac_part_data->is_driver = _rawpart_is_driver (raw_part);
596 if (mac_part_data->is_driver)
597 mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
598 mac_part_data->is_root = _rawpart_is_root (raw_part);
599 mac_part_data->is_swap = _rawpart_is_swap (raw_part);
600 mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
601 mac_part_data->is_raid = _rawpart_is_raid (raw_part);
604 #ifndef DISCOVER_ONLY
605 if (raw_part->data_start) {
606 ped_exception_throw (
608 PED_EXCEPTION_CANCEL,
609 _("The data region doesn't start at the start "
610 "of the partition."));
611 goto error_destroy_part;
613 #endif /* !DISCOVER_ONLY */
614 mac_part_data->data_region_length
615 = PED_BE32_TO_CPU (raw_part->data_count) * block_size;
617 /* boot region - we have no idea what this is for, but Mac OSX
618 * seems to put garbage here, and doesn't pay any attention to
619 * it afterwards. [clausen, dan burcaw]
622 if (raw_part->boot_start) {
623 ped_exception_throw (
625 PED_EXCEPTION_CANCEL,
626 _("The boot region doesn't start at the start "
627 "of the partition."));
628 goto error_destroy_part;
631 mac_part_data->boot_region_length
632 = PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
634 #ifndef DISCOVER_ONLY
635 if (mac_part_data->has_driver) {
636 if (mac_part_data->boot_region_length < part->geom.length) {
637 if (ped_exception_throw (
639 PED_EXCEPTION_IGNORE_CANCEL,
640 _("The partition's boot region doesn't occupy "
641 "the entire partition."))
642 != PED_EXCEPTION_IGNORE)
643 goto error_destroy_part;
646 if (mac_part_data->data_region_length < part->geom.length &&
647 !mac_part_data->is_boot) {
648 if (ped_exception_throw (
650 PED_EXCEPTION_IGNORE_CANCEL,
651 _("The partition's data region doesn't occupy "
652 "the entire partition."))
653 != PED_EXCEPTION_IGNORE)
654 goto error_destroy_part;
657 #endif /* !DISCOVER_ONLY */
659 mac_part_data->boot_base_address
660 = PED_BE32_TO_CPU (raw_part->boot_load);
661 mac_part_data->boot_entry_address
662 = PED_BE32_TO_CPU (raw_part->boot_entry);
663 mac_part_data->boot_checksum
664 = PED_BE32_TO_CPU (raw_part->boot_cksum);
666 mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
667 mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
672 ped_partition_destroy (part);
677 /* looks at the partition map size field in a mac raw partition, and calculates
678 * what the size of the partition map should be, from it
681 _rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
683 MacDiskData* mac_disk_data = disk->disk_specific;
684 PedSector sector_size = disk->dev->sector_size / 512;
685 PedSector part_map_start;
686 PedSector part_map_end;
688 part_map_start = mac_disk_data->ghost_size;
689 part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
691 return part_map_end - part_map_start + 1;
695 _disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
697 PedSector block_size;
699 if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
700 #ifndef DISCOVER_ONLY
701 ped_exception_throw (
703 PED_EXCEPTION_CANCEL,
704 _("Weird block size on device descriptor: %d bytes is "
705 "not divisible by 512."),
706 (int) PED_BE16_TO_CPU (raw_disk->block_size));
711 block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
712 if (block_size != disk->dev->sector_size / 512) {
713 #ifndef DISCOVER_ONLY
714 if (ped_exception_throw (
715 PED_EXCEPTION_WARNING,
716 PED_EXCEPTION_IGNORE_CANCEL,
717 _("The driver descriptor says the physical block size "
718 "is %d bytes, but Linux says it is %d bytes."),
719 (int) block_size * 512,
720 (int) disk->dev->sector_size)
721 != PED_EXCEPTION_IGNORE)
724 disk->dev->sector_size = block_size * 512;
733 /* Tries to figure out the block size used by the drivers, for the ghost
734 * partitioning scheme. Ghost partitioning works like this: the OpenFirmware
735 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
736 * perhaps, some other number?). To remain compatible, the partition map
737 * only has "real" partition map entries on ghost-aligned block numbers (and
738 * the others are padded with Apple_Void partitions). This function tries
739 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
740 * doesn't always equal 2048!!!)
743 _disk_analyse_ghost_size (PedDisk* disk)
745 MacDiskData* mac_disk_data = disk->disk_specific;
747 void *buf = ped_malloc (disk->dev->sector_size);
753 for (i = 1; i < 64; i *= 2) {
754 if (!ped_device_read (disk->dev, buf, i, 1))
756 if (_rawpart_check_signature (buf)
757 && !_rawpart_is_void (buf)) {
758 mac_disk_data->ghost_size = i;
759 PED_ASSERT (i <= disk->dev->sector_size / 512, break);
766 #ifndef DISCOVER_ONLY
768 ped_exception_throw (
770 PED_EXCEPTION_CANCEL,
771 _("No valid partition map found."));
777 mac_read (PedDisk* disk)
779 MacDiskData* mac_disk_data;
782 PedSector ghost_size;
783 PedConstraint* constraint_exact;
784 int last_part_entry_num = 0;
786 PED_ASSERT (disk != NULL, return 0);
788 mac_disk_data = disk->disk_specific;
789 mac_disk_data->part_map_entry_num = 0; /* 0 == none */
792 if (!ptt_read_sector (disk->dev, 0, &buf))
795 MacRawDisk *raw_disk = (MacRawDisk *) buf;
797 if (!_check_signature (raw_disk))
800 if (!_disk_analyse_block_size (disk, raw_disk))
802 if (!_disk_analyse_ghost_size (disk))
804 ghost_size = mac_disk_data->ghost_size;
806 if (!ped_disk_delete_all (disk))
809 if (raw_disk->driver_count && raw_disk->driver_count < 62) {
810 memcpy(&mac_disk_data->driverlist[0], &raw_disk->driverlist[0],
811 sizeof(mac_disk_data->driverlist));
812 mac_disk_data->driver_count = raw_disk->driver_count;
813 mac_disk_data->block_size = raw_disk->block_size;
816 for (num=1; num==1 || num <= last_part_entry_num; num++) {
817 void *raw_part = buf;
818 if (!ped_device_read (disk->dev, raw_part,
819 num * ghost_size, 1))
820 goto error_delete_all;
822 if (!_rawpart_check_signature (raw_part))
827 = _rawpart_get_partmap_size (raw_part, disk);
828 if (_rawpart_get_partmap_size (raw_part, disk)
829 != last_part_entry_num) {
830 if (ped_exception_throw (
832 PED_EXCEPTION_IGNORE_CANCEL,
833 _("Conflicting partition map entry sizes! "
834 "Entry 1 says it is %d, but entry %d says "
837 _rawpart_get_partmap_size (raw_part, disk))
838 != PED_EXCEPTION_IGNORE)
839 goto error_delete_all;
842 if (!_rawpart_is_active (raw_part))
845 part = _rawpart_analyse (raw_part, disk, num);
847 goto error_delete_all;
849 part->fs_type = ped_file_system_probe (&part->geom);
850 constraint_exact = ped_constraint_exact (&part->geom);
851 if (!ped_disk_add_partition (disk, part, constraint_exact))
852 goto error_delete_all;
853 ped_constraint_destroy (constraint_exact);
855 if (_rawpart_is_partition_map (raw_part)) {
856 if (mac_disk_data->part_map_entry_num
857 && ped_exception_throw (
859 PED_EXCEPTION_IGNORE_CANCEL,
860 _("Weird! There are 2 partitions "
862 != PED_EXCEPTION_IGNORE)
863 goto error_delete_all;
865 mac_disk_data->part_map_entry_num = num;
866 mac_disk_data->part_map_entry_count
867 = part->geom.end - ghost_size + 1;
871 if (!mac_disk_data->part_map_entry_num) {
872 if (!_disk_add_part_map_entry (disk, 1))
873 goto error_delete_all;
874 ped_disk_commit_to_dev (disk);
880 ped_disk_delete_all (disk);
886 #ifndef DISCOVER_ONLY
887 /* The Ghost partition: is a blank entry, used to pad out each block (where
888 * there physical block size > 512 bytes). This is because OpenFirmware uses
889 * 512 byte blocks, but device drivers Think Different TM, with a different
890 * lbock size, so we need to do this to avoid a clash (!)
893 _pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
895 MacDiskData* mac_disk_data = disk->disk_specific;
898 size_t ss = disk->dev->sector_size;
899 void *buf = ped_calloc (ss);
903 MacRawPartition *ghost_entry = buf;
904 ghost_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
905 strcpy (ghost_entry->type, "Apple_Void");
906 ghost_entry->map_count
907 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
909 for (i=0; i < mac_disk_data->ghost_size - 1; i++) {
910 PedSector idx = i + (num - 1) * mac_disk_data->ghost_size;
911 memcpy ((char*)part_map + idx * ss, ghost_entry, ss);
919 _update_driver_count (MacRawPartition* part_map_entry,
920 MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
922 uint16_t i, count_orig, count_cur, bsz;
923 uint32_t driver_bs, driver_be, part_be;
925 bsz = mac_disk_data->block_size / 512;
926 count_cur = mac_driverdata->driver_count;
927 count_orig = mac_disk_data->driver_count;
928 for (i = 0; i < count_orig; i++) {
929 driver_bs = mac_disk_data->driverlist[i].block * bsz;
930 driver_be = driver_bs + mac_disk_data->driverlist[i].size;
931 part_be = part_map_entry->start_block + part_map_entry->block_count;
932 if (driver_bs >= part_map_entry->start_block
933 && driver_be <= part_be) {
934 mac_driverdata->driverlist[count_cur].block
935 = mac_disk_data->driverlist[i].block;
936 mac_driverdata->driverlist[count_cur].size
937 = mac_disk_data->driverlist[i].size;
938 mac_driverdata->driverlist[count_cur].type
939 = mac_disk_data->driverlist[i].type;
940 mac_driverdata->driver_count++;
946 static MacRawPartition *
947 get_pme (MacRawPartition const *part_map, PedSector i, PedDisk const *disk)
949 MacDiskData const *mac_disk_data = disk->disk_specific;
950 PedSector idx = i * mac_disk_data->ghost_size - 1;
951 return (MacRawPartition *) ((char*)part_map
952 + idx * disk->dev->sector_size);
955 /* Initialize the disk->dev->sector_size bytes of part_map[part->num]. */
957 _generate_raw_part (PedDisk* disk, PedPartition* part,
958 MacRawPartition* part_map, MacDiskData *mac_driverdata)
960 MacDiskData* mac_disk_data;
961 MacPartitionData* mac_part_data;
962 PedSector block_size = disk->dev->sector_size / 512;
964 PED_ASSERT (part->num > 0, goto error);
966 mac_disk_data = disk->disk_specific;
967 mac_part_data = part->disk_specific;
969 MacRawPartition *part_map_entry = get_pme (part_map, part->num, disk);
970 memset (part_map_entry, 0, disk->dev->sector_size);
972 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
973 part_map_entry->map_count
974 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
975 part_map_entry->start_block
976 = PED_CPU_TO_BE32 (part->geom.start / block_size);
977 part_map_entry->block_count
978 = PED_CPU_TO_BE32 (part->geom.length / block_size);
979 strcpy (part_map_entry->name, mac_part_data->volume_name);
980 strcpy (part_map_entry->type, mac_part_data->system_name);
982 if (mac_part_data->is_driver) {
983 mac_part_data->boot_region_length = part->geom.length;
984 if (mac_part_data->has_driver)
985 _update_driver_count(part_map_entry, mac_driverdata,
988 mac_part_data->data_region_length = part->geom.length;
989 part_map_entry->data_count = PED_CPU_TO_BE32 (
990 mac_part_data->data_region_length / block_size);
991 part_map_entry->boot_count = PED_CPU_TO_BE32 (
992 mac_part_data->boot_region_length / block_size);
993 part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
994 part_map_entry->driver_sig
995 = PED_CPU_TO_BE32 (mac_part_data->driver_sig);
997 part_map_entry->boot_load =
998 PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
999 part_map_entry->boot_entry =
1000 PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
1001 part_map_entry->boot_cksum =
1002 PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
1004 strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
1006 if (!_pad_raw_part (disk, part->num, part_map))
1016 _generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
1017 MacRawPartition* part_map)
1019 MacDiskData* mac_disk_data = disk->disk_specific;
1020 PedSector block_size = disk->dev->sector_size / 512;
1022 PED_ASSERT (num > 0, goto error);
1024 MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
1026 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
1027 part_map_entry->map_count
1028 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
1029 part_map_entry->start_block
1030 = PED_CPU_TO_BE32 (geom->start / block_size);
1031 part_map_entry->block_count
1032 = PED_CPU_TO_BE32 (geom->length / block_size);
1033 strcpy (part_map_entry->name, "Extra");
1034 strcpy (part_map_entry->type, "Apple_Free");
1036 part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
1037 part_map_entry->status = 0;
1038 part_map_entry->driver_sig = 0;
1040 if (!_pad_raw_part (disk, num, part_map))
1050 _generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
1052 MacDiskData* mac_disk_data = disk->disk_specific;
1054 PED_ASSERT (num > 0, return 0);
1056 MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
1057 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
1058 part_map_entry->map_count
1059 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
1060 strcpy (part_map_entry->type, "Apple_Void");
1062 return _pad_raw_part (disk, num, part_map);
1065 /* returns the first empty entry in the partition map */
1067 _get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map)
1069 MacDiskData* mac_disk_data = disk->disk_specific;
1072 for (i=1; i <= mac_disk_data->last_part_entry_num; i++) {
1073 MacRawPartition *part_map_entry = get_pme (part_map, i, disk);
1074 if (!part_map_entry->signature)
1082 write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
1084 PedDevice* dev = disk->dev;
1086 if (!ptt_read_sector (dev, 0, &s0))
1088 MacRawDisk *raw_disk = (MacRawDisk *) s0;
1090 raw_disk->signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
1091 raw_disk->block_size = PED_CPU_TO_BE16 (dev->sector_size);
1092 raw_disk->block_count
1093 = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
1095 raw_disk->driver_count = mac_driverdata->driver_count;
1096 memcpy(&raw_disk->driverlist[0], &mac_driverdata->driverlist[0],
1097 sizeof(raw_disk->driverlist));
1099 int write_ok = ped_device_write (dev, raw_disk, 0, 1);
1105 mac_write (PedDisk* disk)
1107 MacRawPartition* part_map;
1108 MacDiskData* mac_disk_data;
1109 MacDiskData* mac_driverdata; /* updated driver list */
1113 PED_ASSERT (disk != NULL, return 0);
1114 PED_ASSERT (disk->disk_specific != NULL, return 0);
1115 PED_ASSERT (disk->dev != NULL, return 0);
1116 PED_ASSERT (!disk->update_mode, return 0);
1118 mac_disk_data = disk->disk_specific;
1120 if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
1121 if (!_disk_add_part_map_entry (disk, 1))
1125 mac_driverdata = ped_malloc(sizeof(MacDiskData));
1126 if (!mac_driverdata)
1128 memset (mac_driverdata, 0, sizeof(MacDiskData));
1130 size_t pmap_bytes = (mac_disk_data->part_map_entry_count
1131 * mac_disk_data->ghost_size
1132 * disk->dev->sector_size);
1133 part_map = (MacRawPartition*) ped_calloc (pmap_bytes);
1135 goto error_free_driverdata;
1137 /* write (to memory) the "real" partitions */
1138 for (part = ped_disk_next_partition (disk, NULL); part;
1139 part = ped_disk_next_partition (disk, part)) {
1140 if (!ped_partition_is_active (part))
1142 if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
1143 goto error_free_part_map;
1146 /* write the "free space" partitions */
1147 for (part = ped_disk_next_partition (disk, NULL); part;
1148 part = ped_disk_next_partition (disk, part)) {
1149 if (part->type != PED_PARTITION_FREESPACE)
1151 num = _get_first_empty_part_entry (disk, part_map);
1152 if (!_generate_raw_freespace_part (disk, &part->geom, num,
1154 goto error_free_part_map;
1157 /* write the "void" (empty) partitions */
1158 for (num = _get_first_empty_part_entry (disk, part_map); num;
1159 num = _get_first_empty_part_entry (disk, part_map))
1160 _generate_empty_part (disk, num, part_map);
1163 if (!ped_device_write (disk->dev, part_map, 1,
1164 mac_disk_data->part_map_entry_count))
1165 goto error_free_part_map;
1167 int write_ok = write_block_zero (disk, mac_driverdata);
1168 free (mac_driverdata);
1171 error_free_part_map:
1173 error_free_driverdata:
1174 free (mac_driverdata);
1178 #endif /* !DISCOVER_ONLY */
1180 static PedPartition*
1182 const PedDisk* disk, PedPartitionType part_type,
1183 const PedFileSystemType* fs_type, PedSector start, PedSector end)
1186 MacPartitionData* mac_data;
1188 part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1192 if (ped_partition_is_active (part)) {
1194 = mac_data = ped_malloc (sizeof (MacPartitionData));
1196 goto error_free_part;
1198 memset (mac_data, 0, sizeof (MacPartitionData));
1199 strcpy (mac_data->volume_name, "untitled");
1201 part->disk_specific = NULL;
1211 static PedPartition*
1212 mac_partition_duplicate (const PedPartition* part)
1214 PedPartition* new_part;
1215 MacPartitionData* new_mac_data;
1216 MacPartitionData* old_mac_data;
1218 new_part = ped_partition_new (part->disk, part->type,
1219 part->fs_type, part->geom.start,
1223 new_part->num = part->num;
1225 old_mac_data = (MacPartitionData*) part->disk_specific;
1226 new_mac_data = (MacPartitionData*) new_part->disk_specific;
1228 /* ugly, but C is ugly :p */
1229 memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
1234 mac_partition_destroy (PedPartition* part)
1236 PED_ASSERT (part != NULL, return);
1238 if (ped_partition_is_active (part))
1239 free (part->disk_specific);
1244 mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1246 MacPartitionData* mac_data = part->disk_specific;
1248 part->fs_type = fs_type;
1250 if (fs_type && is_linux_swap (fs_type->name))
1251 ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1253 if (mac_data->is_boot) {
1254 strcpy (mac_data->system_name, "Apple_Bootstrap");
1255 mac_data->status = 0x33;
1259 if (fs_type && (!strcmp (fs_type->name, "hfs")
1260 || !strcmp (fs_type->name, "hfs+"))) {
1261 strcpy (mac_data->system_name, "Apple_HFS");
1262 mac_data->status |= 0x7f;
1263 } else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
1264 strcpy (mac_data->system_name, "Apple_HFSX");
1265 mac_data->status |= 0x7f;
1267 strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
1268 mac_data->status = 0x33;
1275 mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1277 MacPartitionData* mac_data;
1279 PED_ASSERT (part != NULL, return 0);
1280 PED_ASSERT (part->disk_specific != NULL, return 0);
1282 mac_data = part->disk_specific;
1285 case PED_PARTITION_BOOT:
1286 mac_data->is_boot = state;
1289 return mac_partition_set_system (part, part->fs_type);
1292 strcpy (mac_data->system_name, "Apple_Bootstrap");
1293 mac_data->status = 0x33;
1297 case PED_PARTITION_ROOT:
1299 strcpy (mac_data->volume_name, "root");
1300 mac_data->is_swap = 0;
1302 if (mac_data->is_root)
1303 strcpy (mac_data->volume_name, "untitled");
1305 mac_data->is_root = state;
1308 case PED_PARTITION_SWAP:
1310 strcpy (mac_data->volume_name, "swap");
1311 mac_data->is_root = 0;
1313 if (mac_data->is_swap)
1314 strcpy (mac_data->volume_name, "untitled");
1316 mac_data->is_swap = state;
1319 case PED_PARTITION_LVM:
1321 strcpy (mac_data->system_name, "Linux_LVM");
1322 mac_data->is_lvm = state;
1324 if (mac_data->is_lvm)
1325 mac_partition_set_system (part, part->fs_type);
1329 case PED_PARTITION_RAID:
1331 strcpy (mac_data->system_name, "Linux_RAID");
1332 mac_data->is_raid = state;
1334 if (mac_data->is_raid)
1335 mac_partition_set_system (part, part->fs_type);
1345 mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1347 MacPartitionData* mac_data;
1349 PED_ASSERT (part != NULL, return 0);
1350 PED_ASSERT (part->disk_specific != NULL, return 0);
1352 mac_data = part->disk_specific;
1354 case PED_PARTITION_BOOT:
1355 return mac_data->is_boot;
1357 case PED_PARTITION_ROOT:
1358 return mac_data->is_root;
1360 case PED_PARTITION_SWAP:
1361 return mac_data->is_swap;
1363 case PED_PARTITION_LVM:
1364 return mac_data->is_lvm;
1366 case PED_PARTITION_RAID:
1367 return mac_data->is_raid;
1375 mac_partition_is_flag_available (
1376 const PedPartition* part, PedPartitionFlag flag)
1379 case PED_PARTITION_BOOT:
1380 case PED_PARTITION_ROOT:
1381 case PED_PARTITION_SWAP:
1382 case PED_PARTITION_LVM:
1383 case PED_PARTITION_RAID:
1392 mac_partition_set_name (PedPartition* part, const char* name)
1394 MacPartitionData* mac_data;
1397 PED_ASSERT (part != NULL, return);
1398 PED_ASSERT (part->disk_specific != NULL, return);
1399 mac_data = part->disk_specific;
1401 #ifndef DISCOVER_ONLY
1402 if (mac_data->is_root || mac_data->is_swap) {
1403 if (ped_exception_throw (
1404 PED_EXCEPTION_WARNING,
1405 PED_EXCEPTION_IGNORE_CANCEL,
1406 _("Changing the name of a root or swap partition "
1407 "will prevent Linux from recognising it as such."))
1408 != PED_EXCEPTION_IGNORE)
1410 mac_data->is_root = mac_data->is_swap = 0;
1414 strncpy (mac_data->volume_name, name, 32);
1415 mac_data->volume_name [32] = 0;
1416 for (i = strlen (mac_data->volume_name) - 1;
1417 mac_data->volume_name[i] == ' '; i--)
1418 mac_data->volume_name [i] = 0;
1422 mac_partition_get_name (const PedPartition* part)
1424 MacPartitionData* mac_data;
1426 PED_ASSERT (part != NULL, return NULL);
1427 PED_ASSERT (part->disk_specific != NULL, return NULL);
1428 mac_data = part->disk_specific;
1430 return mac_data->volume_name;
1433 static PedAlignment*
1434 mac_get_partition_alignment(const PedDisk *disk)
1436 PedSector sector_size = disk->dev->sector_size / 512;
1438 return ped_alignment_new(0, sector_size);
1441 static PedConstraint*
1442 _primary_constraint (PedDisk* disk)
1444 PedAlignment start_align;
1445 PedAlignment end_align;
1446 PedGeometry max_geom;
1447 PedSector sector_size;
1449 sector_size = disk->dev->sector_size / 512;
1451 if (!ped_alignment_init (&start_align, 0, sector_size))
1453 if (!ped_alignment_init (&end_align, -1, sector_size))
1455 if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1458 return ped_constraint_new (&start_align, &end_align, &max_geom,
1459 &max_geom, 1, disk->dev->length);
1463 mac_partition_align (PedPartition* part, const PedConstraint* constraint)
1465 PED_ASSERT (part != NULL, return 0);
1467 if (_ped_partition_attempt_align (part, constraint,
1468 _primary_constraint (part->disk)))
1471 #ifndef DISCOVER_ONLY
1472 ped_exception_throw (
1473 PED_EXCEPTION_ERROR,
1474 PED_EXCEPTION_CANCEL,
1475 _("Unable to satisfy all constraints on the partition."));
1481 mac_partition_enumerate (PedPartition* part)
1484 MacDiskData* mac_disk_data;
1488 PED_ASSERT (part != NULL, return 0);
1489 PED_ASSERT (part->disk != NULL, return 0);
1492 mac_disk_data = (MacDiskData*) disk->disk_specific;
1494 max_part_count = ped_disk_get_max_primary_partition_count (disk);
1496 if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
1499 for (i = 1; i <= max_part_count; i++) {
1500 if (!ped_disk_get_partition (disk, i)) {
1506 #ifndef DISCOVER_ONLY
1507 ped_exception_throw (
1508 PED_EXCEPTION_ERROR,
1509 PED_EXCEPTION_CANCEL,
1510 _("Can't add another partition -- the partition map is too "
1518 _disk_count_partitions (PedDisk* disk)
1520 MacDiskData* mac_disk_data = disk->disk_specific;
1521 PedPartition* part = NULL;
1522 PedPartition* last = NULL;
1524 PED_ASSERT (disk->update_mode, return 0);
1526 mac_disk_data->active_part_entry_count = 0;
1527 mac_disk_data->free_part_entry_count = 0;
1528 mac_disk_data->last_part_entry_num = 0;
1530 /* subtle: we only care about free space after the partition map.
1531 * the partition map is an "active" partition, BTW... */
1532 for (part = ped_disk_next_partition (disk, part); part;
1533 part = ped_disk_next_partition (disk, part)) {
1534 if (!ped_partition_is_active (part))
1537 mac_disk_data->active_part_entry_count++;
1538 if (last && last->geom.end + 1 < part->geom.start)
1539 mac_disk_data->free_part_entry_count++;
1540 mac_disk_data->last_part_entry_num
1541 = PED_MAX (mac_disk_data->last_part_entry_num,
1547 if (last && last->geom.end < disk->dev->length - 1)
1548 mac_disk_data->free_part_entry_count++;
1550 mac_disk_data->last_part_entry_num
1551 = PED_MAX (mac_disk_data->last_part_entry_num,
1552 mac_disk_data->active_part_entry_count
1553 + mac_disk_data->free_part_entry_count);
1558 add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
1560 PedPartition* new_part;
1561 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
1563 PED_ASSERT (disk != NULL, return 0);
1565 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1569 if (!ped_disk_add_partition (disk, new_part, constraint_any))
1570 goto error_destroy_new_part;
1572 ped_constraint_destroy (constraint_any);
1575 error_destroy_new_part:
1576 ped_partition_destroy (new_part);
1578 ped_constraint_destroy (constraint_any);
1583 mac_alloc_metadata (PedDisk* disk)
1585 PED_ASSERT (disk != NULL, return 0);
1586 PED_ASSERT (disk->disk_specific != NULL, return 0);
1587 PED_ASSERT (disk->dev != NULL, return 0);
1589 if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
1592 /* hack: this seems to be a good place, to update the partition map
1593 * entry count, since mac_alloc_metadata() gets called during
1594 * _disk_pop_update_mode()
1596 return _disk_count_partitions (disk);
1600 mac_get_max_primary_partition_count (const PedDisk* disk)
1602 MacDiskData* mac_disk_data = disk->disk_specific;
1603 PedPartition* part_map_partition;
1605 part_map_partition = ped_disk_get_partition (disk,
1606 mac_disk_data->part_map_entry_num);
1608 /* HACK: if we haven't found the partition map partition (yet),
1611 if (!part_map_partition) {
1612 mac_disk_data->part_map_entry_num = 0;
1616 /* HACK: since Mac labels need an entry for free-space regions, we
1617 * must allow half plus 1 entries for free-space partitions. I hate
1618 * this, but things get REALLY complicated, otherwise.
1619 * (I'm prepared to complicate things later, but I want to get
1620 * everything working, first)
1622 return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
1623 - mac_disk_data->free_part_entry_count + 1;
1627 mac_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
1633 #include "pt-common.h"
1634 PT_define_limit_functions (mac)
1636 static PedDiskOps mac_disk_ops = {
1637 clobber: NULL_IF_DISCOVER_ONLY (mac_clobber),
1638 /* FIXME: remove this cast, once mac_write is fixed not to
1639 modify its *DISK parameter. */
1640 write: NULL_IF_DISCOVER_ONLY ((int (*) (const PedDisk*)) mac_write),
1642 partition_set_name: mac_partition_set_name,
1643 partition_get_name: mac_partition_get_name,
1645 get_partition_alignment: mac_get_partition_alignment,
1647 PT_op_function_initializers (mac)
1650 static PedDiskType mac_disk_type = {
1654 features: PED_DISK_TYPE_PARTITION_NAME
1658 ped_disk_mac_init ()
1660 PED_ASSERT (sizeof (MacRawPartition) == 512, return);
1661 PED_ASSERT (sizeof (MacRawDisk) == 512, return);
1663 ped_disk_type_register (&mac_disk_type);
1667 ped_disk_mac_done ()
1669 ped_disk_type_unregister (&mac_disk_type);