1 /* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 2 3 libparted - a library for manipulating disk partitions 4 disk_amiga.c - libparted module to manipulate amiga RDB partition tables. 5 Copyright (C) 2000, 2001, 2004, 2007 Free Software Foundation, Inc. 6 7 This program is free software; you can redistribute it and/or modify 8 it under the terms of the GNU General Public License as published by 9 the Free Software Foundation; either version 3 of the License, or 10 (at your option) any later version. 11 12 This program is distributed in the hope that it will be useful, 13 but WITHOUT ANY WARRANTY; without even the implied warranty of 14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 GNU General Public License for more details. 16 17 You should have received a copy of the GNU General Public License 18 along with this program. If not, see <http://www.gnu.org/licenses/>. 19 20 Contributor: Sven Luther <luther@debian.org> 21 */ 22 23 #include <config.h> 24 25 #include <parted/parted.h> 26 #include <parted/debug.h> 27 #include <parted/endian.h> 28 29 #ifndef MAX 30 # define MAX(a,b) ((a) < (b) ? (b) : (a)) 31 #endif 32 33 #if ENABLE_NLS 34 # include <libintl.h> 35 # define _(String) dgettext (PACKAGE, String) 36 #else 37 # define _(String) (String) 38 #endif /* ENABLE_NLS */ 39 40 /* String manipulation */ 41 static void _amiga_set_bstr (const char *cstr, char *bstr, int maxsize) { 42 int size = strlen (cstr); 43 int i; 44 45 if (size >= maxsize) return; 46 bstr[0] = size; 47 for (i = 0; i<size; i++) bstr[i+1] = cstr[i]; 48 } 49 static const char * _amiga_get_bstr (char * bstr) { 50 char * cstr = bstr + 1; 51 int size = bstr[0]; 52 53 cstr[size] = '\0'; 54 return cstr; 55 } 56 57 #define IDNAME_RIGIDDISK (uint32_t)0x5244534B /* 'RDSK' */ 58 #define IDNAME_BADBLOCK (uint32_t)0x42414442 /* 'BADB' */ 59 #define IDNAME_PARTITION (uint32_t)0x50415254 /* 'PART' */ 60 #define IDNAME_FILESYSHEADER (uint32_t)0x46534844 /* 'FSHD' */ 61 #define IDNAME_LOADSEG (uint32_t)0x4C534547 /* 'LSEG' */ 62 #define IDNAME_BOOT (uint32_t)0x424f4f54 /* 'BOOT' */ 63 #define IDNAME_FREE (uint32_t)0xffffffff 64 65 static const char * 66 _amiga_block_id (uint32_t id) { 67 switch (id) { 68 case IDNAME_RIGIDDISK : 69 return "RDSK"; 70 case IDNAME_BADBLOCK : 71 return "BADB"; 72 case IDNAME_PARTITION : 73 return "PART"; 74 case IDNAME_FILESYSHEADER : 75 return "FSHD"; 76 case IDNAME_LOADSEG : 77 return "LSEG"; 78 case IDNAME_BOOT : 79 return "BOOT"; 80 case IDNAME_FREE : 81 return "<free>"; 82 default : 83 return "<unknown>"; 84 } 85 } 86 87 struct AmigaIds { 88 uint32_t ID; 89 struct AmigaIds *next; 90 }; 91 92 static struct AmigaIds * 93 _amiga_add_id (uint32_t id, struct AmigaIds *ids) { 94 struct AmigaIds *newid; 95 96 if ((newid=ped_malloc(sizeof (struct AmigaIds)))==NULL) 97 return 0; 98 newid->ID = id; 99 newid->next = ids; 100 return newid; 101 } 102 103 static void 104 _amiga_free_ids (struct AmigaIds *ids) { 105 struct AmigaIds *current, *next; 106 107 for (current = ids; current != NULL; current = next) { 108 next = current->next; 109 ped_free (current); 110 } 111 } 112 static int 113 _amiga_id_in_list (uint32_t id, struct AmigaIds *ids) { 114 struct AmigaIds *current; 115 116 for (current = ids; current != NULL; current = current->next) { 117 if (id == current->ID) 118 return 1; 119 } 120 return 0; 121 } 122 123 struct AmigaBlock { 124 uint32_t amiga_ID; /* Identifier 32 bit word */ 125 uint32_t amiga_SummedLongss; /* Size of the structure for checksums */ 126 int32_t amiga_ChkSum; /* Checksum of the structure */ 127 }; 128 #define AMIGA(pos) ((struct AmigaBlock *)(pos)) 129 130 static int 131 _amiga_checksum (struct AmigaBlock *blk) { 132 uint32_t *rdb = (uint32_t *) blk; 133 uint32_t sum; 134 int i, end; 135 136 sum = PED_BE32_TO_CPU (rdb[0]); 137 end = PED_BE32_TO_CPU (rdb[1]); 138 139 if (end > PED_SECTOR_SIZE_DEFAULT) end = PED_SECTOR_SIZE_DEFAULT; 140 141 for (i = 1; i < end; i++) sum += PED_BE32_TO_CPU (rdb[i]); 142 143 return sum; 144 } 145 146 static void 147 _amiga_calculate_checksum (struct AmigaBlock *blk) { 148 blk->amiga_ChkSum = PED_CPU_TO_BE32( 149 PED_BE32_TO_CPU(blk->amiga_ChkSum) - 150 _amiga_checksum((struct AmigaBlock *) blk)); 151 return; 152 } 153 154 static struct AmigaBlock * 155 _amiga_read_block (const PedDevice *dev, struct AmigaBlock *blk, 156 PedSector block, struct AmigaIds *ids) 157 { 158 if (!ped_device_read (dev, blk, block, 1)) 159 return NULL; 160 if (ids && !_amiga_id_in_list(PED_BE32_TO_CPU(blk->amiga_ID), ids)) 161 return NULL; 162 if (_amiga_checksum (blk) != 0) { 163 switch (ped_exception_throw(PED_EXCEPTION_ERROR, 164 PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, 165 _("%s : Bad checksum on block %llu of type %s."), 166 __func__, block, _amiga_block_id(PED_BE32_TO_CPU(blk->amiga_ID)))) 167 { 168 case PED_EXCEPTION_CANCEL : 169 return NULL; 170 case PED_EXCEPTION_FIX : 171 _amiga_calculate_checksum(AMIGA(blk)); 172 if (!ped_device_write ((PedDevice*)dev, blk, block, 1)) 173 return NULL; 174 case PED_EXCEPTION_IGNORE : 175 case PED_EXCEPTION_UNHANDLED : 176 default : 177 return blk; 178 } 179 } 180 return blk; 181 } 182 183 struct RigidDiskBlock { 184 uint32_t rdb_ID; /* Identifier 32 bit word : 'RDSK' */ 185 uint32_t rdb_SummedLongs; /* Size of the structure for checksums */ 186 int32_t rdb_ChkSum; /* Checksum of the structure */ 187 uint32_t rdb_HostID; /* SCSI Target ID of host, not really used */ 188 uint32_t rdb_BlockBytes; /* Size of disk blocks */ 189 uint32_t rdb_Flags; /* RDB Flags */ 190 /* block list heads */ 191 uint32_t rdb_BadBlockList; /* Bad block list */ 192 uint32_t rdb_PartitionList; /* Partition list */ 193 uint32_t rdb_FileSysHeaderList; /* File system header list */ 194 uint32_t rdb_DriveInit; /* Drive specific init code */ 195 uint32_t rdb_BootBlockList; /* Amiga OS 4 Boot Blocks */ 196 uint32_t rdb_Reserved1[5]; /* Unused word, need to be set to $ffffffff */ 197 /* physical drive characteristics */ 198 uint32_t rdb_Cylinders; /* Number of the cylinders of the drive */ 199 uint32_t rdb_Sectors; /* Number of sectors of the drive */ 200 uint32_t rdb_Heads; /* Number of heads of the drive */ 201 uint32_t rdb_Interleave; /* Interleave */ 202 uint32_t rdb_Park; /* Head parking cylinder */ 203 uint32_t rdb_Reserved2[3]; /* Unused word, need to be set to $ffffffff */ 204 uint32_t rdb_WritePreComp; /* Starting cylinder of write precompensation */ 205 uint32_t rdb_ReducedWrite; /* Starting cylinder of reduced write current */ 206 uint32_t rdb_StepRate; /* Step rate of the drive */ 207 uint32_t rdb_Reserved3[5]; /* Unused word, need to be set to $ffffffff */ 208 /* logical drive characteristics */ 209 uint32_t rdb_RDBBlocksLo; /* low block of range reserved for hardblocks */ 210 uint32_t rdb_RDBBlocksHi; /* high block of range for these hardblocks */ 211 uint32_t rdb_LoCylinder; /* low cylinder of partitionable disk area */ 212 uint32_t rdb_HiCylinder; /* high cylinder of partitionable data area */ 213 uint32_t rdb_CylBlocks; /* number of blocks available per cylinder */ 214 uint32_t rdb_AutoParkSeconds; /* zero for no auto park */ 215 uint32_t rdb_HighRDSKBlock; /* highest block used by RDSK */ 216 /* (not including replacement bad blocks) */ 217 uint32_t rdb_Reserved4; 218 /* drive identification */ 219 char rdb_DiskVendor[8]; 220 char rdb_DiskProduct[16]; 221 char rdb_DiskRevision[4]; 222 char rdb_ControllerVendor[8]; 223 char rdb_ControllerProduct[16]; 224 char rdb_ControllerRevision[4]; 225 uint32_t rdb_Reserved5[10]; 226 }; 227 228 #define RDSK(pos) ((struct RigidDiskBlock *)(pos)) 229 230 #define AMIGA_RDB_NOT_FOUND ((uint32_t)0xffffffff) 231 #define RDB_LOCATION_LIMIT 16 232 #define AMIGA_MAX_PARTITIONS 128 233 #define MAX_RDB_BLOCK (RDB_LOCATION_LIMIT + 2 * AMIGA_MAX_PARTITIONS + 2) 234 235 static uint32_t 236 _amiga_find_rdb (const PedDevice *dev, struct RigidDiskBlock *rdb) { 237 int i; 238 struct AmigaIds *ids; 239 240 ids = _amiga_add_id (IDNAME_RIGIDDISK, NULL); 241 242 for (i = 0; i<RDB_LOCATION_LIMIT; i++) { 243 if (!_amiga_read_block (dev, AMIGA(rdb), i, ids)) { 244 continue; 245 } 246 if (PED_BE32_TO_CPU (rdb->rdb_ID) == IDNAME_RIGIDDISK) { 247 _amiga_free_ids (ids); 248 return i; 249 } 250 } 251 _amiga_free_ids (ids); 252 return AMIGA_RDB_NOT_FOUND; 253 } 254 255 struct PartitionBlock { 256 uint32_t pb_ID; /* Identifier 32 bit word : 'PART' */ 257 uint32_t pb_SummedLongs; /* Size of the structure for checksums */ 258 int32_t pb_ChkSum; /* Checksum of the structure */ 259 uint32_t pb_HostID; /* SCSI Target ID of host, not really used */ 260 uint32_t pb_Next; /* Block number of the next PartitionBlock */ 261 uint32_t pb_Flags; /* Part Flags (NOMOUNT and BOOTABLE) */ 262 uint32_t pb_Reserved1[2]; 263 uint32_t pb_DevFlags; /* Preferred flags for OpenDevice */ 264 char pb_DriveName[32]; /* Preferred DOS device name: BSTR form */ 265 uint32_t pb_Reserved2[15]; 266 uint32_t de_TableSize; /* Size of Environment vector */ 267 /* Size of the blocks in 32 bit words, usually 128 */ 268 uint32_t de_SizeBlock; 269 uint32_t de_SecOrg; /* Not used; must be 0 */ 270 uint32_t de_Surfaces; /* Number of heads (surfaces) */ 271 /* Disk sectors per block, used with SizeBlock, usually 1 */ 272 uint32_t de_SectorPerBlock; 273 uint32_t de_BlocksPerTrack; /* Blocks per track. drive specific */ 274 uint32_t de_Reserved; /* DOS reserved blocks at start of partition. */ 275 uint32_t de_PreAlloc; /* DOS reserved blocks at end of partition */ 276 uint32_t de_Interleave; /* Not used, usually 0 */ 277 uint32_t de_LowCyl; /* First cylinder of the partition */ 278 uint32_t de_HighCyl; /* Last cylinder of the partition */ 279 uint32_t de_NumBuffers; /* Initial # DOS of buffers. */ 280 uint32_t de_BufMemType; /* Type of mem to allocate for buffers */ 281 uint32_t de_MaxTransfer; /* Max number of bytes to transfer at a time */ 282 uint32_t de_Mask; /* Address Mask to block out certain memory */ 283 int32_t de_BootPri; /* Boot priority for autoboot */ 284 uint32_t de_DosType; /* Dostype of the file system */ 285 uint32_t de_Baud; /* Baud rate for serial handler */ 286 uint32_t de_Control; /* Control word for handler/filesystem */ 287 uint32_t de_BootBlocks; /* Number of blocks containing boot code */ 288 uint32_t pb_EReserved[12]; 289 }; 290 291 #define PART(pos) ((struct PartitionBlock *)(pos)) 292 293 #define PBFB_BOOTABLE 0 /* this partition is intended to be bootable */ 294 #define PBFF_BOOTABLE 1L /* (expected directories and files exist) */ 295 #define PBFB_NOMOUNT 1 /* do not mount this partition (e.g. manually */ 296 #define PBFF_NOMOUNT 2L /* mounted, but space reserved here) */ 297 #define PBFB_RAID 2 /* this partition is intended to be part of */ 298 #define PBFF_RAID 4L /* a RAID array */ 299 #define PBFB_LVM 3 /* this partition is intended to be part of */ 300 #define PBFF_LVM 8L /* a LVM volume group */ 301 302 303 struct LinkedBlock { 304 uint32_t lk_ID; /* Identifier 32 bit word */ 305 uint32_t lk_SummedLongs; /* Size of the structure for checksums */ 306 int32_t lk_ChkSum; /* Checksum of the structure */ 307 uint32_t pb_HostID; /* SCSI Target ID of host, not really used */ 308 uint32_t lk_Next; /* Block number of the next PartitionBlock */ 309 }; 310 struct Linked2Block { 311 uint32_t lk2_ID; /* Identifier 32 bit word */ 312 uint32_t lk2_SummedLongs; /* Size of the structure for checksums */ 313 int32_t lk2_ChkSum; /* Checksum of the structure */ 314 uint32_t lk2_HostID; /* SCSI Target ID of host, not really used */ 315 uint32_t lk2_Next; /* Block number of the next PartitionBlock */ 316 uint32_t lk2_Reverved[13]; 317 uint32_t lk2_Linked; /* Secondary linked list */ 318 }; 319 #define LINK_END (uint32_t)0xffffffff 320 #define LNK(pos) ((struct LinkedBlock *)(pos)) 321 #define LNK2(pos) ((struct Linked2Block *)(pos)) 322 323 324 static PedDiskType amiga_disk_type; 325 326 static int 327 amiga_probe (const PedDevice *dev) 328 { 329 struct RigidDiskBlock *rdb; 330 uint32_t found; 331 PED_ASSERT(dev != NULL, return 0); 332 333 if ((rdb=RDSK(ped_malloc(dev->sector_size)))==NULL) 334 return 0; 335 found = _amiga_find_rdb (dev, rdb); 336 ped_free (rdb); 337 338 return (found == AMIGA_RDB_NOT_FOUND ? 0 : 1); 339 } 340 341 static PedDisk* 342 amiga_alloc (const PedDevice* dev) 343 { 344 PedDisk *disk; 345 struct RigidDiskBlock *rdb; 346 PedSector cyl_size; 347 int highest_cylinder, highest_block; 348 349 PED_ASSERT(dev != NULL, return NULL); 350 cyl_size = dev->hw_geom.sectors * dev->hw_geom.heads; 351 352 if (!(disk = _ped_disk_alloc (dev, &amiga_disk_type))) 353 return NULL; 354 355 if (!(disk->disk_specific = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { 356 ped_free (disk); 357 return NULL; 358 } 359 rdb = disk->disk_specific; 360 361 memset(rdb, 0, sizeof(struct RigidDiskBlock)); 362 363 rdb->rdb_ID = PED_CPU_TO_BE32 (IDNAME_RIGIDDISK); 364 rdb->rdb_SummedLongs = PED_CPU_TO_BE32 (64); 365 rdb->rdb_HostID = PED_CPU_TO_BE32 (0); 366 rdb->rdb_BlockBytes = PED_CPU_TO_BE32 (PED_SECTOR_SIZE_DEFAULT); 367 rdb->rdb_Flags = PED_CPU_TO_BE32 (0); 368 369 /* Block lists */ 370 rdb->rdb_BadBlockList = PED_CPU_TO_BE32 (LINK_END); 371 rdb->rdb_PartitionList = PED_CPU_TO_BE32 (LINK_END); 372 rdb->rdb_FileSysHeaderList = PED_CPU_TO_BE32 (LINK_END); 373 rdb->rdb_DriveInit = PED_CPU_TO_BE32 (LINK_END); 374 rdb->rdb_BootBlockList = PED_CPU_TO_BE32 (LINK_END); 375 376 /* Physical drive characteristics */ 377 rdb->rdb_Cylinders = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); 378 rdb->rdb_Sectors = PED_CPU_TO_BE32 (dev->hw_geom.sectors); 379 rdb->rdb_Heads = PED_CPU_TO_BE32 (dev->hw_geom.heads); 380 rdb->rdb_Interleave = PED_CPU_TO_BE32 (0); 381 rdb->rdb_Park = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); 382 rdb->rdb_WritePreComp = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); 383 rdb->rdb_ReducedWrite = PED_CPU_TO_BE32 (dev->hw_geom.cylinders); 384 rdb->rdb_StepRate = PED_CPU_TO_BE32 (0); 385 386 highest_cylinder = 1 + MAX_RDB_BLOCK / cyl_size; 387 highest_block = highest_cylinder * cyl_size - 1; 388 389 /* Logical driver characteristics */ 390 rdb->rdb_RDBBlocksLo = PED_CPU_TO_BE32 (0); 391 rdb->rdb_RDBBlocksHi = PED_CPU_TO_BE32 (highest_block); 392 rdb->rdb_LoCylinder = PED_CPU_TO_BE32 (highest_cylinder); 393 rdb->rdb_HiCylinder = PED_CPU_TO_BE32 (dev->hw_geom.cylinders -1); 394 rdb->rdb_CylBlocks = PED_CPU_TO_BE32 (cyl_size); 395 rdb->rdb_AutoParkSeconds = PED_CPU_TO_BE32 (0); 396 /* rdb_HighRDSKBlock will only be set when writing */ 397 rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32 (0); 398 399 /* Driver identification */ 400 _amiga_set_bstr("", rdb->rdb_DiskVendor, 8); 401 _amiga_set_bstr(dev->model, rdb->rdb_DiskProduct, 16); 402 _amiga_set_bstr("", rdb->rdb_DiskRevision, 4); 403 _amiga_set_bstr("", rdb->rdb_ControllerVendor, 8); 404 _amiga_set_bstr("", rdb->rdb_ControllerProduct, 16); 405 _amiga_set_bstr("", rdb->rdb_ControllerRevision, 4); 406 407 /* And calculate the checksum */ 408 _amiga_calculate_checksum ((struct AmigaBlock *) rdb); 409 410 return disk; 411 } 412 413 static PedDisk* 414 amiga_duplicate (const PedDisk* disk) 415 { 416 PedDisk* new_disk; 417 struct RigidDiskBlock * new_rdb; 418 struct RigidDiskBlock * old_rdb; 419 PED_ASSERT(disk != NULL, return NULL); 420 PED_ASSERT(disk->dev != NULL, return NULL); 421 PED_ASSERT(disk->disk_specific != NULL, return NULL); 422 423 old_rdb = (struct RigidDiskBlock *) disk->disk_specific; 424 425 if (!(new_disk = ped_disk_new_fresh (disk->dev, &amiga_disk_type))) 426 return NULL; 427 428 new_rdb = (struct RigidDiskBlock *) new_disk->disk_specific; 429 memcpy (new_rdb, old_rdb, 256); 430 return new_disk; 431 } 432 433 static void 434 amiga_free (PedDisk* disk) 435 { 436 PED_ASSERT(disk != NULL, return); 437 PED_ASSERT(disk->disk_specific != NULL, return); 438 439 ped_free (disk->disk_specific); 440 _ped_disk_free (disk); 441 } 442 443 #ifndef DISCOVER_ONLY 444 static int 445 amiga_clobber (PedDevice* dev) 446 { 447 struct RigidDiskBlock *rdb; 448 uint32_t i; 449 int result = 0; 450 PED_ASSERT(dev != NULL, return 0); 451 452 if ((rdb=RDSK(ped_malloc(PED_SECTOR_SIZE_DEFAULT)))==NULL) 453 return 0; 454 455 while ((i = _amiga_find_rdb (dev, rdb)) != AMIGA_RDB_NOT_FOUND) { 456 rdb->rdb_ID = PED_CPU_TO_BE32 (0); 457 result = ped_device_write (dev, (void*) rdb, i, 1); 458 } 459 460 ped_free (rdb); 461 462 return result; 463 } 464 #endif /* !DISCOVER_ONLY */ 465 466 static int 467 _amiga_loop_check (uint32_t block, uint32_t * blocklist, uint32_t max) 468 { 469 uint32_t i; 470 471 for (i = 0; i < max; i++) 472 if (block == blocklist[i]) { 473 /* We are looping, let's stop. */ 474 return 1; 475 } 476 blocklist[max] = block; 477 return 0; 478 } 479 480 /* We have already allocated a rdb, we are now reading it from the disk */ 481 static int 482 amiga_read (PedDisk* disk) 483 { 484 struct RigidDiskBlock *rdb; 485 struct PartitionBlock *partition; 486 uint32_t partblock; 487 uint32_t partlist[AMIGA_MAX_PARTITIONS]; 488 PedSector cylblocks; 489 int i; 490 491 PED_ASSERT(disk != NULL, return 0); 492 PED_ASSERT(disk->dev != NULL, return 0); 493 PED_ASSERT(disk->dev->sector_size % PED_SECTOR_SIZE_DEFAULT == 0, 494 return 0); 495 PED_ASSERT(disk->disk_specific != NULL, return 0); 496 rdb = RDSK(disk->disk_specific); 497 498 if (_amiga_find_rdb (disk->dev, rdb) == AMIGA_RDB_NOT_FOUND) { 499 ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 500 _("%s : Didn't find rdb block, should never happen."), __func__); 501 return 0; 502 } 503 504 /* Let's copy the rdb read geometry to the dev */ 505 /* FIXME: should this go into disk->dev->bios_geom instead? */ 506 disk->dev->hw_geom.cylinders = PED_BE32_TO_CPU (rdb->rdb_Cylinders); 507 disk->dev->hw_geom.heads = PED_BE32_TO_CPU (rdb->rdb_Heads); 508 disk->dev->hw_geom.sectors = PED_BE32_TO_CPU (rdb->rdb_Sectors); 509 cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) * 510 (PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors); 511 512 /* Remove all partitions in the former in memory table */ 513 ped_disk_delete_all (disk); 514 515 /* Let's allocate a partition block */ 516 if (!(partition = ped_malloc (disk->dev->sector_size))) 517 return 0; 518 519 /* We initialize the hardblock free list to detect loops */ 520 for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = LINK_END; 521 522 for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList); 523 i < AMIGA_MAX_PARTITIONS && partblock != LINK_END; 524 i++, partblock = PED_BE32_TO_CPU(partition->pb_Next)) 525 { 526 PedPartition *part; 527 PedSector start, end; 528 PedConstraint *constraint_exact; 529 530 /* Let's look for loops in the partition table */ 531 if (_amiga_loop_check(partblock, partlist, i)) { 532 break; 533 } 534 535 /* Let's allocate and read a partition block to get its geometry*/ 536 if (!_amiga_read_block (disk->dev, AMIGA(partition), 537 (PedSector)partblock, NULL)) { 538 ped_free(partition); 539 return 0; 540 } 541 542 start = ((PedSector) PED_BE32_TO_CPU (partition->de_LowCyl)) 543 * cylblocks; 544 end = (((PedSector) PED_BE32_TO_CPU (partition->de_HighCyl)) 545 + 1) * cylblocks - 1; 546 547 /* We can now construct a new partition */ 548 if (!(part = ped_partition_new (disk, 0, NULL, start, end))) { 549 ped_free(partition); 550 return 0; 551 } 552 /* And copy over the partition block */ 553 memcpy(part->disk_specific, partition, 256); 554 555 part->num = i; 556 part->type = 0; 557 /* Let's probe what file system is present on the disk */ 558 part->fs_type = ped_file_system_probe (&part->geom); 559 560 constraint_exact = ped_constraint_exact (&part->geom); 561 if (!ped_disk_add_partition (disk, part, constraint_exact)) { 562 ped_partition_destroy(part); 563 ped_free(partition); 564 return 0; 565 } 566 ped_constraint_destroy (constraint_exact); 567 } 568 ped_free(partition); 569 return 1; 570 } 571 572 static int 573 _amiga_find_free_blocks(const PedDisk *disk, uint32_t *table, 574 struct LinkedBlock *block, uint32_t first, uint32_t type) 575 { 576 PedSector next; 577 578 PED_ASSERT(disk != NULL, return 0); 579 PED_ASSERT(disk->dev != NULL, return 0); 580 581 for (next = first; next != LINK_END; next = PED_BE32_TO_CPU(block->lk_Next)) { 582 if (table[next] != IDNAME_FREE) { 583 switch (ped_exception_throw(PED_EXCEPTION_ERROR, 584 PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, 585 _("%s : Loop detected at block %d."), __func__, next)) 586 { 587 case PED_EXCEPTION_CANCEL : 588 return 0; 589 case PED_EXCEPTION_FIX : 590 /* TODO : Need to add fixing code */ 591 case PED_EXCEPTION_IGNORE : 592 case PED_EXCEPTION_UNHANDLED : 593 default : 594 return 1; 595 } 596 } 597 598 if (!_amiga_read_block (disk->dev, AMIGA(block), next, NULL)) { 599 return 0; 600 } 601 if (PED_BE32_TO_CPU(block->lk_ID) != type) { 602 switch (ped_exception_throw(PED_EXCEPTION_ERROR, 603 PED_EXCEPTION_CANCEL, 604 _("%s : The %s list seems bad at block %s."), 605 __func__, _amiga_block_id(PED_BE32_TO_CPU(block->lk_ID)), next)) 606 { 607 /* TODO : to more subtile things here */ 608 case PED_EXCEPTION_CANCEL : 609 case PED_EXCEPTION_UNHANDLED : 610 default : 611 return 0; 612 } 613 } 614 table[next] = type; 615 if (PED_BE32_TO_CPU(block->lk_ID) == IDNAME_FILESYSHEADER) { 616 if (_amiga_find_free_blocks(disk, table, block, 617 PED_BE32_TO_CPU(LNK2(block)->lk2_Linked), 618 IDNAME_LOADSEG) == 0) return 0; 619 } 620 } 621 return 1; 622 } 623 static uint32_t 624 _amiga_next_free_block(uint32_t *table, uint32_t start, uint32_t type) { 625 int i; 626 627 for (i = start; table[i] != type && table[i] != IDNAME_FREE; i++); 628 return i; 629 } 630 static PedPartition * 631 _amiga_next_real_partition(const PedDisk *disk, PedPartition *part) { 632 PedPartition *next; 633 634 for (next = ped_disk_next_partition (disk, part); 635 next != NULL && !ped_partition_is_active (next); 636 next = ped_disk_next_partition (disk, next)); 637 return next; 638 } 639 #ifndef DISCOVER_ONLY 640 static int 641 amiga_write (const PedDisk* disk) 642 { 643 struct RigidDiskBlock *rdb; 644 struct LinkedBlock *block; 645 struct PartitionBlock *partition; 646 PedPartition *part, *next_part; 647 PedSector cylblocks, first_hb, last_hb, last_used_hb; 648 uint32_t * table; 649 uint32_t i; 650 uint32_t rdb_num, part_num, block_num, next_num; 651 652 PED_ASSERT (disk != NULL, return 0); 653 PED_ASSERT (disk->dev != NULL, return 0); 654 PED_ASSERT (disk->disk_specific != NULL, return 0); 655 656 if (!(rdb = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) 657 return 0; 658 659 /* Let's read the rdb */ 660 if ((rdb_num = _amiga_find_rdb (disk->dev, rdb)) == AMIGA_RDB_NOT_FOUND) { 661 rdb_num = 2; 662 size_t pb_size = sizeof (struct PartitionBlock); 663 /* Initialize only the part that won't be copied over 664 with a partition block in amiga_read. */ 665 memset ((char *)(RDSK(disk->disk_specific)) + pb_size, 666 0, PED_SECTOR_SIZE_DEFAULT - pb_size); 667 } else { 668 memcpy (RDSK(disk->disk_specific), rdb, PED_SECTOR_SIZE_DEFAULT); 669 } 670 ped_free (rdb); 671 rdb = RDSK(disk->disk_specific); 672 673 cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) * 674 (PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors); 675 first_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksLo); 676 last_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksHi); 677 last_used_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock); 678 679 /* Allocate a free block table and initialize it. 680 There must be room for at least RDB_NUM + 2 entries, since 681 the first RDB_NUM+1 entries get IDNAME_RIGIDDISK, and the 682 following one must have LINK_END to serve as sentinel. */ 683 size_t tab_size = 2 + MAX (last_hb - first_hb, rdb_num); 684 if (!(table = ped_malloc (tab_size * sizeof *table))) 685 return 0; 686 687 for (i = 0; i <= rdb_num; i++) 688 table[i] = IDNAME_RIGIDDISK; 689 for ( ; i < tab_size; i++) 690 table[i] = LINK_END; 691 692 /* Let's allocate a partition block */ 693 if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { 694 ped_free (table); 695 return 0; 696 } 697 698 /* And fill the free block table */ 699 if (_amiga_find_free_blocks(disk, table, block, 700 PED_BE32_TO_CPU (rdb->rdb_BadBlockList), IDNAME_BADBLOCK) == 0) 701 { 702 ped_exception_throw(PED_EXCEPTION_ERROR, 703 PED_EXCEPTION_CANCEL, 704 _("%s : Failed to list bad blocks."), __func__); 705 goto error_free_table; 706 } 707 if (_amiga_find_free_blocks(disk, table, block, 708 PED_BE32_TO_CPU (rdb->rdb_PartitionList), IDNAME_PARTITION) == 0) 709 { 710 ped_exception_throw(PED_EXCEPTION_ERROR, 711 PED_EXCEPTION_CANCEL, 712 _("%s : Failed to list partition blocks."), __func__); 713 goto error_free_table; 714 } 715 if (_amiga_find_free_blocks(disk, table, block, 716 PED_BE32_TO_CPU (rdb->rdb_FileSysHeaderList), IDNAME_FILESYSHEADER) == 0) 717 { 718 ped_exception_throw(PED_EXCEPTION_ERROR, 719 PED_EXCEPTION_CANCEL, 720 _("%s : Failed to list file system blocks."), __func__); 721 goto error_free_table; 722 } 723 if (_amiga_find_free_blocks(disk, table, block, 724 PED_BE32_TO_CPU (rdb->rdb_BootBlockList), IDNAME_BOOT) == 0) 725 { 726 ped_exception_throw(PED_EXCEPTION_ERROR, 727 PED_EXCEPTION_CANCEL, 728 _("%s : Failed to list boot blocks."), __func__); 729 goto error_free_table; 730 } 731 732 block_num = next_num = part_num = _amiga_next_free_block(table, rdb_num+1, 733 IDNAME_PARTITION); 734 part = _amiga_next_real_partition(disk, NULL); 735 rdb->rdb_PartitionList = PED_CPU_TO_BE32(part ? part_num : LINK_END); 736 for (; part != NULL; part = next_part, block_num = next_num) { 737 PED_ASSERT(part->disk_specific != NULL, return 0); 738 PED_ASSERT(part->geom.start % cylblocks == 0, return 0); 739 PED_ASSERT((part->geom.end + 1) % cylblocks == 0, return 0); 740 741 next_part = _amiga_next_real_partition(disk, part); 742 next_num = _amiga_next_free_block(table, block_num+1, IDNAME_PARTITION); 743 744 partition = PART(part->disk_specific); 745 if (next_part == NULL) 746 partition->pb_Next = PED_CPU_TO_BE32(LINK_END); 747 else 748 partition->pb_Next = PED_CPU_TO_BE32(next_num); 749 partition->de_LowCyl = PED_CPU_TO_BE32(part->geom.start/cylblocks); 750 partition->de_HighCyl = PED_CPU_TO_BE32((part->geom.end+1)/cylblocks-1); 751 _amiga_calculate_checksum(AMIGA(partition)); 752 if (!ped_device_write (disk->dev, (void*) partition, block_num, 1)) { 753 ped_exception_throw(PED_EXCEPTION_ERROR, 754 PED_EXCEPTION_CANCEL, 755 _("Failed to write partition block at %d."), 756 block_num); 757 goto error_free_table; 758 /* WARNING : If we fail here, we stop everything, 759 * and the partition table is lost. A better 760 * solution should be found, using the second 761 * half of the hardblocks to not overwrite the 762 * old partition table. It becomes problematic 763 * if we use more than half of the hardblocks. */ 764 } 765 } 766 767 if (block_num > PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock)) 768 rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32(block_num); 769 770 _amiga_calculate_checksum(AMIGA(rdb)); 771 if (!ped_device_write (disk->dev, (void*) disk->disk_specific, rdb_num, 1)) 772 goto error_free_table; 773 774 ped_free (table); 775 ped_free (block); 776 return ped_device_sync (disk->dev); 777 778 error_free_table: 779 ped_free (table); 780 ped_free (block); 781 return 0; 782 } 783 #endif /* !DISCOVER_ONLY */ 784 785 static PedPartition* 786 amiga_partition_new (const PedDisk* disk, PedPartitionType part_type, 787 const PedFileSystemType* fs_type, 788 PedSector start, PedSector end) 789 { 790 PedPartition *part; 791 PedDevice *dev; 792 PedSector cyl; 793 struct PartitionBlock *partition; 794 struct RigidDiskBlock *rdb; 795 796 PED_ASSERT(disk != NULL, return NULL); 797 PED_ASSERT(disk->dev != NULL, return NULL); 798 PED_ASSERT(disk->disk_specific != NULL, return NULL); 799 dev = disk->dev; 800 cyl = (PedSector) (dev->hw_geom.sectors * dev->hw_geom.heads); 801 rdb = RDSK(disk->disk_specific); 802 803 if (!(part = _ped_partition_alloc (disk, part_type, fs_type, start, end))) 804 return NULL; 805 806 if (ped_partition_is_active (part)) { 807 if (!(part->disk_specific = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { 808 ped_free (part); 809 return NULL; 810 } 811 partition = PART(part->disk_specific); 812 memset(partition, 0, sizeof(struct PartitionBlock)); 813 814 partition->pb_ID = PED_CPU_TO_BE32(IDNAME_PARTITION); 815 partition->pb_SummedLongs = PED_CPU_TO_BE32(64); 816 partition->pb_HostID = rdb->rdb_HostID; 817 partition->pb_Flags = PED_CPU_TO_BE32(0); 818 /* TODO : use a scheme including the device name and the 819 * partition number, if it is possible */ 820 _amiga_set_bstr("dhx", partition->pb_DriveName, 32); 821 822 partition->de_TableSize = PED_CPU_TO_BE32(19); 823 partition->de_SizeBlock = PED_CPU_TO_BE32(128); 824 partition->de_SecOrg = PED_CPU_TO_BE32(0); 825 partition->de_Surfaces = PED_CPU_TO_BE32(dev->hw_geom.heads); 826 partition->de_SectorPerBlock = PED_CPU_TO_BE32(1); 827 partition->de_BlocksPerTrack 828 = PED_CPU_TO_BE32(dev->hw_geom.sectors); 829 partition->de_Reserved = PED_CPU_TO_BE32(2); 830 partition->de_PreAlloc = PED_CPU_TO_BE32(0); 831 partition->de_Interleave = PED_CPU_TO_BE32(0); 832 partition->de_LowCyl = PED_CPU_TO_BE32(start/cyl); 833 partition->de_HighCyl = PED_CPU_TO_BE32((end+1)/cyl-1); 834 partition->de_NumBuffers = PED_CPU_TO_BE32(30); 835 partition->de_BufMemType = PED_CPU_TO_BE32(0); 836 partition->de_MaxTransfer = PED_CPU_TO_BE32(0x7fffffff); 837 partition->de_Mask = PED_CPU_TO_BE32(0xffffffff); 838 partition->de_BootPri = PED_CPU_TO_BE32(0); 839 partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); 840 partition->de_Baud = PED_CPU_TO_BE32(0); 841 partition->de_Control = PED_CPU_TO_BE32(0); 842 partition->de_BootBlocks = PED_CPU_TO_BE32(0); 843 844 } else { 845 part->disk_specific = NULL; 846 } 847 return part; 848 } 849 850 static PedPartition* 851 amiga_partition_duplicate (const PedPartition* part) 852 { 853 PedPartition *new_part; 854 struct PartitionBlock *new_amiga_part; 855 struct PartitionBlock *old_amiga_part; 856 857 PED_ASSERT(part != NULL, return NULL); 858 PED_ASSERT(part->disk != NULL, return NULL); 859 PED_ASSERT(part->disk_specific != NULL, return NULL); 860 old_amiga_part = (struct PartitionBlock *) part->disk_specific; 861 862 new_part = ped_partition_new (part->disk, part->type, 863 part->fs_type, part->geom.start, 864 part->geom.end); 865 if (!new_part) 866 return NULL; 867 868 new_amiga_part = (struct PartitionBlock *) new_part->disk_specific; 869 memcpy (new_amiga_part, old_amiga_part, 256); 870 871 return new_part; 872 } 873 874 static void 875 amiga_partition_destroy (PedPartition* part) 876 { 877 PED_ASSERT (part != NULL, return); 878 879 if (ped_partition_is_active (part)) { 880 PED_ASSERT (part->disk_specific != NULL, return); 881 ped_free (part->disk_specific); 882 } 883 _ped_partition_free (part); 884 } 885 886 static int 887 amiga_partition_set_system (PedPartition* part, 888 const PedFileSystemType* fs_type) 889 { 890 struct PartitionBlock *partition; 891 892 PED_ASSERT (part != NULL, return 0); 893 PED_ASSERT (part->disk_specific != NULL, return 0); 894 partition = PART(part->disk_specific); 895 896 part->fs_type = fs_type; 897 898 if (!fs_type) 899 partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */ 900 else if (!strcmp (fs_type->name, "ext2")) 901 partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */ 902 else if (!strcmp (fs_type->name, "ext3")) 903 partition->de_DosType = PED_CPU_TO_BE32(0x45585403); /* 'EXT\3' */ 904 else if (!strcmp (fs_type->name, "linux-swap")) 905 partition->de_DosType = PED_CPU_TO_BE32(0x53575000); /* 'SWP\0' */ 906 else if (!strcmp (fs_type->name, "fat16")) 907 partition->de_DosType = PED_CPU_TO_BE32(0x46415400); /* 'FAT\0' */ 908 else if (!strcmp (fs_type->name, "fat32")) 909 partition->de_DosType = PED_CPU_TO_BE32(0x46415401); /* 'FAT\1'*/ 910 else if (!strcmp (fs_type->name, "hfs")) 911 partition->de_DosType = PED_CPU_TO_BE32(0x48465300); /* 'HFS\0' */ 912 else if (!strcmp (fs_type->name, "jfs")) 913 partition->de_DosType = PED_CPU_TO_BE32(0x4a465300); /* 'JFS\0' */ 914 else if (!strcmp (fs_type->name, "ntfs")) 915 partition->de_DosType = PED_CPU_TO_BE32(0x4e544653); /* 'NTFS' */ 916 else if (!strcmp (fs_type->name, "reiserfs")) 917 partition->de_DosType = PED_CPU_TO_BE32(0x52465300); /* 'RFS\0' */ 918 else if (!strcmp (fs_type->name, "sun-ufs")) 919 partition->de_DosType = PED_CPU_TO_BE32(0x53554653); /* 'SUFS' */ 920 else if (!strcmp (fs_type->name, "hp-ufs")) 921 partition->de_DosType = PED_CPU_TO_BE32(0x48554653); /* 'HUFS' */ 922 else if (!strcmp (fs_type->name, "xfs")) 923 partition->de_DosType = PED_CPU_TO_BE32(0x58465300); /* 'XFS\0' */ 924 else 925 partition->de_DosType = PED_CPU_TO_BE32(0x00000000); /* unknown */ 926 return 1; 927 } 928 929 static int 930 amiga_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state) 931 { 932 struct PartitionBlock *partition; 933 934 PED_ASSERT (part != NULL, return 0); 935 PED_ASSERT (part->disk_specific != NULL, return 0); 936 937 partition = PART(part->disk_specific); 938 939 switch (flag) { 940 case PED_PARTITION_BOOT: 941 if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_BOOTABLE); 942 else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_BOOTABLE)); 943 return 1; 944 case PED_PARTITION_HIDDEN: 945 if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_NOMOUNT); 946 else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_NOMOUNT)); 947 return 1; 948 case PED_PARTITION_RAID: 949 if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_RAID); 950 else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_RAID)); 951 return 1; 952 case PED_PARTITION_LVM: 953 if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_LVM); 954 else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_LVM)); 955 return 1; 956 default: 957 return 0; 958 } 959 } 960 961 static int 962 amiga_partition_get_flag (const PedPartition* part, PedPartitionFlag flag) 963 { 964 struct PartitionBlock *partition; 965 966 PED_ASSERT (part != NULL, return 0); 967 PED_ASSERT (part->disk_specific != NULL, return 0); 968 969 partition = PART(part->disk_specific); 970 971 switch (flag) { 972 case PED_PARTITION_BOOT: 973 return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_BOOTABLE)); 974 case PED_PARTITION_HIDDEN: 975 return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_NOMOUNT)); 976 case PED_PARTITION_RAID: 977 return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_RAID)); 978 case PED_PARTITION_LVM: 979 return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_LVM)); 980 default: 981 return 0; 982 } 983 } 984 985 static int 986 amiga_partition_is_flag_available (const PedPartition* part, 987 PedPartitionFlag flag) 988 { 989 switch (flag) { 990 case PED_PARTITION_BOOT: 991 case PED_PARTITION_HIDDEN: 992 case PED_PARTITION_RAID: 993 case PED_PARTITION_LVM: 994 return 1; 995 default: 996 return 0; 997 } 998 } 999 1000 static void 1001 amiga_partition_set_name (PedPartition* part, const char* name) 1002 { 1003 struct PartitionBlock *partition; 1004 1005 PED_ASSERT (part != NULL, return); 1006 PED_ASSERT (part->disk_specific != NULL, return); 1007 1008 partition = PART(part->disk_specific); 1009 _amiga_set_bstr(name, partition->pb_DriveName, 32); 1010 } 1011 static const char* 1012 amiga_partition_get_name (const PedPartition* part) 1013 { 1014 struct PartitionBlock *partition; 1015 1016 PED_ASSERT (part != NULL, return 0); 1017 PED_ASSERT (part->disk_specific != NULL, return 0); 1018 1019 partition = PART(part->disk_specific); 1020 1021 return _amiga_get_bstr(partition->pb_DriveName); 1022 } 1023 1024 static PedConstraint* 1025 _amiga_get_constraint (const PedDisk *disk) 1026 { 1027 PedDevice *dev = disk->dev; 1028 PedAlignment start_align, end_align; 1029 PedGeometry max_geom; 1030 PedSector cyl_size = dev->hw_geom.sectors * dev->hw_geom.heads; 1031 1032 if (!ped_alignment_init(&start_align, 0, cyl_size)) 1033 return NULL; 1034 if (!ped_alignment_init(&end_align, -1, cyl_size)) 1035 return NULL; 1036 if (!ped_geometry_init(&max_geom, dev, MAX_RDB_BLOCK + 1, 1037 dev->length - MAX_RDB_BLOCK - 1)) 1038 return NULL; 1039 1040 return ped_constraint_new (&start_align, &end_align, 1041 &max_geom, &max_geom, 1, dev->length); 1042 } 1043 1044 static int 1045 amiga_partition_align (PedPartition* part, const PedConstraint* constraint) 1046 { 1047 PED_ASSERT (part != NULL, return 0); 1048 PED_ASSERT (part->disk != NULL, return 0); 1049 1050 if (_ped_partition_attempt_align (part, constraint, 1051 _amiga_get_constraint (part->disk))) 1052 return 1; 1053 1054 #ifndef DISCOVER_ONLY 1055 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 1056 _("Unable to satisfy all constraints on the partition.")); 1057 #endif 1058 return 0; 1059 } 1060 1061 static int 1062 amiga_partition_enumerate (PedPartition* part) 1063 { 1064 int i; 1065 PedPartition* p; 1066 1067 PED_ASSERT (part != NULL, return 0); 1068 PED_ASSERT (part->disk != NULL, return 0); 1069 1070 /* never change the partition numbers */ 1071 if (part->num != -1) 1072 return 1; 1073 for (i = 1; i <= AMIGA_MAX_PARTITIONS; i++) { 1074 p = ped_disk_get_partition (part->disk, i); 1075 if (!p) { 1076 part->num = i; 1077 return 1; 1078 } 1079 } 1080 1081 /* failed to allocate a number */ 1082 #ifndef DISCOVER_ONLY 1083 ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, 1084 _("Unable to allocate a partition number.")); 1085 #endif 1086 return 0; 1087 } 1088 1089 static int 1090 amiga_alloc_metadata (PedDisk* disk) 1091 { 1092 PedPartition* new_part; 1093 PedConstraint* constraint_any = NULL; 1094 1095 PED_ASSERT (disk != NULL, goto error); 1096 PED_ASSERT (disk->dev != NULL, goto error); 1097 1098 constraint_any = ped_constraint_any (disk->dev); 1099 1100 /* Allocate space for the RDB */ 1101 new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 1102 0, MAX_RDB_BLOCK); 1103 if (!new_part) 1104 goto error; 1105 1106 if (!ped_disk_add_partition (disk, new_part, constraint_any)) { 1107 ped_partition_destroy (new_part); 1108 goto error; 1109 } 1110 1111 ped_constraint_destroy (constraint_any); 1112 return 1; 1113 error: 1114 ped_constraint_destroy (constraint_any); 1115 return 0; 1116 } 1117 1118 static int 1119 amiga_get_max_primary_partition_count (const PedDisk* disk) 1120 { 1121 return AMIGA_MAX_PARTITIONS; 1122 } 1123 1124 static PedDiskOps amiga_disk_ops = { 1125 .probe = amiga_probe, 1126 #ifndef DISCOVER_ONLY 1127 .clobber = amiga_clobber, 1128 #else 1129 .clobber = NULL, 1130 #endif 1131 .alloc = amiga_alloc, 1132 .duplicate = amiga_duplicate, 1133 .free = amiga_free, 1134 .read = amiga_read, 1135 #ifndef DISCOVER_ONLY 1136 .write = amiga_write, 1137 #else 1138 .write = NULL, 1139 #endif 1140 1141 .partition_new = amiga_partition_new, 1142 .partition_duplicate = amiga_partition_duplicate, 1143 .partition_destroy = amiga_partition_destroy, 1144 .partition_set_system = amiga_partition_set_system, 1145 .partition_set_flag = amiga_partition_set_flag, 1146 .partition_get_flag = amiga_partition_get_flag, 1147 .partition_is_flag_available = 1148 amiga_partition_is_flag_available, 1149 .partition_set_name = amiga_partition_set_name, 1150 .partition_get_name = amiga_partition_get_name, 1151 .partition_align = amiga_partition_align, 1152 .partition_enumerate = amiga_partition_enumerate, 1153 1154 1155 .alloc_metadata = amiga_alloc_metadata, 1156 .get_max_primary_partition_count = 1157 amiga_get_max_primary_partition_count 1158 }; 1159 1160 static PedDiskType amiga_disk_type = { 1161 .next = NULL, 1162 .name = "amiga", 1163 .ops = &amiga_disk_ops, 1164 .features = PED_DISK_TYPE_PARTITION_NAME 1165 }; 1166 1167 void 1168 ped_disk_amiga_init () 1169 { 1170 PED_ASSERT (sizeof (struct AmigaBlock) != 3, return); 1171 PED_ASSERT (sizeof (struct RigidDiskBlock) != 64, return); 1172 PED_ASSERT (sizeof (struct PartitionBlock) != 64, return); 1173 PED_ASSERT (sizeof (struct LinkedBlock) != 5, return); 1174 PED_ASSERT (sizeof (struct Linked2Block) != 18, return); 1175 1176 ped_disk_type_register (&amiga_disk_type); 1177 } 1178 1179 void 1180 ped_disk_amiga_done () 1181 { 1182 ped_disk_type_unregister (&amiga_disk_type); 1183 }