1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 3 libparted - a library for manipulating disk partitions 4 Copyright (C) 2000, 2001, 2005, 2007 Free Software Foundation, Inc. 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 3 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program. If not, see <http://www.gnu.org/licenses/>. 18 19 Contributor: Ben Collins <bcollins@debian.org> 20 */ 21 22 #include <config.h> 23 24 #include <parted/parted.h> 25 #include <parted/debug.h> 26 #include <parted/endian.h> 27 28 #if ENABLE_NLS 29 # include <libintl.h> 30 # define _(String) dgettext (PACKAGE, String) 31 #else 32 # define _(String) (String) 33 #endif /* ENABLE_NLS */ 34 35 /* Most of this came from util-linux's sun support, which was mostly done 36 by Jakub Jelinek. */ 37 38 #define SUN_DISK_MAGIC 0xDABE /* Disk magic number */ 39 #define SUN_DISK_MAXPARTITIONS 8 40 41 #define WHOLE_DISK_ID 0x05 42 #define WHOLE_DISK_PART 2 /* as in 0, 1, 2 (3rd partition) */ 43 #define LINUX_SWAP_ID 0x82 44 45 typedef struct _SunRawPartition SunRawPartition; 46 typedef struct _SunPartitionInfo SunPartitionInfo; 47 typedef struct _SunRawLabel SunRawLabel; 48 typedef struct _SunPartitionData SunPartitionData; 49 typedef struct _SunDiskData SunDiskData; 50 51 #if defined(__sun) 52 typedef uint8_t u_int8_t; 53 typedef uint16_t u_int16_t; 54 typedef uint32_t u_int32_t; 55 #endif 56 57 #ifdef __sun 58 #define __attribute__(X) /*nothing*/ 59 #endif /* __sun */ 60 61 #ifdef __sun 62 #pragma pack(1) 63 #endif 64 struct __attribute__ ((packed)) _SunRawPartition { 65 u_int32_t start_cylinder; /* where the part starts... */ 66 u_int32_t num_sectors; /* ...and it's length */ 67 }; 68 69 struct __attribute__ ((packed)) _SunPartitionInfo { 70 u_int8_t spare1; 71 u_int8_t id; /* Partition type */ 72 u_int8_t spare2; 73 u_int8_t flags; /* Partition flags */ 74 }; 75 76 struct __attribute__ ((packed)) _SunRawLabel { 77 char info[128]; /* Informative text string */ 78 u_int8_t spare0[14]; 79 SunPartitionInfo infos[SUN_DISK_MAXPARTITIONS]; 80 u_int8_t spare1[246]; /* Boot information etc. */ 81 u_int16_t rspeed; /* Disk rotational speed */ 82 u_int16_t pcylcount; /* Physical cylinder count */ 83 u_int16_t sparecyl; /* extra sects per cylinder */ 84 u_int8_t spare2[4]; /* More magic... */ 85 u_int16_t ilfact; /* Interleave factor */ 86 u_int16_t ncyl; /* Data cylinder count */ 87 u_int16_t nacyl; /* Alt. cylinder count */ 88 u_int16_t ntrks; /* Tracks per cylinder */ 89 u_int16_t nsect; /* Sectors per track */ 90 u_int8_t spare3[4]; /* Even more magic... */ 91 SunRawPartition partitions[SUN_DISK_MAXPARTITIONS]; 92 u_int16_t magic; /* Magic number */ 93 u_int16_t csum; /* Label xor'd checksum */ 94 }; 95 #ifdef __sun 96 #pragma pack() 97 #endif 98 99 struct _SunPartitionData { 100 u_int8_t type; 101 int is_boot; 102 int is_root; 103 int is_lvm; 104 }; 105 106 struct _SunDiskData { 107 PedSector length; /* This is based on cyl - alt-cyl */ 108 SunRawLabel raw_label; 109 }; 110 111 static PedDiskType sun_disk_type; 112 113 /* Checksum computation */ 114 static void 115 sun_compute_checksum (SunRawLabel *label) 116 { 117 u_int16_t *ush = (u_int16_t *)label; 118 u_int16_t csum = 0; 119 120 while(ush < (u_int16_t *)(&label->csum)) 121 csum ^= *ush++; 122 label->csum = csum; 123 } 124 125 /* Checksum Verification */ 126 static int 127 sun_verify_checksum (SunRawLabel *label) 128 { 129 u_int16_t *ush = ((u_int16_t *)(label + 1)) - 1; 130 u_int16_t csum = 0; 131 132 while (ush >= (u_int16_t *)label) 133 csum ^= *ush--; 134 135 return !csum; 136 } 137 138 static int 139 sun_probe (const PedDevice *dev) 140 { 141 SunRawLabel label; 142 143 PED_ASSERT (dev != NULL, return 0); 144 145 if (dev->sector_size != 512) 146 return 0; 147 148 if (!ped_device_read (dev, &label, 0, 1)) 149 return 0; 150 151 /* check magic */ 152 if (PED_BE16_TO_CPU (label.magic) != SUN_DISK_MAGIC) 153 return 0; 154 155 #ifndef DISCOVER_ONLY 156 if (!sun_verify_checksum(&label)) { 157 ped_exception_throw ( 158 PED_EXCEPTION_ERROR, 159 PED_EXCEPTION_CANCEL, 160 _("Corrupted Sun disk label detected.")); 161 return 0; 162 } 163 #endif 164 165 return 1; 166 } 167 168 #ifndef DISCOVER_ONLY 169 static int 170 sun_clobber (PedDevice* dev) 171 { 172 SunRawLabel label; 173 174 PED_ASSERT (dev != NULL, return 0); 175 PED_ASSERT (sun_probe (dev), return 0); 176 177 if (!ped_device_read (dev, &label, 0, 1)) 178 return 0; 179 180 label.magic = 0; 181 return ped_device_write (dev, &label, 0, 1); 182 } 183 #endif /* !DISCOVER_ONLY */ 184 185 static PedDisk* 186 sun_alloc (const PedDevice* dev) 187 { 188 PedDisk* disk; 189 SunRawLabel* label; 190 SunDiskData* sun_specific; 191 PedCHSGeometry* bios_geom = &((PedDevice*)dev)->bios_geom; 192 PedSector cyl_size = bios_geom->sectors * bios_geom->heads; 193 194 disk = _ped_disk_alloc (dev, &sun_disk_type); 195 if (!disk) 196 goto error; 197 198 disk->disk_specific = (SunDiskData*) ped_malloc (sizeof (SunDiskData)); 199 if (!disk->disk_specific) 200 goto error_free_disk; 201 sun_specific = (SunDiskData*) disk->disk_specific; 202 203 bios_geom->cylinders = dev->length / cyl_size; 204 sun_specific->length = bios_geom->cylinders * cyl_size; 205 206 label = &sun_specific->raw_label; 207 memset(label, 0, sizeof(SunRawLabel)); 208 209 /* #gentoo-sparc people agree that nacyl = 0 is the best option */ 210 label->magic = PED_CPU_TO_BE16 (SUN_DISK_MAGIC); 211 label->nacyl = 0; 212 label->pcylcount = PED_CPU_TO_BE16 (bios_geom->cylinders); 213 label->rspeed = PED_CPU_TO_BE16 (5400); 214 label->ilfact = PED_CPU_TO_BE16 (1); 215 label->sparecyl = 0; 216 label->ntrks = PED_CPU_TO_BE16 (bios_geom->heads); 217 label->nsect = PED_CPU_TO_BE16 (bios_geom->sectors); 218 label->ncyl = PED_CPU_TO_BE16 (bios_geom->cylinders - 0); 219 220 /* Add a whole disk partition at a minimum */ 221 label->infos[WHOLE_DISK_PART].id = WHOLE_DISK_ID; 222 label->partitions[WHOLE_DISK_PART].start_cylinder = 0; 223 label->partitions[WHOLE_DISK_PART].num_sectors = 224 PED_CPU_TO_BE32(bios_geom->cylinders * cyl_size); 225 226 /* Now a neato string to describe this label */ 227 snprintf(label->info, sizeof(label->info) - 1, 228 "GNU Parted Custom cyl %d alt %d hd %d sec %d", 229 PED_BE16_TO_CPU(label->ncyl), 230 PED_BE16_TO_CPU(label->nacyl), 231 PED_BE16_TO_CPU(label->ntrks), 232 PED_BE16_TO_CPU(label->nsect)); 233 234 sun_compute_checksum(label); 235 return disk; 236 237 error_free_disk: 238 _ped_disk_free (disk); 239 error: 240 return NULL; 241 } 242 243 static PedDisk* 244 sun_duplicate (const PedDisk* disk) 245 { 246 PedDisk* new_disk; 247 SunDiskData* new_sun_data; 248 SunDiskData* old_sun_data = (SunDiskData*) disk->disk_specific; 249 250 new_disk = ped_disk_new_fresh (disk->dev, &sun_disk_type); 251 if (!new_disk) 252 return NULL; 253 254 new_sun_data = (SunDiskData*) new_disk->disk_specific; 255 memcpy (new_sun_data, old_sun_data, sizeof (SunDiskData)); 256 return new_disk; 257 } 258 259 static void 260 sun_free (PedDisk *disk) 261 { 262 ped_free (disk->disk_specific); 263 _ped_disk_free (disk); 264 } 265 266 static int 267 _check_geometry_sanity (PedDisk* disk, SunRawLabel* label) 268 { 269 PedDevice* dev = disk->dev; 270 271 if (PED_BE16_TO_CPU(label->nsect) == dev->hw_geom.sectors && 272 PED_BE16_TO_CPU(label->ntrks) == dev->hw_geom.heads) 273 dev->bios_geom = dev->hw_geom; 274 275 if (PED_BE16_TO_CPU(label->nsect) != dev->bios_geom.sectors || 276 PED_BE16_TO_CPU(label->ntrks) != dev->bios_geom.heads) { 277 #ifndef DISCOVER_ONLY 278 if (ped_exception_throw ( 279 PED_EXCEPTION_WARNING, 280 PED_EXCEPTION_IGNORE_CANCEL, 281 _("The disk CHS geometry (%d,%d,%d) reported " 282 "by the operating system does not match " 283 "the geometry stored on the disk label " 284 "(%d,%d,%d)."), 285 dev->bios_geom.cylinders, 286 dev->bios_geom.heads, 287 dev->bios_geom.sectors, 288 PED_BE16_TO_CPU(label->pcylcount), 289 PED_BE16_TO_CPU(label->ntrks), 290 PED_BE16_TO_CPU(label->nsect)) 291 == PED_EXCEPTION_CANCEL) 292 return 0; 293 #endif 294 dev->bios_geom.sectors = PED_BE16_TO_CPU(label->nsect); 295 dev->bios_geom.heads = PED_BE16_TO_CPU(label->ntrks); 296 dev->bios_geom.cylinders = PED_BE16_TO_CPU(label->pcylcount); 297 298 if (dev->bios_geom.sectors * dev->bios_geom.heads 299 * dev->bios_geom.cylinders > dev->length) { 300 if (ped_exception_throw ( 301 PED_EXCEPTION_WARNING, 302 PED_EXCEPTION_IGNORE_CANCEL, 303 _("The disk label describes a disk bigger than " 304 "%s."), 305 dev->path) 306 != PED_EXCEPTION_IGNORE) 307 return 0; 308 } 309 } 310 return 1; 311 } 312 313 static int 314 sun_read (PedDisk* disk) 315 { 316 SunRawLabel* label; 317 SunPartitionData* sun_data; 318 SunDiskData* disk_data; 319 int i; 320 PedPartition* part; 321 PedSector end, start, block; 322 PedConstraint* constraint_exact; 323 324 PED_ASSERT (disk != NULL, return 0); 325 PED_ASSERT (disk->dev != NULL, return 0); 326 PED_ASSERT (disk->disk_specific != NULL, return 0); 327 328 disk_data = (SunDiskData*) disk->disk_specific; 329 label = &disk_data->raw_label; 330 331 ped_disk_delete_all (disk); 332 333 if (!ped_device_read (disk->dev, label, 0, 1)) 334 goto error; 335 if (!_check_geometry_sanity (disk, label)) 336 goto error; 337 338 block = disk->dev->bios_geom.sectors * disk->dev->bios_geom.heads; 339 disk_data->length = block * disk->dev->bios_geom.cylinders; 340 341 for (i = 0; i < SUN_DISK_MAXPARTITIONS; i++) { 342 if (!PED_BE32_TO_CPU(label->partitions[i].num_sectors)) 343 continue; 344 if (!label->infos[i].id) 345 continue; 346 if (label->infos[i].id == WHOLE_DISK_ID) 347 continue; 348 349 start = PED_BE32_TO_CPU(label->partitions[i].start_cylinder) 350 * block; 351 end = start 352 + PED_BE32_TO_CPU(label->partitions[i].num_sectors) - 1; 353 354 part = ped_partition_new (disk, 0, NULL, start, end); 355 if (!part) 356 goto error; 357 358 sun_data = part->disk_specific; 359 sun_data->type = label->infos[i].id; 360 sun_data->is_boot = sun_data->type == 0x1; 361 sun_data->is_root = sun_data->type == 0x2; 362 sun_data->is_lvm = sun_data->type == 0x8e; 363 364 part->num = i + 1; 365 part->fs_type = ped_file_system_probe (&part->geom); 366 367 constraint_exact = ped_constraint_exact (&part->geom); 368 if (!ped_disk_add_partition (disk, part, constraint_exact)) 369 goto error; 370 ped_constraint_destroy (constraint_exact); 371 } 372 373 return 1; 374 375 error: 376 return 0; 377 } 378 379 #ifndef DISCOVER_ONLY 380 static void 381 _probe_and_use_old_info (const PedDisk* disk) 382 { 383 SunDiskData* sun_specific; 384 SunRawLabel old_label; 385 386 sun_specific = (SunDiskData*) disk->disk_specific; 387 388 if (!ped_device_read (disk->dev, &old_label, 0, 1)) 389 return; 390 if (old_label.info [0] 391 && PED_BE16_TO_CPU (old_label.magic) == SUN_DISK_MAGIC) 392 memcpy (&sun_specific->raw_label, &old_label, 512); 393 } 394 395 static int 396 sun_write (const PedDisk* disk) 397 { 398 SunRawLabel* label; 399 SunPartitionData* sun_data; 400 SunDiskData* disk_data; 401 PedPartition* part; 402 int i; 403 404 PED_ASSERT (disk != NULL, return 0); 405 PED_ASSERT (disk->dev != NULL, return 0); 406 407 _probe_and_use_old_info (disk); 408 409 disk_data = (SunDiskData*) disk->disk_specific; 410 label = &disk_data->raw_label; 411 412 memset (label->partitions, 0, 413 sizeof (SunRawPartition) * SUN_DISK_MAXPARTITIONS); 414 memset (label->infos, 0, 415 sizeof (SunPartitionInfo) * SUN_DISK_MAXPARTITIONS); 416 417 for (i = 0; i < SUN_DISK_MAXPARTITIONS; i++) { 418 part = ped_disk_get_partition (disk, i + 1); 419 420 if (!part && i == WHOLE_DISK_PART) { 421 /* Ok, nothing explicitly in the whole disk 422 partition, so let's put it there for safety 423 sake. */ 424 425 label->infos[i].id = WHOLE_DISK_ID; 426 label->partitions[i].start_cylinder = 0; 427 label->partitions[i].num_sectors = 428 PED_CPU_TO_BE32(disk_data->length); 429 continue; 430 } 431 if (!part) 432 continue; 433 434 sun_data = part->disk_specific; 435 label->infos[i].id = sun_data->type; 436 label->partitions[i].start_cylinder 437 = PED_CPU_TO_BE32 (part->geom.start 438 / (disk->dev->bios_geom.sectors 439 * disk->dev->bios_geom.heads)); 440 label->partitions[i].num_sectors 441 = PED_CPU_TO_BE32 (part->geom.end 442 - part->geom.start + 1); 443 } 444 445 /* We assume the harddrive is always right, and that the label may 446 be wrong. I don't think this will cause any problems, since the 447 cylinder count is always enforced by our alignment, and we 448 sanity checked the sectors/heads when we detected the device. The 449 worst that could happen here is that the drive seems bigger or 450 smaller than it really is, but we'll have that problem even if we 451 don't do this. */ 452 453 if (disk->dev->bios_geom.cylinders > 65536) { 454 ped_exception_throw ( 455 PED_EXCEPTION_WARNING, 456 PED_EXCEPTION_IGNORE, 457 _("The disk has %d cylinders, which is greater than " 458 "the maximum of 65536."), 459 disk->dev->bios_geom.cylinders); 460 } 461 462 label->pcylcount = PED_CPU_TO_BE16 (disk->dev->bios_geom.cylinders); 463 label->ncyl = PED_CPU_TO_BE16 (disk->dev->bios_geom.cylinders 464 - PED_BE16_TO_CPU (label->nacyl)); 465 466 sun_compute_checksum (label); 467 468 if (!ped_device_write (disk->dev, label, 0, 1)) 469 goto error; 470 return ped_device_sync (disk->dev); 471 472 error: 473 return 0; 474 } 475 #endif /* !DISCOVER_ONLY */ 476 477 static PedPartition* 478 sun_partition_new (const PedDisk* disk, PedPartitionType part_type, 479 const PedFileSystemType* fs_type, 480 PedSector start, PedSector end) 481 { 482 PedPartition* part; 483 SunPartitionData* sun_data; 484 485 part = _ped_partition_alloc (disk, part_type, fs_type, start, end); 486 if (!part) 487 goto error; 488 489 if (ped_partition_is_active (part)) { 490 part->disk_specific 491 = sun_data = ped_malloc (sizeof (SunPartitionData)); 492 if (!sun_data) 493 goto error_free_part; 494 sun_data->type = 0; 495 sun_data->is_boot = 0; 496 sun_data->is_root = 0; 497 sun_data->is_lvm = 0; 498 } else { 499 part->disk_specific = NULL; 500 } 501 502 return part; 503 504 ped_free (sun_data); 505 error_free_part: 506 ped_free (part); 507 error: 508 return NULL; 509 } 510 511 static PedPartition* 512 sun_partition_duplicate (const PedPartition* part) 513 { 514 PedPartition* new_part; 515 SunPartitionData* new_sun_data; 516 SunPartitionData* old_sun_data; 517 518 new_part = ped_partition_new (part->disk, part->type, 519 part->fs_type, part->geom.start, 520 part->geom.end); 521 if (!new_part) 522 return NULL; 523 new_part->num = part->num; 524 525 old_sun_data = (SunPartitionData*) part->disk_specific; 526 new_sun_data = (SunPartitionData*) new_part->disk_specific; 527 new_sun_data->type = old_sun_data->type; 528 new_sun_data->is_boot = old_sun_data->is_boot; 529 new_sun_data->is_root = old_sun_data->is_root; 530 new_sun_data->is_lvm = old_sun_data->is_lvm; 531 return new_part; 532 } 533 534 static void 535 sun_partition_destroy (PedPartition* part) 536 { 537 PED_ASSERT (part != NULL, return); 538 539 if (ped_partition_is_active (part)) 540 ped_free (part->disk_specific); 541 ped_free (part); 542 } 543 544 static int 545 sun_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type) 546 { 547 SunPartitionData* sun_data = part->disk_specific; 548 549 part->fs_type = fs_type; 550 551 if (sun_data->is_boot) { 552 sun_data->type = 0x1; 553 return 1; 554 } 555 if (sun_data->is_root) { 556 sun_data->type = 0x2; 557 return 1; 558 } 559 if (sun_data->is_lvm) { 560 sun_data->type = 0x8e; 561 return 1; 562 } 563 564 sun_data->type = 0x83; 565 if (fs_type) { 566 if (!strcmp (fs_type->name, "linux-swap")) 567 sun_data->type = 0x82; 568 else if (!strcmp (fs_type->name, "ufs")) 569 sun_data->type = 0x6; 570 } 571 572 return 1; 573 } 574 575 static int 576 sun_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) 577 { 578 SunPartitionData* sun_data; 579 580 PED_ASSERT (part != NULL, return 0); 581 PED_ASSERT (part->disk_specific != NULL, return 0); 582 PED_ASSERT (ped_partition_is_flag_available (part, flag), return 0); 583 584 sun_data = part->disk_specific; 585 586 switch (flag) { 587 case PED_PARTITION_BOOT: 588 sun_data->is_boot = state; 589 if (state) 590 sun_data->is_root = sun_data->is_lvm = 0; 591 return ped_partition_set_system (part, part->fs_type); 592 593 case PED_PARTITION_ROOT: 594 sun_data->is_root = state; 595 if (state) 596 sun_data->is_boot = sun_data->is_lvm = 0; 597 return ped_partition_set_system (part, part->fs_type); 598 599 case PED_PARTITION_LVM: 600 sun_data->is_lvm = state; 601 if (state) 602 sun_data->is_root = sun_data->is_boot = 0; 603 return ped_partition_set_system (part, part->fs_type); 604 605 default: 606 return 0; 607 } 608 } 609 610 611 static int 612 sun_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) 613 { 614 SunPartitionData* sun_data; 615 616 PED_ASSERT (part != NULL, return 0); 617 PED_ASSERT (part->disk_specific != NULL, return 0); 618 619 sun_data = part->disk_specific; 620 621 switch (flag) { 622 case PED_PARTITION_BOOT: 623 return sun_data->is_boot; 624 case PED_PARTITION_ROOT: 625 return sun_data->is_root; 626 case PED_PARTITION_LVM: 627 return sun_data->is_lvm; 628 629 default: 630 return 0; 631 } 632 } 633 634 635 static int 636 sun_partition_is_flag_available (const PedPartition* part, 637 PedPartitionFlag flag) 638 { 639 switch (flag) { 640 case PED_PARTITION_BOOT: 641 case PED_PARTITION_ROOT: 642 case PED_PARTITION_LVM: 643 return 1; 644 645 default: 646 return 0; 647 } 648 } 649 650 651 static int 652 sun_get_max_primary_partition_count (const PedDisk* disk) 653 { 654 return SUN_DISK_MAXPARTITIONS; 655 } 656 657 static PedConstraint* 658 _get_strict_constraint (PedDisk* disk) 659 { 660 PedDevice* dev = disk->dev; 661 PedAlignment start_align; 662 PedAlignment end_align; 663 PedGeometry max_geom; 664 SunDiskData* disk_data = disk->disk_specific; 665 PedSector block = dev->bios_geom.sectors * dev->bios_geom.heads; 666 667 if (!ped_alignment_init (&start_align, 0, block)) 668 return NULL; 669 if (!ped_alignment_init (&end_align, -1, block)) 670 return NULL; 671 if (!ped_geometry_init (&max_geom, dev, 0, disk_data->length)) 672 return NULL; 673 674 return ped_constraint_new (&start_align, &end_align, &max_geom, 675 &max_geom, 1, dev->length); 676 } 677 678 static PedConstraint* 679 _get_lax_constraint (PedDisk* disk) 680 { 681 PedDevice* dev = disk->dev; 682 PedAlignment start_align; 683 PedGeometry max_geom; 684 SunDiskData* disk_data = disk->disk_specific; 685 PedSector block = dev->bios_geom.sectors * dev->bios_geom.heads; 686 687 if (!ped_alignment_init (&start_align, 0, block)) 688 return NULL; 689 if (!ped_geometry_init (&max_geom, dev, 0, disk_data->length)) 690 return NULL; 691 692 return ped_constraint_new (&start_align, ped_alignment_any, &max_geom, 693 &max_geom, 1, dev->length); 694 } 695 696 /* _get_strict_constraint() will align the partition to the end of the cylinder. 697 * This isn't required, but since partitions must start at the start of the 698 * cylinder, space between the end of a partition and the end of a cylinder 699 * is unusable, so there's no point wasting space! 700 * However, if they really insist (via constraint)... which they will 701 * if they're reading a weird table of the disk... then we allow the end to 702 * be anywhere, with _get_lax_constraint() 703 */ 704 static int 705 sun_partition_align (PedPartition* part, const PedConstraint* constraint) 706 { 707 PED_ASSERT (part != NULL, return 0); 708 709 if (_ped_partition_attempt_align (part, constraint, 710 _get_strict_constraint (part->disk))) 711 return 1; 712 if (_ped_partition_attempt_align (part, constraint, 713 _get_lax_constraint (part->disk))) 714 return 1; 715 716 #ifndef DISCOVER_ONLY 717 ped_exception_throw ( 718 PED_EXCEPTION_ERROR, 719 PED_EXCEPTION_CANCEL, 720 _("Unable to satisfy all constraints on the partition.")); 721 #endif 722 return 0; 723 } 724 725 static int 726 sun_partition_enumerate (PedPartition* part) 727 { 728 int i; 729 PedPartition* p; 730 731 /* never change the partition numbers */ 732 if (part->num != -1) 733 return 1; 734 for (i = 1; i <= SUN_DISK_MAXPARTITIONS; i++) { 735 /* skip the Whole Disk partition for now */ 736 if (i == WHOLE_DISK_PART + 1) 737 continue; 738 p = ped_disk_get_partition (part->disk, i); 739 if (!p) { 740 part->num = i; 741 return 1; 742 } 743 } 744 745 #ifndef DISCOVER_ONLY 746 /* Ok, now allocate the Whole disk if it isn't already */ 747 p = ped_disk_get_partition (part->disk, WHOLE_DISK_PART + 1); 748 if (!p) { 749 int j = ped_exception_throw ( 750 PED_EXCEPTION_WARNING, 751 PED_EXCEPTION_IGNORE_CANCEL, 752 _("The Whole Disk partition is the only " 753 "available one left. Generally, it is not a " 754 "good idea to overwrite this partition with " 755 "a real one. Solaris may not be able to " 756 "boot without it, and SILO (the sparc boot " 757 "loader) appreciates it as well.")); 758 if (j == PED_EXCEPTION_IGNORE) { 759 /* bad bad bad...you will suffer your own fate */ 760 part->num = WHOLE_DISK_PART + 1; 761 return 1; 762 } 763 } 764 765 /* failed to allocate a number, this means we are full */ 766 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 767 _("Sun disk label is full.")); 768 #endif 769 return 0; 770 } 771 772 static int 773 sun_alloc_metadata (PedDisk* disk) 774 { 775 PedPartition* new_part; 776 SunDiskData* disk_data; 777 PedConstraint* constraint_any; 778 779 PED_ASSERT (disk != NULL, return 0); 780 PED_ASSERT (disk->disk_specific != NULL, return 0); 781 PED_ASSERT (disk->dev != NULL, return 0); 782 783 constraint_any = ped_constraint_any (disk->dev); 784 785 /* Sun disk label does not need to allocate a sector. The disk 786 label is contained within the first 512 bytes, which should not 787 be overwritten by any boot loader or superblock. It is safe for 788 most partitions to start at sector 0. We do however, allocate 789 the space used by alt-cyl's, since we cannot use those. Put them 790 at the end of the disk. */ 791 792 disk_data = disk->disk_specific; 793 794 if (disk->dev->length <= 0 || 795 disk_data->length <= 0 || 796 disk->dev->length == disk_data->length) 797 goto error; 798 799 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 800 disk_data->length, disk->dev->length - 1); 801 if (!new_part) 802 goto error; 803 804 if (!ped_disk_add_partition (disk, new_part, constraint_any)) { 805 ped_partition_destroy (new_part); 806 goto error; 807 } 808 809 ped_constraint_destroy (constraint_any); 810 return 1; 811 error: 812 ped_constraint_destroy (constraint_any); 813 return 0; 814 } 815 816 static PedDiskOps sun_disk_ops = { 817 .probe = sun_probe, 818 #ifndef DISCOVER_ONLY 819 .clobber = sun_clobber, 820 #else 821 .clobber = NULL, 822 #endif 823 .alloc = sun_alloc, 824 .duplicate = sun_duplicate, 825 .free = sun_free, 826 .read = sun_read, 827 #ifndef DISCOVER_ONLY 828 .write = sun_write, 829 #else 830 .write = NULL, 831 #endif 832 833 .partition_new = sun_partition_new, 834 .partition_duplicate = sun_partition_duplicate, 835 .partition_destroy = sun_partition_destroy, 836 .partition_set_system = sun_partition_set_system, 837 .partition_set_flag = sun_partition_set_flag, 838 .partition_get_flag = sun_partition_get_flag, 839 .partition_is_flag_available = sun_partition_is_flag_available, 840 .partition_align = sun_partition_align, 841 .partition_enumerate = sun_partition_enumerate, 842 .alloc_metadata = sun_alloc_metadata, 843 .get_max_primary_partition_count = 844 sun_get_max_primary_partition_count, 845 846 .partition_set_name = NULL, 847 .partition_get_name = NULL, 848 }; 849 850 static PedDiskType sun_disk_type = { 851 .next = NULL, 852 .name = "sun", 853 .ops = &sun_disk_ops, 854 .features = 0 855 }; 856 857 void 858 ped_disk_sun_init () 859 { 860 PED_ASSERT (sizeof (SunRawLabel) == 512, return); 861 ped_disk_type_register (&sun_disk_type); 862 } 863 864 void 865 ped_disk_sun_done () 866 { 867 ped_disk_type_unregister (&sun_disk_type); 868 }