2
libparted - a library for manipulating disk partitions
3
Copyright (C) 2000, 2002, 2004, 2007-2012 Free Software Foundation, Inc.
5
This program is free software; you can redistribute it and/or modify
6
it under the terms of the GNU General Public License as published by
7
the Free Software Foundation; either version 3 of the License, or
8
(at your option) any later version.
10
This program is distributed in the hope that it will be useful,
11
but WITHOUT ANY WARRANTY; without even the implied warranty of
12
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
GNU General Public License for more details.
15
You should have received a copy of the GNU General Public License
16
along with this program. If not, see <http://www.gnu.org/licenses/>.
21
#include <parted/parted.h>
22
#include <parted/debug.h>
23
#include <parted/endian.h>
28
# define _(String) dgettext (PACKAGE, String)
30
# define _(String) (String)
31
#endif /* ENABLE_NLS */
36
/* struct's hacked from Linux source: fs/partitions/mac.h
37
* I believe it was originally written by Paul Mackerras (from comments in
41
* http://developer.apple.com/documentation/mac/Devices/Devices-126.html
42
* http://developer.apple.com/documentation/mac/Devices/Devices-121.html
43
* http://devworld.apple.com/technotes/tn/tn1189.html
46
* Apple_Bootstrap new-world (HFS) boot partition
47
* Apple_partition_map partition map (table)
48
* Apple_Driver device driver
49
* Apple_Driver43 SCSI Manager 4.3 device driver
50
* Apple_MFS original Macintosh File System
51
* Apple_HFS Hierarchical File System (and +)
52
* Apple_HFSX HFS+ with case sensitivity and more
53
* Apple_UNIX_SVR2 UNIX file system (UFS?)
54
* Apple_PRODOS ProDOS file system
55
* Apple_Free unused space
57
* Apple_Void padding for iso9660
58
* Apple_Extra an unused partition map entry
68
* partition volume or partition
71
* * All space must be accounted for, except block 0 (driver block) and
72
* block 1-X (the partition map: i.e. lots of MacRawPartitions)
74
* * It's really hard to grow/shrink the number of MacRawPartition
75
* entries in the partition map, because the first partition starts
76
* immediately after the partition map. When we can move the start of
77
* HFS and ext2 partitions, this problem will disappear ;-)
80
#define MAC_PARTITION_MAGIC_1 0x5453 /* old */
81
#define MAC_PARTITION_MAGIC_2 0x504d
82
#define MAC_DISK_MAGIC 0x4552
84
#define MAC_STATUS_BOOTABLE 8 /* partition is bootable */
86
typedef struct _MacRawPartition MacRawPartition;
87
typedef struct _MacRawDisk MacRawDisk;
88
typedef struct _MacDeviceDriver MacDeviceDriver;
89
typedef struct _MacPartitionData MacPartitionData;
90
typedef struct _MacDiskData MacDiskData;
92
struct __attribute__ ((packed)) _MacRawPartition {
93
uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */
95
uint32_t map_count; /* # blocks in partition map */
96
uint32_t start_block; /* absolute starting block # of partition */
97
uint32_t block_count; /* number of blocks in partition */
98
char name[32]; /* partition name */
99
char type[32]; /* string type description */
100
uint32_t data_start; /* rel block # of first data block */
101
uint32_t data_count; /* number of data blocks */
102
uint32_t status; /* partition status bits */
108
uint32_t boot_entry2;
110
char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */
115
/* Driver descriptor structure, in block 0 */
116
struct __attribute__ ((packed)) _MacRawDisk {
117
uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */
118
uint16_t block_size; /* physical sector size */
119
uint32_t block_count; /* size of device in blocks */
120
uint16_t dev_type; /* reserved */
121
uint16_t dev_id; /* reserved */
122
uint32_t data; /* reserved */
123
uint16_t driver_count; /* # of driver descriptor entries */
124
uint8_t driverlist[488];/* info about available drivers */
125
uint16_t padding[3]; /* pad to 512 bytes */
128
struct __attribute__ ((packed)) _MacDeviceDriver {
129
uint32_t block; /* startblock in MacRawDisk->block_size units */
130
uint16_t size; /* size in 512 byte units */
131
uint16_t type; /* operating system type (MacOS = 1) */
134
struct _MacPartitionData {
135
char volume_name[33]; /* eg: "Games" */
136
char system_name[33]; /* eg: "Apple_Unix_SVR2" */
137
char processor_name[17];
147
PedSector data_region_length;
148
PedSector boot_region_length;
150
uint32_t boot_base_address;
151
uint32_t boot_entry_address;
152
uint32_t boot_checksum;
158
struct _MacDiskData {
159
int ghost_size; /* sectors per "driver" block */
160
int part_map_entry_count; /* # entries (incl. ghost) */
161
int part_map_entry_num; /* partition map location */
163
int active_part_entry_count; /* # real partitions */
164
int free_part_entry_count; /* # free space */
165
int last_part_entry_num; /* last entry number */
167
uint16_t block_size; /* physical sector size */
168
uint16_t driver_count;
169
MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */
172
static PedDiskType mac_disk_type;
175
_check_signature (MacRawDisk const *raw_disk)
177
if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) {
181
return ped_exception_throw (
183
PED_EXCEPTION_IGNORE_CANCEL,
184
_("Invalid signature %x for Mac disk labels."),
185
(int) PED_BE16_TO_CPU (raw_disk->signature))
186
== PED_EXCEPTION_IGNORE;
194
_rawpart_check_signature (MacRawPartition* raw_part)
196
int sig = (int) PED_BE16_TO_CPU (raw_part->signature);
197
return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2;
201
mac_probe (const PedDevice * dev)
203
PED_ASSERT (dev != NULL);
205
if (dev->sector_size < sizeof (MacRawDisk))
209
if (!ptt_read_sector (dev, 0, &label))
212
int valid = _check_signature (label);
219
_disk_add_part_map_entry (PedDisk* disk, int warn)
221
MacDiskData* mac_disk_data = disk->disk_specific;
222
PedPartition* new_part;
223
MacPartitionData* mac_part_data;
224
PedSector part_map_size;
225
PedConstraint* constraint_any = ped_constraint_any (disk->dev);
227
#ifndef DISCOVER_ONLY
228
if (warn && ped_exception_throw (
230
PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL,
231
_("Partition map has no partition map entry!"))
232
!= PED_EXCEPTION_FIX)
234
#endif /* !DISCOVER_ONLY */
237
= ped_round_up_to (mac_disk_data->last_part_entry_num, 64);
238
if (part_map_size == 0)
241
new_part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
242
1, part_map_size - 1);
246
mac_part_data = new_part->disk_specific;
247
strcpy (mac_part_data->volume_name, "Apple");
248
strcpy (mac_part_data->system_name, "Apple_partition_map");
250
if (!ped_disk_add_partition (disk, new_part, constraint_any))
251
goto error_destroy_new_part;
253
mac_disk_data->part_map_entry_num = new_part->num;
254
mac_disk_data->part_map_entry_count
255
= new_part->geom.end - mac_disk_data->ghost_size;
256
ped_constraint_destroy (constraint_any);
259
error_destroy_new_part:
260
ped_partition_destroy (new_part);
262
ped_constraint_destroy (constraint_any);
267
mac_alloc (const PedDevice* dev)
270
MacDiskData* mac_disk_data;
272
PED_ASSERT (dev != NULL);
274
#ifndef DISCOVER_ONLY
275
if (dev->length < 256) {
276
ped_exception_throw (
278
PED_EXCEPTION_CANCEL,
279
_("%s is too small for a Mac disk label!"),
285
disk = _ped_disk_alloc (dev, &mac_disk_type);
289
mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData));
291
goto error_free_disk;
292
disk->disk_specific = mac_disk_data;
293
mac_disk_data->ghost_size = disk->dev->sector_size / 512;
294
mac_disk_data->active_part_entry_count = 0;
295
mac_disk_data->free_part_entry_count = 1;
296
mac_disk_data->last_part_entry_num = 1;
297
mac_disk_data->block_size = 0;
298
mac_disk_data->driver_count = 0;
299
memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist));
301
if (!_disk_add_part_map_entry (disk, 0))
302
goto error_free_disk;
306
_ped_disk_free (disk);
312
mac_duplicate (const PedDisk* disk)
315
MacDiskData* new_mac_data;
316
MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific;
318
new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type);
322
new_mac_data = (MacDiskData*) new_disk->disk_specific;
324
/* remove the partition map partition - it will be duplicated
327
PedSector first_part_map_sector = old_mac_data->ghost_size;
328
PedPartition *partition_map
329
= ped_disk_get_partition_by_sector (new_disk, first_part_map_sector);
330
PED_ASSERT (partition_map != NULL);
332
/* ped_disk_remove_partition may be used only to delete a "normal"
333
partition. Trying to delete at least "freespace" or "metadata"
334
partitions leads to a violation of assumptions in
335
ped_disk_remove_partition, since it calls _disk_push_update_mode,
336
which destroys all "freespace" and "metadata" partitions, and
337
depends on that destruction not freeing its PART parameter. */
338
PED_ASSERT (partition_map->type == PED_PARTITION_NORMAL);
339
ped_disk_remove_partition (new_disk, partition_map);
341
/* ugly, but C is ugly :p */
342
memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData));
347
mac_free (PedDisk* disk)
349
MacDiskData* mac_disk_data = disk->disk_specific;
351
_ped_disk_free (disk);
352
free (mac_disk_data);
356
_rawpart_cmp_type (const MacRawPartition* raw_part, const char* type)
358
return strncasecmp (raw_part->type, type, 32) == 0;
362
_rawpart_cmp_name (const MacRawPartition* raw_part, const char* name)
364
return strncasecmp (raw_part->name, name, 32) == 0;
368
_rawpart_is_partition_map (const MacRawPartition* raw_part)
370
return _rawpart_cmp_type (raw_part, "Apple_partition_map");
374
strncasestr (const char* haystack, const char* needle, int n)
376
int needle_size = strlen (needle);
379
for (i = 0; haystack[i] && i < n - needle_size; i++) {
380
if (strncasecmp (haystack + i, needle, needle_size) == 0)
388
_rawpart_is_boot (const MacRawPartition* raw_part)
390
if (!strcasecmp(raw_part->type, "Apple_Bootstrap"))
393
if (!strcasecmp(raw_part->type, "Apple_Boot"))
400
_rawpart_is_driver (const MacRawPartition* raw_part)
402
if (strncmp (raw_part->type, "Apple_", 6) != 0)
404
if (!strncasestr (raw_part->type, "driver", 32))
409
static int _GL_ATTRIBUTE_PURE
410
_rawpart_has_driver (const MacRawPartition* raw_part, MacDiskData* mac_disk_data)
412
MacDeviceDriver *driverlist;
414
uint32_t driver_bs, driver_be, part_be;
416
driverlist = &mac_disk_data->driverlist[0];
417
bsz = mac_disk_data->block_size / 512;
418
for (i = 0; i < mac_disk_data->driver_count; i++) {
419
driver_bs = driverlist->block * bsz;
420
driver_be = driver_bs + driverlist->size;
421
part_be = raw_part->start_block + raw_part->block_count;
422
if (driver_bs >= raw_part->start_block && driver_be <= part_be)
430
_rawpart_is_root (MacRawPartition* raw_part)
432
if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
434
if (strcmp (raw_part->name, "root") != 0)
440
_rawpart_is_swap (MacRawPartition* raw_part)
442
if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2"))
444
if (strcmp (raw_part->name, "swap") != 0)
450
_rawpart_is_lvm (MacRawPartition* raw_part)
452
if (strcmp (raw_part->type, "Linux_LVM") != 0)
458
_rawpart_is_raid (MacRawPartition* raw_part)
460
if (strcmp (raw_part->type, "Linux_RAID") != 0)
466
_rawpart_is_void (MacRawPartition* raw_part)
468
return _rawpart_cmp_type (raw_part, "Apple_Void");
471
/* returns 1 if the raw_part represents a partition that is "unused space", or
472
* doesn't represent a partition at all. NOTE: some people make Apple_Free
473
* partitions with MacOS, because they can't select another type. So, if the
474
* name is anything other than "Extra" or "", it is treated as a "real"
478
_rawpart_is_active (MacRawPartition* raw_part)
480
if (_rawpart_cmp_type (raw_part, "Apple_Free")
481
&& (_rawpart_cmp_name (raw_part, "Extra")
482
|| _rawpart_cmp_name (raw_part, "")))
484
if (_rawpart_cmp_type (raw_part, "Apple_Void"))
486
if (_rawpart_cmp_type (raw_part, "Apple_Scratch"))
488
if (_rawpart_cmp_type (raw_part, "Apple_Extra"))
495
_rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num)
497
MacDiskData* mac_disk_data;
499
MacPartitionData* mac_part_data;
500
PedSector block_size;
501
PedSector start, length;
503
if (!_rawpart_check_signature (raw_part)) {
504
#ifndef DISCOVER_ONLY
505
if (ped_exception_throw (
506
PED_EXCEPTION_WARNING,
507
PED_EXCEPTION_IGNORE_CANCEL,
508
_("Partition %d has an invalid signature %x."),
510
(int) PED_BE16_TO_CPU (raw_part->signature))
511
!= PED_EXCEPTION_IGNORE)
516
mac_disk_data = (MacDiskData*) disk->disk_specific;
517
block_size = disk->dev->sector_size / 512;
519
start = PED_BE32_TO_CPU (raw_part->start_block) * block_size;
520
length = PED_BE32_TO_CPU (raw_part->block_count) * block_size;
522
#ifndef DISCOVER_ONLY
523
ped_exception_throw (
525
PED_EXCEPTION_CANCEL,
526
_("Partition %d has an invalid length of 0 bytes!"),
531
part = ped_partition_new (disk, PED_PARTITION_NORMAL, NULL,
532
start, start + length - 1);
536
mac_part_data = part->disk_specific;
538
strncpy (mac_part_data->volume_name, raw_part->name, 32);
539
strncpy (mac_part_data->system_name, raw_part->type, 32);
540
strncpy (mac_part_data->processor_name, raw_part->processor, 16);
542
mac_part_data->is_boot = _rawpart_is_boot (raw_part);
543
mac_part_data->is_driver = _rawpart_is_driver (raw_part);
544
if (mac_part_data->is_driver)
545
mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data);
546
mac_part_data->is_root = _rawpart_is_root (raw_part);
547
mac_part_data->is_swap = _rawpart_is_swap (raw_part);
548
mac_part_data->is_lvm = _rawpart_is_lvm (raw_part);
549
mac_part_data->is_raid = _rawpart_is_raid (raw_part);
552
#ifndef DISCOVER_ONLY
553
if (raw_part->data_start) {
554
ped_exception_throw (
556
PED_EXCEPTION_CANCEL,
557
_("The data region doesn't start at the start "
558
"of the partition."));
559
goto error_destroy_part;
561
#endif /* !DISCOVER_ONLY */
562
mac_part_data->data_region_length
563
= PED_BE32_TO_CPU (raw_part->data_count) * block_size;
565
/* boot region - we have no idea what this is for, but Mac OSX
566
* seems to put garbage here, and doesn't pay any attention to
567
* it afterwards. [clausen, dan burcaw]
570
if (raw_part->boot_start) {
571
ped_exception_throw (
573
PED_EXCEPTION_CANCEL,
574
_("The boot region doesn't start at the start "
575
"of the partition."));
576
goto error_destroy_part;
579
mac_part_data->boot_region_length
580
= PED_BE32_TO_CPU (raw_part->boot_count) * block_size;
582
#ifndef DISCOVER_ONLY
583
if (mac_part_data->has_driver) {
584
if (mac_part_data->boot_region_length < part->geom.length) {
585
if (ped_exception_throw (
587
PED_EXCEPTION_IGNORE_CANCEL,
588
_("The partition's boot region doesn't occupy "
589
"the entire partition."))
590
!= PED_EXCEPTION_IGNORE)
591
goto error_destroy_part;
594
if (mac_part_data->data_region_length < part->geom.length &&
595
!mac_part_data->is_boot) {
596
if (ped_exception_throw (
598
PED_EXCEPTION_IGNORE_CANCEL,
599
_("The partition's data region doesn't occupy "
600
"the entire partition."))
601
!= PED_EXCEPTION_IGNORE)
602
goto error_destroy_part;
605
#endif /* !DISCOVER_ONLY */
607
mac_part_data->boot_base_address
608
= PED_BE32_TO_CPU (raw_part->boot_load);
609
mac_part_data->boot_entry_address
610
= PED_BE32_TO_CPU (raw_part->boot_entry);
611
mac_part_data->boot_checksum
612
= PED_BE32_TO_CPU (raw_part->boot_cksum);
614
mac_part_data->status = PED_BE32_TO_CPU (raw_part->status);
615
mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig);
620
ped_partition_destroy (part);
625
/* looks at the partition map size field in a mac raw partition, and calculates
626
* what the size of the partition map should be, from it
629
_rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk)
631
MacDiskData* mac_disk_data = disk->disk_specific;
632
PedSector sector_size = disk->dev->sector_size / 512;
633
PedSector part_map_start;
634
PedSector part_map_end;
636
part_map_start = mac_disk_data->ghost_size;
637
part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count);
639
return part_map_end - part_map_start + 1;
643
_disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk)
645
PedSector block_size;
647
if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) {
648
#ifndef DISCOVER_ONLY
649
ped_exception_throw (
651
PED_EXCEPTION_CANCEL,
652
_("Weird block size on device descriptor: %d bytes is "
653
"not divisible by 512."),
654
(int) PED_BE16_TO_CPU (raw_disk->block_size));
659
block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512;
660
if (block_size != disk->dev->sector_size / 512) {
661
#ifndef DISCOVER_ONLY
662
if (ped_exception_throw (
663
PED_EXCEPTION_WARNING,
664
PED_EXCEPTION_IGNORE_CANCEL,
665
_("The driver descriptor says the physical block size "
666
"is %d bytes, but Linux says it is %d bytes."),
667
(int) block_size * 512,
668
(int) disk->dev->sector_size)
669
!= PED_EXCEPTION_IGNORE)
672
disk->dev->sector_size = block_size * 512;
681
/* Tries to figure out the block size used by the drivers, for the ghost
682
* partitioning scheme. Ghost partitioning works like this: the OpenFirmware
683
* (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and,
684
* perhaps, some other number?). To remain compatible, the partition map
685
* only has "real" partition map entries on ghost-aligned block numbers (and
686
* the others are padded with Apple_Void partitions). This function tries
687
* to figure out what the "ghost-aligned" size is... (which, believe-it-or-not,
688
* doesn't always equal 2048!!!)
691
_disk_analyse_ghost_size (PedDisk* disk)
693
MacDiskData* mac_disk_data = disk->disk_specific;
695
void *buf = ped_malloc (disk->dev->sector_size);
701
for (i = 1; i < 64; i *= 2) {
702
if (!ped_device_read (disk->dev, buf, i, 1))
704
if (_rawpart_check_signature (buf)
705
&& !_rawpart_is_void (buf)) {
706
mac_disk_data->ghost_size = i;
707
found = (i <= disk->dev->sector_size / 512);
713
#ifndef DISCOVER_ONLY
715
ped_exception_throw (
717
PED_EXCEPTION_CANCEL,
718
_("No valid partition map found."));
724
mac_read (PedDisk* disk)
726
MacDiskData* mac_disk_data;
729
PedSector ghost_size;
730
int last_part_entry_num = 0;
732
PED_ASSERT (disk != NULL);
734
mac_disk_data = disk->disk_specific;
735
mac_disk_data->part_map_entry_num = 0; /* 0 == none */
738
if (!ptt_read_sector (disk->dev, 0, &buf))
741
MacRawDisk *raw_disk = (MacRawDisk *) buf;
743
if (!_check_signature (raw_disk))
746
if (!_disk_analyse_block_size (disk, raw_disk))
748
if (!_disk_analyse_ghost_size (disk))
750
ghost_size = mac_disk_data->ghost_size;
752
if (!ped_disk_delete_all (disk))
755
if (raw_disk->driver_count && raw_disk->driver_count < 62) {
756
memcpy(&mac_disk_data->driverlist[0], &raw_disk->driverlist[0],
757
sizeof(mac_disk_data->driverlist));
758
mac_disk_data->driver_count = raw_disk->driver_count;
759
mac_disk_data->block_size = raw_disk->block_size;
762
for (num=1; num==1 || num <= last_part_entry_num; num++) {
763
void *raw_part = buf;
764
if (!ped_device_read (disk->dev, raw_part,
765
num * ghost_size, 1))
766
goto error_delete_all;
768
if (!_rawpart_check_signature (raw_part))
773
= _rawpart_get_partmap_size (raw_part, disk);
774
if (_rawpart_get_partmap_size (raw_part, disk)
775
!= last_part_entry_num) {
776
if (ped_exception_throw (
778
PED_EXCEPTION_IGNORE_CANCEL,
779
_("Conflicting partition map entry sizes! "
780
"Entry 1 says it is %d, but entry %d says "
783
_rawpart_get_partmap_size (raw_part, disk))
784
!= PED_EXCEPTION_IGNORE)
785
goto error_delete_all;
788
if (!_rawpart_is_active (raw_part))
791
part = _rawpart_analyse (raw_part, disk, num);
793
goto error_delete_all;
795
part->fs_type = ped_file_system_probe (&part->geom);
796
PedConstraint *constraint_exact
797
= ped_constraint_exact (&part->geom);
798
if (constraint_exact == NULL)
799
goto error_delete_all;
800
bool ok = ped_disk_add_partition (disk, part, constraint_exact);
801
ped_constraint_destroy (constraint_exact);
803
goto error_delete_all;
805
if (_rawpart_is_partition_map (raw_part)) {
806
if (mac_disk_data->part_map_entry_num
807
&& ped_exception_throw (
809
PED_EXCEPTION_IGNORE_CANCEL,
810
_("Weird! There are 2 partitions "
812
!= PED_EXCEPTION_IGNORE)
813
goto error_delete_all;
815
mac_disk_data->part_map_entry_num = num;
816
mac_disk_data->part_map_entry_count
817
= part->geom.end - ghost_size + 1;
821
if (!mac_disk_data->part_map_entry_num) {
822
if (!_disk_add_part_map_entry (disk, 1))
823
goto error_delete_all;
824
ped_disk_commit_to_dev (disk);
830
ped_disk_delete_all (disk);
836
#ifndef DISCOVER_ONLY
837
/* The Ghost partition: is a blank entry, used to pad out each block (where
838
* there physical block size > 512 bytes). This is because OpenFirmware uses
839
* 512 byte blocks, but device drivers Think Different TM, with a different
840
* lbock size, so we need to do this to avoid a clash (!)
843
_pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map)
845
MacDiskData* mac_disk_data = disk->disk_specific;
848
size_t ss = disk->dev->sector_size;
849
void *buf = ped_calloc (ss);
853
MacRawPartition *ghost_entry = buf;
854
ghost_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
855
strcpy (ghost_entry->type, "Apple_Void");
856
ghost_entry->map_count
857
= PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
859
for (i=0; i < mac_disk_data->ghost_size - 1; i++) {
860
PedSector idx = i + (num - 1) * mac_disk_data->ghost_size;
861
memcpy ((char*)part_map + idx * ss, ghost_entry, ss);
869
_update_driver_count (MacRawPartition* part_map_entry,
870
MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data)
872
uint16_t i, count_orig, count_cur, bsz;
873
uint32_t driver_bs, driver_be, part_be;
875
bsz = mac_disk_data->block_size / 512;
876
count_cur = mac_driverdata->driver_count;
877
count_orig = mac_disk_data->driver_count;
878
for (i = 0; i < count_orig; i++) {
879
driver_bs = mac_disk_data->driverlist[i].block * bsz;
880
driver_be = driver_bs + mac_disk_data->driverlist[i].size;
881
part_be = part_map_entry->start_block + part_map_entry->block_count;
882
if (driver_bs >= part_map_entry->start_block
883
&& driver_be <= part_be) {
884
mac_driverdata->driverlist[count_cur].block
885
= mac_disk_data->driverlist[i].block;
886
mac_driverdata->driverlist[count_cur].size
887
= mac_disk_data->driverlist[i].size;
888
mac_driverdata->driverlist[count_cur].type
889
= mac_disk_data->driverlist[i].type;
890
mac_driverdata->driver_count++;
896
static MacRawPartition *
897
get_pme (MacRawPartition const *part_map, PedSector i, PedDisk const *disk)
899
MacDiskData const *mac_disk_data = disk->disk_specific;
900
PedSector idx = i * mac_disk_data->ghost_size - 1;
901
return (MacRawPartition *) ((char*)part_map
902
+ idx * disk->dev->sector_size);
905
/* Initialize the disk->dev->sector_size bytes of part_map[part->num]. */
907
_generate_raw_part (PedDisk* disk, PedPartition* part,
908
MacRawPartition* part_map, MacDiskData *mac_driverdata)
910
MacDiskData* mac_disk_data;
911
MacPartitionData* mac_part_data;
912
PedSector block_size = disk->dev->sector_size / 512;
914
PED_ASSERT (part->num > 0);
916
mac_disk_data = disk->disk_specific;
917
mac_part_data = part->disk_specific;
919
MacRawPartition *part_map_entry = get_pme (part_map, part->num, disk);
920
memset (part_map_entry, 0, disk->dev->sector_size);
922
part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
923
part_map_entry->map_count
924
= PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
925
part_map_entry->start_block
926
= PED_CPU_TO_BE32 (part->geom.start / block_size);
927
part_map_entry->block_count
928
= PED_CPU_TO_BE32 (part->geom.length / block_size);
929
strcpy (part_map_entry->name, mac_part_data->volume_name);
930
strcpy (part_map_entry->type, mac_part_data->system_name);
932
if (mac_part_data->is_driver) {
933
mac_part_data->boot_region_length = part->geom.length;
934
if (mac_part_data->has_driver)
935
_update_driver_count(part_map_entry, mac_driverdata,
938
mac_part_data->data_region_length = part->geom.length;
939
part_map_entry->data_count = PED_CPU_TO_BE32 (
940
mac_part_data->data_region_length / block_size);
941
part_map_entry->boot_count = PED_CPU_TO_BE32 (
942
mac_part_data->boot_region_length / block_size);
943
part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status);
944
part_map_entry->driver_sig
945
= PED_CPU_TO_BE32 (mac_part_data->driver_sig);
947
part_map_entry->boot_load =
948
PED_CPU_TO_BE32 (mac_part_data->boot_base_address);
949
part_map_entry->boot_entry =
950
PED_CPU_TO_BE32 (mac_part_data->boot_entry_address);
951
part_map_entry->boot_cksum =
952
PED_CPU_TO_BE32 (mac_part_data->boot_checksum);
954
strncpy (part_map_entry->processor, mac_part_data->processor_name, 16);
956
if (!_pad_raw_part (disk, part->num, part_map))
966
_generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num,
967
MacRawPartition* part_map)
969
MacDiskData* mac_disk_data = disk->disk_specific;
970
PedSector block_size = disk->dev->sector_size / 512;
972
PED_ASSERT (num > 0);
974
MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
976
part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2);
977
part_map_entry->map_count
978
= PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num);
979
part_map_entry->start_block
980
= PED_CPU_TO_BE32 (geom->start / block_size);
981
part_map_entry->block_count
982
= PED_CPU_TO_BE32 (geom->length / block_size);
983
strcpy (part_map_entry->name, "Extra");
984
strcpy (part_map_entry->type, "Apple_Free");
986
part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length);
987
part_map_entry->status = 0;
988
part_map_entry->driver_sig = 0;
990
if (!_pad_raw_part (disk, num, part_map))
1000
_generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map)
1002
MacDiskData* mac_disk_data = disk->disk_specific;
1004
PED_ASSERT (num > 0);
1006
MacRawPartition *part_map_entry = get_pme (part_map, num, disk);
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 */
1016
static int _GL_ATTRIBUTE_PURE
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
MacRawPartition *part_map_entry = get_pme (part_map, i, disk);
1024
if (!part_map_entry->signature)
1032
write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata)
1034
PedDevice* dev = disk->dev;
1036
if (!ptt_read_sector (dev, 0, &s0))
1038
MacRawDisk *raw_disk = (MacRawDisk *) s0;
1040
raw_disk->signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC);
1041
raw_disk->block_size = PED_CPU_TO_BE16 (dev->sector_size);
1042
raw_disk->block_count
1043
= PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512));
1045
raw_disk->driver_count = mac_driverdata->driver_count;
1046
memcpy(&raw_disk->driverlist[0], &mac_driverdata->driverlist[0],
1047
sizeof(raw_disk->driverlist));
1049
int write_ok = ped_device_write (dev, raw_disk, 0, 1);
1055
mac_write (PedDisk* disk)
1057
MacRawPartition* part_map;
1058
MacDiskData* mac_disk_data;
1059
MacDiskData* mac_driverdata; /* updated driver list */
1063
PED_ASSERT (disk != NULL);
1064
PED_ASSERT (disk->disk_specific != NULL);
1065
PED_ASSERT (disk->dev != NULL);
1066
PED_ASSERT (!disk->update_mode);
1068
mac_disk_data = disk->disk_specific;
1070
if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) {
1071
if (!_disk_add_part_map_entry (disk, 1))
1075
mac_driverdata = ped_malloc(sizeof(MacDiskData));
1076
if (!mac_driverdata)
1078
memset (mac_driverdata, 0, sizeof(MacDiskData));
1080
size_t pmap_bytes = (mac_disk_data->part_map_entry_count
1081
* mac_disk_data->ghost_size
1082
* disk->dev->sector_size);
1083
part_map = (MacRawPartition*) ped_calloc (pmap_bytes);
1085
goto error_free_driverdata;
1087
/* write (to memory) the "real" partitions */
1088
for (part = ped_disk_next_partition (disk, NULL); part;
1089
part = ped_disk_next_partition (disk, part)) {
1090
if (!ped_partition_is_active (part))
1092
if (!_generate_raw_part (disk, part, part_map, mac_driverdata))
1093
goto error_free_part_map;
1096
/* write the "free space" partitions */
1097
for (part = ped_disk_next_partition (disk, NULL); part;
1098
part = ped_disk_next_partition (disk, part)) {
1099
if (part->type != PED_PARTITION_FREESPACE)
1101
num = _get_first_empty_part_entry (disk, part_map);
1102
if (!_generate_raw_freespace_part (disk, &part->geom, num,
1104
goto error_free_part_map;
1107
/* write the "void" (empty) partitions */
1108
for (num = _get_first_empty_part_entry (disk, part_map); num;
1109
num = _get_first_empty_part_entry (disk, part_map))
1110
_generate_empty_part (disk, num, part_map);
1113
if (!ped_device_write (disk->dev, part_map, 1,
1114
mac_disk_data->part_map_entry_count))
1115
goto error_free_part_map;
1117
int write_ok = write_block_zero (disk, mac_driverdata);
1118
free (mac_driverdata);
1121
error_free_part_map:
1123
error_free_driverdata:
1124
free (mac_driverdata);
1128
#endif /* !DISCOVER_ONLY */
1130
static PedPartition*
1132
const PedDisk* disk, PedPartitionType part_type,
1133
const PedFileSystemType* fs_type, PedSector start, PedSector end)
1136
MacPartitionData* mac_data;
1138
part = _ped_partition_alloc (disk, part_type, fs_type, start, end);
1142
if (ped_partition_is_active (part)) {
1144
= mac_data = ped_malloc (sizeof (MacPartitionData));
1146
goto error_free_part;
1148
memset (mac_data, 0, sizeof (MacPartitionData));
1149
strcpy (mac_data->volume_name, "untitled");
1151
part->disk_specific = NULL;
1161
static PedPartition*
1162
mac_partition_duplicate (const PedPartition* part)
1164
PedPartition* new_part;
1165
MacPartitionData* new_mac_data;
1166
MacPartitionData* old_mac_data;
1168
new_part = ped_partition_new (part->disk, part->type,
1169
part->fs_type, part->geom.start,
1173
new_part->num = part->num;
1175
old_mac_data = (MacPartitionData*) part->disk_specific;
1176
new_mac_data = (MacPartitionData*) new_part->disk_specific;
1178
/* ugly, but C is ugly :p */
1179
memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData));
1184
mac_partition_destroy (PedPartition* part)
1186
PED_ASSERT (part != NULL);
1188
if (ped_partition_is_active (part))
1189
free (part->disk_specific);
1194
mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
1196
MacPartitionData* mac_data = part->disk_specific;
1198
part->fs_type = fs_type;
1200
if (fs_type && is_linux_swap (fs_type->name))
1201
ped_partition_set_flag (part, PED_PARTITION_SWAP, 1);
1203
if (mac_data->is_boot) {
1204
strcpy (mac_data->system_name, "Apple_Bootstrap");
1205
mac_data->status = 0x33;
1209
if (fs_type && (!strcmp (fs_type->name, "hfs")
1210
|| !strcmp (fs_type->name, "hfs+"))) {
1211
strcpy (mac_data->system_name, "Apple_HFS");
1212
mac_data->status |= 0x7f;
1213
} else if (fs_type && !strcmp (fs_type->name, "hfsx")) {
1214
strcpy (mac_data->system_name, "Apple_HFSX");
1215
mac_data->status |= 0x7f;
1217
strcpy (mac_data->system_name, "Apple_UNIX_SVR2");
1218
mac_data->status = 0x33;
1225
mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
1227
MacPartitionData* mac_data;
1229
PED_ASSERT (part != NULL);
1230
PED_ASSERT (part->disk_specific != NULL);
1232
mac_data = part->disk_specific;
1235
case PED_PARTITION_BOOT:
1236
mac_data->is_boot = state;
1239
return mac_partition_set_system (part, part->fs_type);
1242
strcpy (mac_data->system_name, "Apple_Bootstrap");
1243
mac_data->status = 0x33;
1247
case PED_PARTITION_ROOT:
1249
strcpy (mac_data->volume_name, "root");
1250
mac_data->is_swap = 0;
1252
if (mac_data->is_root)
1253
strcpy (mac_data->volume_name, "untitled");
1255
mac_data->is_root = state;
1258
case PED_PARTITION_SWAP:
1260
strcpy (mac_data->volume_name, "swap");
1261
mac_data->is_root = 0;
1263
if (mac_data->is_swap)
1264
strcpy (mac_data->volume_name, "untitled");
1266
mac_data->is_swap = state;
1269
case PED_PARTITION_LVM:
1271
strcpy (mac_data->system_name, "Linux_LVM");
1272
mac_data->is_lvm = state;
1274
if (mac_data->is_lvm)
1275
mac_partition_set_system (part, part->fs_type);
1279
case PED_PARTITION_RAID:
1281
strcpy (mac_data->system_name, "Linux_RAID");
1282
mac_data->is_raid = state;
1284
if (mac_data->is_raid)
1285
mac_partition_set_system (part, part->fs_type);
1294
static int _GL_ATTRIBUTE_PURE
1295
mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
1297
MacPartitionData* mac_data;
1299
PED_ASSERT (part != NULL);
1300
PED_ASSERT (part->disk_specific != NULL);
1302
mac_data = part->disk_specific;
1304
case PED_PARTITION_BOOT:
1305
return mac_data->is_boot;
1307
case PED_PARTITION_ROOT:
1308
return mac_data->is_root;
1310
case PED_PARTITION_SWAP:
1311
return mac_data->is_swap;
1313
case PED_PARTITION_LVM:
1314
return mac_data->is_lvm;
1316
case PED_PARTITION_RAID:
1317
return mac_data->is_raid;
1325
mac_partition_is_flag_available (
1326
const PedPartition* part, PedPartitionFlag flag)
1329
case PED_PARTITION_BOOT:
1330
case PED_PARTITION_ROOT:
1331
case PED_PARTITION_SWAP:
1332
case PED_PARTITION_LVM:
1333
case PED_PARTITION_RAID:
1342
mac_partition_set_name (PedPartition* part, const char* name)
1344
MacPartitionData* mac_data;
1347
PED_ASSERT (part != NULL);
1348
PED_ASSERT (part->disk_specific != NULL);
1349
mac_data = part->disk_specific;
1351
#ifndef DISCOVER_ONLY
1352
if (mac_data->is_root || mac_data->is_swap) {
1353
if (ped_exception_throw (
1354
PED_EXCEPTION_WARNING,
1355
PED_EXCEPTION_IGNORE_CANCEL,
1356
_("Changing the name of a root or swap partition "
1357
"will prevent Linux from recognising it as such."))
1358
!= PED_EXCEPTION_IGNORE)
1360
mac_data->is_root = mac_data->is_swap = 0;
1364
strncpy (mac_data->volume_name, name, 32);
1365
mac_data->volume_name [32] = 0;
1366
for (i = strlen (mac_data->volume_name) - 1;
1367
mac_data->volume_name[i] == ' '; i--)
1368
mac_data->volume_name [i] = 0;
1371
static const char* _GL_ATTRIBUTE_PURE
1372
mac_partition_get_name (const PedPartition* part)
1374
MacPartitionData* mac_data;
1376
PED_ASSERT (part != NULL);
1377
PED_ASSERT (part->disk_specific != NULL);
1378
mac_data = part->disk_specific;
1380
return mac_data->volume_name;
1383
static PedAlignment*
1384
mac_get_partition_alignment(const PedDisk *disk)
1386
PedSector sector_size = disk->dev->sector_size / 512;
1388
return ped_alignment_new(0, sector_size);
1391
static PedConstraint*
1392
_primary_constraint (PedDisk* disk)
1394
PedAlignment start_align;
1395
PedAlignment end_align;
1396
PedGeometry max_geom;
1397
PedSector sector_size;
1399
sector_size = disk->dev->sector_size / 512;
1401
if (!ped_alignment_init (&start_align, 0, sector_size))
1403
if (!ped_alignment_init (&end_align, -1, sector_size))
1405
if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1))
1408
return ped_constraint_new (&start_align, &end_align, &max_geom,
1409
&max_geom, 1, disk->dev->length);
1413
mac_partition_align (PedPartition* part, const PedConstraint* constraint)
1415
PED_ASSERT (part != NULL);
1417
if (_ped_partition_attempt_align (part, constraint,
1418
_primary_constraint (part->disk)))
1421
#ifndef DISCOVER_ONLY
1422
ped_exception_throw (
1423
PED_EXCEPTION_ERROR,
1424
PED_EXCEPTION_CANCEL,
1425
_("Unable to satisfy all constraints on the partition."));
1431
mac_partition_enumerate (PedPartition* part)
1434
MacDiskData* mac_disk_data;
1438
PED_ASSERT (part != NULL);
1439
PED_ASSERT (part->disk != NULL);
1442
mac_disk_data = (MacDiskData*) disk->disk_specific;
1444
max_part_count = ped_disk_get_max_primary_partition_count (disk);
1446
if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count)
1449
for (i = 1; i <= max_part_count; i++) {
1450
if (!ped_disk_get_partition (disk, i)) {
1456
#ifndef DISCOVER_ONLY
1457
ped_exception_throw (
1458
PED_EXCEPTION_ERROR,
1459
PED_EXCEPTION_CANCEL,
1460
_("Can't add another partition -- the partition map is too "
1468
_disk_count_partitions (PedDisk* disk)
1470
MacDiskData* mac_disk_data = disk->disk_specific;
1471
PedPartition* part = NULL;
1472
PedPartition* last = NULL;
1474
PED_ASSERT (disk->update_mode);
1476
mac_disk_data->active_part_entry_count = 0;
1477
mac_disk_data->free_part_entry_count = 0;
1478
mac_disk_data->last_part_entry_num = 0;
1480
/* subtle: we only care about free space after the partition map.
1481
* the partition map is an "active" partition, BTW... */
1482
for (part = ped_disk_next_partition (disk, part); part;
1483
part = ped_disk_next_partition (disk, part)) {
1484
if (!ped_partition_is_active (part))
1487
mac_disk_data->active_part_entry_count++;
1488
if (last && last->geom.end + 1 < part->geom.start)
1489
mac_disk_data->free_part_entry_count++;
1490
mac_disk_data->last_part_entry_num
1491
= PED_MAX (mac_disk_data->last_part_entry_num,
1497
if (last && last->geom.end < disk->dev->length - 1)
1498
mac_disk_data->free_part_entry_count++;
1500
mac_disk_data->last_part_entry_num
1501
= PED_MAX (mac_disk_data->last_part_entry_num,
1502
mac_disk_data->active_part_entry_count
1503
+ mac_disk_data->free_part_entry_count);
1508
add_metadata_part (PedDisk* disk, PedSector start, PedSector end)
1510
PedPartition* new_part;
1511
PedConstraint* constraint_any = ped_constraint_any (disk->dev);
1513
PED_ASSERT (disk != NULL);
1515
new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL,
1519
if (!ped_disk_add_partition (disk, new_part, constraint_any))
1520
goto error_destroy_new_part;
1522
ped_constraint_destroy (constraint_any);
1525
error_destroy_new_part:
1526
ped_partition_destroy (new_part);
1528
ped_constraint_destroy (constraint_any);
1533
mac_alloc_metadata (PedDisk* disk)
1535
PED_ASSERT (disk != NULL);
1536
PED_ASSERT (disk->disk_specific != NULL);
1537
PED_ASSERT (disk->dev != NULL);
1539
if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1))
1542
/* hack: this seems to be a good place, to update the partition map
1543
* entry count, since mac_alloc_metadata() gets called during
1544
* _disk_pop_update_mode()
1546
return _disk_count_partitions (disk);
1550
mac_get_max_primary_partition_count (const PedDisk* disk)
1552
MacDiskData* mac_disk_data = disk->disk_specific;
1553
PedPartition* part_map_partition;
1555
part_map_partition = ped_disk_get_partition (disk,
1556
mac_disk_data->part_map_entry_num);
1558
/* HACK: if we haven't found the partition map partition (yet),
1561
if (!part_map_partition) {
1562
mac_disk_data->part_map_entry_num = 0;
1566
/* HACK: since Mac labels need an entry for free-space regions, we
1567
* must allow half plus 1 entries for free-space partitions. I hate
1568
* this, but things get REALLY complicated, otherwise.
1569
* (I'm prepared to complicate things later, but I want to get
1570
* everything working, first)
1572
return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size
1573
- mac_disk_data->free_part_entry_count + 1;
1577
mac_get_max_supported_partition_count (const PedDisk* disk, int *max_n)
1583
#include "pt-common.h"
1584
PT_define_limit_functions (mac)
1586
static PedDiskOps mac_disk_ops = {
1588
/* FIXME: remove this cast, once mac_write is fixed not to
1589
modify its *DISK parameter. */
1590
write: NULL_IF_DISCOVER_ONLY ((int (*) (const PedDisk*)) mac_write),
1592
partition_set_name: mac_partition_set_name,
1593
partition_get_name: mac_partition_get_name,
1595
get_partition_alignment: mac_get_partition_alignment,
1597
PT_op_function_initializers (mac)
1600
static PedDiskType mac_disk_type = {
1604
features: PED_DISK_TYPE_PARTITION_NAME
1608
ped_disk_mac_init ()
1610
PED_ASSERT (sizeof (MacRawPartition) == 512);
1611
PED_ASSERT (sizeof (MacRawDisk) == 512);
1613
ped_disk_type_register (&mac_disk_type);
1617
ped_disk_mac_done ()
1619
ped_disk_type_unregister (&mac_disk_type);