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>
29 # define _(String) dgettext (PACKAGE, String)
31 # define _(String) (String)
32 #endif /* ENABLE_NLS */
34 /* struct's hacked from Linux source: fs/partitions/mac.h
35 * I believe it was originally written by Paul Mackerras (from comments in
39 * http://developer.apple.com/documentation/mac/Devices/Devices-126.html
40 * http://developer.apple.com/documentation/mac/Devices/Devices-121.html
41 * http://devworld.apple.com/technotes/tn/tn1189.html
44 * Apple_Bootstrap new-world (HFS) boot partition
45 * Apple_partition_map partition map (table)
46 * Apple_Driver device driver
47 * Apple_Driver43 SCSI Manager 4.3 device driver
48 * Apple_MFS original Macintosh File System
49 * Apple_HFS Hierarchical File System (and +)
50 * Apple_HFSX HFS+ with case sensitivity and more
51 * Apple_UNIX_SVR2 UNIX file system (UFS?)
52 * Apple_PRODOS ProDOS file system
53 * Apple_Free unused space
55 * Apple_Void padding for iso9660
56 * Apple_Extra an unused partition map entry
66 * partition volume or partition
69 * * All space must be accounted for, except block 0 (driver block) and
70 * block 1-X (the partition map: i.e. lots of MacRawPartitions)
72 * * It's really hard to grow/shrink the number of MacRawPartition
73 * entries in the partition map, because the first partition starts
74 * immediately after the partition map. When we can move the start of
75 * HFS and ext2 partitions, this problem will disappear ;-)
78 #define MAC_PARTITION_MAGIC_1 0x5453 /* old */
79 #define MAC_PARTITION_MAGIC_2 0x504d
80 #define MAC_DISK_MAGIC 0x4552
82 #define MAC_STATUS_BOOTABLE 8 /* partition is bootable */
85 uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
87 uint32_t map_count; /* # blocks in partition map */
88 uint32_t start_block; /* absolute starting block # of partition */
89 uint32_t block_count; /* number of blocks in partition */
90 char name[32]; /* partition name */
91 char type[32]; /* string type description */
92 uint32_t data_start; /* rel block # of first data block */
93 uint32_t data_count; /* number of data blocks */
94 uint32_t status; /* partition status bits */
100 uint32_t boot_entry2;
102 char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
105 } __attribute__ ((packed)) MacRawPartition;
107 /* Driver descriptor structure, in block 0 */
109 uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
110 uint16_t block_size; /* physical sector size */
111 uint32_t block_count; /* size of device in blocks */
112 uint16_t dev_type; /* reserved */
113 uint16_t dev_id; /* reserved */
114 uint32_t data; /* reserved */
115 uint16_t driver_count; /* # of driver descriptor entries */
116 uint8_t driverlist[488]; /* info about available drivers */
117 uint16_t padding[3]; /* pad to 512 bytes */
118 } __attribute__ ((packed)) MacRawDisk;
121 uint32_t block; /* startblock in MacRawDisk->block_size units */
122 uint16_t size; /* size in 512 byte units */
123 uint16_t type; /* operating system type (MacOS = 1) */
124 } __attribute__ ((packed)) MacDeviceDriver;
127 char volume_name[33]; /* eg: "Games" */
128 char system_name[33]; /* eg: "Apple_Unix_SVR2" */
129 char processor_name[17];
139 PedSector data_region_length;
140 PedSector boot_region_length;
142 uint32_t boot_base_address;
143 uint32_t boot_entry_address;
144 uint32_t boot_checksum;
151 int ghost_size; /* sectors per "driver" block */
152 int part_map_entry_count; /* # entries (incl. ghost) */
153 int part_map_entry_num; /* partition map location */
155 int active_part_entry_count; /* # real partitions */
156 int free_part_entry_count; /* # free space */
157 int last_part_entry_num; /* last entry number */
159 uint16_t block_size; /* physical sector size */
160 uint16_t driver_count;
161 MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */
164 static PedDiskType mac_disk_type;
167 _check_signature (MacRawDisk* raw_disk)
169 if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
173 return ped_exception_throw (
175 PED_EXCEPTION_IGNORE_CANCEL,
176 _("Invalid signature %x for Mac disk labels."),
177 (int) PED_BE16_TO_CPU (raw_disk->signature))
178 == PED_EXCEPTION_IGNORE;
186 _rawpart_check_signature (MacRawPartition* raw_part)
188 int sig = (int) PED_BE16_TO_CPU (raw_part->signature);
189 return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
193 mac_probe (const PedDevice * dev)
197 PED_ASSERT (dev != NULL, return 0);
199 if (dev->sector_size != 512)
202 if (!ped_device_read (dev, &buf, 0, 1))
205 return _check_signature (&buf);
209 _disk_add_part_map_entry (PedDisk* disk, int warn)
211 MacDiskData* mac_disk_data = disk->disk_specific;
212 PedPartition* new_part;
213 MacPartitionData* mac_part_data;
214 PedSector part_map_size;
215 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
217 #ifndef DISCOVER_ONLY
218 if (warn && ped_exception_throw (
220 PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
221 _("Partition map has no partition map entry!"))
222 != PED_EXCEPTION_FIX)
224 #endif /* !DISCOVER_ONLY */
227 = ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
228 if (part_map_size == 0)
231 new_part = ped_partition_new (disk, 0, NULL, 1, part_map_size - 1);
235 mac_part_data = new_part->disk_specific;
236 strcpy (mac_part_data->volume_name, "Apple");
237 strcpy (mac_part_data->system_name, "Apple_partition_map");
239 if (!ped_disk_add_partition (disk, new_part, constraint_any))
240 goto error_destroy_new_part;
242 mac_disk_data->part_map_entry_num = new_part->num;
243 mac_disk_data->part_map_entry_count
244 = new_part->geom.end - mac_disk_data->ghost_size;
245 ped_constraint_destroy (constraint_any);
248 error_destroy_new_part:
249 ped_partition_destroy (new_part);
251 ped_constraint_destroy (constraint_any);
256 mac_alloc (const PedDevice* dev)
259 MacDiskData* mac_disk_data;
261 PED_ASSERT (dev != NULL, return NULL);
263 #ifndef DISCOVER_ONLY
264 if (dev->length < 256) {
265 ped_exception_throw (
267 PED_EXCEPTION_CANCEL,
268 _("%s is too small for a Mac disk label!"),
274 disk = _ped_disk_alloc (dev, &mac_disk_type);
278 mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
280 goto error_free_disk;
281 disk->disk_specific = mac_disk_data;
282 mac_disk_data->ghost_size = disk->dev->sector_size / 512;
283 mac_disk_data->active_part_entry_count = 0;
284 mac_disk_data->free_part_entry_count = 1;
285 mac_disk_data->last_part_entry_num = 1;
286 mac_disk_data->block_size = 0;
287 mac_disk_data->driver_count = 0;
288 memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
290 if (!_disk_add_part_map_entry (disk, 0))
291 goto error_free_disk;
295 _ped_disk_free (disk);
301 mac_duplicate (const PedDisk* disk)
304 MacDiskData* new_mac_data;
305 MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific;
306 PedPartition* partition_map;
308 new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type);
312 new_mac_data = (MacDiskData*) new_disk->disk_specific;
314 /* remove the partition map partition - it will be duplicated
317 partition_map = ped_disk_get_partition_by_sector (new_disk, 1);
318 PED_ASSERT (partition_map != NULL, return 0);
319 ped_disk_remove_partition (new_disk, partition_map);
321 /* ugly, but C is ugly :p */
322 memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
326 _ped_disk_free (new_disk);
332 mac_free (PedDisk* disk)
334 MacDiskData* mac_disk_data = disk->disk_specific;
336 _ped_disk_free (disk);
337 ped_free (mac_disk_data);
340 #ifndef DISCOVER_ONLY
342 _clobber_part_map (PedDevice* dev)
344 MacRawPartition raw_part;
347 for (sector=1; 1; sector++) {
348 if (!ped_device_read (dev, &raw_part, sector, 1))
350 if (!_rawpart_check_signature (&raw_part))
352 memset (&raw_part, 0, 512);
353 if (!ped_device_write (dev, &raw_part, sector, 1))
359 mac_clobber (PedDevice* dev)
363 if (!ped_device_read (dev, &raw_disk, 0, 1))
365 if (!_check_signature (&raw_disk))
367 memset (&raw_disk, 0, 512);
368 if (!ped_device_write (dev, &raw_disk, 0, 1))
371 return _clobber_part_map (dev);
373 #endif /* !DISCOVER_ONLY */
376 _rawpart_cmp_type (MacRawPartition* raw_part, char* type)
378 return strncasecmp (raw_part->type, type, 32) == 0;
382 _rawpart_cmp_name (MacRawPartition* raw_part, char* name)
384 return strncasecmp (raw_part->name, name, 32) == 0;
388 _rawpart_is_partition_map (MacRawPartition* raw_part)
390 return _rawpart_cmp_type (raw_part, "Apple_partition_map");
394 strncasestr (const char* haystack, const char* needle, int n)
396 int needle_size = strlen (needle);
399 for (i = 0; haystack[i] && i < n - needle_size; i++) {
400 if (strncasecmp (haystack + i, needle, needle_size) == 0)
408 _rawpart_is_boot (MacRawPartition* raw_part)
410 return !strcasecmp (raw_part->type, "Apple_Bootstrap");
414 _rawpart_is_driver (MacRawPartition* raw_part)
416 if (strncmp (raw_part->type, "Apple_", 6) != 0)
418 if (!strncasestr (raw_part->type, "driver", 32))
424 _rawpart_has_driver (MacRawPartition* raw_part, MacDiskData* mac_disk_data)
426 MacDeviceDriver *driverlist;
428 uint32_t driver_bs, driver_be, part_be;
430 driverlist = &mac_disk_data->driverlist[0];
431 bsz = mac_disk_data->block_size / 512;
432 for (i = 0; i < mac_disk_data->driver_count; i++) {
433 driver_bs = driverlist->block * bsz;
434 driver_be = driver_bs + driverlist->size;
435 part_be = raw_part->start_block + raw_part->block_count;
436 if (driver_bs >= raw_part->start_block && driver_be <= part_be)
444 _rawpart_is_root (MacRawPartition* raw_part)
446 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
448 if (strcmp (raw_part->name, "root") != 0)
454 _rawpart_is_swap (MacRawPartition* raw_part)
456 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
458 if (strcmp (raw_part->name, "swap") != 0)
464 _rawpart_is_lvm (MacRawPartition* raw_part)
466 if (strcmp (raw_part->type, "Linux_LVM") != 0)
472 _rawpart_is_raid (MacRawPartition* raw_part)
474 if (strcmp (raw_part->type, "Linux_RAID") != 0)
480 _rawpart_is_void (MacRawPartition* raw_part)
482 return _rawpart_cmp_type (raw_part, "Apple_Void");
485 /* returns 1 if the raw_part represents a partition that is "unused space", or
486 * doesn't represent a partition at all. NOTE: some people make Apple_Free
487 * partitions with MacOS, because they can't select another type. So, if the
488 * name is anything other than "Extra" or "", it is treated as a "real"
492 _rawpart_is_active (MacRawPartition* raw_part)
494 if (_rawpart_cmp_type (raw_part, "Apple_Free")
495 && (_rawpart_cmp_name (raw_part, "Extra")
496 || _rawpart_cmp_name (raw_part, "")))
498 if (_rawpart_cmp_type (raw_part, "Apple_Void"))
500 if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
502 if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
509 _rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
511 MacDiskData* mac_disk_data;
513 MacPartitionData* mac_part_data;
514 PedSector block_size;
515 PedSector start, length;
517 if (!_rawpart_check_signature (raw_part)) {
518 #ifndef DISCOVER_ONLY
519 if (ped_exception_throw (
520 PED_EXCEPTION_WARNING,
521 PED_EXCEPTION_IGNORE_CANCEL,
522 _("Partition %d has an invalid signature %x."),
524 (int) PED_BE16_TO_CPU (raw_part->signature))
525 != PED_EXCEPTION_IGNORE)
530 mac_disk_data = (MacDiskData*) disk->disk_specific;
531 block_size = disk->dev->sector_size / 512;
533 start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
534 length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
536 #ifndef DISCOVER_ONLY
537 ped_exception_throw (
539 PED_EXCEPTION_CANCEL,
540 _("Partition %d has an invalid length of 0 bytes!"),
545 part = ped_partition_new (disk, 0, NULL, start, start + length - 1);
549 mac_part_data = part->disk_specific;
551 strncpy (mac_part_data->volume_name, raw_part->name, 32);
552 strncpy (mac_part_data->system_name, raw_part->type, 32);
553 strncpy (mac_part_data->processor_name, raw_part->processor, 16);
555 mac_part_data->is_boot = _rawpart_is_boot (raw_part);
556 mac_part_data->is_driver = _rawpart_is_driver (raw_part);
557 if (mac_part_data->is_driver)
558 mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
559 mac_part_data->is_root = _rawpart_is_root (raw_part);
560 mac_part_data->is_swap = _rawpart_is_swap (raw_part);
561 mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
562 mac_part_data->is_raid = _rawpart_is_raid (raw_part);
565 #ifndef DISCOVER_ONLY
566 if (raw_part->data_start) {
567 ped_exception_throw (
569 PED_EXCEPTION_CANCEL,
570 _("The data region doesn't start at the start "
571 "of the partition."));
572 goto error_destroy_part;
574 #endif /* !DISCOVER_ONLY */
575 mac_part_data->data_region_length
576 = PED_BE32_TO_CPU (raw_part->data_count) * block_size;
578 /* boot region - we have no idea what this is for, but Mac OSX
579 * seems to put garbage here, and doesn't pay any attention to
580 * it afterwards. [clausen, dan burcaw]
583 if (raw_part->boot_start) {
584 ped_exception_throw (
586 PED_EXCEPTION_CANCEL,
587 _("The boot region doesn't start at the start "
588 "of the partition."));
589 goto error_destroy_part;
592 mac_part_data->boot_region_length
593 = PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
595 #ifndef DISCOVER_ONLY
596 if (mac_part_data->has_driver) {
597 if (mac_part_data->boot_region_length < part->geom.length) {
598 if (ped_exception_throw (
600 PED_EXCEPTION_IGNORE_CANCEL,
601 _("The partition's boot region doesn't occupy "
602 "the entire partition."))
603 != PED_EXCEPTION_IGNORE)
604 goto error_destroy_part;
607 if (mac_part_data->data_region_length < part->geom.length) {
608 if (ped_exception_throw (
610 PED_EXCEPTION_IGNORE_CANCEL,
611 _("The partition's data region doesn't occupy "
612 "the entire partition."))
613 != PED_EXCEPTION_IGNORE)
614 goto error_destroy_part;
617 #endif /* !DISCOVER_ONLY */
619 mac_part_data->boot_base_address
620 = PED_BE32_TO_CPU (raw_part->boot_load);
621 mac_part_data->boot_entry_address
622 = PED_BE32_TO_CPU (raw_part->boot_entry);
623 mac_part_data->boot_checksum
624 = PED_BE32_TO_CPU (raw_part->boot_cksum);
626 mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
627 mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
632 ped_partition_destroy (part);
637 /* looks at the partition map size field in a mac raw partition, and calculates
638 * what the size of the partition map should be, from it
641 _rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
643 MacDiskData* mac_disk_data = disk->disk_specific;
644 PedSector sector_size = disk->dev->sector_size / 512;
645 PedSector part_map_start;
646 PedSector part_map_end;
648 part_map_start = mac_disk_data->ghost_size;
649 part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
651 return part_map_end - part_map_start + 1;
655 _disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
657 PedSector block_size;
659 if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
660 #ifndef DISCOVER_ONLY
661 ped_exception_throw (
663 PED_EXCEPTION_CANCEL,
664 _("Weird block size on device descriptor: %d bytes is "
665 "not divisible by 512."),
666 (int) PED_BE16_TO_CPU (raw_disk->block_size));
671 block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
672 if (block_size != disk->dev->sector_size / 512) {
673 #ifndef DISCOVER_ONLY
674 if (ped_exception_throw (
675 PED_EXCEPTION_WARNING,
676 PED_EXCEPTION_IGNORE_CANCEL,
677 _("The driver descriptor says the physical block size "
678 "is %d bytes, but Linux says it is %d bytes."),
679 (int) block_size * 512,
680 (int) disk->dev->sector_size)
681 != PED_EXCEPTION_IGNORE)
684 disk->dev->sector_size = block_size * 512;
693 /* Tries to figure out the block size used by the drivers, for the ghost
694 * partitioning scheme. Ghost partitioning works like this: the OpenFirmware
695 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
696 * perhaps, some other number?). To remain compatible, the partition map
697 * only has "real" partition map entries on ghost-aligned block numbers (and
698 * the others are padded with Apple_Void partitions). This function tries
699 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
700 * doesn't always equal 2048!!!)
703 _disk_analyse_ghost_size (PedDisk* disk)
705 MacDiskData* mac_disk_data = disk->disk_specific;
706 MacRawPartition raw_part;
709 for (i = 1; i < 64; i *= 2) {
710 if (!ped_device_read (disk->dev, &raw_part, i, 1))
712 if (_rawpart_check_signature (&raw_part)
713 && !_rawpart_is_void (&raw_part)) {
714 mac_disk_data->ghost_size = i;
715 PED_ASSERT (i <= disk->dev->sector_size / 512,
721 #ifndef DISCOVER_ONLY
722 ped_exception_throw (
724 PED_EXCEPTION_CANCEL,
725 _("No valid partition map found."));
731 mac_read (PedDisk* disk)
734 MacRawPartition raw_part;
735 MacDiskData* mac_disk_data;
738 PedSector ghost_size;
739 PedConstraint* constraint_exact;
740 int last_part_entry_num = 0;
742 PED_ASSERT (disk != NULL, return 0);
744 mac_disk_data = disk->disk_specific;
745 mac_disk_data->part_map_entry_num = 0; /* 0 == none */
747 if (!ped_device_read (disk->dev, &raw_disk, 0, 1))
749 if (!_check_signature (&raw_disk))
752 if (!_disk_analyse_block_size (disk, &raw_disk))
754 if (!_disk_analyse_ghost_size (disk))
756 ghost_size = mac_disk_data->ghost_size;
758 if (!ped_disk_delete_all (disk))
761 if (raw_disk.driver_count && raw_disk.driver_count < 62) {
762 memcpy(&mac_disk_data->driverlist[0], &raw_disk.driverlist[0],
763 sizeof(mac_disk_data->driverlist));
764 mac_disk_data->driver_count = raw_disk.driver_count;
765 mac_disk_data->block_size = raw_disk.block_size;
768 for (num=1; num==1 || num <= last_part_entry_num; num++) {
769 if (!ped_device_read (disk->dev, &raw_part,
770 num * ghost_size, 1))
771 goto error_delete_all;
773 if (!_rawpart_check_signature (&raw_part))
778 = _rawpart_get_partmap_size (&raw_part, disk);
779 if (_rawpart_get_partmap_size (&raw_part, disk)
780 != last_part_entry_num) {
781 if (ped_exception_throw (
783 PED_EXCEPTION_IGNORE_CANCEL,
784 _("Conflicting partition map entry sizes! "
785 "Entry 1 says it is %d, but entry %d says "
788 _rawpart_get_partmap_size (&raw_part, disk))
789 != PED_EXCEPTION_IGNORE)
790 goto error_delete_all;
793 if (!_rawpart_is_active (&raw_part))
796 part = _rawpart_analyse (&raw_part, disk, num);
798 goto error_delete_all;
800 part->fs_type = ped_file_system_probe (&part->geom);
801 constraint_exact = ped_constraint_exact (&part->geom);
802 if (!ped_disk_add_partition (disk, part, constraint_exact))
803 goto error_delete_all;
804 ped_constraint_destroy (constraint_exact);
806 if (_rawpart_is_partition_map (&raw_part)) {
807 if (mac_disk_data->part_map_entry_num
808 && ped_exception_throw (
810 PED_EXCEPTION_IGNORE_CANCEL,
811 _("Weird! There are 2 partitions "
813 != PED_EXCEPTION_IGNORE)
814 goto error_delete_all;
816 mac_disk_data->part_map_entry_num = num;
817 mac_disk_data->part_map_entry_count
818 = part->geom.end - ghost_size + 1;
822 if (!mac_disk_data->part_map_entry_num) {
823 if (!_disk_add_part_map_entry (disk, 1))
824 goto error_delete_all;
825 ped_disk_commit_to_dev (disk);
830 ped_disk_delete_all (disk);
835 #ifndef DISCOVER_ONLY
836 /* The Ghost partition: is a blank entry, used to pad out each block (where
837 * there physical block size > 512 bytes). This is because OpenFirmware uses
838 * 512 byte blocks, but device drivers Think Different TM, with a different
839 * lbock size, so we need to do this to avoid a clash (!)
842 _pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
844 MacDiskData* mac_disk_data = disk->disk_specific;
845 MacRawPartition ghost_entry;
848 memset (&ghost_entry, 0, sizeof (ghost_entry));
849 ghost_entry.signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
850 strcpy (ghost_entry.type, "Apple_Void");
851 ghost_entry.map_count
852 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
854 for (i=0; i < mac_disk_data->ghost_size - 1; i++)
855 memcpy (&part_map [i + (num - 1) * mac_disk_data->ghost_size],
856 &ghost_entry, sizeof (MacRawPartition));
862 _update_driver_count (MacRawPartition* part_map_entry,
863 MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
865 uint16_t i, count_orig, count_cur, bsz;
866 uint32_t driver_bs, driver_be, part_be;
868 bsz = mac_disk_data->block_size / 512;
869 count_cur = mac_driverdata->driver_count;
870 count_orig = mac_disk_data->driver_count;
871 for (i = 0; i < count_orig; i++) {
872 driver_bs = mac_disk_data->driverlist[i].block * bsz;
873 driver_be = driver_bs + mac_disk_data->driverlist[i].size;
874 part_be = part_map_entry->start_block + part_map_entry->block_count;
875 if (driver_bs >= part_map_entry->start_block
876 && driver_be <= part_be) {
877 mac_driverdata->driverlist[count_cur].block
878 = mac_disk_data->driverlist[i].block;
879 mac_driverdata->driverlist[count_cur].size
880 = mac_disk_data->driverlist[i].size;
881 mac_driverdata->driverlist[count_cur].type
882 = mac_disk_data->driverlist[i].type;
883 mac_driverdata->driver_count++;
890 _generate_raw_part (PedDisk* disk, PedPartition* part,
891 MacRawPartition* part_map, MacDiskData *mac_driverdata)
893 MacDiskData* mac_disk_data;
894 MacPartitionData* mac_part_data;
895 MacRawPartition* part_map_entry;
896 PedSector block_size = disk->dev->sector_size / 512;
898 PED_ASSERT (part->num > 0, goto error);
900 mac_disk_data = disk->disk_specific;
901 mac_part_data = part->disk_specific;
903 part_map_entry = &part_map [part->num * mac_disk_data->ghost_size - 1];
905 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
906 part_map_entry->map_count
907 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
908 part_map_entry->start_block
909 = PED_CPU_TO_BE32 (part->geom.start / block_size);
910 part_map_entry->block_count
911 = PED_CPU_TO_BE32 (part->geom.length / block_size);
912 strcpy (part_map_entry->name, mac_part_data->volume_name);
913 strcpy (part_map_entry->type, mac_part_data->system_name);
915 if (mac_part_data->is_driver) {
916 mac_part_data->boot_region_length = part->geom.length;
917 if (mac_part_data->has_driver)
918 _update_driver_count(part_map_entry, mac_driverdata,
921 mac_part_data->data_region_length = part->geom.length;
922 part_map_entry->data_count = PED_CPU_TO_BE32 (
923 mac_part_data->data_region_length / block_size);
924 part_map_entry->boot_count = PED_CPU_TO_BE32 (
925 mac_part_data->boot_region_length / block_size);
926 part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
927 part_map_entry->driver_sig
928 = PED_CPU_TO_BE32 (mac_part_data->driver_sig);
930 part_map_entry->boot_load =
931 PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
932 part_map_entry->boot_entry =
933 PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
934 part_map_entry->boot_cksum =
935 PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
937 strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
939 if (!_pad_raw_part (disk, part->num, part_map))
949 _generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
950 MacRawPartition* part_map)
952 MacDiskData* mac_disk_data = disk->disk_specific;
953 MacRawPartition* part_map_entry;
954 PedSector block_size = disk->dev->sector_size / 512;
956 PED_ASSERT (num > 0, goto error);
958 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
960 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
961 part_map_entry->map_count
962 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
963 part_map_entry->start_block
964 = PED_CPU_TO_BE32 (geom->start / block_size);
965 part_map_entry->block_count
966 = PED_CPU_TO_BE32 (geom->length / block_size);
967 strcpy (part_map_entry->name, "Extra");
968 strcpy (part_map_entry->type, "Apple_Free");
970 part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
971 part_map_entry->status = 0;
972 part_map_entry->driver_sig = 0;
974 if (!_pad_raw_part (disk, num, part_map))
984 _generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
986 MacDiskData* mac_disk_data = disk->disk_specific;
987 MacRawPartition* part_map_entry;
989 PED_ASSERT (num > 0, return 0);
991 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1];
992 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
993 part_map_entry->map_count
994 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
995 strcpy (part_map_entry->type, "Apple_Void");
997 return _pad_raw_part (disk, num, part_map);
1000 /* returns the first empty entry in the partition map */
1002 _get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map)
1004 MacDiskData* mac_disk_data = disk->disk_specific;
1007 for (i=1; i <= mac_disk_data->last_part_entry_num; i++) {
1008 if (!part_map[i * mac_disk_data->ghost_size - 1].signature)
1016 write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
1018 PedDevice* dev = disk->dev;
1019 MacRawDisk raw_disk;
1021 if (!ped_device_read (dev, &raw_disk, 0, 1))
1024 raw_disk.signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
1025 raw_disk.block_size = PED_CPU_TO_BE16 (dev->sector_size);
1026 raw_disk.block_count
1027 = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
1029 raw_disk.driver_count = mac_driverdata->driver_count;
1030 memcpy(&raw_disk.driverlist[0], &mac_driverdata->driverlist[0],
1031 sizeof(raw_disk.driverlist));
1033 return ped_device_write (dev, &raw_disk, 0, 1);
1037 mac_write (PedDisk* disk)
1039 MacRawPartition* part_map;
1040 MacDiskData* mac_disk_data;
1041 MacDiskData* mac_driverdata; /* updated driver list */
1045 PED_ASSERT (disk != NULL, return 0);
1046 PED_ASSERT (disk->disk_specific != NULL, return 0);
1047 PED_ASSERT (disk->dev != NULL, return 0);
1048 PED_ASSERT (!disk->update_mode, return 0);
1050 mac_disk_data = disk->disk_specific;
1052 if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
1053 if (!_disk_add_part_map_entry (disk, 1))
1057 mac_driverdata = ped_malloc(sizeof(MacDiskData));
1058 if (!mac_driverdata)
1060 memset (mac_driverdata, 0, sizeof(MacDiskData));
1062 part_map = (MacRawPartition*)
1063 ped_malloc (mac_disk_data->part_map_entry_count * 512);
1065 goto error_free_driverdata;
1066 memset (part_map, 0, mac_disk_data->part_map_entry_count * 512);
1068 /* write (to memory) the "real" partitions */
1069 for (part = ped_disk_next_partition (disk, NULL); part;
1070 part = ped_disk_next_partition (disk, part)) {
1071 if (!ped_partition_is_active (part))
1073 if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
1074 goto error_free_part_map;
1077 /* write the "free space" partitions */
1078 for (part = ped_disk_next_partition (disk, NULL); part;
1079 part = ped_disk_next_partition (disk, part)) {
1080 if (part->type != PED_PARTITION_FREESPACE)
1082 num = _get_first_empty_part_entry (disk, part_map);
1083 if (!_generate_raw_freespace_part (disk, &part->geom, num,
1085 goto error_free_part_map;
1088 /* write the "void" (empty) partitions */
1089 for (num = _get_first_empty_part_entry (disk, part_map); num;
1090 num = _get_first_empty_part_entry (disk, part_map))
1091 _generate_empty_part (disk, num, part_map);
1094 if (!ped_device_write (disk->dev, part_map, 1,
1095 mac_disk_data->part_map_entry_count))
1096 goto error_free_part_map;
1097 ped_free (part_map);
1098 return write_block_zero (disk, mac_driverdata);
1100 error_free_part_map:
1101 ped_free (part_map);
1102 error_free_driverdata:
1103 ped_free (mac_driverdata);
1107 #endif /* !DISCOVER_ONLY */
1109 static PedPartition*
1111 const PedDisk* disk, PedPartitionType part_type,
1112 const PedFileSystemType* fs_type, PedSector start, PedSector end)
1115 MacPartitionData* mac_data;
1117 part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1121 if (ped_partition_is_active (part)) {
1123 = mac_data = ped_malloc (sizeof (MacPartitionData));
1125 goto error_free_part;
1127 memset (mac_data, 0, sizeof (MacPartitionData));
1129 mac_data->data_region_length = 0;
1130 mac_data->boot_region_length = 0;
1131 mac_data->is_driver = 0;
1132 mac_data->has_driver = 0;
1133 mac_data->is_boot = 0;
1134 mac_data->is_root = 0;
1135 mac_data->is_swap = 0;
1136 mac_data->is_lvm = 0;
1137 mac_data->is_raid = 0;
1139 strcpy (mac_data->volume_name, "untitled");
1141 part->disk_specific = NULL;
1145 error_free_mac_data:
1146 ped_free (mac_data);
1153 static PedPartition*
1154 mac_partition_duplicate (const PedPartition* part)
1156 PedPartition* new_part;
1157 MacPartitionData* new_mac_data;
1158 MacPartitionData* old_mac_data;
1160 new_part = ped_partition_new (part->disk, part->type,
1161 part->fs_type, part->geom.start,
1165 new_part->num = part->num;
1167 old_mac_data = (MacPartitionData*) part->disk_specific;
1168 new_mac_data = (MacPartitionData*) new_part->disk_specific;
1170 /* ugly, but C is ugly :p */
1171 memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
1176 mac_partition_destroy (PedPartition* part)
1178 PED_ASSERT (part != NULL, return);
1180 if (ped_partition_is_active (part))
1181 ped_free (part->disk_specific);
1186 mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1188 MacPartitionData* mac_data = part->disk_specific;
1190 part->fs_type = fs_type;
1192 if (fs_type && !strcmp (fs_type->name, "linux-swap"))
1193 ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1195 if (mac_data->is_boot) {
1196 strcpy (mac_data->system_name, "Apple_Bootstrap");
1197 mac_data->status = 0x33;
1201 if (fs_type && (!strcmp (fs_type->name, "hfs")
1202 || !strcmp (fs_type->name, "hfs+"))) {
1203 strcpy (mac_data->system_name, "Apple_HFS");
1204 mac_data->status |= 0x7f;
1205 } else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
1206 strcpy (mac_data->system_name, "Apple_HFSX");
1207 mac_data->status |= 0x7f;
1209 strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
1210 mac_data->status = 0x33;
1217 mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1219 PedFileSystemType* hfs = ped_file_system_type_get ("hfs");
1220 MacPartitionData* mac_data;
1222 PED_ASSERT (part != NULL, return 0);
1223 PED_ASSERT (part->disk_specific != NULL, return 0);
1225 mac_data = part->disk_specific;
1228 case PED_PARTITION_BOOT:
1229 mac_data->is_boot = state;
1232 return mac_partition_set_system (part, part->fs_type);
1235 strcpy (mac_data->system_name, "Apple_Bootstrap");
1236 mac_data->status = 0x33;
1240 case PED_PARTITION_ROOT:
1242 strcpy (mac_data->volume_name, "root");
1243 mac_data->is_swap = 0;
1245 if (mac_data->is_root)
1246 strcpy (mac_data->volume_name, "untitled");
1248 mac_data->is_root = state;
1251 case PED_PARTITION_SWAP:
1253 strcpy (mac_data->volume_name, "swap");
1254 mac_data->is_root = 0;
1256 if (mac_data->is_swap)
1257 strcpy (mac_data->volume_name, "untitled");
1259 mac_data->is_swap = state;
1262 case PED_PARTITION_LVM:
1263 mac_data->is_lvm = state;
1265 strcpy (mac_data->system_name, "Linux_LVM");
1267 mac_partition_set_system (part, part->fs_type);
1270 case PED_PARTITION_RAID:
1271 mac_data->is_raid = state;
1273 strcpy (mac_data->system_name, "Linux_RAID");
1275 mac_partition_set_system (part, part->fs_type);
1284 mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1286 MacPartitionData* mac_data;
1288 PED_ASSERT (part != NULL, return 0);
1289 PED_ASSERT (part->disk_specific != NULL, return 0);
1291 mac_data = part->disk_specific;
1293 case PED_PARTITION_BOOT:
1294 return mac_data->is_boot;
1296 case PED_PARTITION_ROOT:
1297 return mac_data->is_root;
1299 case PED_PARTITION_SWAP:
1300 return mac_data->is_swap;
1302 case PED_PARTITION_LVM:
1303 return mac_data->is_lvm;
1305 case PED_PARTITION_RAID:
1306 return mac_data->is_raid;
1314 mac_partition_is_flag_available (
1315 const PedPartition* part, PedPartitionFlag flag)
1318 case PED_PARTITION_BOOT:
1319 case PED_PARTITION_ROOT:
1320 case PED_PARTITION_SWAP:
1321 case PED_PARTITION_LVM:
1322 case PED_PARTITION_RAID:
1331 mac_partition_set_name (PedPartition* part, const char* name)
1333 MacPartitionData* mac_data;
1336 PED_ASSERT (part != NULL, return);
1337 PED_ASSERT (part->disk_specific != NULL, return);
1338 mac_data = part->disk_specific;
1340 #ifndef DISCOVER_ONLY
1341 if (mac_data->is_root || mac_data->is_swap) {
1342 if (ped_exception_throw (
1343 PED_EXCEPTION_WARNING,
1344 PED_EXCEPTION_IGNORE_CANCEL,
1345 _("Changing the name of a root or swap partition "
1346 "will prevent Linux from recognising it as such."))
1347 != PED_EXCEPTION_IGNORE)
1349 mac_data->is_root = mac_data->is_swap = 0;
1353 strncpy (mac_data->volume_name, name, 32);
1354 mac_data->volume_name [32] = 0;
1355 for (i = strlen (mac_data->volume_name) - 1;
1356 mac_data->volume_name[i] == ' '; i--)
1357 mac_data->volume_name [i] = 0;
1361 mac_partition_get_name (const PedPartition* part)
1363 MacPartitionData* mac_data;
1365 PED_ASSERT (part != NULL, return NULL);
1366 PED_ASSERT (part->disk_specific != NULL, return NULL);
1367 mac_data = part->disk_specific;
1369 return mac_data->volume_name;
1372 static PedConstraint*
1373 _primary_constraint (PedDisk* disk)
1375 PedAlignment start_align;
1376 PedAlignment end_align;
1377 PedGeometry max_geom;
1378 PedSector sector_size;
1380 sector_size = disk->dev->sector_size / 512;
1382 if (!ped_alignment_init (&start_align, 0, sector_size))
1384 if (!ped_alignment_init (&end_align, -1, sector_size))
1386 if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1389 return ped_constraint_new (&start_align, &end_align, &max_geom,
1390 &max_geom, 1, disk->dev->length);
1394 mac_partition_align (PedPartition* part, const PedConstraint* constraint)
1396 PED_ASSERT (part != NULL, return 0);
1398 if (_ped_partition_attempt_align (part, constraint,
1399 _primary_constraint (part->disk)))
1402 #ifndef DISCOVER_ONLY
1403 ped_exception_throw (
1404 PED_EXCEPTION_ERROR,
1405 PED_EXCEPTION_CANCEL,
1406 _("Unable to satisfy all constraints on the partition."));
1412 mac_partition_enumerate (PedPartition* part)
1415 MacDiskData* mac_disk_data;
1419 PED_ASSERT (part != NULL, return 0);
1420 PED_ASSERT (part->disk != NULL, return 0);
1423 mac_disk_data = (MacDiskData*) disk->disk_specific;
1425 max_part_count = ped_disk_get_max_primary_partition_count (disk);
1427 if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
1430 for (i = 1; i <= max_part_count; i++) {
1431 if (!ped_disk_get_partition (disk, i)) {
1437 #ifndef DISCOVER_ONLY
1438 ped_exception_throw (
1439 PED_EXCEPTION_ERROR,
1440 PED_EXCEPTION_CANCEL,
1441 _("Can't add another partition -- the partition map is too "
1449 _disk_count_partitions (PedDisk* disk)
1451 MacDiskData* mac_disk_data = disk->disk_specific;
1452 PedPartition* part = NULL;
1453 PedPartition* last = NULL;
1455 PED_ASSERT (disk->update_mode, return 0);
1457 mac_disk_data->active_part_entry_count = 0;
1458 mac_disk_data->free_part_entry_count = 0;
1459 mac_disk_data->last_part_entry_num = 0;
1461 /* subtle: we only care about free space after the partition map.
1462 * the partition map is an "active" partition, BTW... */
1463 for (part = ped_disk_next_partition (disk, part); part;
1464 part = ped_disk_next_partition (disk, part)) {
1465 if (!ped_partition_is_active (part))
1468 mac_disk_data->active_part_entry_count++;
1469 if (last && last->geom.end + 1 < part->geom.start)
1470 mac_disk_data->free_part_entry_count++;
1471 mac_disk_data->last_part_entry_num
1472 = PED_MAX (mac_disk_data->last_part_entry_num,
1478 if (last && last->geom.end < disk->dev->length - 1)
1479 mac_disk_data->free_part_entry_count++;
1481 mac_disk_data->last_part_entry_num
1482 = PED_MAX (mac_disk_data->last_part_entry_num,
1483 mac_disk_data->active_part_entry_count
1484 + mac_disk_data->free_part_entry_count);
1489 add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
1491 PedPartition* new_part;
1492 PedConstraint* constraint_any = ped_constraint_any (disk->dev);
1494 PED_ASSERT (disk != NULL, return 0);
1496 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1500 if (!ped_disk_add_partition (disk, new_part, constraint_any))
1501 goto error_destroy_new_part;
1503 ped_constraint_destroy (constraint_any);
1506 error_destroy_new_part:
1507 ped_partition_destroy (new_part);
1509 ped_constraint_destroy (constraint_any);
1514 mac_alloc_metadata (PedDisk* disk)
1516 MacDiskData* mac_disk_data;
1518 PED_ASSERT (disk != NULL, return 0);
1519 PED_ASSERT (disk->disk_specific != NULL, return 0);
1520 PED_ASSERT (disk->dev != NULL, return 0);
1522 mac_disk_data = disk->disk_specific;
1524 if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
1527 /* hack: this seems to be a good place, to update the partition map
1528 * entry count, since mac_alloc_metadata() gets called during
1529 * _disk_pop_update_mode()
1531 return _disk_count_partitions (disk);
1535 mac_get_max_primary_partition_count (const PedDisk* disk)
1537 MacDiskData* mac_disk_data = disk->disk_specific;
1538 PedPartition* part_map_partition;
1540 part_map_partition = ped_disk_get_partition (disk,
1541 mac_disk_data->part_map_entry_num);
1543 /* HACK: if we haven't found the partition map partition (yet),
1546 if (!part_map_partition) {
1547 mac_disk_data->part_map_entry_num = 0;
1551 /* HACK: since Mac labels need an entry for free-space regions, we
1552 * must allow half plus 1 entries for free-space partitions. I hate
1553 * this, but things get REALLY complicated, otherwise.
1554 * (I'm prepared to complicate things later, but I want to get
1555 * everything working, first)
1557 return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
1558 - mac_disk_data->free_part_entry_count + 1;
1561 static PedDiskOps mac_disk_ops = {
1563 #ifndef DISCOVER_ONLY
1564 clobber: mac_clobber,
1569 duplicate: mac_duplicate,
1572 #ifndef DISCOVER_ONLY
1578 partition_new: mac_partition_new,
1579 partition_duplicate: mac_partition_duplicate,
1580 partition_destroy: mac_partition_destroy,
1581 partition_set_system: mac_partition_set_system,
1582 partition_set_flag: mac_partition_set_flag,
1583 partition_get_flag: mac_partition_get_flag,
1584 partition_is_flag_available: mac_partition_is_flag_available,
1585 partition_set_name: mac_partition_set_name,
1586 partition_get_name: mac_partition_get_name,
1587 partition_align: mac_partition_align,
1588 partition_enumerate: mac_partition_enumerate,
1590 alloc_metadata: mac_alloc_metadata,
1591 get_max_primary_partition_count:
1592 mac_get_max_primary_partition_count
1595 static PedDiskType mac_disk_type = {
1599 features: PED_DISK_TYPE_PARTITION_NAME
1603 ped_disk_mac_init ()
1605 PED_ASSERT (sizeof (MacRawPartition) == 512, return);
1606 PED_ASSERT (sizeof (MacRawDisk) == 512, return);
1608 ped_register_disk_type (&mac_disk_type);
1612 ped_disk_mac_done ()
1614 ped_unregister_disk_type (&mac_disk_type);