diff -urN parted-1.6.6.orig/libparted/disk_amiga.c parted-1.6.6/libparted/disk_amiga.c
--- parted-1.6.6.orig/libparted/disk_amiga.c 1970-01-01 01:00:00.000000000 +0100
+++ parted-1.6.6/libparted/disk_amiga.c 2003-10-31 16:30:52.000000000 +0100
@@ -0,0 +1,1519 @@
+/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+
+ libparted - a library for manipulating disk partitions
+ Copyright (C) 2000, 2001 Free Software Foundation, Inc.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program; if not, write to the Free Software
+ Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+ Contributor: Sven Luther
+*/
+
+#include "config.h"
+
+#include
+
+#include
+#include
+#include
+
+#if ENABLE_NLS
+# include
+# define _(String) dgettext (PACKAGE, String)
+#else
+# define _(String) (String)
+#endif /* ENABLE_NLS */
+
+#define DEBUG_BLOCK 0x01
+#define DEBUG_CONST 0x02
+#define DEBUG_FUNCS 0x04
+#define DEBUG_ERROR 0x08
+#define DEBUG_READ 0X10
+#define DEBUG_WRITE 0X20
+#if 0
+#define MASTER_DEBUG DEBUG_BLOCK | DEBUG_CONST | DEBUG_FUNCS | DEBUG_ERROR | DEBUG_READ | DEBUG_WRITE
+#endif
+
+#ifdef MASTER_DEBUG
+#define DPRINT(l,a,b...) do { if ((l) & (MASTER_DEBUG)) fprintf(stderr, "AMIGA : %s: " a, __func__ , ## b); } while (0)
+#define DPRINTF(l,a,b...) do { if ((l) & (MASTER_DEBUG)) fprintf(stderr, a, ## b); } while (0)
+#define TRACE() DPRINT(DEBUG_FUNCS, "\n")
+#else
+#define DPRINT(l,a,b...)
+#define DPRINTF(l,a,b...)
+#define TRACE()
+#endif /* MASTER_DEBUG */
+
+/* String manipulation */
+static void _amiga_set_bstr (const char *cstr, char *bstr, int maxsize) {
+ int size = strlen (cstr);
+ int i;
+ TRACE();
+
+ if (size >= maxsize) return;
+ bstr[0] = size;
+ for (i = 0; i";
+ default :
+ return "";
+ }
+}
+static int
+_amiga_valid_block_id (uint32_t id) {
+ TRACE();
+ switch (id) {
+ case IDNAME_RIGIDDISK :
+ case IDNAME_BADBLOCK :
+ case IDNAME_PARTITION :
+ case IDNAME_FILESYSHEADER :
+ case IDNAME_LOADSEG :
+ case IDNAME_BOOT :
+ return 1;
+ case IDNAME_FREE :
+ default :
+ return 0;
+ }
+}
+struct AmigaBlock {
+ uint32_t amiga_ID; /* Identifier 32 bit word */
+ uint32_t amiga_SummedLongss; /* Size of the structure for checksums */
+ int32_t amiga_ChkSum; /* Checksum of the structure */
+};
+#define AMIGA(pos) ((struct AmigaBlock *)(pos))
+
+static int
+_amiga_checksum (struct AmigaBlock *blk) {
+ uint32_t *rdb = (uint32_t *) blk;
+ uint32_t sum;
+ int i, end;
+ TRACE();
+
+ sum = PED_BE32_TO_CPU (rdb[0]);
+ end = PED_BE32_TO_CPU (rdb[1]);
+
+ if (end > PED_SECTOR_SIZE) end = PED_SECTOR_SIZE;
+
+ for (i = 1; i < end; i++) sum += PED_BE32_TO_CPU (rdb[i]);
+
+ return sum;
+}
+
+static void
+_amiga_calculate_checksum (struct AmigaBlock *blk) {
+ TRACE();
+ blk->amiga_ChkSum = PED_CPU_TO_BE32(
+ PED_BE32_TO_CPU(blk->amiga_ChkSum) -
+ _amiga_checksum((struct AmigaBlock *) blk));
+ return;
+}
+
+struct RigidDiskBlock {
+ uint32_t rdb_ID; /* Identifier 32 bit word : 'RDSK' */
+ uint32_t rdb_SummedLongs; /* Size of the structure for checksums */
+ int32_t rdb_ChkSum; /* Checksum of the structure */
+ uint32_t rdb_HostID; /* SCSI Target ID of host, not really used */
+ uint32_t rdb_BlockBytes; /* Size of disk blocks */
+ uint32_t rdb_Flags; /* RDB Flags */
+ /* block list heads */
+ uint32_t rdb_BadBlockList; /* Bad block list */
+ uint32_t rdb_PartitionList; /* Partition list */
+ uint32_t rdb_FileSysHeaderList; /* File system header list */
+ uint32_t rdb_DriveInit; /* Drive specific init code */
+ uint32_t rdb_BootBlockList; /* Amiga OS 4 Boot Blocks */
+ uint32_t rdb_Reserved1[5]; /* Unused word, need to be set to $ffffffff */
+ /* physical drive characteristics */
+ uint32_t rdb_Cylinders; /* Number of the cylinders of the drive */
+ uint32_t rdb_Sectors; /* Number of sectors of the drive */
+ uint32_t rdb_Heads; /* Number of heads of the drive */
+ uint32_t rdb_Interleave; /* Interleave */
+ uint32_t rdb_Park; /* Head parking cylinder */
+ uint32_t rdb_Reserved2[3]; /* Unused word, need to be set to $ffffffff */
+ uint32_t rdb_WritePreComp; /* Starting cylinder of write precompensation */
+ uint32_t rdb_ReducedWrite; /* Starting cylinder of reduced write current */
+ uint32_t rdb_StepRate; /* Step rate of the drive */
+ uint32_t rdb_Reserved3[5]; /* Unused word, need to be set to $ffffffff */
+ /* logical drive characteristics */
+ uint32_t rdb_RDBBlocksLo; /* low block of range reserved for hardblocks */
+ uint32_t rdb_RDBBlocksHi; /* high block of range for these hardblocks */
+ uint32_t rdb_LoCylinder; /* low cylinder of partitionable disk area */
+ uint32_t rdb_HiCylinder; /* high cylinder of partitionable data area */
+ uint32_t rdb_CylBlocks; /* number of blocks available per cylinder */
+ uint32_t rdb_AutoParkSeconds; /* zero for no auto park */
+ uint32_t rdb_HighRDSKBlock; /* highest block used by RDSK */
+ /* (not including replacement bad blocks) */
+ uint32_t rdb_Reserved4;
+ /* drive identification */
+ char rdb_DiskVendor[8];
+ char rdb_DiskProduct[16];
+ char rdb_DiskRevision[4];
+ char rdb_ControllerVendor[8];
+ char rdb_ControllerProduct[16];
+ char rdb_ControllerRevision[4];
+ uint32_t rdb_Reserved5[10];
+};
+
+#define RDB_LOCATION_LIMIT 16
+#define RDSK(pos) ((struct RigidDiskBlock *)(pos))
+
+/* TODO : print drive ident strings */
+void _amiga_dump_rdb (struct RigidDiskBlock * rdb) {
+ TRACE();
+ DPRINT(DEBUG_BLOCK, "RigidDiskBlock\n\trgb_ID = %08x %s\n",
+ PED_BE32_TO_CPU(rdb->rdb_ID),
+ (PED_BE32_TO_CPU(rdb->rdb_ID)==IDNAME_RIGIDDISK ? "RDSK" : ""));
+ DPRINT(DEBUG_BLOCK, "\trdb_SummedLongs = %08x\n",
+ PED_BE32_TO_CPU(rdb->rdb_SummedLongs));
+ DPRINT(DEBUG_BLOCK, "\trdb_ChkSum = %08x (block checksum is %d)\n",
+ PED_BE32_TO_CPU(rdb->rdb_ChkSum), _amiga_checksum (AMIGA(rdb)));
+ DPRINT(DEBUG_BLOCK, "\trdb_HostID = %08x\n", PED_BE32_TO_CPU(rdb->rdb_HostID));
+ DPRINT(DEBUG_BLOCK, "\trdb_BlockBytes = %08x\n", PED_BE32_TO_CPU(rdb->rdb_BlockBytes));
+ DPRINT(DEBUG_BLOCK, "\trdb_Flags = %08x\n", PED_BE32_TO_CPU(rdb->rdb_Flags));
+ DPRINT(DEBUG_BLOCK, "\trdb_BadBlockList = %08x\n", PED_BE32_TO_CPU(rdb->rdb_BadBlockList));
+ DPRINT(DEBUG_BLOCK, "\trdb_PartitionList = %08x\n", PED_BE32_TO_CPU(rdb->rdb_PartitionList));
+ DPRINT(DEBUG_BLOCK, "\trdb_FileSysHeaderList = %08x\n", PED_BE32_TO_CPU(rdb->rdb_FileSysHeaderList));
+ DPRINT(DEBUG_BLOCK, "\trdb_DriveInit = %08x\n", PED_BE32_TO_CPU(rdb->rdb_DriveInit));
+ DPRINT(DEBUG_BLOCK, "\trdb_BootBlockList = %08x\n", PED_BE32_TO_CPU(rdb->rdb_BootBlockList));
+ DPRINT(DEBUG_BLOCK, "\trdb_Cylinders = %08x\n", PED_BE32_TO_CPU(rdb->rdb_Cylinders));
+ DPRINT(DEBUG_BLOCK, "\trdb_Sectors = %08x\n", PED_BE32_TO_CPU(rdb->rdb_Sectors));
+ DPRINT(DEBUG_BLOCK, "\trdb_Heads = %08x\n", PED_BE32_TO_CPU(rdb->rdb_Heads));
+ DPRINT(DEBUG_BLOCK, "\trdb_Interleave = %08x\n", PED_BE32_TO_CPU(rdb->rdb_Interleave));
+ DPRINT(DEBUG_BLOCK, "\trdb_Park = %08x\n", PED_BE32_TO_CPU(rdb->rdb_Park));
+ DPRINT(DEBUG_BLOCK, "\trdb_WritePreComp = %08x\n", PED_BE32_TO_CPU(rdb->rdb_WritePreComp));
+ DPRINT(DEBUG_BLOCK, "\trdb_ReducedWrite = %08x\n", PED_BE32_TO_CPU(rdb->rdb_ReducedWrite));
+ DPRINT(DEBUG_BLOCK, "\trdb_StepRate = %08x\n", PED_BE32_TO_CPU(rdb->rdb_StepRate));
+ DPRINT(DEBUG_BLOCK, "\trdb_RDBBlocksLo = %u\n", PED_BE32_TO_CPU(rdb->rdb_RDBBlocksLo));
+ DPRINT(DEBUG_BLOCK, "\trdb_RDBBlocksHi = %u\n", PED_BE32_TO_CPU(rdb->rdb_RDBBlocksHi));
+ DPRINT(DEBUG_BLOCK, "\trdb_LoCylinder = %u\n", PED_BE32_TO_CPU(rdb->rdb_LoCylinder));
+ DPRINT(DEBUG_BLOCK, "\trdb_HiCylinder = %u\n", PED_BE32_TO_CPU(rdb->rdb_HiCylinder));
+ DPRINT(DEBUG_BLOCK, "\trdb_CylBlocks = %u (Heads*Sectors = %u\n",
+ PED_BE32_TO_CPU(rdb->rdb_CylBlocks),
+ PED_BE32_TO_CPU(rdb->rdb_Sectors)*PED_BE32_TO_CPU(rdb->rdb_Heads));
+ DPRINT(DEBUG_BLOCK, "\trdb_AutoParkSeconds = %08x\n", PED_BE32_TO_CPU(rdb->rdb_AutoParkSeconds));
+ DPRINT(DEBUG_BLOCK, "\trdb_HighRDSKBlock = %08x\n", PED_BE32_TO_CPU(rdb->rdb_HighRDSKBlock));
+}
+
+#define AMIGA_RDB_NOT_FOUND ((uint32_t)0xffffffff)
+static uint32_t
+_amiga_find_rdb (PedDevice *dev, struct RigidDiskBlock *rdb) {
+ int i;
+ TRACE();
+
+ for (i = 0; irdb_ID) == IDNAME_RIGIDDISK) {
+ if (_amiga_checksum (AMIGA(rdb)) != 0) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL,
+ _("%s : Bad checksum on rdb block %d\n"), __func__, i))
+ {
+ case PED_EXCEPTION_CANCEL :
+ return AMIGA_RDB_NOT_FOUND ;
+ case PED_EXCEPTION_FIX :
+ _amiga_calculate_checksum(AMIGA(rdb));
+ ped_device_write (dev, rdb, i, 1);
+ case PED_EXCEPTION_IGNORE :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return i;
+ }
+ } else return i;
+ }
+ }
+ return AMIGA_RDB_NOT_FOUND;
+}
+
+struct PartitionBlock {
+ uint32_t pb_ID; /* Identifier 32 bit word : 'PART' */
+ uint32_t pb_SummedLongs; /* Size of the structure for checksums */
+ int32_t pb_ChkSum; /* Checksum of the structure */
+ uint32_t pb_HostID; /* SCSI Target ID of host, not really used */
+ uint32_t pb_Next; /* Block number of the next PartitionBlock */
+ uint32_t pb_Flags; /* Part Flags (NOMOUNT and BOOTABLE) */
+ uint32_t pb_Reserved1[2];
+ uint32_t pb_DevFlags; /* Preferred flags for OpenDevice */
+ uint8_t pb_DriveName[32]; /* Preferred DOS device name: BSTR form */
+ uint32_t pb_Reserved2[15];
+ uint32_t de_TableSize; /* Size of Environment vector */
+ uint32_t de_SizeBlock; /* Size of the blocks in 32 bit words, usually 128 */
+ uint32_t de_SecOrg; /* Not used; must be 0 */
+ uint32_t de_Surfaces; /* Number of heads (surfaces) */
+ uint32_t de_SectorPerBlock; /* Disk sectors per block, used with SizeBlock, usually 1 */
+ uint32_t de_BlocksPerTrack; /* Blocks per track. drive specific */
+ uint32_t de_Reserved; /* DOS reserved blocks at start of partition. */
+ uint32_t de_PreAlloc; /* DOS reserved blocks at end of partition */
+ uint32_t de_Interleave; /* Not used, usually 0 */
+ uint32_t de_LowCyl; /* First cylinder of the partition */
+ uint32_t de_HighCyl; /* Last cylinder of the partition */
+ uint32_t de_NumBuffers; /* Initial # DOS of buffers. */
+ uint32_t de_BufMemType; /* Type of mem to allocate for buffers */
+ uint32_t de_MaxTransfer; /* Max number of bytes to transfer at a time */
+ uint32_t de_Mask; /* Address Mask to block out certain memory */
+ int32_t de_BootPri; /* Boot priority for autoboot */
+ uint32_t de_DosType; /* Dostype of the filesystem */
+ uint32_t de_Baud; /* Baud rate for serial handler */
+ uint32_t de_Control; /* Control word for handler/filesystem */
+ uint32_t de_BootBlocks; /* Number of blocks containing boot code */
+ uint32_t pb_EReserved[12];
+};
+
+#define PART(pos) ((struct PartitionBlock *)(pos))
+
+#define PBFB_BOOTABLE 0 /* this partition is intended to be bootable */
+#define PBFF_BOOTABLE 1L /* (expected directories and files exist) */
+#define PBFB_NOMOUNT 1 /* do not mount this partition (e.g. manually */
+#define PBFF_NOMOUNT 2L /* mounted, but space reserved here) */
+
+void _amiga_dump_part (struct PartitionBlock * part) {
+ TRACE();
+ DPRINT(DEBUG_BLOCK, "Partition : cylinder %d to %d, blocksize : %d (in bytes)\n",
+ PED_BE32_TO_CPU(part->de_LowCyl),
+ PED_BE32_TO_CPU(part->de_HighCyl),
+ PED_BE32_TO_CPU(part->de_SizeBlock)*4*PED_BE32_TO_CPU(part->de_SectorPerBlock));
+ DPRINT(DEBUG_BLOCK, "\tdostype : %08x, reserved : %d, prealloc : %d\n",
+ PED_BE32_TO_CPU(part->de_DosType),
+ PED_BE32_TO_CPU(part->de_Reserved),
+ PED_BE32_TO_CPU(part->de_PreAlloc));
+ DPRINT(DEBUG_BLOCK, "PartitionBlock\n");
+ DPRINT(DEBUG_BLOCK, "\tpart_ID = %08x %s\n", PED_BE32_TO_CPU(part->pb_ID),
+ (PED_BE32_TO_CPU(part->pb_ID)==IDNAME_PARTITION ? "PART" : ""));
+ DPRINT(DEBUG_BLOCK, "\tpart_SummedLongs = %08x\n",
+ PED_BE32_TO_CPU(part->pb_SummedLongs));
+ DPRINT(DEBUG_BLOCK, "\tpart_ChkSum = %08x (block checksum is %d)\n",
+ PED_BE32_TO_CPU(part->pb_ChkSum), _amiga_checksum (AMIGA(part)));
+ DPRINT(DEBUG_BLOCK, "\tpart_HostID = %08x\n", PED_BE32_TO_CPU(part->pb_HostID));
+ DPRINT(DEBUG_BLOCK, "\tpart_Next = %08x (%d)\n",
+ PED_BE32_TO_CPU(part->pb_Next), PED_BE32_TO_CPU(part->pb_Next));
+ DPRINT(DEBUG_BLOCK, "\tpart_Flags = %08x\n", PED_BE32_TO_CPU(part->pb_Flags));
+ DPRINT(DEBUG_BLOCK, "\tpart_DevFlags = %08x\n", PED_BE32_TO_CPU(part->pb_DevFlags));
+ DPRINT(DEBUG_BLOCK, "\tpart_DriveName = %s\n", _amiga_get_bstr(part->pb_DriveName));
+ DPRINT(DEBUG_BLOCK, "\tde_TableSize = %08x\n", PED_BE32_TO_CPU(part->de_TableSize));
+ DPRINT(DEBUG_BLOCK, "\tde_SizeBlock = %08x\n", PED_BE32_TO_CPU(part->de_SizeBlock));
+ DPRINT(DEBUG_BLOCK, "\tde_SecOrg = %08x\n", PED_BE32_TO_CPU(part->de_SecOrg));
+ DPRINT(DEBUG_BLOCK, "\tde_Surfaces = %08x\n", PED_BE32_TO_CPU(part->de_Surfaces));
+ DPRINT(DEBUG_BLOCK, "\tde_SectorPerBlock = %08x\n", PED_BE32_TO_CPU(part->de_SectorPerBlock));
+ DPRINT(DEBUG_BLOCK, "\tde_BlocksPerTrack = %08x\n", PED_BE32_TO_CPU(part->de_BlocksPerTrack));
+ DPRINT(DEBUG_BLOCK, "\tde_Reserved = %08x\n", PED_BE32_TO_CPU(part->de_Reserved));
+ DPRINT(DEBUG_BLOCK, "\tde_PreAlloc = %08x\n", PED_BE32_TO_CPU(part->de_PreAlloc));
+ DPRINT(DEBUG_BLOCK, "\tde_Interleave = %08x\n", PED_BE32_TO_CPU(part->de_Interleave));
+ DPRINT(DEBUG_BLOCK, "\tde_LowCyl = %08x\n", PED_BE32_TO_CPU(part->de_LowCyl));
+ DPRINT(DEBUG_BLOCK, "\tde_HighCyl = %08x\n", PED_BE32_TO_CPU(part->de_HighCyl));
+ DPRINT(DEBUG_BLOCK, "\tde_NumBuffers = %08x\n", PED_BE32_TO_CPU(part->de_NumBuffers));
+ DPRINT(DEBUG_BLOCK, "\tde_BufMemType = %08x\n", PED_BE32_TO_CPU(part->de_BufMemType));
+ DPRINT(DEBUG_BLOCK, "\tde_MaxTransfer = %08x\n", PED_BE32_TO_CPU(part->de_MaxTransfer));
+ DPRINT(DEBUG_BLOCK, "\tde_Mask = %08x\n", PED_BE32_TO_CPU(part->de_Mask));
+ DPRINT(DEBUG_BLOCK, "\tde_BootPri = %08x\n", PED_BE32_TO_CPU(part->de_BootPri));
+ DPRINT(DEBUG_BLOCK, "\tde_DosType = %08x\n", PED_BE32_TO_CPU(part->de_DosType));
+ DPRINT(DEBUG_BLOCK, "\tde_Baud = %08x\n", PED_BE32_TO_CPU(part->de_Baud));
+ DPRINT(DEBUG_BLOCK, "\tde_Control = %08x\n", PED_BE32_TO_CPU(part->de_Control));
+ DPRINT(DEBUG_BLOCK, "\tde_BootBlocks = %08x\n", PED_BE32_TO_CPU(part->de_BootBlocks));
+}
+
+#define AMIGA_MAX_PARTITIONS 128
+
+struct LinkedBlock {
+ uint32_t lk_ID; /* Identifier 32 bit word */
+ uint32_t lk_SummedLongs; /* Size of the structure for checksums */
+ int32_t lk_ChkSum; /* Checksum of the structure */
+ uint32_t pb_HostID; /* SCSI Target ID of host, not really used */
+ uint32_t lk_Next; /* Block number of the next PartitionBlock */
+};
+struct Linked2Block {
+ uint32_t lk2_ID; /* Identifier 32 bit word */
+ uint32_t lk2_SummedLongs; /* Size of the structure for checksums */
+ int32_t lk2_ChkSum; /* Checksum of the structure */
+ uint32_t lk2_Next; /* Block number of the next PartitionBlock */
+ uint32_t lk2_Reverved[13];
+ uint32_t lk2_Linked; /* Secondary linked list */
+};
+#define LINK_END 0xffffffff
+#define LNK(pos) ((struct LinkedBlock *)(pos))
+#define LNK2(pos) ((struct Linked2Block *)(pos))
+
+void _amiga_dump_linked (struct LinkedBlock * block) {
+ TRACE();
+ DPRINT(DEBUG_BLOCK, "LinkedBlock\n\tpart_ID = %08x %s\n",
+ PED_BE32_TO_CPU(block->lk_ID),
+ _amiga_block_id(PED_BE32_TO_CPU(block->lk_ID)));
+ DPRINT(DEBUG_BLOCK, "\tlk_SummedLongs = %08x\n",
+ PED_BE32_TO_CPU(block->lk_SummedLongs));
+ DPRINT(DEBUG_BLOCK, "\tlk_ChkSum = %08x (block checksum is %d)\n",
+ block->lk_ChkSum, _amiga_checksum (AMIGA(block)));
+ DPRINT(DEBUG_BLOCK, "\tlk_Next = %08x (%d)\n",
+ PED_BE32_TO_CPU(block->lk_Next), PED_BE32_TO_CPU(block->lk_Next));
+ if (PED_BE32_TO_CPU(block->lk_ID)==IDNAME_FILESYSHEADER) {
+ DPRINT(DEBUG_BLOCK, "\tlk2_Linked = %08x (%d)\n",
+ PED_BE32_TO_CPU(LNK2(block)->lk2_Linked),
+ PED_BE32_TO_CPU(LNK2(block)->lk2_Linked));
+ }
+}
+
+#define MAX_RDB_BLOCK (RDB_LOCATION_LIMIT + 2 * AMIGA_MAX_PARTITIONS + 2)
+
+static PedDiskType amiga_disk_type;
+
+static int
+amiga_probe (PedDevice *dev)
+{
+ struct RigidDiskBlock *rdb;
+ uint32_t found;
+ TRACE();
+ PED_ASSERT(dev!= NULL, return 0);
+
+ if ((rdb=RDSK(ped_malloc(PED_SECTOR_SIZE)))==NULL) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate rdb block\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+ found = _amiga_find_rdb (dev, rdb);
+ ped_free (rdb);
+
+ return (found == AMIGA_RDB_NOT_FOUND ? 0 : 1);
+}
+
+static PedDisk*
+amiga_alloc (PedDevice* dev)
+{
+ PedDisk *disk;
+ struct AmigaDisk *adsk;
+ struct RigidDiskBlock *rdb;
+ int highest_cylinder, highest_block;
+ TRACE();
+ PED_ASSERT(dev!= NULL, return NULL);
+
+ if (!(disk = _ped_disk_alloc (dev, &amiga_disk_type))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate disk structure\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return NULL;
+ }
+ }
+
+ if (!(disk->disk_specific = ped_malloc (PED_SECTOR_SIZE))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate disk_specific rdb block\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (disk);
+ return NULL;
+ }
+ }
+ rdb = disk->disk_specific;
+
+ memset(rdb, -1, sizeof(struct RigidDiskBlock));
+
+ rdb->rdb_ID = PED_CPU_TO_BE32 (IDNAME_RIGIDDISK);
+ rdb->rdb_SummedLongs = PED_CPU_TO_BE32 (64);
+ rdb->rdb_HostID = PED_CPU_TO_BE32 (0);
+ rdb->rdb_BlockBytes = PED_CPU_TO_BE32 (PED_SECTOR_SIZE);
+ rdb->rdb_Flags = PED_CPU_TO_BE32 (0);
+
+ /* Block lists */
+ rdb->rdb_BadBlockList = PED_CPU_TO_BE32 (0xffffffff);
+ rdb->rdb_PartitionList = PED_CPU_TO_BE32 (0xffffffff);
+ rdb->rdb_FileSysHeaderList = PED_CPU_TO_BE32 (0xffffffff);
+ rdb->rdb_DriveInit = PED_CPU_TO_BE32 (0xffffffff);
+
+ /* Physical drive characteristics */
+ rdb->rdb_Cylinders = PED_CPU_TO_BE32 (dev->cylinders);
+ rdb->rdb_Sectors = PED_CPU_TO_BE32 (dev->sectors);
+ rdb->rdb_Heads = PED_CPU_TO_BE32 (dev->heads);
+ rdb->rdb_Interleave = PED_CPU_TO_BE32 (0);
+ rdb->rdb_Park = PED_CPU_TO_BE32 (dev->cylinders);
+ rdb->rdb_WritePreComp = PED_CPU_TO_BE32 (dev->cylinders);
+ rdb->rdb_ReducedWrite = PED_CPU_TO_BE32 (dev->cylinders);
+ rdb->rdb_StepRate = PED_CPU_TO_BE32 (0);
+
+ highest_cylinder = MAX_RDB_BLOCK / (dev->sectors * dev->heads) + 1;
+ highest_block = highest_cylinder * dev->sectors * dev->heads - 1;
+
+ /* Logical driver characteristics */
+ rdb->rdb_RDBBlocksLo = PED_CPU_TO_BE32 (0);
+ rdb->rdb_RDBBlocksHi = PED_CPU_TO_BE32 (highest_block);
+ rdb->rdb_LoCylinder = PED_CPU_TO_BE32 (highest_cylinder);
+ rdb->rdb_HiCylinder = PED_CPU_TO_BE32 (dev->cylinders -1);
+ rdb->rdb_CylBlocks = PED_CPU_TO_BE32 (dev->sectors * dev->heads);
+ rdb->rdb_AutoParkSeconds = PED_CPU_TO_BE32 (0);
+ /* rdb_HighRDSKBlock will only be set when writing */
+ rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32 (0);
+
+ /* Driver identification */
+ _amiga_set_bstr("", rdb->rdb_DiskVendor, 8);
+ _amiga_set_bstr(dev->model, rdb->rdb_DiskProduct, 16);
+ _amiga_set_bstr("", rdb->rdb_DiskRevision, 4);
+ _amiga_set_bstr("", rdb->rdb_ControllerVendor, 8);
+ _amiga_set_bstr("", rdb->rdb_ControllerProduct, 16);
+ _amiga_set_bstr("", rdb->rdb_ControllerRevision, 4);
+
+ /* And calculate the checksum */
+ _amiga_calculate_checksum ((struct AmigaBlock *) rdb);
+
+ return disk;
+}
+
+static PedDisk*
+amiga_duplicate (const PedDisk* disk)
+{
+ PedDisk* new_disk;
+ struct RigidDiskBlock * new_rdb;
+ struct RigidDiskBlock * old_rdb;
+ TRACE();
+ PED_ASSERT(disk!= NULL, return NULL);
+ PED_ASSERT(disk->dev!= NULL, return NULL);
+ PED_ASSERT(disk->disk_specific!= NULL, return NULL);
+
+ old_rdb = (struct RigidDiskBlock *) disk->disk_specific;
+
+ if (!(new_disk = ped_disk_new_fresh (disk->dev, &amiga_disk_type))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate a new disk structure\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return NULL;
+ }
+ }
+
+ new_rdb = (struct RigidDiskBlock *) new_disk->disk_specific;
+ memcpy (new_rdb, old_rdb, 256);
+ return new_disk;
+}
+
+static void
+amiga_free (PedDisk* disk)
+{
+ TRACE();
+ PED_ASSERT(disk!= NULL, return);
+ PED_ASSERT(disk->disk_specific!= NULL, return);
+
+ ped_free (disk->disk_specific);
+ _ped_disk_free (disk);
+}
+
+#ifndef DISCOVER_ONLY
+static int
+amiga_clobber (PedDevice* dev)
+{
+ struct RigidDiskBlock *rdb;
+ uint32_t i;
+ int result = 0;
+ TRACE();
+ PED_ASSERT(dev!= NULL, return 0);
+
+ if ((rdb=RDSK(ped_malloc(PED_SECTOR_SIZE)))==NULL) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate rdb block\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+
+ while ((i = _amiga_find_rdb (dev, rdb)) != AMIGA_RDB_NOT_FOUND) {
+ rdb->rdb_ID = PED_CPU_TO_BE32 (0);
+ result = ped_device_write (dev, (void*) rdb, i, 1);
+ }
+
+ ped_free (rdb);
+
+ return result;
+}
+#endif /* !DISCOVER_ONLY */
+
+static int
+_amiga_loop_check (uint32_t block, uint32_t * blocklist, uint32_t max)
+{
+ uint32_t i;
+ TRACE();
+
+ for (i = 0; i < max; i++)
+ if (block == blocklist[i]) {
+ /* We are looping, let's stop. */
+ return 1;
+ }
+ blocklist[max] = block;
+ return 0;
+}
+
+/* We have already allocated a rdb, we are now reading it from the disk */
+static int
+amiga_read (PedDisk* disk)
+{
+ struct RigidDiskBlock *rdb;
+ struct PartitionBlock *partition;
+ uint32_t partblock;
+ uint32_t partlist[AMIGA_MAX_PARTITIONS];
+ PedSector cylblocks;
+ int i;
+ TRACE();
+ PED_ASSERT(disk!= NULL, return 0);
+ PED_ASSERT(disk->dev!= NULL, return 0);
+ PED_ASSERT(disk->disk_specific!= NULL, return 0);
+ rdb = RDSK(disk->disk_specific);
+
+ if (_amiga_find_rdb (disk->dev, rdb) == AMIGA_RDB_NOT_FOUND) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Didn't find rdb block, should never happen\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+#if (DEBUG_BLOCKS & MASTER_DEBUG)
+ _amiga_dump_rdb(rdb);
+#endif
+
+ /* Let's copy the rdb read geometry to the dev */
+ disk->dev->cylinders = PED_BE32_TO_CPU (rdb->rdb_Cylinders);
+ disk->dev->heads = PED_BE32_TO_CPU (rdb->rdb_Heads);
+ disk->dev->sectors = PED_BE32_TO_CPU (rdb->rdb_Sectors);
+ cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) *
+ (PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors);
+
+ /* Remove all partitions in the former in memory table */
+ ped_disk_delete_all (disk);
+
+ /* Let's allocate a partition block */
+ if (!(partition = ped_malloc (PED_SECTOR_SIZE))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate partition block\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+
+ /* We initialize the hardblock free list to detect loops */
+ for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = 0xffffffff;
+
+ for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList);
+ i < AMIGA_MAX_PARTITIONS && partblock != 0xffffffff;
+ i++, partblock = PED_BE32_TO_CPU(partition->pb_Next))
+ {
+ PedPartition *part;
+ PedSector start, end;
+ struct DosEnvec *de;
+ PedConstraint *constraint_exact;
+ int j;
+
+ /* Let's look for loops in the partition table */
+ if (_amiga_loop_check(partblock, partlist, i)) {
+ break;
+ }
+
+ /* Let's allocate and read a partition block to get its geometry*/
+ if (!ped_device_read (disk->dev, partition, (PedSector)partblock, 1)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to to read partition block %llu\n"),
+ __func__, (PedSector)partblock))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free(partition);
+ return 0;
+ }
+ }
+#if (DEBUG_BLOCK & MASTER_DEBUG)
+ _amiga_dump_part(partition);
+#endif
+
+ start = ((PedSector) PED_BE32_TO_CPU (partition->de_LowCyl)) * cylblocks;
+ end = ((((PedSector) PED_BE32_TO_CPU (partition->de_HighCyl))+1) * (cylblocks))-1;
+
+ /* We can now construct a new partition */
+ if (!(part = ped_partition_new (disk, 0, NULL, start, end))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate new partition (%llu -> %llu)\n"),
+ __func__, start, end))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free(partition);
+ return 0;
+ }
+ }
+ /* And copy over the partition block */
+ memcpy(part->disk_specific, partition, 256);
+
+ part->num = i;
+ part->type = 0;
+ /* Let's probe what filesystem is present on the disk */
+ part->fs_type = ped_file_system_probe (&part->geom);
+
+ constraint_exact = ped_constraint_exact (&part->geom);
+ if (!ped_disk_add_partition (disk, part, constraint_exact)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to add new partition\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free(partition);
+ return 0;
+ }
+ }
+ ped_constraint_destroy (constraint_exact);
+ }
+ return 1;
+}
+
+static int
+_amiga_find_free_blocks(PedDisk *disk, uint32_t *table,
+ struct LinkedBlock *block, uint32_t first, uint32_t type)
+{
+ PedSector next;
+ TRACE();
+ PED_ASSERT(disk!= NULL, return 0);
+ PED_ASSERT(disk->dev!= NULL, return 0);
+
+ for (next = first; next != LINK_END; next = PED_BE32_TO_CPU(block->lk_Next)) {
+ if (table[next] != IDNAME_FREE) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL,
+ _("%s : Loop detected at block %d\n"), __func__, next))
+ {
+ case PED_EXCEPTION_CANCEL :
+ return 0;
+ case PED_EXCEPTION_FIX :
+ /* Need to add fixing code */
+ case PED_EXCEPTION_IGNORE :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 1;
+ }
+ }
+ if (!ped_device_read (disk->dev, block, next, 1)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to read block %d\n"), __func__, next))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+#if (DEBUG_BLOCK & MASTER_DEBUG)
+ _amiga_dump_linked(block);
+#endif
+ if (PED_BE32_TO_CPU(block->lk_ID) != type) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : The %s list seems bad at block %s\n"),
+ __func__, _amiga_block_id(PED_BE32_TO_CPU(block->lk_ID)), next))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+ table[next] = type;
+ if (PED_BE32_TO_CPU(block->lk_ID) == IDNAME_FILESYSHEADER) {
+ if (_amiga_find_free_blocks(disk, table, block,
+ PED_BE32_TO_CPU(LNK2(block)->lk2_Linked),
+ IDNAME_LOADSEG) == 0) return 0;
+ }
+ }
+ return 1;
+}
+static uint32_t
+_amiga_next_free_block(uint32_t *table, uint32_t start, uint32_t type) {
+ int i;
+ TRACE();
+
+ for (i = start; table[i] != type && table[i] != IDNAME_FREE; i++);
+ return i;
+}
+static PedPartition *
+_amiga_next_real_partition(PedDisk *disk, PedPartition *part) {
+ PedPartition *next;
+ TRACE();
+
+ for (next = ped_disk_next_partition (disk, part);
+ next != NULL && !ped_partition_is_active (next);
+ next = ped_disk_next_partition (disk, next));
+ return next;
+}
+#ifndef DISCOVER_ONLY
+static int
+amiga_write (PedDisk* disk)
+{
+ struct RigidDiskBlock *rdb;
+ struct LinkedBlock *block;
+ struct PartitionBlock *partition;
+ PedPartition *part, *next_part;
+ PedSector cylblocks, first_hb, last_hb, last_used_hb;
+ uint32_t * table;
+ uint32_t i, rdb_block, max_part;
+ uint32_t rdb_num, part_num, block_num, next_num;
+ TRACE();
+
+ PED_ASSERT (disk != NULL, return 0;);
+ PED_ASSERT (disk->dev != NULL, return 0;);
+ PED_ASSERT (disk->disk_specific != NULL, return 0;);
+
+ if (!(rdb = ped_malloc (PED_SECTOR_SIZE))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate rdb block\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+ /* Let's read the rdb */
+ if ((rdb_num = _amiga_find_rdb (disk->dev, rdb)) == AMIGA_RDB_NOT_FOUND) {
+ rdb_num = 2;
+ } else {
+ memcpy (RDSK(disk->disk_specific), rdb, PED_SECTOR_SIZE);
+ }
+ ped_free (rdb);
+ rdb = RDSK(disk->disk_specific);
+#if (DEBUG_BLOCK & MASTER_DEBUG)
+ _amiga_dump_rdb(rdb);
+#endif
+
+ /* Let's copy the rdb read geometry to the dev */
+ disk->dev->cylinders = PED_BE32_TO_CPU (rdb->rdb_Cylinders);
+ disk->dev->heads = PED_BE32_TO_CPU (rdb->rdb_Heads);
+ disk->dev->sectors = PED_BE32_TO_CPU (rdb->rdb_Sectors);
+ cylblocks = (PedSector) PED_BE32_TO_CPU (rdb->rdb_Heads) *
+ (PedSector) PED_BE32_TO_CPU (rdb->rdb_Sectors);
+ first_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksLo);
+ last_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_RDBBlocksHi);
+ last_used_hb = (PedSector) PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock);
+
+ /* let's allocate a free block table and initialize it */
+ if (!(table = ped_malloc ((last_hb - first_hb + 1) * sizeof(uint32_t)))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate free block table\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return 0;
+ }
+ }
+ memset(table, 0xff, (last_hb - first_hb + 1) * sizeof(uint32_t));
+ for (i = 0; i<=rdb_num; i++) table[i] = IDNAME_RIGIDDISK;
+
+ /* Let's allocate a partition block */
+ if (!(block = ped_malloc (PED_SECTOR_SIZE))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate partition block\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (table);
+ return 0;
+ }
+ }
+
+ /* And fill the free block table */
+ if (_amiga_find_free_blocks(disk, table, block,
+ PED_BE32_TO_CPU (rdb->rdb_BadBlockList), IDNAME_BADBLOCK) == 0)
+ {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to list badblocks\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (table);
+ ped_free (block);
+ return 0;
+ }
+ }
+ if (_amiga_find_free_blocks(disk, table, block,
+ PED_BE32_TO_CPU (rdb->rdb_PartitionList), IDNAME_PARTITION) == 0)
+ {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to list partitionblocks\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (table);
+ ped_free (block);
+ return 0;
+ }
+ }
+ if (_amiga_find_free_blocks(disk, table, block,
+ PED_BE32_TO_CPU (rdb->rdb_FileSysHeaderList), IDNAME_FILESYSHEADER) == 0)
+ {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to list filesystemblocks\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (table);
+ ped_free (block);
+ return 0;
+ }
+ }
+ if (_amiga_find_free_blocks(disk, table, block,
+ PED_BE32_TO_CPU (rdb->rdb_BootBlockList), IDNAME_BOOT) == 0)
+ {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to list bootblocks\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (table);
+ ped_free (block);
+ return 0;
+ }
+ }
+
+ block_num = next_num = part_num = _amiga_next_free_block(table, rdb_num+1, IDNAME_PARTITION);
+ part = _amiga_next_real_partition(disk, NULL);
+ if (part == NULL) {
+ rdb->rdb_PartitionList = PED_CPU_TO_BE32(LINK_END);
+ } else {
+ rdb->rdb_PartitionList = PED_CPU_TO_BE32(part_num);
+ while (part != NULL) {
+ PED_ASSERT(part->disk_specific!=NULL, return 0);
+ next_part = _amiga_next_real_partition(disk, part);
+ block_num = next_num;
+ next_num = _amiga_next_free_block(table, block_num+1, IDNAME_PARTITION);
+ partition = PART(part->disk_specific);
+ partition->pb_Next = next_part==NULL ? PED_CPU_TO_BE32(LINK_END):PED_CPU_TO_BE32(next_num);
+ partition->de_LowCyl = PED_CPU_TO_BE32(part->geom.start/cylblocks);
+ partition->de_HighCyl = PED_CPU_TO_BE32((part->geom.end+1)/cylblocks-1);
+ _amiga_calculate_checksum(AMIGA(partition));
+ if (!ped_device_write (disk->dev, (void*) partition, block_num, 1)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to write partition block at\n"), __func__, block_num))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (table);
+ ped_free (block);
+ /* WARNING : If we fail here, we stop everything,
+ * and the partition table is lost. A Better
+ * solution should be found, using the second
+ * half of the hardblocks to not overwrite the
+ * old partition table. It becomes problematic
+ * if we use more than half of the hardblocks. */
+ return 0;
+ }
+ }
+ part = next_part;
+ }
+ }
+ if (block_num >PED_BE32_TO_CPU (rdb->rdb_HighRDSKBlock)) {
+ rdb->rdb_HighRDSKBlock = PED_CPU_TO_BE32(block_num);
+ }
+ _amiga_calculate_checksum(AMIGA(rdb));
+ if (!ped_device_write (disk->dev, (void*) disk->disk_specific, rdb_num, 1)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to write rdb block at\n"), __func__, rdb_num))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (table);
+ ped_free (block);
+ return 0;
+ }
+ }
+
+#if (DEBUG_BLOCK & MASTER_DEBUG)
+ _amiga_dump_rdb(rdb);
+#endif
+ ped_free (table);
+ ped_free (block);
+ return ped_device_sync (disk->dev);
+}
+#endif /* !DISCOVER_ONLY */
+
+static PedPartition*
+amiga_partition_new (const PedDisk* disk, PedPartitionType part_type,
+ const PedFileSystemType* fs_type,
+ PedSector start, PedSector end)
+{
+ PedPartition *part;
+ PedDevice *dev;
+ PedSector cyl;
+ struct PartitionBlock *partition;
+ struct RigidDiskBlock *rdb;
+ TRACE();
+ PED_ASSERT(disk!= NULL, return NULL);
+ PED_ASSERT(disk->dev!= NULL, return NULL);
+ PED_ASSERT(disk->disk_specific!= NULL, return NULL);
+ dev = disk->dev;
+ cyl = (PedSector) (dev->sectors * dev->heads);
+ rdb = RDSK(disk->disk_specific);
+
+ if (!(part = _ped_partition_alloc (disk, part_type, fs_type, start, end))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate a partition structure (%llu, %llu)"),
+ __func__, start, end))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return NULL;
+ }
+ }
+
+
+ if (ped_partition_is_active (part)) {
+ if (!(part->disk_specific = ped_malloc (PED_SECTOR_SIZE))) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate a partition disk_specific block\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ ped_free (part);
+ return NULL;
+ }
+ }
+ partition = PART(part->disk_specific);
+ memset(partition, -1, sizeof(struct PartitionBlock));
+
+ partition->pb_ID = PED_CPU_TO_BE32(IDNAME_PARTITION);
+ partition->pb_SummedLongs = PED_CPU_TO_BE32(64);
+ partition->pb_HostID = rdb->rdb_HostID;
+ partition->pb_Flags = PED_CPU_TO_BE32(0);
+ /* TODO : use a scheme including the device name and the
+ * partition number, if it is possible */
+ _amiga_set_bstr("dhx", partition->pb_DriveName, 32);
+
+ partition->de_TableSize = PED_CPU_TO_BE32(19);
+ partition->de_SizeBlock = PED_CPU_TO_BE32(128);
+ partition->de_SecOrg = PED_CPU_TO_BE32(0);
+ partition->de_Surfaces = PED_CPU_TO_BE32(dev->heads);
+ partition->de_SectorPerBlock = PED_CPU_TO_BE32(1);
+ partition->de_BlocksPerTrack = PED_CPU_TO_BE32(dev->sectors);
+ partition->de_Reserved = PED_CPU_TO_BE32(2);
+ partition->de_PreAlloc = PED_CPU_TO_BE32(0);
+ partition->de_Interleave = PED_CPU_TO_BE32(0);
+ partition->de_LowCyl = PED_CPU_TO_BE32(start/cyl);
+ partition->de_HighCyl = PED_CPU_TO_BE32((end+1)/cyl-1);
+ partition->de_NumBuffers = PED_CPU_TO_BE32(30);
+ partition->de_BufMemType = PED_CPU_TO_BE32(0);
+ partition->de_MaxTransfer = PED_CPU_TO_BE32(0x7fffffff);
+ partition->de_Mask = PED_CPU_TO_BE32(0xffffffff);
+ partition->de_BootPri = PED_CPU_TO_BE32(0);
+ partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800);
+ partition->de_Baud = PED_CPU_TO_BE32(0);
+ partition->de_Control = PED_CPU_TO_BE32(0);
+ partition->de_BootBlocks = PED_CPU_TO_BE32(0);
+
+#if (DEBUG_BLOCK & MASTER_DEBUG)
+ _amiga_dump_part(partition);
+#endif
+ } else {
+ part->disk_specific = NULL;
+ }
+ return part;
+}
+
+static PedPartition*
+amiga_partition_duplicate (const PedPartition* part)
+{
+ PedPartition *new_part;
+ struct PartitionBlock *new_amiga_part;
+ struct PartitionBlock *old_amiga_part;
+ TRACE();
+ PED_ASSERT(part!= NULL, return NULL);
+ PED_ASSERT(part->disk!= NULL, return NULL);
+ PED_ASSERT(part->disk_specific!= NULL, return NULL);
+ old_amiga_part = (struct PartitionBlock *) part->disk_specific;
+
+ new_part = ped_partition_new (part->disk, part->type,
+ part->fs_type, part->geom.start,
+ part->geom.end);
+ if (!new_part) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to allocate a new partition structure\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return NULL;
+ }
+ }
+
+ new_amiga_part = (struct PartitionBlock *) new_part->disk_specific;
+ memcpy (new_amiga_part, old_amiga_part, 256);
+
+ return new_part;
+}
+
+static void
+amiga_partition_destroy (PedPartition* part)
+{
+ TRACE();
+ PED_ASSERT (part != NULL, return);
+
+ if (ped_partition_is_active (part)) {
+ PED_ASSERT (part->disk_specific!= NULL, return);
+ ped_free (part->disk_specific);
+ }
+ _ped_partition_free (part);
+}
+
+static int
+amiga_partition_set_system (PedPartition* part, const PedFileSystemType* fs_type)
+{
+ struct PartitionBlock *partition;
+ TRACE();
+
+ PED_ASSERT (part != NULL, return 0);
+ PED_ASSERT (part->disk_specific != NULL, return 0);
+ partition = PART(part->disk_specific);
+
+ part->fs_type = fs_type;
+
+ if (!fs_type)
+ partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */
+ else if (!strcmp (fs_type->name, "ext2"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x4c4e5800); /* 'LNX\0' */
+ else if (!strcmp (fs_type->name, "ext3"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x45585403); /* 'EXT\3' */
+ else if (!strcmp (fs_type->name, "linux-swap"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x53575000); /* 'SWP\0' */
+ else if (!strcmp (fs_type->name, "fat16"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x46415400); /* 'FAT\0' */
+ else if (!strcmp (fs_type->name, "fat32"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x46415401); /* 'FAT\1'*/
+ else if (!strcmp (fs_type->name, "hfs"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x48465300); /* 'HFS\0' */
+ else if (!strcmp (fs_type->name, "jfs"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x4a465300); /* 'JFS\0' */
+ else if (!strcmp (fs_type->name, "ntfs"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x4e544653); /* 'NTFS' */
+ else if (!strcmp (fs_type->name, "reiserfs"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x52465300); /* 'RFS\0' */
+ else if (!strcmp (fs_type->name, "sun-ufs"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x53554653); /* 'SUFS' */
+ else if (!strcmp (fs_type->name, "hp-ufs"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x48554653); /* 'HUFS' */
+ else if (!strcmp (fs_type->name, "xfs"))
+ partition->de_DosType = PED_CPU_TO_BE32(0x58465300); /* 'XFS\0' */
+ else
+ partition->de_DosType = PED_CPU_TO_BE32(0x00000000); /* unknown */
+ return 1;
+}
+
+static int
+amiga_partition_set_flag (PedPartition* part, PedPartitionFlag flag, int state)
+{
+ struct PartitionBlock *partition;
+ TRACE();
+
+ PED_ASSERT (part != NULL, return 0);
+ PED_ASSERT (part->disk_specific != NULL, return 0);
+
+ partition = PART(part->disk_specific);
+
+ switch (flag) {
+ case PED_PARTITION_BOOT:
+ if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_BOOTABLE);
+ else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_BOOTABLE));
+ return 1;
+ case PED_PARTITION_HIDDEN:
+ if (state) partition->pb_Flags |= PED_CPU_TO_BE32(PBFF_NOMOUNT);
+ else partition->pb_Flags &= ~(PED_CPU_TO_BE32(PBFF_NOMOUNT));
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static int
+amiga_partition_get_flag (const PedPartition* part, PedPartitionFlag flag)
+{
+ struct PartitionBlock *partition;
+ TRACE();
+
+ PED_ASSERT (part != NULL, return 0);
+ PED_ASSERT (part->disk_specific != NULL, return 0);
+
+ partition = PART(part->disk_specific);
+
+ switch (flag) {
+ case PED_PARTITION_BOOT:
+ return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_BOOTABLE));
+ case PED_PARTITION_HIDDEN:
+ return (partition->pb_Flags & PED_CPU_TO_BE32(PBFF_NOMOUNT));
+ default:
+ return 0;
+ }
+}
+
+static int
+amiga_partition_is_flag_available (const PedPartition* part,
+ PedPartitionFlag flag)
+{
+ TRACE();
+ switch (flag) {
+ case PED_PARTITION_BOOT:
+ case PED_PARTITION_HIDDEN:
+ return 1;
+ default:
+ return 0;
+ }
+}
+
+static void
+amiga_partition_set_name (PedPartition* part, const char* name)
+{
+ struct PartitionBlock *partition;
+ TRACE();
+
+ PED_ASSERT (part != NULL, return);
+ PED_ASSERT (part->disk_specific != NULL, return);
+
+ partition = PART(part->disk_specific);
+ _amiga_set_bstr(name, partition->pb_DriveName, 32);
+}
+static const char*
+amiga_partition_get_name (const PedPartition* part)
+{
+ struct PartitionBlock *partition;
+ TRACE();
+
+ PED_ASSERT (part != NULL, return 0);
+ PED_ASSERT (part->disk_specific != NULL, return 0);
+
+ partition = PART(part->disk_specific);
+
+ return _amiga_get_bstr(partition->pb_DriveName);
+}
+
+static PedConstraint*
+_amiga_get_constraint (const PedDisk *disk)
+{
+ PedDevice *dev = disk->dev;
+ PedAlignment start_align, end_align;
+ PedGeometry max_geom;
+ struct RigidDiskBlock *rdb = RDSK(disk->disk_specific);
+ PedSector cyl = (PedSector) PED_BE32_TO_CPU(rdb->rdb_Sectors) *
+ PED_BE32_TO_CPU(rdb->rdb_Heads);
+ PedSector start = ((273 / cyl) + 1) * cyl;
+ PedSector length = dev->length - start;
+ PedSector max_part = (length / cyl) * cyl;
+ TRACE();
+
+ if (!ped_alignment_init(&start_align, 0, cyl)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to initialize the start constraint\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return NULL;
+ }
+ }
+ if (!ped_alignment_init(&end_align, -1, cyl)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to initialize the end constraint\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return NULL;
+ }
+ }
+ if (!ped_geometry_init(&max_geom, dev, start, length)) {
+ switch (ped_exception_throw(PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Failed to initialize the max constraint\n"), __func__))
+ {
+ case PED_EXCEPTION_CANCEL :
+ case PED_EXCEPTION_UNHANDLED :
+ default :
+ return NULL;
+ }
+ }
+
+ return ped_constraint_new (&start_align, &end_align,
+ &max_geom, &max_geom, cyl, max_part);
+}
+
+static void
+_amiga_dump_constraint (const PedConstraint* constraint)
+{
+ DPRINT (DEBUG_CONST, "Align Start : offset = %lld, grain = %lld\n",
+ constraint->start_align->offset,
+ constraint->start_align->grain_size);
+ DPRINT (DEBUG_CONST, "Align End : offset = %lld, grain = %lld\n",
+ constraint->end_align->offset,
+ constraint->end_align->grain_size);
+ DPRINT (DEBUG_CONST, "Range Start : start = %lld, length = %lld, end = %lld\n",
+ constraint->start_range->start,
+ constraint->start_range->length,
+ constraint->start_range->end);
+ DPRINT (DEBUG_CONST, "Range End : start = %lld, length = %lld, end = %lld\n",
+ constraint->end_range->start,
+ constraint->end_range->length,
+ constraint->end_range->end);
+ DPRINT (DEBUG_CONST, "Size : min = %lld, Max = %lld\n",
+ constraint->min_size, constraint->max_size);
+}
+
+static int
+amiga_partition_align (PedPartition* part, const PedConstraint* constraint)
+{
+ TRACE();
+
+ PED_ASSERT (part != NULL, return 0);
+ PED_ASSERT (part->disk != NULL, return 0);
+
+#if (DEBUG_CONST & MASTER_DEBUG)
+ _amiga_dump_constraint (constraint);
+ _amiga_dump_constraint (_amiga_get_constraint (part->disk));
+#endif
+ if (_ped_partition_attempt_align (part, constraint,
+ _amiga_get_constraint (part->disk)))
+ {
+ return 1;
+ }
+
+#ifndef DISCOVER_ONLY
+ ped_exception_throw (
+ PED_EXCEPTION_ERROR,
+ PED_EXCEPTION_CANCEL,
+ _("%s : Unable to satisfy all constraints on the partition."), __func__);
+#endif
+ return 0;
+}
+
+static int
+amiga_partition_enumerate (PedPartition* part)
+{
+
+ int i;
+ PedPartition* p;
+ TRACE();
+
+ PED_ASSERT (part != NULL, return 0);
+ PED_ASSERT (part->disk != NULL, return 0);
+
+ /* never change the partition numbers */
+ if (part->num != -1)
+ return 1;
+ for (i = 1; i <= AMIGA_MAX_PARTITIONS; i++) {
+ p = ped_disk_get_partition (part->disk, i);
+ if (!p) {
+ part->num = i;
+ return 1;
+ }
+ }
+
+ /* failed to allocate a number */
+#ifndef DISCOVER_ONLY
+ ped_exception_throw (PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL,
+ _("%s : Unable to allocate a partition"), __func__);
+#endif
+ return 0;
+}
+
+static int
+amiga_alloc_metadata (PedDisk* disk)
+{
+ PedPartition* new_part;
+ PedConstraint* constraint_any = NULL;
+ PedSector highest_block;
+ TRACE();
+
+ PED_ASSERT (disk != NULL, goto error);
+ PED_ASSERT (disk->dev != NULL, goto error);
+
+ constraint_any = ped_constraint_any (disk->dev);
+
+ /* Allocate space for the RDB */
+ new_part = ped_partition_new (disk, PED_PARTITION_METADATA, NULL, 0, MAX_RDB_BLOCK);
+ if (!new_part)
+ goto error;
+
+ if (!ped_disk_add_partition (disk, new_part, constraint_any)) {
+ ped_partition_destroy (new_part);
+ goto error;
+ }
+
+ ped_constraint_destroy (constraint_any);
+ return 1;
+error:
+ ped_constraint_destroy (constraint_any);
+ return 0;
+}
+
+static int
+amiga_get_max_primary_partition_count (const PedDisk* disk)
+{
+ TRACE();
+ return AMIGA_MAX_PARTITIONS;
+}
+
+static PedDiskOps amiga_disk_ops = {
+ probe: amiga_probe,
+#ifndef DISCOVER_ONLY
+ clobber: amiga_clobber,
+#else
+ clobber: NULL,
+#endif
+ alloc: amiga_alloc,
+ duplicate: amiga_duplicate,
+ free: amiga_free,
+ read: amiga_read,
+#ifndef DISCOVER_ONLY
+ write: amiga_write,
+#else
+ write: NULL,
+#endif
+
+ partition_new: amiga_partition_new,
+ partition_duplicate: amiga_partition_duplicate,
+ partition_destroy: amiga_partition_destroy,
+ partition_set_system: amiga_partition_set_system,
+ partition_set_flag: amiga_partition_set_flag,
+ partition_get_flag: amiga_partition_get_flag,
+ partition_is_flag_available:
+ amiga_partition_is_flag_available,
+ partition_set_name: amiga_partition_set_name,
+ partition_get_name: amiga_partition_get_name,
+ partition_align: amiga_partition_align,
+ partition_enumerate: amiga_partition_enumerate,
+
+
+ alloc_metadata: amiga_alloc_metadata,
+ get_max_primary_partition_count:
+ amiga_get_max_primary_partition_count
+};
+
+static PedDiskType amiga_disk_type = {
+ next: NULL,
+ name: "amiga",
+ ops: &amiga_disk_ops,
+ features: PED_DISK_TYPE_PARTITION_NAME
+};
+
+void
+ped_disk_amiga_init ()
+{
+ TRACE();
+ PED_ASSERT(sizeof(struct AmigaBlock) != 3, return);
+ PED_ASSERT(sizeof(struct RigidDiskBlock) != 64, return);
+ PED_ASSERT(sizeof(struct PartitionBlock) != 64, return);
+ PED_ASSERT(sizeof(struct LinkedBlock) != 5, return);
+ PED_ASSERT(sizeof(struct Linked2Block) != 18, return);
+
+ ped_register_disk_type (&amiga_disk_type);
+}
+
+void
+ped_disk_amiga_done ()
+{
+ TRACE();
+
+ ped_unregister_disk_type (&amiga_disk_type);
+}
diff -urN parted-1.6.6.orig/libparted/libparted.c parted-1.6.6/libparted/libparted.c
--- parted-1.6.6.orig/libparted/libparted.c 2002-12-31 01:21:45.000000000 +0100
+++ parted-1.6.6/libparted/libparted.c 2003-10-30 15:56:44.000000000 +0100
@@ -86,12 +86,14 @@
extern void ped_disk_msdos_init ();
extern void ped_disk_pc98_init ();
extern void ped_disk_sun_init ();
+extern void ped_disk_amiga_init ();
static void
init_disk_types ()
{
ped_disk_loop_init (); /* must be last in the probe list */
+ ped_disk_amiga_init ();
ped_disk_sun_init ();
#ifdef ENABLE_PC98
ped_disk_pc98_init ();
@@ -137,10 +139,12 @@
extern void ped_disk_msdos_done ();
extern void ped_disk_pc98_done ();
extern void ped_disk_sun_done ();
+extern void ped_disk_amiga_done ();
static void
done_disk_types ()
{
+ ped_disk_amiga_done ();
ped_disk_sun_done ();
#ifdef ENABLE_PC98
ped_disk_pc98_done ();
diff -urN parted-1.6.6.orig/libparted/Makefile.am parted-1.6.6/libparted/Makefile.am
--- parted-1.6.6.orig/libparted/Makefile.am 2002-12-31 01:19:17.000000000 +0100
+++ parted-1.6.6/libparted/Makefile.am 2003-10-30 15:56:44.000000000 +0100
@@ -41,6 +41,7 @@
disk_dvh.c \
disk_pc98.c \
disk_sun.c \
+ disk_amiga.c \
@address@hidden
EXTRA_libparted_la_SOURCES = linux.c \