2 libparted - a library for manipulating disk partitions
3 Copyright (C) 2000, 2002, 2004 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 */
84 uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
86 uint32_t map_count; /* # blocks in partition map */
87 uint32_t start_block; /* absolute starting block # of partition */
88 uint32_t block_count; /* number of blocks in partition */
89 char name[32]; /* partition name */
90 char type[32]; /* string type description */
91 uint32_t data_start; /* rel block # of first data block */
92 uint32_t data_count; /* number of data blocks */
93 uint32_t status; /* partition status bits */
101 char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
104 } __attribute__ ((packed)) MacRawPartition;
106 /* Driver descriptor structure, in block 0 */
108 uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
109 uint16_t block_size; /* physical sector size */
110 uint32_t block_count; /* size of device in blocks */
111 uint16_t dev_type; /* reserved */
112 uint16_t dev_id; /* reserved */
113 uint32_t data; /* reserved */
114 uint16_t driver_count; /* # of driver descriptor entries */
115 uint8_t driverlist[488]; /* info about available drivers */
116 uint16_t padding[3]; /* pad to 512 bytes */
117 } __attribute__ ((packed)) MacRawDisk;
120 uint32_t block; /* startblock in MacRawDisk->block_size units */
121 uint16_t size; /* size in 512 byte units */
122 uint16_t type; /* operating system type (MacOS = 1) */
123 } __attribute__ ((packed)) MacDeviceDriver;
126 char volume_name[33]; /* eg: "Games" */
127 char system_name[33]; /* eg: "Apple_Unix_SVR2" */
128 char processor_name[17];
138 PedSector data_region_length;
139 PedSector boot_region_length;
141 uint32_t boot_base_address;
142 uint32_t boot_entry_address;
143 uint32_t boot_checksum;
150 int ghost_size; /* sectors per "driver" block */
151 int part_map_entry_count; /* # entries (incl. ghost) */
152 int part_map_entry_num; /* partition map location */
154 int active_part_entry_count; /* # real partitions */
155 int free_part_entry_count; /* # free space */
156 int last_part_entry_num; /* last entry number */
158 uint16_t block_size; /* physical sector size */
159 uint16_t driver_count;
160 MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */
163 static PedDiskType mac_disk_type;
166 _check_signature (MacRawDisk* raw_disk)
168 if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
172 return ped_exception_throw (
174 PED_EXCEPTION_IGNORE_CANCEL,
175 _("Invalid signature %x for Mac disk labels."),
176 (int) PED_BE16_TO_CPU (raw_disk->signature))
177 == PED_EXCEPTION_IGNORE;
185 _rawpart_check_signature (MacRawPartition* raw_part)
187 int sig = (int) PED_BE16_TO_CPU (raw_part->signature);
188 return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
192 mac_probe (const PedDevice * dev)
196 PED_ASSERT (dev != NULL, return 0);
198 if (dev->sector_size != 512)
201 if (!ped_device_read (dev, &buf, 0, 1))
204 return _check_signature (&buf);
208 _disk_add_part_map_entry (PedDisk* disk, int warn)
210 MacDiskData* mac_disk_data = disk->disk_specific;
211 PedPartition* new_part;
212 MacPartitionData* mac_part_data;
213 PedSector part_map_size;
214 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
216 #ifndef DISCOVER_ONLY
217 if (warn && ped_exception_throw (
219 PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
220 _("Partition map has no partition map entry!"))
221 != PED_EXCEPTION_FIX)
223 #endif /* !DISCOVER_ONLY */
226 = ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
227 if (part_map_size == 0)
230 new_part = ped_partition_new (disk, 0, NULL, 1, part_map_size - 1);
234 mac_part_data = new_part->disk_specific;
235 strcpy (mac_part_data->volume_name, "Apple");
236 strcpy (mac_part_data->system_name, "Apple_partition_map");
238 if (!ped_disk_add_partition (disk, new_part, constraint_any))
239 goto error_destroy_new_part;
241 mac_disk_data->part_map_entry_num = new_part->num;
242 mac_disk_data->part_map_entry_count
243 = new_part->geom.end - mac_disk_data->ghost_size;
244 ped_constraint_destroy (constraint_any);
247 error_destroy_new_part:
248 ped_partition_destroy (new_part);
250 ped_constraint_destroy (constraint_any);
255 mac_alloc (const PedDevice* dev)
258 MacDiskData* mac_disk_data;
260 PED_ASSERT (dev != NULL, return NULL);
262 #ifndef DISCOVER_ONLY
263 if (dev->length < 256) {
264 ped_exception_throw (
266 PED_EXCEPTION_CANCEL,
267 _("%s is too small for a Mac disk label!"),
273 disk = _ped_disk_alloc (dev, &mac_disk_type);
277 mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
279 goto error_free_disk;
280 disk->disk_specific = mac_disk_data;
281 mac_disk_data->ghost_size = disk->dev->sector_size / 512;
282 mac_disk_data->active_part_entry_count = 0;
283 mac_disk_data->free_part_entry_count = 1;
284 mac_disk_data->last_part_entry_num = 1;
285 mac_disk_data->block_size = 0;
286 mac_disk_data->driver_count = 0;
287 memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
289 if (!_disk_add_part_map_entry (disk, 0))
290 goto error_free_disk;
294 _ped_disk_free (disk);
300 mac_duplicate (const PedDisk* disk)
303 MacDiskData* new_mac_data;
304 MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific;
305 PedPartition* partition_map;
307 new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type);
311 new_mac_data = (MacDiskData*) new_disk->disk_specific;
313 /* remove the partition map partition - it will be duplicated
316 partition_map = ped_disk_get_partition_by_sector (new_disk, 1);
317 PED_ASSERT (partition_map != NULL, return 0);
318 ped_disk_remove_partition (new_disk, partition_map);
320 /* ugly, but C is ugly :p */
321 memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
325 _ped_disk_free (new_disk);
331 mac_free (PedDisk* disk)
333 MacDiskData* mac_disk_data = disk->disk_specific;
335 _ped_disk_free (disk);
336 ped_free (mac_disk_data);
339 #ifndef DISCOVER_ONLY
341 _clobber_part_map (PedDevice* dev)
343 MacRawPartition raw_part;
346 for (sector=1; 1; sector++) {
347 if (!ped_device_read (dev, &raw_part, sector, 1))
349 if (!_rawpart_check_signature (&raw_part))
351 memset (&raw_part, 0, 512);
352 if (!ped_device_write (dev, &raw_part, sector, 1))
358 mac_clobber (PedDevice* dev)
362 if (!ped_device_read (dev, &raw_disk, 0, 1))
364 if (!_check_signature (&raw_disk))
366 memset (&raw_disk, 0, 512);
367 if (!ped_device_write (dev, &raw_disk, 0, 1))
370 return _clobber_part_map (dev);
372 #endif /* !DISCOVER_ONLY */
375 _rawpart_cmp_type (MacRawPartition* raw_part, char* type)
377 return strncasecmp (raw_part->type, type, 32) == 0;
381 _rawpart_cmp_name (MacRawPartition* raw_part, char* name)
383 return strncasecmp (raw_part->name, name, 32) == 0;
387 _rawpart_is_partition_map (MacRawPartition* raw_part)
389 return _rawpart_cmp_type (raw_part, "Apple_partition_map");
393 strncasestr (const char* haystack, const char* needle, int n)
395 int needle_size = strlen (needle);
398 for (i = 0; haystack[i] && i < n - needle_size; i++) {
399 if (strncasecmp (haystack + i, needle, needle_size) == 0)
407 _rawpart_is_boot (MacRawPartition* raw_part)
409 if (!strcasecmp(raw_part->type, "Apple_Bootstrap"))
412 if (!strcasecmp(raw_part->type, "Apple_Boot"))
419 _rawpart_is_driver (MacRawPartition* raw_part)
421 if (strncmp (raw_part->type, "Apple_", 6) != 0)
423 if (!strncasestr (raw_part->type, "driver", 32))
429 _rawpart_has_driver (MacRawPartition* raw_part, MacDiskData* mac_disk_data)
431 MacDeviceDriver *driverlist;
433 uint32_t driver_bs, driver_be, part_be;
435 driverlist = &mac_disk_data->driverlist[0];
436 bsz = mac_disk_data->block_size / 512;
437 for (i = 0; i < mac_disk_data->driver_count; i++) {
438 driver_bs = driverlist->block * bsz;
439 driver_be = driver_bs + driverlist->size;
440 part_be = raw_part->start_block + raw_part->block_count;
441 if (driver_bs >= raw_part->start_block && driver_be <= part_be)
449 _rawpart_is_root (MacRawPartition* raw_part)
451 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
453 if (strcmp (raw_part->name, "root") != 0)
459 _rawpart_is_swap (MacRawPartition* raw_part)
461 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
463 if (strcmp (raw_part->name, "swap") != 0)
469 _rawpart_is_lvm (MacRawPartition* raw_part)
471 if (strcmp (raw_part->type, "Linux_LVM") != 0)
477 _rawpart_is_raid (MacRawPartition* raw_part)
479 if (strcmp (raw_part->type, "Linux_RAID") != 0)
485 _rawpart_is_void (MacRawPartition* raw_part)
487 return _rawpart_cmp_type (raw_part, "Apple_Void");
490 /* returns 1 if the raw_part represents a partition that is "unused space", or
491 * doesn't represent a partition at all. NOTE: some people make Apple_Free
492 * partitions with MacOS, because they can't select another type. So, if the
493 * name is anything other than "Extra" or "", it is treated as a "real"
497 _rawpart_is_active (MacRawPartition* raw_part)
499 if (_rawpart_cmp_type (raw_part, "Apple_Free")
500 && (_rawpart_cmp_name (raw_part, "Extra")
501 || _rawpart_cmp_name (raw_part, "")))
503 if (_rawpart_cmp_type (raw_part, "Apple_Void"))
505 if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
507 if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
514 _rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
516 MacDiskData* mac_disk_data;
518 MacPartitionData* mac_part_data;
519 PedSector block_size;
520 PedSector start, length;
522 if (!_rawpart_check_signature (raw_part)) {
523 #ifndef DISCOVER_ONLY
524 if (ped_exception_throw (
525 PED_EXCEPTION_WARNING,
526 PED_EXCEPTION_IGNORE_CANCEL,
527 _("Partition %d has an invalid signature %x."),
529 (int) PED_BE16_TO_CPU (raw_part->signature))
530 != PED_EXCEPTION_IGNORE)
535 mac_disk_data = (MacDiskData*) disk->disk_specific;
536 block_size = disk->dev->sector_size / 512;
538 start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
539 length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
541 #ifndef DISCOVER_ONLY
542 ped_exception_throw (
544 PED_EXCEPTION_CANCEL,
545 _("Partition %d has an invalid length of 0 bytes!"),
550 part = ped_partition_new (disk, 0, NULL, start, start + length - 1);
554 mac_part_data = part->disk_specific;
556 strncpy (mac_part_data->volume_name, raw_part->name, 32);
557 strncpy (mac_part_data->system_name, raw_part->type, 32);
558 strncpy (mac_part_data->processor_name, raw_part->processor, 16);
560 mac_part_data->is_boot = _rawpart_is_boot (raw_part);
561 mac_part_data->is_driver = _rawpart_is_driver (raw_part);
562 if (mac_part_data->is_driver)
563 mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
564 mac_part_data->is_root = _rawpart_is_root (raw_part);
565 mac_part_data->is_swap = _rawpart_is_swap (raw_part);
566 mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
567 mac_part_data->is_raid = _rawpart_is_raid (raw_part);
570 #ifndef DISCOVER_ONLY
571 if (raw_part->data_start) {
572 ped_exception_throw (
574 PED_EXCEPTION_CANCEL,
575 _("The data region doesn't start at the start "
576 "of the partition."));
577 goto error_destroy_part;
579 #endif /* !DISCOVER_ONLY */
580 mac_part_data->data_region_length
581 = PED_BE32_TO_CPU (raw_part->data_count) * block_size;
583 /* boot region - we have no idea what this is for, but Mac OSX
584 * seems to put garbage here, and doesn't pay any attention to
585 * it afterwards. [clausen, dan burcaw]
588 if (raw_part->boot_start) {
589 ped_exception_throw (
591 PED_EXCEPTION_CANCEL,
592 _("The boot region doesn't start at the start "
593 "of the partition."));
594 goto error_destroy_part;
597 mac_part_data->boot_region_length
598 = PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
600 #ifndef DISCOVER_ONLY
601 if (mac_part_data->has_driver) {
602 if (mac_part_data->boot_region_length < part->geom.length) {
603 if (ped_exception_throw (
605 PED_EXCEPTION_IGNORE_CANCEL,
606 _("The partition's boot region doesn't occupy "
607 "the entire partition."))
608 != PED_EXCEPTION_IGNORE)
609 goto error_destroy_part;
612 if (mac_part_data->data_region_length < part->geom.length &&
613 !mac_part_data->is_boot) {
614 if (ped_exception_throw (
616 PED_EXCEPTION_IGNORE_CANCEL,
617 _("The partition's data region doesn't occupy "
618 "the entire partition."))
619 != PED_EXCEPTION_IGNORE)
620 goto error_destroy_part;
623 #endif /* !DISCOVER_ONLY */
625 mac_part_data->boot_base_address
626 = PED_BE32_TO_CPU (raw_part->boot_load);
627 mac_part_data->boot_entry_address
628 = PED_BE32_TO_CPU (raw_part->boot_entry);
629 mac_part_data->boot_checksum
630 = PED_BE32_TO_CPU (raw_part->boot_cksum);
632 mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
633 mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
638 ped_partition_destroy (part);
643 /* looks at the partition map size field in a mac raw partition, and calculates
644 * what the size of the partition map should be, from it
647 _rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
649 MacDiskData* mac_disk_data = disk->disk_specific;
650 PedSector sector_size = disk->dev->sector_size / 512;
651 PedSector part_map_start;
652 PedSector part_map_end;
654 part_map_start = mac_disk_data->ghost_size;
655 part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
657 return part_map_end - part_map_start + 1;
661 _disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
663 PedSector block_size;
665 if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
666 #ifndef DISCOVER_ONLY
667 ped_exception_throw (
669 PED_EXCEPTION_CANCEL,
670 _("Weird block size on device descriptor: %d bytes is "
671 "not divisible by 512."),
672 (int) PED_BE16_TO_CPU (raw_disk->block_size));
677 block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
678 if (block_size != disk->dev->sector_size / 512) {
679 #ifndef DISCOVER_ONLY
680 if (ped_exception_throw (
681 PED_EXCEPTION_WARNING,
682 PED_EXCEPTION_IGNORE_CANCEL,
683 _("The driver descriptor says the physical block size "
684 "is %d bytes, but Linux says it is %d bytes."),
685 (int) block_size * 512,
686 (int) disk->dev->sector_size)
687 != PED_EXCEPTION_IGNORE)
690 disk->dev->sector_size = block_size * 512;
699 /* Tries to figure out the block size used by the drivers, for the ghost
700 * partitioning scheme. Ghost partitioning works like this: the OpenFirmware
701 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
702 * perhaps, some other number?). To remain compatible, the partition map
703 * only has "real" partition map entries on ghost-aligned block numbers (and
704 * the others are padded with Apple_Void partitions). This function tries
705 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
706 * doesn't always equal 2048!!!)
709 _disk_analyse_ghost_size (PedDisk* disk)
711 MacDiskData* mac_disk_data = disk->disk_specific;
712 MacRawPartition raw_part;
715 for (i = 1; i < 64; i *= 2) {
716 if (!ped_device_read (disk->dev, &raw_part, i, 1))
718 if (_rawpart_check_signature (&raw_part)
719 && !_rawpart_is_void (&raw_part)) {
720 mac_disk_data->ghost_size = i;
721 PED_ASSERT (i <= disk->dev->sector_size / 512,
727 #ifndef DISCOVER_ONLY
728 ped_exception_throw (
730 PED_EXCEPTION_CANCEL,
731 _("No valid partition map found."));
737 mac_read (PedDisk* disk)
740 MacRawPartition raw_part;
741 MacDiskData* mac_disk_data;
744 PedSector ghost_size;
745 PedConstraint* constraint_exact;
746 int last_part_entry_num = 0;
748 PED_ASSERT (disk != NULL, return 0);
750 mac_disk_data = disk->disk_specific;
751 mac_disk_data->part_map_entry_num = 0; /* 0 == none */
753 if (!ped_device_read (disk->dev, &raw_disk, 0, 1))
755 if (!_check_signature (&raw_disk))
758 if (!_disk_analyse_block_size (disk, &raw_disk))
760 if (!_disk_analyse_ghost_size (disk))
762 ghost_size = mac_disk_data->ghost_size;
764 if (!ped_disk_delete_all (disk))
767 if (raw_disk.driver_count && raw_disk.driver_count < 62) {
768 memcpy(&mac_disk_data->driverlist[0], &raw_disk.driverlist[0],
769 sizeof(mac_disk_data->driverlist));
770 mac_disk_data->driver_count = raw_disk.driver_count;
771 mac_disk_data->block_size = raw_disk.block_size;
774 for (num=1; num==1 || num <= last_part_entry_num; num++) {
775 if (!ped_device_read (disk->dev, &raw_part,
776 num * ghost_size, 1))
777 goto error_delete_all;
779 if (!_rawpart_check_signature (&raw_part))
784 = _rawpart_get_partmap_size (&raw_part, disk);
785 if (_rawpart_get_partmap_size (&raw_part, disk)
786 != last_part_entry_num) {
787 if (ped_exception_throw (
789 PED_EXCEPTION_IGNORE_CANCEL,
790 _("Conflicting partition map entry sizes! "
791 "Entry 1 says it is %d, but entry %d says "
794 _rawpart_get_partmap_size (&raw_part, disk))
795 != PED_EXCEPTION_IGNORE)
796 goto error_delete_all;
799 if (!_rawpart_is_active (&raw_part))
802 part = _rawpart_analyse (&raw_part, disk, num);
804 goto error_delete_all;
806 part->fs_type = ped_file_system_probe (&part->geom);
807 constraint_exact = ped_constraint_exact (&part->geom);
808 if (!ped_disk_add_partition (disk, part, constraint_exact))
809 goto error_delete_all;
810 ped_constraint_destroy (constraint_exact);
812 if (_rawpart_is_partition_map (&raw_part)) {
813 if (mac_disk_data->part_map_entry_num
814 && ped_exception_throw (
816 PED_EXCEPTION_IGNORE_CANCEL,
817 _("Weird! There are 2 partitions "
819 != PED_EXCEPTION_IGNORE)
820 goto error_delete_all;
822 mac_disk_data->part_map_entry_num = num;
823 mac_disk_data->part_map_entry_count
824 = part->geom.end - ghost_size + 1;
828 if (!mac_disk_data->part_map_entry_num) {
829 if (!_disk_add_part_map_entry (disk, 1))
830 goto error_delete_all;
831 ped_disk_commit_to_dev (disk);
836 ped_disk_delete_all (disk);
841 #ifndef DISCOVER_ONLY
842 /* The Ghost partition: is a blank entry, used to pad out each block (where
843 * there physical block size > 512 bytes). This is because OpenFirmware uses
844 * 512 byte blocks, but device drivers Think Different TM, with a different
845 * lbock size, so we need to do this to avoid a clash (!)
848 _pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
850 MacDiskData* mac_disk_data = disk->disk_specific;
851 MacRawPartition ghost_entry;
854 memset (&ghost_entry, 0, sizeof (ghost_entry));
855 ghost_entry.signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
856 strcpy (ghost_entry.type, "Apple_Void");
857 ghost_entry.map_count
858 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
860 for (i=0; i < mac_disk_data->ghost_size - 1; i++)
861 memcpy (&part_map [i + (num - 1) * mac_disk_data->ghost_size],
862 &ghost_entry, sizeof (MacRawPartition));
868 _update_driver_count (MacRawPartition* part_map_entry,
869 MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
871 uint16_t i, count_orig, count_cur, bsz;
872 uint32_t driver_bs, driver_be, part_be;
874 bsz = mac_disk_data->block_size / 512;
875 count_cur = mac_driverdata->driver_count;
876 count_orig = mac_disk_data->driver_count;
877 for (i = 0; i < count_orig; i++) {
878 driver_bs = mac_disk_data->driverlist[i].block * bsz;
879 driver_be = driver_bs + mac_disk_data->driverlist[i].size;
880 part_be = part_map_entry->start_block + part_map_entry->block_count;
881 if (driver_bs >= part_map_entry->start_block
882 && driver_be <= part_be) {
883 mac_driverdata->driverlist[count_cur].block
884 = mac_disk_data->driverlist[i].block;
885 mac_driverdata->driverlist[count_cur].size
886 = mac_disk_data->driverlist[i].size;
887 mac_driverdata->driverlist[count_cur].type
888 = mac_disk_data->driverlist[i].type;
889 mac_driverdata->driver_count++;
896 _generate_raw_part (PedDisk* disk, PedPartition* part,
897 MacRawPartition* part_map, MacDiskData *mac_driverdata)
899 MacDiskData* mac_disk_data;
900 MacPartitionData* mac_part_data;
901 MacRawPartition* part_map_entry;
902 PedSector block_size = disk->dev->sector_size / 512;
904 PED_ASSERT (part->num > 0, goto error);
906 mac_disk_data = disk->disk_specific;
907 mac_part_data = part->disk_specific;
909 part_map_entry = &part_map [part->num * mac_disk_data->ghost_size - 1];
911 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
912 part_map_entry->map_count
913 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
914 part_map_entry->start_block
915 = PED_CPU_TO_BE32 (part->geom.start / block_size);
916 part_map_entry->block_count
917 = PED_CPU_TO_BE32 (part->geom.length / block_size);
918 strcpy (part_map_entry->name, mac_part_data->volume_name);
919 strcpy (part_map_entry->type, mac_part_data->system_name);
921 if (mac_part_data->is_driver) {
922 mac_part_data->boot_region_length = part->geom.length;
923 if (mac_part_data->has_driver)
924 _update_driver_count(part_map_entry, mac_driverdata,
927 mac_part_data->data_region_length = part->geom.length;
928 part_map_entry->data_count = PED_CPU_TO_BE32 (
929 mac_part_data->data_region_length / block_size);
930 part_map_entry->boot_count = PED_CPU_TO_BE32 (
931 mac_part_data->boot_region_length / block_size);
932 part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
933 part_map_entry->driver_sig
934 = PED_CPU_TO_BE32 (mac_part_data->driver_sig);
936 part_map_entry->boot_load =
937 PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
938 part_map_entry->boot_entry =
939 PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
940 part_map_entry->boot_cksum =
941 PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
943 strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
945 if (!_pad_raw_part (disk, part->num, part_map))
955 _generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
956 MacRawPartition* part_map)
958 MacDiskData* mac_disk_data = disk->disk_specific;
959 MacRawPartition* part_map_entry;
960 PedSector block_size = disk->dev->sector_size / 512;
962 PED_ASSERT (num > 0, goto error);
964 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
966 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
967 part_map_entry->map_count
968 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
969 part_map_entry->start_block
970 = PED_CPU_TO_BE32 (geom->start / block_size);
971 part_map_entry->block_count
972 = PED_CPU_TO_BE32 (geom->length / block_size);
973 strcpy (part_map_entry->name, "Extra");
974 strcpy (part_map_entry->type, "Apple_Free");
976 part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
977 part_map_entry->status = 0;
978 part_map_entry->driver_sig = 0;
980 if (!_pad_raw_part (disk, num, part_map))
990 _generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
992 MacDiskData* mac_disk_data = disk->disk_specific;
993 MacRawPartition* part_map_entry;
995 PED_ASSERT (num > 0, return 0);
997 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
998 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
999 part_map_entry->map_count
1000 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
1001 strcpy (part_map_entry->type, "Apple_Void");
1003 return _pad_raw_part (disk, num, part_map);
1006 /* returns the first empty entry in the partition map */
1008 _get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map)
1010 MacDiskData* mac_disk_data = disk->disk_specific;
1013 for (i=1; i <= mac_disk_data->last_part_entry_num; i++) {
1014 if (!part_map[i * mac_disk_data->ghost_size - 1].signature)
1022 write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
1024 PedDevice* dev = disk->dev;
1025 MacRawDisk raw_disk;
1027 if (!ped_device_read (dev, &raw_disk, 0, 1))
1030 raw_disk.signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
1031 raw_disk.block_size = PED_CPU_TO_BE16 (dev->sector_size);
1032 raw_disk.block_count
1033 = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
1035 raw_disk.driver_count = mac_driverdata->driver_count;
1036 memcpy(&raw_disk.driverlist[0], &mac_driverdata->driverlist[0],
1037 sizeof(raw_disk.driverlist));
1039 return ped_device_write (dev, &raw_disk, 0, 1);
1043 mac_write (PedDisk* disk)
1045 MacRawPartition* part_map;
1046 MacDiskData* mac_disk_data;
1047 MacDiskData* mac_driverdata; /* updated driver list */
1051 PED_ASSERT (disk != NULL, return 0);
1052 PED_ASSERT (disk->disk_specific != NULL, return 0);
1053 PED_ASSERT (disk->dev != NULL, return 0);
1054 PED_ASSERT (!disk->update_mode, return 0);
1056 mac_disk_data = disk->disk_specific;
1058 if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
1059 if (!_disk_add_part_map_entry (disk, 1))
1063 mac_driverdata = ped_malloc(sizeof(MacDiskData));
1064 if (!mac_driverdata)
1066 memset (mac_driverdata, 0, sizeof(MacDiskData));
1068 part_map = (MacRawPartition*)
1069 ped_malloc (mac_disk_data->part_map_entry_count * 512);
1071 goto error_free_driverdata;
1072 memset (part_map, 0, mac_disk_data->part_map_entry_count * 512);
1074 /* write (to memory) the "real" partitions */
1075 for (part = ped_disk_next_partition (disk, NULL); part;
1076 part = ped_disk_next_partition (disk, part)) {
1077 if (!ped_partition_is_active (part))
1079 if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
1080 goto error_free_part_map;
1083 /* write the "free space" partitions */
1084 for (part = ped_disk_next_partition (disk, NULL); part;
1085 part = ped_disk_next_partition (disk, part)) {
1086 if (part->type != PED_PARTITION_FREESPACE)
1088 num = _get_first_empty_part_entry (disk, part_map);
1089 if (!_generate_raw_freespace_part (disk, &part->geom, num,
1091 goto error_free_part_map;
1094 /* write the "void" (empty) partitions */
1095 for (num = _get_first_empty_part_entry (disk, part_map); num;
1096 num = _get_first_empty_part_entry (disk, part_map))
1097 _generate_empty_part (disk, num, part_map);
1100 if (!ped_device_write (disk->dev, part_map, 1,
1101 mac_disk_data->part_map_entry_count))
1102 goto error_free_part_map;
1103 ped_free (part_map);
1104 return write_block_zero (disk, mac_driverdata);
1106 error_free_part_map:
1107 ped_free (part_map);
1108 error_free_driverdata:
1109 ped_free (mac_driverdata);
1113 #endif /* !DISCOVER_ONLY */
1115 static PedPartition*
1117 const PedDisk* disk, PedPartitionType part_type,
1118 const PedFileSystemType* fs_type, PedSector start, PedSector end)
1121 MacPartitionData* mac_data;
1123 part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1127 if (ped_partition_is_active (part)) {
1129 = mac_data = ped_malloc (sizeof (MacPartitionData));
1131 goto error_free_part;
1133 memset (mac_data, 0, sizeof (MacPartitionData));
1134 strcpy (mac_data->volume_name, "untitled");
1136 part->disk_specific = NULL;
1140 error_free_mac_data:
1141 ped_free (mac_data);
1148 static PedPartition*
1149 mac_partition_duplicate (const PedPartition* part)
1151 PedPartition* new_part;
1152 MacPartitionData* new_mac_data;
1153 MacPartitionData* old_mac_data;
1155 new_part = ped_partition_new (part->disk, part->type,
1156 part->fs_type, part->geom.start,
1160 new_part->num = part->num;
1162 old_mac_data = (MacPartitionData*) part->disk_specific;
1163 new_mac_data = (MacPartitionData*) new_part->disk_specific;
1165 /* ugly, but C is ugly :p */
1166 memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
1171 mac_partition_destroy (PedPartition* part)
1173 PED_ASSERT (part != NULL, return);
1175 if (ped_partition_is_active (part))
1176 ped_free (part->disk_specific);
1181 mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1183 MacPartitionData* mac_data = part->disk_specific;
1185 part->fs_type = fs_type;
1187 if (fs_type && !strcmp (fs_type->name, "linux-swap"))
1188 ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1190 if (mac_data->is_boot) {
1191 strcpy (mac_data->system_name, "Apple_Bootstrap");
1192 mac_data->status = 0x33;
1196 if (fs_type && (!strcmp (fs_type->name, "hfs")
1197 || !strcmp (fs_type->name, "hfs+"))) {
1198 strcpy (mac_data->system_name, "Apple_HFS");
1199 mac_data->status |= 0x7f;
1200 } else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
1201 strcpy (mac_data->system_name, "Apple_HFSX");
1202 mac_data->status |= 0x7f;
1204 strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
1205 mac_data->status = 0x33;
1212 mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1214 PedFileSystemType* hfs = ped_file_system_type_get ("hfs");
1215 MacPartitionData* mac_data;
1217 PED_ASSERT (part != NULL, return 0);
1218 PED_ASSERT (part->disk_specific != NULL, return 0);
1220 mac_data = part->disk_specific;
1223 case PED_PARTITION_BOOT:
1224 mac_data->is_boot = state;
1227 return mac_partition_set_system (part, part->fs_type);
1230 strcpy (mac_data->system_name, "Apple_Bootstrap");
1231 mac_data->status = 0x33;
1235 case PED_PARTITION_ROOT:
1237 strcpy (mac_data->volume_name, "root");
1238 mac_data->is_swap = 0;
1240 if (mac_data->is_root)
1241 strcpy (mac_data->volume_name, "untitled");
1243 mac_data->is_root = state;
1246 case PED_PARTITION_SWAP:
1248 strcpy (mac_data->volume_name, "swap");
1249 mac_data->is_root = 0;
1251 if (mac_data->is_swap)
1252 strcpy (mac_data->volume_name, "untitled");
1254 mac_data->is_swap = state;
1257 case PED_PARTITION_LVM:
1259 strcpy (mac_data->system_name, "Linux_LVM");
1260 mac_data->is_lvm = state;
1262 if (mac_data->is_lvm)
1263 mac_partition_set_system (part, part->fs_type);
1267 case PED_PARTITION_RAID:
1269 strcpy (mac_data->system_name, "Linux_RAID");
1270 mac_data->is_raid = state;
1272 if (mac_data->is_raid)
1273 mac_partition_set_system (part, part->fs_type);
1283 mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1285 MacPartitionData* mac_data;
1287 PED_ASSERT (part != NULL, return 0);
1288 PED_ASSERT (part->disk_specific != NULL, return 0);
1290 mac_data = part->disk_specific;
1292 case PED_PARTITION_BOOT:
1293 return mac_data->is_boot;
1295 case PED_PARTITION_ROOT:
1296 return mac_data->is_root;
1298 case PED_PARTITION_SWAP:
1299 return mac_data->is_swap;
1301 case PED_PARTITION_LVM:
1302 return mac_data->is_lvm;
1304 case PED_PARTITION_RAID:
1305 return mac_data->is_raid;
1313 mac_partition_is_flag_available (
1314 const PedPartition* part, PedPartitionFlag flag)
1317 case PED_PARTITION_BOOT:
1318 case PED_PARTITION_ROOT:
1319 case PED_PARTITION_SWAP:
1320 case PED_PARTITION_LVM:
1321 case PED_PARTITION_RAID:
1330 mac_partition_set_name (PedPartition* part, const char* name)
1332 MacPartitionData* mac_data;
1335 PED_ASSERT (part != NULL, return);
1336 PED_ASSERT (part->disk_specific != NULL, return);
1337 mac_data = part->disk_specific;
1339 #ifndef DISCOVER_ONLY
1340 if (mac_data->is_root || mac_data->is_swap) {
1341 if (ped_exception_throw (
1342 PED_EXCEPTION_WARNING,
1343 PED_EXCEPTION_IGNORE_CANCEL,
1344 _("Changing the name of a root or swap partition "
1345 "will prevent Linux from recognising it as such."))
1346 != PED_EXCEPTION_IGNORE)
1348 mac_data->is_root = mac_data->is_swap = 0;
1352 strncpy (mac_data->volume_name, name, 32);
1353 mac_data->volume_name [32] = 0;
1354 for (i = strlen (mac_data->volume_name) - 1;
1355 mac_data->volume_name[i] == ' '; i--)
1356 mac_data->volume_name [i] = 0;
1360 mac_partition_get_name (const PedPartition* part)
1362 MacPartitionData* mac_data;
1364 PED_ASSERT (part != NULL, return NULL);
1365 PED_ASSERT (part->disk_specific != NULL, return NULL);
1366 mac_data = part->disk_specific;
1368 return mac_data->volume_name;
1371 static PedConstraint*
1372 _primary_constraint (PedDisk* disk)
1374 PedAlignment start_align;
1375 PedAlignment end_align;
1376 PedGeometry max_geom;
1377 PedSector sector_size;
1379 sector_size = disk->dev->sector_size / 512;
1381 if (!ped_alignment_init (&start_align, 0, sector_size))
1383 if (!ped_alignment_init (&end_align, -1, sector_size))
1385 if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1388 return ped_constraint_new (&start_align, &end_align, &max_geom,
1389 &max_geom, 1, disk->dev->length);
1393 mac_partition_align (PedPartition* part, const PedConstraint* constraint)
1395 PED_ASSERT (part != NULL, return 0);
1397 if (_ped_partition_attempt_align (part, constraint,
1398 _primary_constraint (part->disk)))
1401 #ifndef DISCOVER_ONLY
1402 ped_exception_throw (
1403 PED_EXCEPTION_ERROR,
1404 PED_EXCEPTION_CANCEL,
1405 _("Unable to satisfy all constraints on the partition."));
1411 mac_partition_enumerate (PedPartition* part)
1414 MacDiskData* mac_disk_data;
1418 PED_ASSERT (part != NULL, return 0);
1419 PED_ASSERT (part->disk != NULL, return 0);
1422 mac_disk_data = (MacDiskData*) disk->disk_specific;
1424 max_part_count = ped_disk_get_max_primary_partition_count (disk);
1426 if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
1429 for (i = 1; i <= max_part_count; i++) {
1430 if (!ped_disk_get_partition (disk, i)) {
1436 #ifndef DISCOVER_ONLY
1437 ped_exception_throw (
1438 PED_EXCEPTION_ERROR,
1439 PED_EXCEPTION_CANCEL,
1440 _("Can't add another partition -- the partition map is too "
1448 _disk_count_partitions (PedDisk* disk)
1450 MacDiskData* mac_disk_data = disk->disk_specific;
1451 PedPartition* part = NULL;
1452 PedPartition* last = NULL;
1454 PED_ASSERT (disk->update_mode, return 0);
1456 mac_disk_data->active_part_entry_count = 0;
1457 mac_disk_data->free_part_entry_count = 0;
1458 mac_disk_data->last_part_entry_num = 0;
1460 /* subtle: we only care about free space after the partition map.
1461 * the partition map is an "active" partition, BTW... */
1462 for (part = ped_disk_next_partition (disk, part); part;
1463 part = ped_disk_next_partition (disk, part)) {
1464 if (!ped_partition_is_active (part))
1467 mac_disk_data->active_part_entry_count++;
1468 if (last && last->geom.end + 1 < part->geom.start)
1469 mac_disk_data->free_part_entry_count++;
1470 mac_disk_data->last_part_entry_num
1471 = PED_MAX (mac_disk_data->last_part_entry_num,
1477 if (last && last->geom.end < disk->dev->length - 1)
1478 mac_disk_data->free_part_entry_count++;
1480 mac_disk_data->last_part_entry_num
1481 = PED_MAX (mac_disk_data->last_part_entry_num,
1482 mac_disk_data->active_part_entry_count
1483 + mac_disk_data->free_part_entry_count);
1488 add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
1490 PedPartition* new_part;
1491 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
1493 PED_ASSERT (disk != NULL, return 0);
1495 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1499 if (!ped_disk_add_partition (disk, new_part, constraint_any))
1500 goto error_destroy_new_part;
1502 ped_constraint_destroy (constraint_any);
1505 error_destroy_new_part:
1506 ped_partition_destroy (new_part);
1508 ped_constraint_destroy (constraint_any);
1513 mac_alloc_metadata (PedDisk* disk)
1515 MacDiskData* mac_disk_data;
1517 PED_ASSERT (disk != NULL, return 0);
1518 PED_ASSERT (disk->disk_specific != NULL, return 0);
1519 PED_ASSERT (disk->dev != NULL, return 0);
1521 mac_disk_data = disk->disk_specific;
1523 if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
1526 /* hack: this seems to be a good place, to update the partition map
1527 * entry count, since mac_alloc_metadata() gets called during
1528 * _disk_pop_update_mode()
1530 return _disk_count_partitions (disk);
1534 mac_get_max_primary_partition_count (const PedDisk* disk)
1536 MacDiskData* mac_disk_data = disk->disk_specific;
1537 PedPartition* part_map_partition;
1539 part_map_partition = ped_disk_get_partition (disk,
1540 mac_disk_data->part_map_entry_num);
1542 /* HACK: if we haven't found the partition map partition (yet),
1545 if (!part_map_partition) {
1546 mac_disk_data->part_map_entry_num = 0;
1550 /* HACK: since Mac labels need an entry for free-space regions, we
1551 * must allow half plus 1 entries for free-space partitions. I hate
1552 * this, but things get REALLY complicated, otherwise.
1553 * (I'm prepared to complicate things later, but I want to get
1554 * everything working, first)
1556 return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
1557 - mac_disk_data->free_part_entry_count + 1;
1560 static PedDiskOps mac_disk_ops = {
1562 #ifndef DISCOVER_ONLY
1563 clobber: mac_clobber,
1568 duplicate: mac_duplicate,
1571 #ifndef DISCOVER_ONLY
1577 partition_new: mac_partition_new,
1578 partition_duplicate: mac_partition_duplicate,
1579 partition_destroy: mac_partition_destroy,
1580 partition_set_system: mac_partition_set_system,
1581 partition_set_flag: mac_partition_set_flag,
1582 partition_get_flag: mac_partition_get_flag,
1583 partition_is_flag_available: mac_partition_is_flag_available,
1584 partition_set_name: mac_partition_set_name,
1585 partition_get_name: mac_partition_get_name,
1586 partition_align: mac_partition_align,
1587 partition_enumerate: mac_partition_enumerate,
1589 alloc_metadata: mac_alloc_metadata,
1590 get_max_primary_partition_count:
1591 mac_get_max_primary_partition_count
1594 static PedDiskType mac_disk_type = {
1598 features: PED_DISK_TYPE_PARTITION_NAME
1602 ped_disk_mac_init ()
1604 PED_ASSERT (sizeof (MacRawPartition) == 512, return);
1605 PED_ASSERT (sizeof (MacRawDisk) == 512, return);
1607 ped_register_disk_type (&mac_disk_type);
1611 ped_disk_mac_done ()
1613 ped_unregister_disk_type (&mac_disk_type);