1 /* 2 libparted - a library for manipulating disk partitions 3 Copyright (C) 2000, 2002, 2004, 2007 Free Software Foundation, Inc. 4 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. 9 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. 14 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/>. 17 */ 18 19 #include <config.h> 20 21 #include <parted/parted.h> 22 #include <parted/debug.h> 23 #include <parted/endian.h> 24 25 #if ENABLE_NLS 26 # include <libintl.h> 27 # define _(String) dgettext (PACKAGE, String) 28 #else 29 # define _(String) (String) 30 #endif /* ENABLE_NLS */ 31 32 /* struct's hacked from Linux source: fs/partitions/mac.h 33 * I believe it was originally written by Paul Mackerras (from comments in 34 * Quik source) 35 * 36 * See also: 37 * http://developer.apple.com/documentation/mac/Devices/Devices-126.html 38 * http://developer.apple.com/documentation/mac/Devices/Devices-121.html 39 * http://devworld.apple.com/technotes/tn/tn1189.html 40 * 41 * Partition types: 42 * Apple_Bootstrap new-world (HFS) boot partition 43 * Apple_partition_map partition map (table) 44 * Apple_Driver device driver 45 * Apple_Driver43 SCSI Manager 4.3 device driver 46 * Apple_MFS original Macintosh File System 47 * Apple_HFS Hierarchical File System (and +) 48 * Apple_HFSX HFS+ with case sensitivity and more 49 * Apple_UNIX_SVR2 UNIX file system (UFS?) 50 * Apple_PRODOS ProDOS file system 51 * Apple_Free unused space 52 * Apple_Scratch empty 53 * Apple_Void padding for iso9660 54 * Apple_Extra an unused partition map entry 55 * 56 * Quick explanation: 57 * ------------------ 58 * Terminology: 59 * 60 * Parted Apple 61 * ------ ----- 62 * device disk/device 63 * disk no equivalent. 64 * partition volume or partition 65 * sector block 66 * 67 * * All space must be accounted for, except block 0 (driver block) and 68 * block 1-X (the partition map: i.e. lots of MacRawPartitions) 69 * 70 * * It's really hard to grow/shrink the number of MacRawPartition 71 * entries in the partition map, because the first partition starts 72 * immediately after the partition map. When we can move the start of 73 * HFS and ext2 partitions, this problem will disappear ;-) 74 */ 75 76 #define MAC_PARTITION_MAGIC_1 0x5453 /* old */ 77 #define MAC_PARTITION_MAGIC_2 0x504d 78 #define MAC_DISK_MAGIC 0x4552 79 80 #define MAC_STATUS_BOOTABLE 8 /* partition is bootable */ 81 82 typedef struct _MacRawPartition MacRawPartition; 83 typedef struct _MacRawDisk MacRawDisk; 84 typedef struct _MacDeviceDriver MacDeviceDriver; 85 typedef struct _MacPartitionData MacPartitionData; 86 typedef struct _MacDiskData MacDiskData; 87 88 #ifdef __sun 89 #define __attribute__(X) /*nothing*/ 90 #endif /* __sun */ 91 92 #ifdef __sun 93 #pragma pack(1) 94 #endif 95 struct __attribute__ ((packed)) _MacRawPartition { 96 uint16_t signature; /* expected to be MAC_PARTITION_MAGIC */ 97 uint16_t res1; 98 uint32_t map_count; /* # blocks in partition map */ 99 uint32_t start_block; /* absolute starting block # of partition */ 100 uint32_t block_count; /* number of blocks in partition */ 101 char name[32]; /* partition name */ 102 char type[32]; /* string type description */ 103 uint32_t data_start; /* rel block # of first data block */ 104 uint32_t data_count; /* number of data blocks */ 105 uint32_t status; /* partition status bits */ 106 uint32_t boot_start; 107 uint32_t boot_count; 108 uint32_t boot_load; 109 uint32_t boot_load2; 110 uint32_t boot_entry; 111 uint32_t boot_entry2; 112 uint32_t boot_cksum; 113 char processor[16]; /* Contains 680x0, x=0,2,3,4; or empty */ 114 uint32_t driver_sig; 115 char _padding[372]; 116 }; 117 118 /* Driver descriptor structure, in block 0 */ 119 struct __attribute__ ((packed)) _MacRawDisk { 120 uint16_t signature; /* expected to be MAC_DRIVER_MAGIC */ 121 uint16_t block_size; /* physical sector size */ 122 uint32_t block_count; /* size of device in blocks */ 123 uint16_t dev_type; /* reserved */ 124 uint16_t dev_id; /* reserved */ 125 uint32_t data; /* reserved */ 126 uint16_t driver_count; /* # of driver descriptor entries */ 127 uint8_t driverlist[488];/* info about available drivers */ 128 uint16_t padding[3]; /* pad to 512 bytes */ 129 }; 130 131 struct __attribute__ ((packed)) _MacDeviceDriver { 132 uint32_t block; /* startblock in MacRawDisk->block_size units */ 133 uint16_t size; /* size in 512 byte units */ 134 uint16_t type; /* operating system type (MacOS = 1) */ 135 }; 136 #ifdef __sun 137 #pragma pack() 138 #endif 139 140 struct _MacPartitionData { 141 char volume_name[33]; /* eg: "Games" */ 142 char system_name[33]; /* eg: "Apple_Unix_SVR2" */ 143 char processor_name[17]; 144 145 int is_boot; 146 int is_driver; 147 int has_driver; 148 int is_root; 149 int is_swap; 150 int is_lvm; 151 int is_raid; 152 153 PedSector data_region_length; 154 PedSector boot_region_length; 155 156 uint32_t boot_base_address; 157 uint32_t boot_entry_address; 158 uint32_t boot_checksum; 159 160 uint32_t status; 161 uint32_t driver_sig; 162 }; 163 164 struct _MacDiskData { 165 int ghost_size; /* sectors per "driver" block */ 166 int part_map_entry_count; /* # entries (incl. ghost) */ 167 int part_map_entry_num; /* partition map location */ 168 169 int active_part_entry_count; /* # real partitions */ 170 int free_part_entry_count; /* # free space */ 171 int last_part_entry_num; /* last entry number */ 172 173 uint16_t block_size; /* physical sector size */ 174 uint16_t driver_count; 175 MacDeviceDriver driverlist[1 + 60]; /* 488 bytes */ 176 }; 177 178 static PedDiskType mac_disk_type; 179 180 static int 181 _check_signature (MacRawDisk* raw_disk) 182 { 183 if (PED_BE16_TO_CPU (raw_disk->signature) != MAC_DISK_MAGIC) { 184 #ifdef DISCOVER_ONLY 185 return 0; 186 #else 187 return ped_exception_throw ( 188 PED_EXCEPTION_ERROR, 189 PED_EXCEPTION_IGNORE_CANCEL, 190 _("Invalid signature %x for Mac disk labels."), 191 (int) PED_BE16_TO_CPU (raw_disk->signature)) 192 == PED_EXCEPTION_IGNORE; 193 #endif 194 } 195 196 return 1; 197 } 198 199 static int 200 _rawpart_check_signature (MacRawPartition* raw_part) 201 { 202 int sig = (int) PED_BE16_TO_CPU (raw_part->signature); 203 return sig == MAC_PARTITION_MAGIC_1 || sig == MAC_PARTITION_MAGIC_2; 204 } 205 206 static int 207 mac_probe (const PedDevice * dev) 208 { 209 MacRawDisk buf; 210 211 PED_ASSERT (dev != NULL, return 0); 212 213 if (dev->sector_size != 512) 214 return 0; 215 216 if (!ped_device_read (dev, &buf, 0, 1)) 217 return 0; 218 219 return _check_signature (&buf); 220 } 221 222 static int 223 _disk_add_part_map_entry (PedDisk* disk, int warn) 224 { 225 MacDiskData* mac_disk_data = disk->disk_specific; 226 PedPartition* new_part; 227 MacPartitionData* mac_part_data; 228 PedSector part_map_size; 229 PedConstraint* constraint_any = ped_constraint_any (disk->dev); 230 231 #ifndef DISCOVER_ONLY 232 if (warn && ped_exception_throw ( 233 PED_EXCEPTION_ERROR, 234 PED_EXCEPTION_FIX | PED_EXCEPTION_CANCEL, 235 _("Partition map has no partition map entry!")) 236 != PED_EXCEPTION_FIX) 237 goto error; 238 #endif /* !DISCOVER_ONLY */ 239 240 part_map_size 241 = ped_round_up_to (mac_disk_data->last_part_entry_num, 64); 242 if (part_map_size == 0) 243 part_map_size = 64; 244 245 new_part = ped_partition_new (disk, 0, NULL, 1, part_map_size - 1); 246 if (!new_part) 247 goto error; 248 249 mac_part_data = new_part->disk_specific; 250 strcpy (mac_part_data->volume_name, "Apple"); 251 strcpy (mac_part_data->system_name, "Apple_partition_map"); 252 253 if (!ped_disk_add_partition (disk, new_part, constraint_any)) 254 goto error_destroy_new_part; 255 256 mac_disk_data->part_map_entry_num = new_part->num; 257 mac_disk_data->part_map_entry_count 258 = new_part->geom.end - mac_disk_data->ghost_size; 259 ped_constraint_destroy (constraint_any); 260 return 1; 261 262 error_destroy_new_part: 263 ped_partition_destroy (new_part); 264 error: 265 ped_constraint_destroy (constraint_any); 266 return 0; 267 } 268 269 static PedDisk* 270 mac_alloc (const PedDevice* dev) 271 { 272 PedDisk* disk; 273 MacDiskData* mac_disk_data; 274 275 PED_ASSERT (dev != NULL, return NULL); 276 277 #ifndef DISCOVER_ONLY 278 if (dev->length < 256) { 279 ped_exception_throw ( 280 PED_EXCEPTION_ERROR, 281 PED_EXCEPTION_CANCEL, 282 _("%s is too small for a Mac disk label!"), 283 dev->path); 284 goto error; 285 } 286 #endif 287 288 disk = _ped_disk_alloc (dev, &mac_disk_type); 289 if (!disk) 290 goto error; 291 292 mac_disk_data = (MacDiskData*) ped_malloc (sizeof (MacDiskData)); 293 if (!mac_disk_data) 294 goto error_free_disk; 295 disk->disk_specific = mac_disk_data; 296 mac_disk_data->ghost_size = disk->dev->sector_size / 512; 297 mac_disk_data->active_part_entry_count = 0; 298 mac_disk_data->free_part_entry_count = 1; 299 mac_disk_data->last_part_entry_num = 1; 300 mac_disk_data->block_size = 0; 301 mac_disk_data->driver_count = 0; 302 memset(&mac_disk_data->driverlist[0], 0, sizeof(mac_disk_data->driverlist)); 303 304 if (!_disk_add_part_map_entry (disk, 0)) 305 goto error_free_disk; 306 return disk; 307 308 error_free_disk: 309 _ped_disk_free (disk); 310 error: 311 return NULL; 312 } 313 314 static PedDisk* 315 mac_duplicate (const PedDisk* disk) 316 { 317 PedDisk* new_disk; 318 MacDiskData* new_mac_data; 319 MacDiskData* old_mac_data = (MacDiskData*) disk->disk_specific; 320 PedPartition* partition_map; 321 322 new_disk = ped_disk_new_fresh (disk->dev, &mac_disk_type); 323 if (!new_disk) 324 goto error; 325 326 new_mac_data = (MacDiskData*) new_disk->disk_specific; 327 328 /* remove the partition map partition - it will be duplicated 329 * later. 330 */ 331 partition_map = ped_disk_get_partition_by_sector (new_disk, 1); 332 PED_ASSERT (partition_map != NULL, return 0); 333 ped_disk_remove_partition (new_disk, partition_map); 334 335 /* ugly, but C is ugly :p */ 336 memcpy (new_mac_data, old_mac_data, sizeof (MacDiskData)); 337 return new_disk; 338 339 _ped_disk_free (new_disk); 340 error: 341 return NULL; 342 } 343 344 static void 345 mac_free (PedDisk* disk) 346 { 347 MacDiskData* mac_disk_data = disk->disk_specific; 348 349 _ped_disk_free (disk); 350 ped_free (mac_disk_data); 351 } 352 353 #ifndef DISCOVER_ONLY 354 static int 355 _clobber_part_map (PedDevice* dev) 356 { 357 MacRawPartition raw_part; 358 PedSector sector; 359 360 for (sector=1; 1; sector++) { 361 if (!ped_device_read (dev, &raw_part, sector, 1)) 362 return 0; 363 if (!_rawpart_check_signature (&raw_part)) 364 return 1; 365 memset (&raw_part, 0, 512); 366 if (!ped_device_write (dev, &raw_part, sector, 1)) 367 return 0; 368 } 369 } 370 371 static int 372 mac_clobber (PedDevice* dev) 373 { 374 MacRawDisk raw_disk; 375 376 if (!ped_device_read (dev, &raw_disk, 0, 1)) 377 return 0; 378 if (!_check_signature (&raw_disk)) 379 return 0; 380 memset (&raw_disk, 0, 512); 381 if (!ped_device_write (dev, &raw_disk, 0, 1)) 382 return 0; 383 384 return _clobber_part_map (dev); 385 } 386 #endif /* !DISCOVER_ONLY */ 387 388 static int 389 _rawpart_cmp_type (MacRawPartition* raw_part, char* type) 390 { 391 return strncasecmp (raw_part->type, type, 32) == 0; 392 } 393 394 static int 395 _rawpart_cmp_name (MacRawPartition* raw_part, char* name) 396 { 397 return strncasecmp (raw_part->name, name, 32) == 0; 398 } 399 400 static int 401 _rawpart_is_partition_map (MacRawPartition* raw_part) 402 { 403 return _rawpart_cmp_type (raw_part, "Apple_partition_map"); 404 } 405 406 static int 407 strncasestr (const char* haystack, const char* needle, int n) 408 { 409 int needle_size = strlen (needle); 410 int i; 411 412 for (i = 0; haystack[i] && i < n - needle_size; i++) { 413 if (strncasecmp (haystack + i, needle, needle_size) == 0) 414 return 1; 415 } 416 417 return 0; 418 } 419 420 static int 421 _rawpart_is_boot (MacRawPartition* raw_part) 422 { 423 if (!strcasecmp(raw_part->type, "Apple_Bootstrap")) 424 return 1; 425 426 if (!strcasecmp(raw_part->type, "Apple_Boot")) 427 return 1; 428 429 return 0; 430 } 431 432 static int 433 _rawpart_is_driver (MacRawPartition* raw_part) 434 { 435 if (strncmp (raw_part->type, "Apple_", 6) != 0) 436 return 0; 437 if (!strncasestr (raw_part->type, "driver", 32)) 438 return 0; 439 return 1; 440 } 441 442 static int 443 _rawpart_has_driver (MacRawPartition* raw_part, MacDiskData* mac_disk_data) 444 { 445 MacDeviceDriver *driverlist; 446 uint16_t i, bsz; 447 uint32_t driver_bs, driver_be, part_be; 448 449 driverlist = &mac_disk_data->driverlist[0]; 450 bsz = mac_disk_data->block_size / 512; 451 for (i = 0; i < mac_disk_data->driver_count; i++) { 452 driver_bs = driverlist->block * bsz; 453 driver_be = driver_bs + driverlist->size; 454 part_be = raw_part->start_block + raw_part->block_count; 455 if (driver_bs >= raw_part->start_block && driver_be <= part_be) 456 return 1; 457 driverlist++; 458 } 459 return 0; 460 } 461 462 static int 463 _rawpart_is_root (MacRawPartition* raw_part) 464 { 465 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2")) 466 return 0; 467 if (strcmp (raw_part->name, "root") != 0) 468 return 0; 469 return 1; 470 } 471 472 static int 473 _rawpart_is_swap (MacRawPartition* raw_part) 474 { 475 if (!_rawpart_cmp_type (raw_part, "Apple_UNIX_SVR2")) 476 return 0; 477 if (strcmp (raw_part->name, "swap") != 0) 478 return 0; 479 return 1; 480 } 481 482 static int 483 _rawpart_is_lvm (MacRawPartition* raw_part) 484 { 485 if (strcmp (raw_part->type, "Linux_LVM") != 0) 486 return 0; 487 return 1; 488 } 489 490 static int 491 _rawpart_is_raid (MacRawPartition* raw_part) 492 { 493 if (strcmp (raw_part->type, "Linux_RAID") != 0) 494 return 0; 495 return 1; 496 } 497 498 static int 499 _rawpart_is_void (MacRawPartition* raw_part) 500 { 501 return _rawpart_cmp_type (raw_part, "Apple_Void"); 502 } 503 504 /* returns 1 if the raw_part represents a partition that is "unused space", or 505 * doesn't represent a partition at all. NOTE: some people make Apple_Free 506 * partitions with MacOS, because they can't select another type. So, if the 507 * name is anything other than "Extra" or "", it is treated as a "real" 508 * partition. 509 */ 510 static int 511 _rawpart_is_active (MacRawPartition* raw_part) 512 { 513 if (_rawpart_cmp_type (raw_part, "Apple_Free") 514 && (_rawpart_cmp_name (raw_part, "Extra") 515 || _rawpart_cmp_name (raw_part, ""))) 516 return 0; 517 if (_rawpart_cmp_type (raw_part, "Apple_Void")) 518 return 0; 519 if (_rawpart_cmp_type (raw_part, "Apple_Scratch")) 520 return 0; 521 if (_rawpart_cmp_type (raw_part, "Apple_Extra")) 522 return 0; 523 524 return 1; 525 } 526 527 static PedPartition* 528 _rawpart_analyse (MacRawPartition* raw_part, PedDisk* disk, int num) 529 { 530 MacDiskData* mac_disk_data; 531 PedPartition* part; 532 MacPartitionData* mac_part_data; 533 PedSector block_size; 534 PedSector start, length; 535 536 if (!_rawpart_check_signature (raw_part)) { 537 #ifndef DISCOVER_ONLY 538 if (ped_exception_throw ( 539 PED_EXCEPTION_WARNING, 540 PED_EXCEPTION_IGNORE_CANCEL, 541 _("Partition %d has an invalid signature %x."), 542 num, 543 (int) PED_BE16_TO_CPU (raw_part->signature)) 544 != PED_EXCEPTION_IGNORE) 545 #endif 546 goto error; 547 } 548 549 mac_disk_data = (MacDiskData*) disk->disk_specific; 550 block_size = disk->dev->sector_size / 512; 551 552 start = PED_BE32_TO_CPU (raw_part->start_block) * block_size; 553 length = PED_BE32_TO_CPU (raw_part->block_count) * block_size; 554 if (length == 0) { 555 #ifndef DISCOVER_ONLY 556 ped_exception_throw ( 557 PED_EXCEPTION_ERROR, 558 PED_EXCEPTION_CANCEL, 559 _("Partition %d has an invalid length of 0 bytes!"), 560 num); 561 #endif 562 return NULL; 563 } 564 part = ped_partition_new (disk, 0, NULL, start, start + length - 1); 565 if (!part) 566 goto error; 567 568 mac_part_data = part->disk_specific; 569 570 strncpy (mac_part_data->volume_name, raw_part->name, 32); 571 strncpy (mac_part_data->system_name, raw_part->type, 32); 572 strncpy (mac_part_data->processor_name, raw_part->processor, 16); 573 574 mac_part_data->is_boot = _rawpart_is_boot (raw_part); 575 mac_part_data->is_driver = _rawpart_is_driver (raw_part); 576 if (mac_part_data->is_driver) 577 mac_part_data->has_driver = _rawpart_has_driver(raw_part, mac_disk_data); 578 mac_part_data->is_root = _rawpart_is_root (raw_part); 579 mac_part_data->is_swap = _rawpart_is_swap (raw_part); 580 mac_part_data->is_lvm = _rawpart_is_lvm (raw_part); 581 mac_part_data->is_raid = _rawpart_is_raid (raw_part); 582 583 /* "data" region */ 584 #ifndef DISCOVER_ONLY 585 if (raw_part->data_start) { 586 ped_exception_throw ( 587 PED_EXCEPTION_ERROR, 588 PED_EXCEPTION_CANCEL, 589 _("The data region doesn't start at the start " 590 "of the partition.")); 591 goto error_destroy_part; 592 } 593 #endif /* !DISCOVER_ONLY */ 594 mac_part_data->data_region_length 595 = PED_BE32_TO_CPU (raw_part->data_count) * block_size; 596 597 /* boot region - we have no idea what this is for, but Mac OSX 598 * seems to put garbage here, and doesn't pay any attention to 599 * it afterwards. [clausen, dan burcaw] 600 */ 601 #if 0 602 if (raw_part->boot_start) { 603 ped_exception_throw ( 604 PED_EXCEPTION_ERROR, 605 PED_EXCEPTION_CANCEL, 606 _("The boot region doesn't start at the start " 607 "of the partition.")); 608 goto error_destroy_part; 609 } 610 #endif 611 mac_part_data->boot_region_length 612 = PED_BE32_TO_CPU (raw_part->boot_count) * block_size; 613 614 #ifndef DISCOVER_ONLY 615 if (mac_part_data->has_driver) { 616 if (mac_part_data->boot_region_length < part->geom.length) { 617 if (ped_exception_throw ( 618 PED_EXCEPTION_ERROR, 619 PED_EXCEPTION_IGNORE_CANCEL, 620 _("The partition's boot region doesn't occupy " 621 "the entire partition.")) 622 != PED_EXCEPTION_IGNORE) 623 goto error_destroy_part; 624 } 625 } else { 626 if (mac_part_data->data_region_length < part->geom.length && 627 !mac_part_data->is_boot) { 628 if (ped_exception_throw ( 629 PED_EXCEPTION_ERROR, 630 PED_EXCEPTION_IGNORE_CANCEL, 631 _("The partition's data region doesn't occupy " 632 "the entire partition.")) 633 != PED_EXCEPTION_IGNORE) 634 goto error_destroy_part; 635 } 636 } 637 #endif /* !DISCOVER_ONLY */ 638 639 mac_part_data->boot_base_address 640 = PED_BE32_TO_CPU (raw_part->boot_load); 641 mac_part_data->boot_entry_address 642 = PED_BE32_TO_CPU (raw_part->boot_entry); 643 mac_part_data->boot_checksum 644 = PED_BE32_TO_CPU (raw_part->boot_cksum); 645 646 mac_part_data->status = PED_BE32_TO_CPU (raw_part->status); 647 mac_part_data->driver_sig = PED_BE32_TO_CPU (raw_part->driver_sig); 648 649 return part; 650 651 error_destroy_part: 652 ped_partition_destroy (part); 653 error: 654 return NULL; 655 } 656 657 /* looks at the partition map size field in a mac raw partition, and calculates 658 * what the size of the partition map should be, from it 659 */ 660 static int 661 _rawpart_get_partmap_size (MacRawPartition* raw_part, PedDisk* disk) 662 { 663 MacDiskData* mac_disk_data = disk->disk_specific; 664 PedSector sector_size = disk->dev->sector_size / 512; 665 PedSector part_map_start; 666 PedSector part_map_end; 667 668 part_map_start = mac_disk_data->ghost_size; 669 part_map_end = sector_size * PED_BE32_TO_CPU (raw_part->map_count); 670 671 return part_map_end - part_map_start + 1; 672 } 673 674 static int 675 _disk_analyse_block_size (PedDisk* disk, MacRawDisk* raw_disk) 676 { 677 PedSector block_size; 678 679 if (PED_BE16_TO_CPU (raw_disk->block_size) % 512) { 680 #ifndef DISCOVER_ONLY 681 ped_exception_throw ( 682 PED_EXCEPTION_ERROR, 683 PED_EXCEPTION_CANCEL, 684 _("Weird block size on device descriptor: %d bytes is " 685 "not divisible by 512."), 686 (int) PED_BE16_TO_CPU (raw_disk->block_size)); 687 #endif 688 goto error; 689 } 690 691 block_size = PED_BE16_TO_CPU (raw_disk->block_size) / 512; 692 if (block_size != disk->dev->sector_size / 512) { 693 #ifndef DISCOVER_ONLY 694 if (ped_exception_throw ( 695 PED_EXCEPTION_WARNING, 696 PED_EXCEPTION_IGNORE_CANCEL, 697 _("The driver descriptor says the physical block size " 698 "is %d bytes, but Linux says it is %d bytes."), 699 (int) block_size * 512, 700 (int) disk->dev->sector_size) 701 != PED_EXCEPTION_IGNORE) 702 goto error; 703 #endif 704 disk->dev->sector_size = block_size * 512; 705 } 706 707 return 1; 708 709 error: 710 return 0; 711 } 712 713 /* Tries to figure out the block size used by the drivers, for the ghost 714 * partitioning scheme. Ghost partitioning works like this: the OpenFirmware 715 * (OF) sees 512 byte blocks, but some drivers use 2048 byte blocks (and, 716 * perhaps, some other number?). To remain compatible, the partition map 717 * only has "real" partition map entries on ghost-aligned block numbers (and 718 * the others are padded with Apple_Void partitions). This function tries 719 * to figure out what the "ghost-aligned" size is... (which, believe-it-or-not, 720 * doesn't always equal 2048!!!) 721 */ 722 static int 723 _disk_analyse_ghost_size (PedDisk* disk) 724 { 725 MacDiskData* mac_disk_data = disk->disk_specific; 726 MacRawPartition raw_part; 727 int i; 728 729 for (i = 1; i < 64; i *= 2) { 730 if (!ped_device_read (disk->dev, &raw_part, i, 1)) 731 return 0; 732 if (_rawpart_check_signature (&raw_part) 733 && !_rawpart_is_void (&raw_part)) { 734 mac_disk_data->ghost_size = i; 735 PED_ASSERT (i <= disk->dev->sector_size / 512, 736 return 0); 737 return 1; 738 } 739 } 740 741 #ifndef DISCOVER_ONLY 742 ped_exception_throw ( 743 PED_EXCEPTION_ERROR, 744 PED_EXCEPTION_CANCEL, 745 _("No valid partition map found.")); 746 #endif 747 return 0; 748 } 749 750 static int 751 mac_read (PedDisk* disk) 752 { 753 MacRawDisk raw_disk; 754 MacRawPartition raw_part; 755 MacDiskData* mac_disk_data; 756 PedPartition* part; 757 int num; 758 PedSector ghost_size; 759 PedConstraint* constraint_exact; 760 int last_part_entry_num = 0; 761 762 PED_ASSERT (disk != NULL, return 0); 763 764 mac_disk_data = disk->disk_specific; 765 mac_disk_data->part_map_entry_num = 0; /* 0 == none */ 766 767 if (!ped_device_read (disk->dev, &raw_disk, 0, 1)) 768 goto error; 769 if (!_check_signature (&raw_disk)) 770 goto error; 771 772 if (!_disk_analyse_block_size (disk, &raw_disk)) 773 goto error; 774 if (!_disk_analyse_ghost_size (disk)) 775 goto error; 776 ghost_size = mac_disk_data->ghost_size; 777 778 if (!ped_disk_delete_all (disk)) 779 goto error; 780 781 if (raw_disk.driver_count && raw_disk.driver_count < 62) { 782 memcpy(&mac_disk_data->driverlist[0], &raw_disk.driverlist[0], 783 sizeof(mac_disk_data->driverlist)); 784 mac_disk_data->driver_count = raw_disk.driver_count; 785 mac_disk_data->block_size = raw_disk.block_size; 786 } 787 788 for (num=1; num==1 || num <= last_part_entry_num; num++) { 789 if (!ped_device_read (disk->dev, &raw_part, 790 num * ghost_size, 1)) 791 goto error_delete_all; 792 793 if (!_rawpart_check_signature (&raw_part)) 794 continue; 795 796 if (num == 1) 797 last_part_entry_num 798 = _rawpart_get_partmap_size (&raw_part, disk); 799 if (_rawpart_get_partmap_size (&raw_part, disk) 800 != last_part_entry_num) { 801 if (ped_exception_throw ( 802 PED_EXCEPTION_ERROR, 803 PED_EXCEPTION_IGNORE_CANCEL, 804 _("Conflicting partition map entry sizes! " 805 "Entry 1 says it is %d, but entry %d says " 806 "it is %d!"), 807 last_part_entry_num, 808 _rawpart_get_partmap_size (&raw_part, disk)) 809 != PED_EXCEPTION_IGNORE) 810 goto error_delete_all; 811 } 812 813 if (!_rawpart_is_active (&raw_part)) 814 continue; 815 816 part = _rawpart_analyse (&raw_part, disk, num); 817 if (!part) 818 goto error_delete_all; 819 part->num = num; 820 part->fs_type = ped_file_system_probe (&part->geom); 821 constraint_exact = ped_constraint_exact (&part->geom); 822 if (!ped_disk_add_partition (disk, part, constraint_exact)) 823 goto error_delete_all; 824 ped_constraint_destroy (constraint_exact); 825 826 if (_rawpart_is_partition_map (&raw_part)) { 827 if (mac_disk_data->part_map_entry_num 828 && ped_exception_throw ( 829 PED_EXCEPTION_ERROR, 830 PED_EXCEPTION_IGNORE_CANCEL, 831 _("Weird! There are 2 partitions " 832 "map entries!")) 833 != PED_EXCEPTION_IGNORE) 834 goto error_delete_all; 835 836 mac_disk_data->part_map_entry_num = num; 837 mac_disk_data->part_map_entry_count 838 = part->geom.end - ghost_size + 1; 839 } 840 } 841 842 if (!mac_disk_data->part_map_entry_num) { 843 if (!_disk_add_part_map_entry (disk, 1)) 844 goto error_delete_all; 845 ped_disk_commit_to_dev (disk); 846 } 847 return 1; 848 849 error_delete_all: 850 ped_disk_delete_all (disk); 851 error: 852 return 0; 853 } 854 855 #ifndef DISCOVER_ONLY 856 /* The Ghost partition: is a blank entry, used to pad out each block (where 857 * there physical block size > 512 bytes). This is because OpenFirmware uses 858 * 512 byte blocks, but device drivers Think Different TM, with a different 859 * lbock size, so we need to do this to avoid a clash (!) 860 */ 861 static int 862 _pad_raw_part (PedDisk* disk, int num, MacRawPartition* part_map) 863 { 864 MacDiskData* mac_disk_data = disk->disk_specific; 865 MacRawPartition ghost_entry; 866 int i; 867 868 memset (&ghost_entry, 0, sizeof (ghost_entry)); 869 ghost_entry.signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); 870 strcpy (ghost_entry.type, "Apple_Void"); 871 ghost_entry.map_count 872 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); 873 874 for (i=0; i < mac_disk_data->ghost_size - 1; i++) 875 memcpy (&part_map [i + (num - 1) * mac_disk_data->ghost_size], 876 &ghost_entry, sizeof (MacRawPartition)); 877 878 return 1; 879 } 880 881 static void 882 _update_driver_count (MacRawPartition* part_map_entry, 883 MacDiskData *mac_driverdata, const MacDiskData* mac_disk_data) 884 { 885 uint16_t i, count_orig, count_cur, bsz; 886 uint32_t driver_bs, driver_be, part_be; 887 888 bsz = mac_disk_data->block_size / 512; 889 count_cur = mac_driverdata->driver_count; 890 count_orig = mac_disk_data->driver_count; 891 for (i = 0; i < count_orig; i++) { 892 driver_bs = mac_disk_data->driverlist[i].block * bsz; 893 driver_be = driver_bs + mac_disk_data->driverlist[i].size; 894 part_be = part_map_entry->start_block + part_map_entry->block_count; 895 if (driver_bs >= part_map_entry->start_block 896 && driver_be <= part_be) { 897 mac_driverdata->driverlist[count_cur].block 898 = mac_disk_data->driverlist[i].block; 899 mac_driverdata->driverlist[count_cur].size 900 = mac_disk_data->driverlist[i].size; 901 mac_driverdata->driverlist[count_cur].type 902 = mac_disk_data->driverlist[i].type; 903 mac_driverdata->driver_count++; 904 break; 905 } 906 } 907 } 908 909 static int 910 _generate_raw_part (PedDisk* disk, PedPartition* part, 911 MacRawPartition* part_map, MacDiskData *mac_driverdata) 912 { 913 MacDiskData* mac_disk_data; 914 MacPartitionData* mac_part_data; 915 MacRawPartition* part_map_entry; 916 PedSector block_size = disk->dev->sector_size / 512; 917 918 PED_ASSERT (part->num > 0, goto error); 919 920 mac_disk_data = disk->disk_specific; 921 mac_part_data = part->disk_specific; 922 923 part_map_entry = &part_map [part->num * mac_disk_data->ghost_size - 1]; 924 925 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); 926 part_map_entry->map_count 927 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); 928 part_map_entry->start_block 929 = PED_CPU_TO_BE32 (part->geom.start / block_size); 930 part_map_entry->block_count 931 = PED_CPU_TO_BE32 (part->geom.length / block_size); 932 strcpy (part_map_entry->name, mac_part_data->volume_name); 933 strcpy (part_map_entry->type, mac_part_data->system_name); 934 935 if (mac_part_data->is_driver) { 936 mac_part_data->boot_region_length = part->geom.length; 937 if (mac_part_data->has_driver) 938 _update_driver_count(part_map_entry, mac_driverdata, 939 mac_disk_data); 940 } else 941 mac_part_data->data_region_length = part->geom.length; 942 part_map_entry->data_count = PED_CPU_TO_BE32 ( 943 mac_part_data->data_region_length / block_size); 944 part_map_entry->boot_count = PED_CPU_TO_BE32 ( 945 mac_part_data->boot_region_length / block_size); 946 part_map_entry->status = PED_CPU_TO_BE32 (mac_part_data->status); 947 part_map_entry->driver_sig 948 = PED_CPU_TO_BE32 (mac_part_data->driver_sig); 949 950 part_map_entry->boot_load = 951 PED_CPU_TO_BE32 (mac_part_data->boot_base_address); 952 part_map_entry->boot_entry = 953 PED_CPU_TO_BE32 (mac_part_data->boot_entry_address); 954 part_map_entry->boot_cksum = 955 PED_CPU_TO_BE32 (mac_part_data->boot_checksum); 956 957 strncpy (part_map_entry->processor, mac_part_data->processor_name, 16); 958 959 if (!_pad_raw_part (disk, part->num, part_map)) 960 goto error; 961 962 return 1; 963 964 error: 965 return 0; 966 } 967 968 static int 969 _generate_raw_freespace_part (PedDisk* disk, PedGeometry* geom, int num, 970 MacRawPartition* part_map) 971 { 972 MacDiskData* mac_disk_data = disk->disk_specific; 973 MacRawPartition* part_map_entry; 974 PedSector block_size = disk->dev->sector_size / 512; 975 976 PED_ASSERT (num > 0, goto error); 977 978 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1]; 979 980 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); 981 part_map_entry->map_count 982 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); 983 part_map_entry->start_block 984 = PED_CPU_TO_BE32 (geom->start / block_size); 985 part_map_entry->block_count 986 = PED_CPU_TO_BE32 (geom->length / block_size); 987 strcpy (part_map_entry->name, "Extra"); 988 strcpy (part_map_entry->type, "Apple_Free"); 989 990 part_map_entry->data_count = PED_CPU_TO_BE32 (geom->length); 991 part_map_entry->status = 0; 992 part_map_entry->driver_sig = 0; 993 994 if (!_pad_raw_part (disk, num, part_map)) 995 goto error; 996 997 return 1; 998 999 error: 1000 return 0; 1001 } 1002 1003 static int 1004 _generate_empty_part (PedDisk* disk, int num, MacRawPartition* part_map) 1005 { 1006 MacDiskData* mac_disk_data = disk->disk_specific; 1007 MacRawPartition* part_map_entry; 1008 1009 PED_ASSERT (num > 0, return 0); 1010 1011 part_map_entry = &part_map [num * mac_disk_data->ghost_size - 1]; 1012 part_map_entry->signature = PED_CPU_TO_BE16 (MAC_PARTITION_MAGIC_2); 1013 part_map_entry->map_count 1014 = PED_CPU_TO_BE32 (mac_disk_data->last_part_entry_num); 1015 strcpy (part_map_entry->type, "Apple_Void"); 1016 1017 return _pad_raw_part (disk, num, part_map); 1018 } 1019 1020 /* returns the first empty entry in the partition map */ 1021 static int 1022 _get_first_empty_part_entry (PedDisk* disk, MacRawPartition* part_map) 1023 { 1024 MacDiskData* mac_disk_data = disk->disk_specific; 1025 int i; 1026 1027 for (i=1; i <= mac_disk_data->last_part_entry_num; i++) { 1028 if (!part_map[i * mac_disk_data->ghost_size - 1].signature) 1029 return i; 1030 } 1031 1032 return 0; 1033 } 1034 1035 static int 1036 write_block_zero (PedDisk* disk, MacDiskData* mac_driverdata) 1037 { 1038 PedDevice* dev = disk->dev; 1039 MacRawDisk raw_disk; 1040 1041 if (!ped_device_read (dev, &raw_disk, 0, 1)) 1042 return 0; 1043 1044 raw_disk.signature = PED_CPU_TO_BE16 (MAC_DISK_MAGIC); 1045 raw_disk.block_size = PED_CPU_TO_BE16 (dev->sector_size); 1046 raw_disk.block_count 1047 = PED_CPU_TO_BE32 (dev->length / (dev->sector_size / 512)); 1048 1049 raw_disk.driver_count = mac_driverdata->driver_count; 1050 memcpy(&raw_disk.driverlist[0], &mac_driverdata->driverlist[0], 1051 sizeof(raw_disk.driverlist)); 1052 1053 return ped_device_write (dev, &raw_disk, 0, 1); 1054 } 1055 1056 static int 1057 mac_write (PedDisk* disk) 1058 { 1059 MacRawPartition* part_map; 1060 MacDiskData* mac_disk_data; 1061 MacDiskData* mac_driverdata; /* updated driver list */ 1062 PedPartition* part; 1063 int num; 1064 1065 PED_ASSERT (disk != NULL, return 0); 1066 PED_ASSERT (disk->disk_specific != NULL, return 0); 1067 PED_ASSERT (disk->dev != NULL, return 0); 1068 PED_ASSERT (!disk->update_mode, return 0); 1069 1070 mac_disk_data = disk->disk_specific; 1071 1072 if (!ped_disk_get_partition (disk, mac_disk_data->part_map_entry_num)) { 1073 if (!_disk_add_part_map_entry (disk, 1)) 1074 goto error; 1075 } 1076 1077 mac_driverdata = ped_malloc(sizeof(MacDiskData)); 1078 if (!mac_driverdata) 1079 goto error; 1080 memset (mac_driverdata, 0, sizeof(MacDiskData)); 1081 1082 part_map = (MacRawPartition*) 1083 ped_malloc (mac_disk_data->part_map_entry_count * 512); 1084 if (!part_map) 1085 goto error_free_driverdata; 1086 memset (part_map, 0, mac_disk_data->part_map_entry_count * 512); 1087 1088 /* write (to memory) the "real" partitions */ 1089 for (part = ped_disk_next_partition (disk, NULL); part; 1090 part = ped_disk_next_partition (disk, part)) { 1091 if (!ped_partition_is_active (part)) 1092 continue; 1093 if (!_generate_raw_part (disk, part, part_map, mac_driverdata)) 1094 goto error_free_part_map; 1095 } 1096 1097 /* write the "free space" partitions */ 1098 for (part = ped_disk_next_partition (disk, NULL); part; 1099 part = ped_disk_next_partition (disk, part)) { 1100 if (part->type != PED_PARTITION_FREESPACE) 1101 continue; 1102 num = _get_first_empty_part_entry (disk, part_map); 1103 if (!_generate_raw_freespace_part (disk, &part->geom, num, 1104 part_map)) 1105 goto error_free_part_map; 1106 } 1107 1108 /* write the "void" (empty) partitions */ 1109 for (num = _get_first_empty_part_entry (disk, part_map); num; 1110 num = _get_first_empty_part_entry (disk, part_map)) 1111 _generate_empty_part (disk, num, part_map); 1112 1113 /* write to disk */ 1114 if (!ped_device_write (disk->dev, part_map, 1, 1115 mac_disk_data->part_map_entry_count)) 1116 goto error_free_part_map; 1117 ped_free (part_map); 1118 return write_block_zero (disk, mac_driverdata); 1119 1120 error_free_part_map: 1121 ped_free (part_map); 1122 error_free_driverdata: 1123 ped_free (mac_driverdata); 1124 error: 1125 return 0; 1126 } 1127 #endif /* !DISCOVER_ONLY */ 1128 1129 static PedPartition* 1130 mac_partition_new ( 1131 const PedDisk* disk, PedPartitionType part_type, 1132 const PedFileSystemType* fs_type, PedSector start, PedSector end) 1133 { 1134 PedPartition* part; 1135 MacPartitionData* mac_data; 1136 1137 part = _ped_partition_alloc (disk, part_type, fs_type, start, end); 1138 if (!part) 1139 goto error; 1140 1141 if (ped_partition_is_active (part)) { 1142 part->disk_specific 1143 = mac_data = ped_malloc (sizeof (MacPartitionData)); 1144 if (!mac_data) 1145 goto error_free_part; 1146 1147 memset (mac_data, 0, sizeof (MacPartitionData)); 1148 strcpy (mac_data->volume_name, "untitled"); 1149 } else { 1150 part->disk_specific = NULL; 1151 } 1152 return part; 1153 1154 ped_free (mac_data); 1155 error_free_part: 1156 ped_free (part); 1157 error: 1158 return 0; 1159 } 1160 1161 static PedPartition* 1162 mac_partition_duplicate (const PedPartition* part) 1163 { 1164 PedPartition* new_part; 1165 MacPartitionData* new_mac_data; 1166 MacPartitionData* old_mac_data; 1167 1168 new_part = ped_partition_new (part->disk, part->type, 1169 part->fs_type, part->geom.start, 1170 part->geom.end); 1171 if (!new_part) 1172 return NULL; 1173 new_part->num = part->num; 1174 1175 old_mac_data = (MacPartitionData*) part->disk_specific; 1176 new_mac_data = (MacPartitionData*) new_part->disk_specific; 1177 1178 /* ugly, but C is ugly :p */ 1179 memcpy (new_mac_data, old_mac_data, sizeof (MacPartitionData)); 1180 return new_part; 1181 } 1182 1183 static void 1184 mac_partition_destroy (PedPartition* part) 1185 { 1186 PED_ASSERT (part != NULL, return); 1187 1188 if (ped_partition_is_active (part)) 1189 ped_free (part->disk_specific); 1190 ped_free (part); 1191 } 1192 1193 static int 1194 mac_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) 1195 { 1196 MacPartitionData* mac_data = part->disk_specific; 1197 1198 part->fs_type = fs_type; 1199 1200 if (fs_type && !strcmp (fs_type->name, "linux-swap")) 1201 ped_partition_set_flag (part, PED_PARTITION_SWAP, 1); 1202 1203 if (mac_data->is_boot) { 1204 strcpy (mac_data->system_name, "Apple_Bootstrap"); 1205 mac_data->status = 0x33; 1206 return 1; 1207 } 1208 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; 1216 } else { 1217 strcpy (mac_data->system_name, "Apple_UNIX_SVR2"); 1218 mac_data->status = 0x33; 1219 } 1220 1221 return 1; 1222 } 1223 1224 static int 1225 mac_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) 1226 { 1227 MacPartitionData* mac_data; 1228 1229 PED_ASSERT (part != NULL, return 0); 1230 PED_ASSERT (part->disk_specific != NULL, return 0); 1231 1232 mac_data = part->disk_specific; 1233 1234 switch (flag) { 1235 case PED_PARTITION_BOOT: 1236 mac_data->is_boot = state; 1237 1238 if (part->fs_type) 1239 return mac_partition_set_system (part, part->fs_type); 1240 1241 if (state) { 1242 strcpy (mac_data->system_name, "Apple_Bootstrap"); 1243 mac_data->status = 0x33; 1244 } 1245 return 1; 1246 1247 case PED_PARTITION_ROOT: 1248 if (state) { 1249 strcpy (mac_data->volume_name, "root"); 1250 mac_data->is_swap = 0; 1251 } else { 1252 if (mac_data->is_root) 1253 strcpy (mac_data->volume_name, "untitled"); 1254 } 1255 mac_data->is_root = state; 1256 return 1; 1257 1258 case PED_PARTITION_SWAP: 1259 if (state) { 1260 strcpy (mac_data->volume_name, "swap"); 1261 mac_data->is_root = 0; 1262 } else { 1263 if (mac_data->is_swap) 1264 strcpy (mac_data->volume_name, "untitled"); 1265 } 1266 mac_data->is_swap = state; 1267 return 1; 1268 1269 case PED_PARTITION_LVM: 1270 if (state) { 1271 strcpy (mac_data->system_name, "Linux_LVM"); 1272 mac_data->is_lvm = state; 1273 } else { 1274 if (mac_data->is_lvm) 1275 mac_partition_set_system (part, part->fs_type); 1276 } 1277 return 1; 1278 1279 case PED_PARTITION_RAID: 1280 if (state) { 1281 strcpy (mac_data->system_name, "Linux_RAID"); 1282 mac_data->is_raid = state; 1283 } else { 1284 if (mac_data->is_raid) 1285 mac_partition_set_system (part, part->fs_type); 1286 } 1287 return 1; 1288 1289 default: 1290 return 0; 1291 } 1292 } 1293 1294 static int 1295 mac_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) 1296 { 1297 MacPartitionData* mac_data; 1298 1299 PED_ASSERT (part != NULL, return 0); 1300 PED_ASSERT (part->disk_specific != NULL, return 0); 1301 1302 mac_data = part->disk_specific; 1303 switch (flag) { 1304 case PED_PARTITION_BOOT: 1305 return mac_data->is_boot; 1306 1307 case PED_PARTITION_ROOT: 1308 return mac_data->is_root; 1309 1310 case PED_PARTITION_SWAP: 1311 return mac_data->is_swap; 1312 1313 case PED_PARTITION_LVM: 1314 return mac_data->is_lvm; 1315 1316 case PED_PARTITION_RAID: 1317 return mac_data->is_raid; 1318 1319 default: 1320 return 0; 1321 } 1322 } 1323 1324 static int 1325 mac_partition_is_flag_available ( 1326 const PedPartition* part, PedPartitionFlag flag) 1327 { 1328 switch (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: 1334 return 1; 1335 1336 default: 1337 return 0; 1338 } 1339 } 1340 1341 static void 1342 mac_partition_set_name (PedPartition* part, const char* name) 1343 { 1344 MacPartitionData* mac_data; 1345 int i; 1346 1347 PED_ASSERT (part != NULL, return); 1348 PED_ASSERT (part->disk_specific != NULL, return); 1349 mac_data = part->disk_specific; 1350 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) 1359 return; 1360 mac_data->is_root = mac_data->is_swap = 0; 1361 } 1362 #endif 1363 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; 1369 } 1370 1371 static const char* 1372 mac_partition_get_name (const PedPartition* part) 1373 { 1374 MacPartitionData* mac_data; 1375 1376 PED_ASSERT (part != NULL, return NULL); 1377 PED_ASSERT (part->disk_specific != NULL, return NULL); 1378 mac_data = part->disk_specific; 1379 1380 return mac_data->volume_name; 1381 } 1382 1383 static PedConstraint* 1384 _primary_constraint (PedDisk* disk) 1385 { 1386 PedAlignment start_align; 1387 PedAlignment end_align; 1388 PedGeometry max_geom; 1389 PedSector sector_size; 1390 1391 sector_size = disk->dev->sector_size / 512; 1392 1393 if (!ped_alignment_init (&start_align, 0, sector_size)) 1394 return NULL; 1395 if (!ped_alignment_init (&end_align, -1, sector_size)) 1396 return NULL; 1397 if (!ped_geometry_init (&max_geom, disk->dev, 1, disk->dev->length - 1)) 1398 return NULL; 1399 1400 return ped_constraint_new (&start_align, &end_align, &max_geom, 1401 &max_geom, 1, disk->dev->length); 1402 } 1403 1404 static int 1405 mac_partition_align (PedPartition* part, const PedConstraint* constraint) 1406 { 1407 PED_ASSERT (part != NULL, return 0); 1408 1409 if (_ped_partition_attempt_align (part, constraint, 1410 _primary_constraint (part->disk))) 1411 return 1; 1412 1413 #ifndef DISCOVER_ONLY 1414 ped_exception_throw ( 1415 PED_EXCEPTION_ERROR, 1416 PED_EXCEPTION_CANCEL, 1417 _("Unable to satisfy all constraints on the partition.")); 1418 #endif 1419 return 0; 1420 } 1421 1422 static int 1423 mac_partition_enumerate (PedPartition* part) 1424 { 1425 PedDisk* disk; 1426 MacDiskData* mac_disk_data; 1427 int i; 1428 int max_part_count; 1429 1430 PED_ASSERT (part != NULL, return 0); 1431 PED_ASSERT (part->disk != NULL, return 0); 1432 1433 disk = part->disk; 1434 mac_disk_data = (MacDiskData*) disk->disk_specific; 1435 1436 max_part_count = ped_disk_get_max_primary_partition_count (disk); 1437 1438 if (part->num > 0 && part->num <= mac_disk_data->part_map_entry_count) 1439 return 1; 1440 1441 for (i = 1; i <= max_part_count; i++) { 1442 if (!ped_disk_get_partition (disk, i)) { 1443 part->num = i; 1444 return 1; 1445 } 1446 } 1447 1448 #ifndef DISCOVER_ONLY 1449 ped_exception_throw ( 1450 PED_EXCEPTION_ERROR, 1451 PED_EXCEPTION_CANCEL, 1452 _("Can't add another partition -- the partition map is too " 1453 "small!")); 1454 #endif 1455 1456 return 0; 1457 } 1458 1459 static int 1460 _disk_count_partitions (PedDisk* disk) 1461 { 1462 MacDiskData* mac_disk_data = disk->disk_specific; 1463 PedPartition* part = NULL; 1464 PedPartition* last = NULL; 1465 1466 PED_ASSERT (disk->update_mode, return 0); 1467 1468 mac_disk_data->active_part_entry_count = 0; 1469 mac_disk_data->free_part_entry_count = 0; 1470 mac_disk_data->last_part_entry_num = 0; 1471 1472 /* subtle: we only care about free space after the partition map. 1473 * the partition map is an "active" partition, BTW... */ 1474 for (part = ped_disk_next_partition (disk, part); part; 1475 part = ped_disk_next_partition (disk, part)) { 1476 if (!ped_partition_is_active (part)) 1477 continue; 1478 1479 mac_disk_data->active_part_entry_count++; 1480 if (last && last->geom.end + 1 < part->geom.start) 1481 mac_disk_data->free_part_entry_count++; 1482 mac_disk_data->last_part_entry_num 1483 = PED_MAX (mac_disk_data->last_part_entry_num, 1484 part->num); 1485 1486 last = part; 1487 } 1488 1489 if (last && last->geom.end < disk->dev->length - 1) 1490 mac_disk_data->free_part_entry_count++; 1491 1492 mac_disk_data->last_part_entry_num 1493 = PED_MAX (mac_disk_data->last_part_entry_num, 1494 mac_disk_data->active_part_entry_count 1495 + mac_disk_data->free_part_entry_count); 1496 return 1; 1497 } 1498 1499 static int 1500 add_metadata_part (PedDisk* disk, PedSector start, PedSector end) 1501 { 1502 PedPartition* new_part; 1503 PedConstraint* constraint_any = ped_constraint_any (disk->dev); 1504 1505 PED_ASSERT (disk != NULL, return 0); 1506 1507 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 1508 start, end); 1509 if (!new_part) 1510 goto error; 1511 if (!ped_disk_add_partition (disk, new_part, constraint_any)) 1512 goto error_destroy_new_part; 1513 1514 ped_constraint_destroy (constraint_any); 1515 return 1; 1516 1517 error_destroy_new_part: 1518 ped_partition_destroy (new_part); 1519 error: 1520 ped_constraint_destroy (constraint_any); 1521 return 0; 1522 } 1523 1524 static int 1525 mac_alloc_metadata (PedDisk* disk) 1526 { 1527 MacDiskData* mac_disk_data; 1528 1529 PED_ASSERT (disk != NULL, return 0); 1530 PED_ASSERT (disk->disk_specific != NULL, return 0); 1531 PED_ASSERT (disk->dev != NULL, return 0); 1532 1533 mac_disk_data = disk->disk_specific; 1534 1535 if (!add_metadata_part (disk, 0, disk->dev->sector_size / 512 - 1)) 1536 return 0; 1537 1538 /* hack: this seems to be a good place, to update the partition map 1539 * entry count, since mac_alloc_metadata() gets called during 1540 * _disk_pop_update_mode() 1541 */ 1542 return _disk_count_partitions (disk); 1543 } 1544 1545 static int 1546 mac_get_max_primary_partition_count (const PedDisk* disk) 1547 { 1548 MacDiskData* mac_disk_data = disk->disk_specific; 1549 PedPartition* part_map_partition; 1550 1551 part_map_partition = ped_disk_get_partition (disk, 1552 mac_disk_data->part_map_entry_num); 1553 1554 /* HACK: if we haven't found the partition map partition (yet), 1555 * we return this. 1556 */ 1557 if (!part_map_partition) { 1558 mac_disk_data->part_map_entry_num = 0; 1559 return 65536; 1560 } 1561 1562 /* HACK: since Mac labels need an entry for free-space regions, we 1563 * must allow half plus 1 entries for free-space partitions. I hate 1564 * this, but things get REALLY complicated, otherwise. 1565 * (I'm prepared to complicate things later, but I want to get 1566 * everything working, first) 1567 */ 1568 return mac_disk_data->part_map_entry_count / mac_disk_data->ghost_size 1569 - mac_disk_data->free_part_entry_count + 1; 1570 } 1571 1572 static PedDiskOps mac_disk_ops = { 1573 .probe = mac_probe, 1574 #ifndef DISCOVER_ONLY 1575 .clobber = mac_clobber, 1576 #else 1577 .clobber = NULL, 1578 #endif 1579 .alloc = mac_alloc, 1580 .duplicate = mac_duplicate, 1581 .free = mac_free, 1582 .read = mac_read, 1583 #ifndef DISCOVER_ONLY 1584 /* FIXME: remove this cast, once mac_write is fixed not to 1585 modify its *DISK parameter. */ 1586 .write = (int (*) (const PedDisk*)) mac_write, 1587 #else 1588 .write = NULL, 1589 #endif 1590 1591 .partition_new = mac_partition_new, 1592 .partition_duplicate = mac_partition_duplicate, 1593 .partition_destroy = mac_partition_destroy, 1594 .partition_set_system = mac_partition_set_system, 1595 .partition_set_flag = mac_partition_set_flag, 1596 .partition_get_flag = mac_partition_get_flag, 1597 .partition_is_flag_available = mac_partition_is_flag_available, 1598 .partition_set_name = mac_partition_set_name, 1599 .partition_get_name = mac_partition_get_name, 1600 .partition_align = mac_partition_align, 1601 .partition_enumerate = mac_partition_enumerate, 1602 1603 .alloc_metadata = mac_alloc_metadata, 1604 .get_max_primary_partition_count = 1605 mac_get_max_primary_partition_count 1606 }; 1607 1608 static PedDiskType mac_disk_type = { 1609 .next = NULL, 1610 .name = "mac", 1611 .ops = &mac_disk_ops, 1612 .features = PED_DISK_TYPE_PARTITION_NAME 1613 }; 1614 1615 void 1616 ped_disk_mac_init () 1617 { 1618 PED_ASSERT (sizeof (MacRawPartition) == 512, return); 1619 PED_ASSERT (sizeof (MacRawDisk) == 512, return); 1620 1621 ped_disk_type_register (&mac_disk_type); 1622 } 1623 1624 void 1625 ped_disk_mac_done () 1626 { 1627 ped_disk_type_unregister (&mac_disk_type); 1628 } 1629