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 */
35 /* struct's hacked from Linux source: fs/partitions/mac.h
36 * I believe it was originally written by Paul Mackerras (from comments in
40 * http://developer.apple.com/documentation/mac/Devices/Devices-126.html
41 * http://developer.apple.com/documentation/mac/Devices/Devices-121.html
42 * http://devworld.apple.com/technotes/tn/tn1189.html
45 * Apple_Bootstrap new-world (HFS) boot partition
46 * Apple_partition_map partition map (table)
47 * Apple_Driver device driver
48 * Apple_Driver43 SCSI Manager 4.3 device driver
49 * Apple_MFS original Macintosh File System
50 * Apple_HFS Hierarchical File System (and +)
51 * Apple_HFSX HFS+ with case sensitivity and more
52 * Apple_UNIX_SVR2 UNIX file system (UFS?)
53 * Apple_PRODOS ProDOS file system
54 * Apple_Free unused space
56 * Apple_Void padding for iso9660
57 * Apple_Extra an unused partition map entry
67 * partition volume or partition
70 * * All space must be accounted for, except block 0 (driver block) and
71 * block 1-X (the partition map: i.e. lots of MacRawPartitions)
73 * * It's really hard to grow/shrink the number of MacRawPartition
74 * entries in the partition map, because the first partition starts
75 * immediately after the partition map. When we can move the start of
76 * HFS and ext2 partitions, this problem will disappear ;-)
79 #define MAC_PARTITION_MAGIC_1 0x5453 /* old */
80 #define MAC_PARTITION_MAGIC_2 0x504d
81 #define MAC_DISK_MAGIC 0x4552
83 #define MAC_STATUS_BOOTABLE 8 /* partition is bootable */
85 typedef struct _MacRawPartition MacRawPartition;
86 typedef struct _MacRawDisk MacRawDisk;
87 typedef struct _MacDeviceDriver MacDeviceDriver;
88 typedef struct _MacPartitionData MacPartitionData;
89 typedef struct _MacDiskData MacDiskData;
91 struct __attribute__ ((packed)) _MacRawPartition {
92 uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
94 uint32_t map_count; /* # blocks in partition map */
95 uint32_t start_block; /* absolute starting block # of partition */
96 uint32_t block_count; /* number of blocks in partition */
97 char name[32]; /* partition name */
98 char type[32]; /* string type description */
99 uint32_t data_start; /* rel block # of first data block */
100 uint32_t data_count; /* number of data blocks */
101 uint32_t status; /* partition status bits */
107 uint32_t boot_entry2;
109 char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
114 /* Driver descriptor structure, in block 0 */
115 struct __attribute__ ((packed)) _MacRawDisk {
116 uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
117 uint16_t block_size; /* physical sector size */
118 uint32_t block_count; /* size of device in blocks */
119 uint16_t dev_type; /* reserved */
120 uint16_t dev_id; /* reserved */
121 uint32_t data; /* reserved */
122 uint16_t driver_count; /* # of driver descriptor entries */
123 uint8_t driverlist[488];/* info about available drivers */
124 uint16_t padding[3]; /* pad to 512 bytes */
127 struct __attribute__ ((packed)) _MacDeviceDriver {
128 uint32_t block; /* startblock in MacRawDisk->block_size units */
129 uint16_t size; /* size in 512 byte units */
130 uint16_t type; /* operating system type (MacOS = 1) */
133 struct _MacPartitionData {
134 char volume_name[33]; /* eg: "Games" */
135 char system_name[33]; /* eg: "Apple_Unix_SVR2" */
136 char processor_name[17];
146 PedSector data_region_length;
147 PedSector boot_region_length;
149 uint32_t boot_base_address;
150 uint32_t boot_entry_address;
151 uint32_t boot_checksum;
157 struct _MacDiskData {
158 int ghost_size; /* sectors per "driver" block */
159 int part_map_entry_count; /* # entries (incl. ghost) */
160 int part_map_entry_num; /* partition map location */
162 int active_part_entry_count; /* # real partitions */
163 int free_part_entry_count; /* # free space */
164 int last_part_entry_num; /* last entry number */
166 uint16_t block_size; /* physical sector size */
167 uint16_t driver_count;
168 MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */
171 static PedDiskType mac_disk_type;
174 _check_signature (MacRawDisk* raw_disk)
176 if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
180 return ped_exception_throw (
182 PED_EXCEPTION_IGNORE_CANCEL,
183 _("Invalid signature %x for Mac disk labels."),
184 (int) PED_BE16_TO_CPU (raw_disk->signature))
185 == PED_EXCEPTION_IGNORE;
193 _rawpart_check_signature (MacRawPartition* raw_part)
195 int sig = (int) PED_BE16_TO_CPU (raw_part->signature);
196 return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
200 mac_probe (const PedDevice * dev)
204 PED_ASSERT (dev != NULL, return 0);
206 if (dev->sector_size != 512)
209 if (!ped_device_read (dev, &buf, 0, 1))
212 return _check_signature (&buf);
216 _disk_add_part_map_entry (PedDisk* disk, int warn)
218 MacDiskData* mac_disk_data = disk->disk_specific;
219 PedPartition* new_part;
220 MacPartitionData* mac_part_data;
221 PedSector part_map_size;
222 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
224 #ifndef DISCOVER_ONLY
225 if (warn && ped_exception_throw (
227 PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
228 _("Partition map has no partition map entry!"))
229 != PED_EXCEPTION_FIX)
231 #endif /* !DISCOVER_ONLY */
234 = ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
235 if (part_map_size == 0)
238 new_part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
239 1, part_map_size - 1);
243 mac_part_data = new_part->disk_specific;
244 strcpy (mac_part_data->volume_name, "Apple");
245 strcpy (mac_part_data->system_name, "Apple_partition_map");
247 if (!ped_disk_add_partition (disk, new_part, constraint_any))
248 goto error_destroy_new_part;
250 mac_disk_data->part_map_entry_num = new_part->num;
251 mac_disk_data->part_map_entry_count
252 = new_part->geom.end - mac_disk_data->ghost_size;
253 ped_constraint_destroy (constraint_any);
256 error_destroy_new_part:
257 ped_partition_destroy (new_part);
259 ped_constraint_destroy (constraint_any);
264 mac_alloc (const PedDevice* dev)
267 MacDiskData* mac_disk_data;
269 PED_ASSERT (dev != NULL, return NULL);
271 #ifndef DISCOVER_ONLY
272 if (dev->length < 256) {
273 ped_exception_throw (
275 PED_EXCEPTION_CANCEL,
276 _("%s is too small for a Mac disk label!"),
282 disk = _ped_disk_alloc (dev, &mac_disk_type);
286 mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
288 goto error_free_disk;
289 disk->disk_specific = mac_disk_data;
290 mac_disk_data->ghost_size = disk->dev->sector_size / 512;
291 mac_disk_data->active_part_entry_count = 0;
292 mac_disk_data->free_part_entry_count = 1;
293 mac_disk_data->last_part_entry_num = 1;
294 mac_disk_data->block_size = 0;
295 mac_disk_data->driver_count = 0;
296 memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
298 if (!_disk_add_part_map_entry (disk, 0))
299 goto error_free_disk;
303 _ped_disk_free (disk);
309 mac_duplicate (const PedDisk* disk)
312 MacDiskData* new_mac_data;
313 MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific;
314 PedPartition* partition_map;
316 new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type);
320 new_mac_data = (MacDiskData*) new_disk->disk_specific;
322 /* remove the partition map partition - it will be duplicated
325 partition_map = ped_disk_get_partition_by_sector (new_disk, 1);
326 PED_ASSERT (partition_map != NULL, return 0);
327 ped_disk_remove_partition (new_disk, partition_map);
329 /* ugly, but C is ugly :p */
330 memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
333 _ped_disk_free (new_disk);
339 mac_free (PedDisk* disk)
341 MacDiskData* mac_disk_data = disk->disk_specific;
343 _ped_disk_free (disk);
344 free (mac_disk_data);
347 #ifndef DISCOVER_ONLY
349 _clobber_part_map (PedDevice* dev)
351 MacRawPartition raw_part;
354 for (sector=1; 1; sector++) {
355 if (!ped_device_read (dev, &raw_part, sector, 1))
357 if (!_rawpart_check_signature (&raw_part))
359 memset (&raw_part, 0, 512);
360 if (!ped_device_write (dev, &raw_part, sector, 1))
366 mac_clobber (PedDevice* dev)
370 if (!ped_device_read (dev, &raw_disk, 0, 1))
372 if (!_check_signature (&raw_disk))
374 memset (&raw_disk, 0, 512);
375 if (!ped_device_write (dev, &raw_disk, 0, 1))
378 return _clobber_part_map (dev);
380 #endif /* !DISCOVER_ONLY */
383 _rawpart_cmp_type (const MacRawPartition* raw_part, const char* type)
385 return strncasecmp (raw_part->type, type, 32) == 0;
389 _rawpart_cmp_name (const MacRawPartition* raw_part, const char* name)
391 return strncasecmp (raw_part->name, name, 32) == 0;
395 _rawpart_is_partition_map (const MacRawPartition* raw_part)
397 return _rawpart_cmp_type (raw_part, "Apple_partition_map");
401 strncasestr (const char* haystack, const char* needle, int n)
403 int needle_size = strlen (needle);
406 for (i = 0; haystack[i] && i < n - needle_size; i++) {
407 if (strncasecmp (haystack + i, needle, needle_size) == 0)
415 _rawpart_is_boot (const MacRawPartition* raw_part)
417 if (!strcasecmp(raw_part->type, "Apple_Bootstrap"))
420 if (!strcasecmp(raw_part->type, "Apple_Boot"))
427 _rawpart_is_driver (const MacRawPartition* raw_part)
429 if (strncmp (raw_part->type, "Apple_", 6) != 0)
431 if (!strncasestr (raw_part->type, "driver", 32))
437 _rawpart_has_driver (const MacRawPartition* raw_part, MacDiskData* mac_disk_data)
439 MacDeviceDriver *driverlist;
441 uint32_t driver_bs, driver_be, part_be;
443 driverlist = &mac_disk_data->driverlist[0];
444 bsz = mac_disk_data->block_size / 512;
445 for (i = 0; i < mac_disk_data->driver_count; i++) {
446 driver_bs = driverlist->block * bsz;
447 driver_be = driver_bs + driverlist->size;
448 part_be = raw_part->start_block + raw_part->block_count;
449 if (driver_bs >= raw_part->start_block && driver_be <= part_be)
457 _rawpart_is_root (MacRawPartition* raw_part)
459 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
461 if (strcmp (raw_part->name, "root") != 0)
467 _rawpart_is_swap (MacRawPartition* raw_part)
469 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
471 if (strcmp (raw_part->name, "swap") != 0)
477 _rawpart_is_lvm (MacRawPartition* raw_part)
479 if (strcmp (raw_part->type, "Linux_LVM") != 0)
485 _rawpart_is_raid (MacRawPartition* raw_part)
487 if (strcmp (raw_part->type, "Linux_RAID") != 0)
493 _rawpart_is_void (MacRawPartition* raw_part)
495 return _rawpart_cmp_type (raw_part, "Apple_Void");
498 /* returns 1 if the raw_part represents a partition that is "unused space", or
499 * doesn't represent a partition at all. NOTE: some people make Apple_Free
500 * partitions with MacOS, because they can't select another type. So, if the
501 * name is anything other than "Extra" or "", it is treated as a "real"
505 _rawpart_is_active (MacRawPartition* raw_part)
507 if (_rawpart_cmp_type (raw_part, "Apple_Free")
508 && (_rawpart_cmp_name (raw_part, "Extra")
509 || _rawpart_cmp_name (raw_part, "")))
511 if (_rawpart_cmp_type (raw_part, "Apple_Void"))
513 if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
515 if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
522 _rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
524 MacDiskData* mac_disk_data;
526 MacPartitionData* mac_part_data;
527 PedSector block_size;
528 PedSector start, length;
530 if (!_rawpart_check_signature (raw_part)) {
531 #ifndef DISCOVER_ONLY
532 if (ped_exception_throw (
533 PED_EXCEPTION_WARNING,
534 PED_EXCEPTION_IGNORE_CANCEL,
535 _("Partition %d has an invalid signature %x."),
537 (int) PED_BE16_TO_CPU (raw_part->signature))
538 != PED_EXCEPTION_IGNORE)
543 mac_disk_data = (MacDiskData*) disk->disk_specific;
544 block_size = disk->dev->sector_size / 512;
546 start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
547 length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
549 #ifndef DISCOVER_ONLY
550 ped_exception_throw (
552 PED_EXCEPTION_CANCEL,
553 _("Partition %d has an invalid length of 0 bytes!"),
558 part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
559 start, start + length - 1);
563 mac_part_data = part->disk_specific;
565 strncpy (mac_part_data->volume_name, raw_part->name, 32);
566 strncpy (mac_part_data->system_name, raw_part->type, 32);
567 strncpy (mac_part_data->processor_name, raw_part->processor, 16);
569 mac_part_data->is_boot = _rawpart_is_boot (raw_part);
570 mac_part_data->is_driver = _rawpart_is_driver (raw_part);
571 if (mac_part_data->is_driver)
572 mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
573 mac_part_data->is_root = _rawpart_is_root (raw_part);
574 mac_part_data->is_swap = _rawpart_is_swap (raw_part);
575 mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
576 mac_part_data->is_raid = _rawpart_is_raid (raw_part);
579 #ifndef DISCOVER_ONLY
580 if (raw_part->data_start) {
581 ped_exception_throw (
583 PED_EXCEPTION_CANCEL,
584 _("The data region doesn't start at the start "
585 "of the partition."));
586 goto error_destroy_part;
588 #endif /* !DISCOVER_ONLY */
589 mac_part_data->data_region_length
590 = PED_BE32_TO_CPU (raw_part->data_count) * block_size;
592 /* boot region - we have no idea what this is for, but Mac OSX
593 * seems to put garbage here, and doesn't pay any attention to
594 * it afterwards. [clausen, dan burcaw]
597 if (raw_part->boot_start) {
598 ped_exception_throw (
600 PED_EXCEPTION_CANCEL,
601 _("The boot region doesn't start at the start "
602 "of the partition."));
603 goto error_destroy_part;
606 mac_part_data->boot_region_length
607 = PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
609 #ifndef DISCOVER_ONLY
610 if (mac_part_data->has_driver) {
611 if (mac_part_data->boot_region_length < part->geom.length) {
612 if (ped_exception_throw (
614 PED_EXCEPTION_IGNORE_CANCEL,
615 _("The partition's boot region doesn't occupy "
616 "the entire partition."))
617 != PED_EXCEPTION_IGNORE)
618 goto error_destroy_part;
621 if (mac_part_data->data_region_length < part->geom.length &&
622 !mac_part_data->is_boot) {
623 if (ped_exception_throw (
625 PED_EXCEPTION_IGNORE_CANCEL,
626 _("The partition's data region doesn't occupy "
627 "the entire partition."))
628 != PED_EXCEPTION_IGNORE)
629 goto error_destroy_part;
632 #endif /* !DISCOVER_ONLY */
634 mac_part_data->boot_base_address
635 = PED_BE32_TO_CPU (raw_part->boot_load);
636 mac_part_data->boot_entry_address
637 = PED_BE32_TO_CPU (raw_part->boot_entry);
638 mac_part_data->boot_checksum
639 = PED_BE32_TO_CPU (raw_part->boot_cksum);
641 mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
642 mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
647 ped_partition_destroy (part);
652 /* looks at the partition map size field in a mac raw partition, and calculates
653 * what the size of the partition map should be, from it
656 _rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
658 MacDiskData* mac_disk_data = disk->disk_specific;
659 PedSector sector_size = disk->dev->sector_size / 512;
660 PedSector part_map_start;
661 PedSector part_map_end;
663 part_map_start = mac_disk_data->ghost_size;
664 part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
666 return part_map_end - part_map_start + 1;
670 _disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
672 PedSector block_size;
674 if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
675 #ifndef DISCOVER_ONLY
676 ped_exception_throw (
678 PED_EXCEPTION_CANCEL,
679 _("Weird block size on device descriptor: %d bytes is "
680 "not divisible by 512."),
681 (int) PED_BE16_TO_CPU (raw_disk->block_size));
686 block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
687 if (block_size != disk->dev->sector_size / 512) {
688 #ifndef DISCOVER_ONLY
689 if (ped_exception_throw (
690 PED_EXCEPTION_WARNING,
691 PED_EXCEPTION_IGNORE_CANCEL,
692 _("The driver descriptor says the physical block size "
693 "is %d bytes, but Linux says it is %d bytes."),
694 (int) block_size * 512,
695 (int) disk->dev->sector_size)
696 != PED_EXCEPTION_IGNORE)
699 disk->dev->sector_size = block_size * 512;
708 /* Tries to figure out the block size used by the drivers, for the ghost
709 * partitioning scheme. Ghost partitioning works like this: the OpenFirmware
710 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
711 * perhaps, some other number?). To remain compatible, the partition map
712 * only has "real" partition map entries on ghost-aligned block numbers (and
713 * the others are padded with Apple_Void partitions). This function tries
714 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
715 * doesn't always equal 2048!!!)
718 _disk_analyse_ghost_size (PedDisk* disk)
720 MacDiskData* mac_disk_data = disk->disk_specific;
721 MacRawPartition raw_part;
724 for (i = 1; i < 64; i *= 2) {
725 if (!ped_device_read (disk->dev, &raw_part, i, 1))
727 if (_rawpart_check_signature (&raw_part)
728 && !_rawpart_is_void (&raw_part)) {
729 mac_disk_data->ghost_size = i;
730 PED_ASSERT (i <= disk->dev->sector_size / 512,
736 #ifndef DISCOVER_ONLY
737 ped_exception_throw (
739 PED_EXCEPTION_CANCEL,
740 _("No valid partition map found."));
746 mac_read (PedDisk* disk)
749 MacRawPartition raw_part;
750 MacDiskData* mac_disk_data;
753 PedSector ghost_size;
754 PedConstraint* constraint_exact;
755 int last_part_entry_num = 0;
757 PED_ASSERT (disk != NULL, return 0);
759 mac_disk_data = disk->disk_specific;
760 mac_disk_data->part_map_entry_num = 0; /* 0 == none */
762 if (!ped_device_read (disk->dev, &raw_disk, 0, 1))
764 if (!_check_signature (&raw_disk))
767 if (!_disk_analyse_block_size (disk, &raw_disk))
769 if (!_disk_analyse_ghost_size (disk))
771 ghost_size = mac_disk_data->ghost_size;
773 if (!ped_disk_delete_all (disk))
776 if (raw_disk.driver_count && raw_disk.driver_count < 62) {
777 memcpy(&mac_disk_data->driverlist[0], &raw_disk.driverlist[0],
778 sizeof(mac_disk_data->driverlist));
779 mac_disk_data->driver_count = raw_disk.driver_count;
780 mac_disk_data->block_size = raw_disk.block_size;
783 for (num=1; num==1 || num <= last_part_entry_num; num++) {
784 if (!ped_device_read (disk->dev, &raw_part,
785 num * ghost_size, 1))
786 goto error_delete_all;
788 if (!_rawpart_check_signature (&raw_part))
793 = _rawpart_get_partmap_size (&raw_part, disk);
794 if (_rawpart_get_partmap_size (&raw_part, disk)
795 != last_part_entry_num) {
796 if (ped_exception_throw (
798 PED_EXCEPTION_IGNORE_CANCEL,
799 _("Conflicting partition map entry sizes! "
800 "Entry 1 says it is %d, but entry %d says "
803 _rawpart_get_partmap_size (&raw_part, disk))
804 != PED_EXCEPTION_IGNORE)
805 goto error_delete_all;
808 if (!_rawpart_is_active (&raw_part))
811 part = _rawpart_analyse (&raw_part, disk, num);
813 goto error_delete_all;
815 part->fs_type = ped_file_system_probe (&part->geom);
816 constraint_exact = ped_constraint_exact (&part->geom);
817 if (!ped_disk_add_partition (disk, part, constraint_exact))
818 goto error_delete_all;
819 ped_constraint_destroy (constraint_exact);
821 if (_rawpart_is_partition_map (&raw_part)) {
822 if (mac_disk_data->part_map_entry_num
823 && ped_exception_throw (
825 PED_EXCEPTION_IGNORE_CANCEL,
826 _("Weird! There are 2 partitions "
828 != PED_EXCEPTION_IGNORE)
829 goto error_delete_all;
831 mac_disk_data->part_map_entry_num = num;
832 mac_disk_data->part_map_entry_count
833 = part->geom.end - ghost_size + 1;
837 if (!mac_disk_data->part_map_entry_num) {
838 if (!_disk_add_part_map_entry (disk, 1))
839 goto error_delete_all;
840 ped_disk_commit_to_dev (disk);
845 ped_disk_delete_all (disk);
850 #ifndef DISCOVER_ONLY
851 /* The Ghost partition: is a blank entry, used to pad out each block (where
852 * there physical block size > 512 bytes). This is because OpenFirmware uses
853 * 512 byte blocks, but device drivers Think Different TM, with a different
854 * lbock size, so we need to do this to avoid a clash (!)
857 _pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
859 MacDiskData* mac_disk_data = disk->disk_specific;
860 MacRawPartition ghost_entry;
863 memset (&ghost_entry, 0, sizeof (ghost_entry));
864 ghost_entry.signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
865 strcpy (ghost_entry.type, "Apple_Void");
866 ghost_entry.map_count
867 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
869 for (i=0; i < mac_disk_data->ghost_size - 1; i++)
870 memcpy (&part_map [i + (num - 1) * mac_disk_data->ghost_size],
871 &ghost_entry, sizeof (MacRawPartition));
877 _update_driver_count (MacRawPartition* part_map_entry,
878 MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
880 uint16_t i, count_orig, count_cur, bsz;
881 uint32_t driver_bs, driver_be, part_be;
883 bsz = mac_disk_data->block_size / 512;
884 count_cur = mac_driverdata->driver_count;
885 count_orig = mac_disk_data->driver_count;
886 for (i = 0; i < count_orig; i++) {
887 driver_bs = mac_disk_data->driverlist[i].block * bsz;
888 driver_be = driver_bs + mac_disk_data->driverlist[i].size;
889 part_be = part_map_entry->start_block + part_map_entry->block_count;
890 if (driver_bs >= part_map_entry->start_block
891 && driver_be <= part_be) {
892 mac_driverdata->driverlist[count_cur].block
893 = mac_disk_data->driverlist[i].block;
894 mac_driverdata->driverlist[count_cur].size
895 = mac_disk_data->driverlist[i].size;
896 mac_driverdata->driverlist[count_cur].type
897 = mac_disk_data->driverlist[i].type;
898 mac_driverdata->driver_count++;
905 _generate_raw_part (PedDisk* disk, PedPartition* part,
906 MacRawPartition* part_map, MacDiskData *mac_driverdata)
908 MacDiskData* mac_disk_data;
909 MacPartitionData* mac_part_data;
910 MacRawPartition* part_map_entry;
911 PedSector block_size = disk->dev->sector_size / 512;
913 PED_ASSERT (part->num > 0, goto error);
915 mac_disk_data = disk->disk_specific;
916 mac_part_data = part->disk_specific;
918 part_map_entry = &part_map [part->num * mac_disk_data->ghost_size - 1];
920 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
921 part_map_entry->map_count
922 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
923 part_map_entry->start_block
924 = PED_CPU_TO_BE32 (part->geom.start / block_size);
925 part_map_entry->block_count
926 = PED_CPU_TO_BE32 (part->geom.length / block_size);
927 strcpy (part_map_entry->name, mac_part_data->volume_name);
928 strcpy (part_map_entry->type, mac_part_data->system_name);
930 if (mac_part_data->is_driver) {
931 mac_part_data->boot_region_length = part->geom.length;
932 if (mac_part_data->has_driver)
933 _update_driver_count(part_map_entry, mac_driverdata,
936 mac_part_data->data_region_length = part->geom.length;
937 part_map_entry->data_count = PED_CPU_TO_BE32 (
938 mac_part_data->data_region_length / block_size);
939 part_map_entry->boot_count = PED_CPU_TO_BE32 (
940 mac_part_data->boot_region_length / block_size);
941 part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
942 part_map_entry->driver_sig
943 = PED_CPU_TO_BE32 (mac_part_data->driver_sig);
945 part_map_entry->boot_load =
946 PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
947 part_map_entry->boot_entry =
948 PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
949 part_map_entry->boot_cksum =
950 PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
952 strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
954 if (!_pad_raw_part (disk, part->num, part_map))
964 _generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
965 MacRawPartition* part_map)
967 MacDiskData* mac_disk_data = disk->disk_specific;
968 MacRawPartition* part_map_entry;
969 PedSector block_size = disk->dev->sector_size / 512;
971 PED_ASSERT (num > 0, goto error);
973 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
975 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
976 part_map_entry->map_count
977 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
978 part_map_entry->start_block
979 = PED_CPU_TO_BE32 (geom->start / block_size);
980 part_map_entry->block_count
981 = PED_CPU_TO_BE32 (geom->length / block_size);
982 strcpy (part_map_entry->name, "Extra");
983 strcpy (part_map_entry->type, "Apple_Free");
985 part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
986 part_map_entry->status = 0;
987 part_map_entry->driver_sig = 0;
989 if (!_pad_raw_part (disk, num, part_map))
999 _generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
1001 MacDiskData* mac_disk_data = disk->disk_specific;
1002 MacRawPartition* part_map_entry;
1004 PED_ASSERT (num > 0, return 0);
1006 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
1007 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
1008 part_map_entry->map_count
1009 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
1010 strcpy (part_map_entry->type, "Apple_Void");
1012 return _pad_raw_part (disk, num, part_map);
1015 /* returns the first empty entry in the partition map */
1017 _get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map)
1019 MacDiskData* mac_disk_data = disk->disk_specific;
1022 for (i=1; i <= mac_disk_data->last_part_entry_num; i++) {
1023 if (!part_map[i * mac_disk_data->ghost_size - 1].signature)
1031 write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
1033 PedDevice* dev = disk->dev;
1034 MacRawDisk raw_disk;
1036 if (!ped_device_read (dev, &raw_disk, 0, 1))
1039 raw_disk.signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
1040 raw_disk.block_size = PED_CPU_TO_BE16 (dev->sector_size);
1041 raw_disk.block_count
1042 = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
1044 raw_disk.driver_count = mac_driverdata->driver_count;
1045 memcpy(&raw_disk.driverlist[0], &mac_driverdata->driverlist[0],
1046 sizeof(raw_disk.driverlist));
1048 return ped_device_write (dev, &raw_disk, 0, 1);
1052 mac_write (PedDisk* disk)
1054 MacRawPartition* part_map;
1055 MacDiskData* mac_disk_data;
1056 MacDiskData* mac_driverdata; /* updated driver list */
1060 PED_ASSERT (disk != NULL, return 0);
1061 PED_ASSERT (disk->disk_specific != NULL, return 0);
1062 PED_ASSERT (disk->dev != NULL, return 0);
1063 PED_ASSERT (!disk->update_mode, return 0);
1065 mac_disk_data = disk->disk_specific;
1067 if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
1068 if (!_disk_add_part_map_entry (disk, 1))
1072 mac_driverdata = ped_malloc(sizeof(MacDiskData));
1073 if (!mac_driverdata)
1075 memset (mac_driverdata, 0, sizeof(MacDiskData));
1077 part_map = (MacRawPartition*)
1078 ped_malloc (mac_disk_data->part_map_entry_count * 512);
1080 goto error_free_driverdata;
1081 memset (part_map, 0, mac_disk_data->part_map_entry_count * 512);
1083 /* write (to memory) the "real" partitions */
1084 for (part = ped_disk_next_partition (disk, NULL); part;
1085 part = ped_disk_next_partition (disk, part)) {
1086 if (!ped_partition_is_active (part))
1088 if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
1089 goto error_free_part_map;
1092 /* write the "free space" partitions */
1093 for (part = ped_disk_next_partition (disk, NULL); part;
1094 part = ped_disk_next_partition (disk, part)) {
1095 if (part->type != PED_PARTITION_FREESPACE)
1097 num = _get_first_empty_part_entry (disk, part_map);
1098 if (!_generate_raw_freespace_part (disk, &part->geom, num,
1100 goto error_free_part_map;
1103 /* write the "void" (empty) partitions */
1104 for (num = _get_first_empty_part_entry (disk, part_map); num;
1105 num = _get_first_empty_part_entry (disk, part_map))
1106 _generate_empty_part (disk, num, part_map);
1109 if (!ped_device_write (disk->dev, part_map, 1,
1110 mac_disk_data->part_map_entry_count))
1111 goto error_free_part_map;
1113 return write_block_zero (disk, mac_driverdata);
1115 error_free_part_map:
1117 error_free_driverdata:
1118 free (mac_driverdata);
1122 #endif /* !DISCOVER_ONLY */
1124 static PedPartition*
1126 const PedDisk* disk, PedPartitionType part_type,
1127 const PedFileSystemType* fs_type, PedSector start, PedSector end)
1130 MacPartitionData* mac_data;
1132 part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1136 if (ped_partition_is_active (part)) {
1138 = mac_data = ped_malloc (sizeof (MacPartitionData));
1140 goto error_free_part;
1142 memset (mac_data, 0, sizeof (MacPartitionData));
1143 strcpy (mac_data->volume_name, "untitled");
1145 part->disk_specific = NULL;
1156 static PedPartition*
1157 mac_partition_duplicate (const PedPartition* part)
1159 PedPartition* new_part;
1160 MacPartitionData* new_mac_data;
1161 MacPartitionData* old_mac_data;
1163 new_part = ped_partition_new (part->disk, part->type,
1164 part->fs_type, part->geom.start,
1168 new_part->num = part->num;
1170 old_mac_data = (MacPartitionData*) part->disk_specific;
1171 new_mac_data = (MacPartitionData*) new_part->disk_specific;
1173 /* ugly, but C is ugly :p */
1174 memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
1179 mac_partition_destroy (PedPartition* part)
1181 PED_ASSERT (part != NULL, return);
1183 if (ped_partition_is_active (part))
1184 free (part->disk_specific);
1189 mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1191 MacPartitionData* mac_data = part->disk_specific;
1193 part->fs_type = fs_type;
1195 if (fs_type && is_linux_swap (fs_type->name))
1196 ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1198 if (mac_data->is_boot) {
1199 strcpy (mac_data->system_name, "Apple_Bootstrap");
1200 mac_data->status = 0x33;
1204 if (fs_type && (!strcmp (fs_type->name, "hfs")
1205 || !strcmp (fs_type->name, "hfs+"))) {
1206 strcpy (mac_data->system_name, "Apple_HFS");
1207 mac_data->status |= 0x7f;
1208 } else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
1209 strcpy (mac_data->system_name, "Apple_HFSX");
1210 mac_data->status |= 0x7f;
1212 strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
1213 mac_data->status = 0x33;
1220 mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1222 MacPartitionData* mac_data;
1224 PED_ASSERT (part != NULL, return 0);
1225 PED_ASSERT (part->disk_specific != NULL, return 0);
1227 mac_data = part->disk_specific;
1230 case PED_PARTITION_BOOT:
1231 mac_data->is_boot = state;
1234 return mac_partition_set_system (part, part->fs_type);
1237 strcpy (mac_data->system_name, "Apple_Bootstrap");
1238 mac_data->status = 0x33;
1242 case PED_PARTITION_ROOT:
1244 strcpy (mac_data->volume_name, "root");
1245 mac_data->is_swap = 0;
1247 if (mac_data->is_root)
1248 strcpy (mac_data->volume_name, "untitled");
1250 mac_data->is_root = state;
1253 case PED_PARTITION_SWAP:
1255 strcpy (mac_data->volume_name, "swap");
1256 mac_data->is_root = 0;
1258 if (mac_data->is_swap)
1259 strcpy (mac_data->volume_name, "untitled");
1261 mac_data->is_swap = state;
1264 case PED_PARTITION_LVM:
1266 strcpy (mac_data->system_name, "Linux_LVM");
1267 mac_data->is_lvm = state;
1269 if (mac_data->is_lvm)
1270 mac_partition_set_system (part, part->fs_type);
1274 case PED_PARTITION_RAID:
1276 strcpy (mac_data->system_name, "Linux_RAID");
1277 mac_data->is_raid = state;
1279 if (mac_data->is_raid)
1280 mac_partition_set_system (part, part->fs_type);
1290 mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1292 MacPartitionData* mac_data;
1294 PED_ASSERT (part != NULL, return 0);
1295 PED_ASSERT (part->disk_specific != NULL, return 0);
1297 mac_data = part->disk_specific;
1299 case PED_PARTITION_BOOT:
1300 return mac_data->is_boot;
1302 case PED_PARTITION_ROOT:
1303 return mac_data->is_root;
1305 case PED_PARTITION_SWAP:
1306 return mac_data->is_swap;
1308 case PED_PARTITION_LVM:
1309 return mac_data->is_lvm;
1311 case PED_PARTITION_RAID:
1312 return mac_data->is_raid;
1320 mac_partition_is_flag_available (
1321 const PedPartition* part, PedPartitionFlag flag)
1324 case PED_PARTITION_BOOT:
1325 case PED_PARTITION_ROOT:
1326 case PED_PARTITION_SWAP:
1327 case PED_PARTITION_LVM:
1328 case PED_PARTITION_RAID:
1337 mac_partition_set_name (PedPartition* part, const char* name)
1339 MacPartitionData* mac_data;
1342 PED_ASSERT (part != NULL, return);
1343 PED_ASSERT (part->disk_specific != NULL, return);
1344 mac_data = part->disk_specific;
1346 #ifndef DISCOVER_ONLY
1347 if (mac_data->is_root || mac_data->is_swap) {
1348 if (ped_exception_throw (
1349 PED_EXCEPTION_WARNING,
1350 PED_EXCEPTION_IGNORE_CANCEL,
1351 _("Changing the name of a root or swap partition "
1352 "will prevent Linux from recognising it as such."))
1353 != PED_EXCEPTION_IGNORE)
1355 mac_data->is_root = mac_data->is_swap = 0;
1359 strncpy (mac_data->volume_name, name, 32);
1360 mac_data->volume_name [32] = 0;
1361 for (i = strlen (mac_data->volume_name) - 1;
1362 mac_data->volume_name[i] == ' '; i--)
1363 mac_data->volume_name [i] = 0;
1367 mac_partition_get_name (const PedPartition* part)
1369 MacPartitionData* mac_data;
1371 PED_ASSERT (part != NULL, return NULL);
1372 PED_ASSERT (part->disk_specific != NULL, return NULL);
1373 mac_data = part->disk_specific;
1375 return mac_data->volume_name;
1378 static PedConstraint*
1379 _primary_constraint (PedDisk* disk)
1381 PedAlignment start_align;
1382 PedAlignment end_align;
1383 PedGeometry max_geom;
1384 PedSector sector_size;
1386 sector_size = disk->dev->sector_size / 512;
1388 if (!ped_alignment_init (&start_align, 0, sector_size))
1390 if (!ped_alignment_init (&end_align, -1, sector_size))
1392 if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1395 return ped_constraint_new (&start_align, &end_align, &max_geom,
1396 &max_geom, 1, disk->dev->length);
1400 mac_partition_align (PedPartition* part, const PedConstraint* constraint)
1402 PED_ASSERT (part != NULL, return 0);
1404 if (_ped_partition_attempt_align (part, constraint,
1405 _primary_constraint (part->disk)))
1408 #ifndef DISCOVER_ONLY
1409 ped_exception_throw (
1410 PED_EXCEPTION_ERROR,
1411 PED_EXCEPTION_CANCEL,
1412 _("Unable to satisfy all constraints on the partition."));
1418 mac_partition_enumerate (PedPartition* part)
1421 MacDiskData* mac_disk_data;
1425 PED_ASSERT (part != NULL, return 0);
1426 PED_ASSERT (part->disk != NULL, return 0);
1429 mac_disk_data = (MacDiskData*) disk->disk_specific;
1431 max_part_count = ped_disk_get_max_primary_partition_count (disk);
1433 if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
1436 for (i = 1; i <= max_part_count; i++) {
1437 if (!ped_disk_get_partition (disk, i)) {
1443 #ifndef DISCOVER_ONLY
1444 ped_exception_throw (
1445 PED_EXCEPTION_ERROR,
1446 PED_EXCEPTION_CANCEL,
1447 _("Can't add another partition -- the partition map is too "
1455 _disk_count_partitions (PedDisk* disk)
1457 MacDiskData* mac_disk_data = disk->disk_specific;
1458 PedPartition* part = NULL;
1459 PedPartition* last = NULL;
1461 PED_ASSERT (disk->update_mode, return 0);
1463 mac_disk_data->active_part_entry_count = 0;
1464 mac_disk_data->free_part_entry_count = 0;
1465 mac_disk_data->last_part_entry_num = 0;
1467 /* subtle: we only care about free space after the partition map.
1468 * the partition map is an "active" partition, BTW... */
1469 for (part = ped_disk_next_partition (disk, part); part;
1470 part = ped_disk_next_partition (disk, part)) {
1471 if (!ped_partition_is_active (part))
1474 mac_disk_data->active_part_entry_count++;
1475 if (last && last->geom.end + 1 < part->geom.start)
1476 mac_disk_data->free_part_entry_count++;
1477 mac_disk_data->last_part_entry_num
1478 = PED_MAX (mac_disk_data->last_part_entry_num,
1484 if (last && last->geom.end < disk->dev->length - 1)
1485 mac_disk_data->free_part_entry_count++;
1487 mac_disk_data->last_part_entry_num
1488 = PED_MAX (mac_disk_data->last_part_entry_num,
1489 mac_disk_data->active_part_entry_count
1490 + mac_disk_data->free_part_entry_count);
1495 add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
1497 PedPartition* new_part;
1498 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
1500 PED_ASSERT (disk != NULL, return 0);
1502 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1506 if (!ped_disk_add_partition (disk, new_part, constraint_any))
1507 goto error_destroy_new_part;
1509 ped_constraint_destroy (constraint_any);
1512 error_destroy_new_part:
1513 ped_partition_destroy (new_part);
1515 ped_constraint_destroy (constraint_any);
1520 mac_alloc_metadata (PedDisk* disk)
1522 MacDiskData* mac_disk_data;
1524 PED_ASSERT (disk != NULL, return 0);
1525 PED_ASSERT (disk->disk_specific != NULL, return 0);
1526 PED_ASSERT (disk->dev != NULL, return 0);
1528 mac_disk_data = disk->disk_specific;
1530 if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
1533 /* hack: this seems to be a good place, to update the partition map
1534 * entry count, since mac_alloc_metadata() gets called during
1535 * _disk_pop_update_mode()
1537 return _disk_count_partitions (disk);
1541 mac_get_max_primary_partition_count (const PedDisk* disk)
1543 MacDiskData* mac_disk_data = disk->disk_specific;
1544 PedPartition* part_map_partition;
1546 part_map_partition = ped_disk_get_partition (disk,
1547 mac_disk_data->part_map_entry_num);
1549 /* HACK: if we haven't found the partition map partition (yet),
1552 if (!part_map_partition) {
1553 mac_disk_data->part_map_entry_num = 0;
1557 /* HACK: since Mac labels need an entry for free-space regions, we
1558 * must allow half plus 1 entries for free-space partitions. I hate
1559 * this, but things get REALLY complicated, otherwise.
1560 * (I'm prepared to complicate things later, but I want to get
1561 * everything working, first)
1563 return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
1564 - mac_disk_data->free_part_entry_count + 1;
1568 mac_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
1574 static PedDiskOps mac_disk_ops = {
1576 #ifndef DISCOVER_ONLY
1577 clobber: mac_clobber,
1582 duplicate: mac_duplicate,
1585 #ifndef DISCOVER_ONLY
1586 /* FIXME: remove this cast, once mac_write is fixed not to
1587 modify its *DISK parameter. */
1588 write: (int (*) (const PedDisk*)) mac_write,
1593 partition_new: mac_partition_new,
1594 partition_duplicate: mac_partition_duplicate,
1595 partition_destroy: mac_partition_destroy,
1596 partition_set_system: mac_partition_set_system,
1597 partition_set_flag: mac_partition_set_flag,
1598 partition_get_flag: mac_partition_get_flag,
1599 partition_is_flag_available: mac_partition_is_flag_available,
1600 partition_set_name: mac_partition_set_name,
1601 partition_get_name: mac_partition_get_name,
1602 partition_align: mac_partition_align,
1603 partition_enumerate: mac_partition_enumerate,
1605 alloc_metadata: mac_alloc_metadata,
1606 get_max_primary_partition_count:
1607 mac_get_max_primary_partition_count,
1608 get_max_supported_partition_count:
1609 mac_get_max_supported_partition_count
1612 static PedDiskType mac_disk_type = {
1616 features: PED_DISK_TYPE_PARTITION_NAME
1620 ped_disk_mac_init ()
1622 PED_ASSERT (sizeof (MacRawPartition) == 512, return);
1623 PED_ASSERT (sizeof (MacRawDisk) == 512, return);
1625 ped_disk_type_register (&mac_disk_type);
1629 ped_disk_mac_done ()
1631 ped_disk_type_unregister (&mac_disk_type);