diff options
Diffstat (limited to 'libparted/fs/amiga')
-rw-r--r-- | libparted/fs/amiga/a-interface.c | 88 | ||||
-rw-r--r-- | libparted/fs/amiga/affs.c | 292 | ||||
-rw-r--r-- | libparted/fs/amiga/affs.h | 19 | ||||
-rw-r--r-- | libparted/fs/amiga/amiga.c | 351 | ||||
-rw-r--r-- | libparted/fs/amiga/amiga.h | 70 | ||||
-rw-r--r-- | libparted/fs/amiga/apfs.c | 128 | ||||
-rw-r--r-- | libparted/fs/amiga/apfs.h | 18 | ||||
-rw-r--r-- | libparted/fs/amiga/asfs.c | 130 | ||||
-rw-r--r-- | libparted/fs/amiga/asfs.h | 18 |
9 files changed, 1114 insertions, 0 deletions
diff --git a/libparted/fs/amiga/a-interface.c b/libparted/fs/amiga/a-interface.c new file mode 100644 index 0000000..0ae84dd --- /dev/null +++ b/libparted/fs/amiga/a-interface.c @@ -0,0 +1,88 @@ +/* + interface.c -- parted support amiga file systems + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + + +#include <config.h> + +#include <parted/parted.h> +#include <parted/debug.h> +#include <parted/endian.h> + +extern PedFileSystemType _affs0_type; +extern PedFileSystemType _affs1_type; +extern PedFileSystemType _affs2_type; +extern PedFileSystemType _affs3_type; +extern PedFileSystemType _affs4_type; +extern PedFileSystemType _affs5_type; +extern PedFileSystemType _affs6_type; +extern PedFileSystemType _affs7_type; +extern PedFileSystemType _amufs_type; +extern PedFileSystemType _amufs0_type; +extern PedFileSystemType _amufs1_type; +extern PedFileSystemType _amufs2_type; +extern PedFileSystemType _amufs3_type; +extern PedFileSystemType _amufs4_type; +extern PedFileSystemType _amufs5_type; +extern PedFileSystemType _asfs_type; +extern PedFileSystemType _apfs1_type; +extern PedFileSystemType _apfs2_type; + +void ped_file_system_amiga_init () +{ + ped_file_system_type_register (&_affs0_type); + ped_file_system_type_register (&_affs1_type); + ped_file_system_type_register (&_affs2_type); + ped_file_system_type_register (&_affs3_type); + ped_file_system_type_register (&_affs4_type); + ped_file_system_type_register (&_affs5_type); + ped_file_system_type_register (&_affs6_type); + ped_file_system_type_register (&_affs7_type); + ped_file_system_type_register (&_amufs_type); + ped_file_system_type_register (&_amufs0_type); + ped_file_system_type_register (&_amufs1_type); + ped_file_system_type_register (&_amufs2_type); + ped_file_system_type_register (&_amufs3_type); + ped_file_system_type_register (&_amufs4_type); + ped_file_system_type_register (&_amufs5_type); + ped_file_system_type_register (&_asfs_type); + ped_file_system_type_register (&_apfs1_type); + ped_file_system_type_register (&_apfs2_type); +} + +void ped_file_system_amiga_done () +{ + ped_file_system_type_unregister (&_affs0_type); + ped_file_system_type_unregister (&_affs1_type); + ped_file_system_type_unregister (&_affs2_type); + ped_file_system_type_unregister (&_affs3_type); + ped_file_system_type_unregister (&_affs4_type); + ped_file_system_type_unregister (&_affs5_type); + ped_file_system_type_unregister (&_affs6_type); + ped_file_system_type_unregister (&_affs7_type); + ped_file_system_type_unregister (&_amufs_type); + ped_file_system_type_unregister (&_amufs0_type); + ped_file_system_type_unregister (&_amufs1_type); + ped_file_system_type_unregister (&_amufs2_type); + ped_file_system_type_unregister (&_amufs3_type); + ped_file_system_type_unregister (&_amufs4_type); + ped_file_system_type_unregister (&_amufs5_type); + ped_file_system_type_unregister (&_asfs_type); + ped_file_system_type_unregister (&_apfs1_type); + ped_file_system_type_unregister (&_apfs2_type); +} diff --git a/libparted/fs/amiga/affs.c b/libparted/fs/amiga/affs.c new file mode 100644 index 0000000..750eab2 --- /dev/null +++ b/libparted/fs/amiga/affs.c @@ -0,0 +1,292 @@ +/* + affs.c -- parted support for affs file systems + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <parted/parted.h> +#include <parted/debug.h> +#include <parted/endian.h> + +#include "amiga.h" +#include "affs.h" + +#if ENABLE_NLS +# include <libintl.h> +# define _(String) dgettext (PACKAGE, String) +#else +# define _(String) (String) +#endif /* ENABLE_NLS */ + +static int +_affs_probe_root (uint32_t *block, int blocksize) { + int i; + uint32_t sum; + + if (PED_BE32_TO_CPU (block[0]) != 2) return 0; + if (PED_BE32_TO_CPU (block[128*blocksize-1]) != 1) return 0; + for (i = 0, sum = 0; i < 128*blocksize; i++) + sum += PED_BE32_TO_CPU (block[i]); + if (sum) return 0; + return 1; +} + +static PedGeometry* +_generic_affs_probe (PedGeometry* geom, uint32_t kind) +{ + uint32_t *block; + PedSector root, len, pos; + struct PartitionBlock * part; + int blocksize = 1, reserved = 2; + + PED_ASSERT (geom != NULL); + PED_ASSERT (geom->dev != NULL); + if (geom->dev->sector_size != 512) + return NULL; + /* Finds the blocksize and reserved values of the partition block */ + if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate partition block\n"), __func__); + goto error_part; + } + if (amiga_find_part(geom, part) != NULL) { + reserved = PED_BE32_TO_CPU (part->de_Reserved); + reserved = reserved == 0 ? 1 : reserved; + blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) + * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; + } + free (part); + + /* Test boot block */ + if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate block\n"), __func__); + goto error_block; + } + if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); + goto error; + } + if (PED_BE32_TO_CPU (block[0]) != kind) { + goto error; + } + + /* Find and test the root block */ + len = geom->length / blocksize - reserved; + pos = (len - 1) / 2; + root = geom->start + (pos + reserved) * blocksize; + + if (!ped_device_read (geom->dev, block, root, blocksize)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Couldn't read root block %llu\n"), __func__, root); + goto error; + } + if (_affs_probe_root(block, blocksize) == 1) { + free (block); + return ped_geometry_duplicate (geom); + } + +error: + free (block); +error_block: +error_part: + return NULL; +} +static PedGeometry* +_affs0_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5300); +} +static PedGeometry* +_affs1_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5301); +} +static PedGeometry* +_affs2_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5302); +} +static PedGeometry* +_affs3_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5303); +} +static PedGeometry* +_affs4_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5304); +} +static PedGeometry* +_affs5_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5305); +} +static PedGeometry* +_affs6_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5306); +} +static PedGeometry* +_affs7_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x444f5307); +} +static PedGeometry* +_amufs_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x6d754653); +} +static PedGeometry* +_amufs0_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x6d754600); +} +static PedGeometry* +_amufs1_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x6d754601); +} +static PedGeometry* +_amufs2_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x6d754602); +} +static PedGeometry* +_amufs3_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x6d754603); +} +static PedGeometry* +_amufs4_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x6d754604); +} +static PedGeometry* +_amufs5_probe (PedGeometry* geom) { + return _generic_affs_probe (geom, 0x6d754605); +} + +static PedFileSystemOps _affs0_ops = { + probe: _affs0_probe, +}; +static PedFileSystemOps _affs1_ops = { + probe: _affs1_probe, +}; +static PedFileSystemOps _affs2_ops = { + probe: _affs2_probe, +}; +static PedFileSystemOps _affs3_ops = { + probe: _affs3_probe, +}; +static PedFileSystemOps _affs4_ops = { + probe: _affs4_probe, +}; +static PedFileSystemOps _affs5_ops = { + probe: _affs5_probe, +}; +static PedFileSystemOps _affs6_ops = { + probe: _affs6_probe, +}; +static PedFileSystemOps _affs7_ops = { + probe: _affs7_probe, +}; +static PedFileSystemOps _amufs_ops = { + probe: _amufs_probe, +}; +static PedFileSystemOps _amufs0_ops = { + probe: _amufs0_probe, +}; +static PedFileSystemOps _amufs1_ops = { + probe: _amufs1_probe, +}; +static PedFileSystemOps _amufs2_ops = { + probe: _amufs2_probe, +}; +static PedFileSystemOps _amufs3_ops = { + probe: _amufs3_probe, +}; +static PedFileSystemOps _amufs4_ops = { + probe: _amufs4_probe, +}; +static PedFileSystemOps _amufs5_ops = { + probe: _amufs5_probe, +}; + +PedFileSystemType _affs0_type = { + next: NULL, + ops: &_affs0_ops, + name: "affs0", +}; +PedFileSystemType _affs1_type = { + next: NULL, + ops: &_affs1_ops, + name: "affs1", +}; +PedFileSystemType _affs2_type = { + next: NULL, + ops: &_affs2_ops, + name: "affs2", +}; +PedFileSystemType _affs3_type = { + next: NULL, + ops: &_affs3_ops, + name: "affs3", +}; +PedFileSystemType _affs4_type = { + next: NULL, + ops: &_affs4_ops, + name: "affs4", +}; +PedFileSystemType _affs5_type = { + next: NULL, + ops: &_affs5_ops, + name: "affs5", +}; +PedFileSystemType _affs6_type = { + next: NULL, + ops: &_affs6_ops, + name: "affs6", +}; +PedFileSystemType _affs7_type = { + next: NULL, + ops: &_affs7_ops, + name: "affs7", +}; +PedFileSystemType _amufs_type = { + next: NULL, + ops: &_amufs_ops, + name: "amufs", +}; +PedFileSystemType _amufs0_type = { + next: NULL, + ops: &_amufs0_ops, + name: "amufs0", +}; +PedFileSystemType _amufs1_type = { + next: NULL, + ops: &_amufs1_ops, + name: "amufs1", +}; +PedFileSystemType _amufs2_type = { + next: NULL, + ops: &_amufs2_ops, + name: "amufs2", +}; +PedFileSystemType _amufs3_type = { + next: NULL, + ops: &_amufs3_ops, + name: "amufs3", +}; +PedFileSystemType _amufs4_type = { + next: NULL, + ops: &_amufs4_ops, + name: "amufs4", +}; +PedFileSystemType _amufs5_type = { + next: NULL, + ops: &_amufs5_ops, + name: "amufs5", +}; diff --git a/libparted/fs/amiga/affs.h b/libparted/fs/amiga/affs.h new file mode 100644 index 0000000..d1650f2 --- /dev/null +++ b/libparted/fs/amiga/affs.h @@ -0,0 +1,19 @@ + +/* + affs.h -- parted suppoer for affs filesystems header files + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ diff --git a/libparted/fs/amiga/amiga.c b/libparted/fs/amiga/amiga.c new file mode 100644 index 0000000..1a909fc --- /dev/null +++ b/libparted/fs/amiga/amiga.c @@ -0,0 +1,351 @@ +/* + libparted/fs_amiga - amiga file system support. + Copyright (C) 2000-2001, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. + + Contributor: Sven Luther <luther@debian.org> +*/ + +#include <config.h> +#include <parted/parted.h> +#include <parted/debug.h> +#include <parted/endian.h> + +#include "amiga.h" + +#if ENABLE_NLS +# include <libintl.h> +# define _(String) dgettext (PACKAGE, String) +#else +# define _(String) (String) +#endif /* ENABLE_NLS */ + +#define IDNAME_RIGIDDISK (uint32_t)0x5244534B /* 'RDSK' */ +#define IDNAME_BADBLOCK (uint32_t)0x42414442 /* 'BADB' */ +#define IDNAME_PARTITION (uint32_t)0x50415254 /* 'PART' */ +#define IDNAME_FILESYSHEADER (uint32_t)0x46534844 /* 'FSHD' */ +#define IDNAME_LOADSEG (uint32_t)0x4C534547 /* 'LSEG' */ +#define IDNAME_BOOT (uint32_t)0x424f4f54 /* 'BOOT' */ +#define IDNAME_FREE (uint32_t)0xffffffff + +static const char * +_amiga_block_id (uint32_t id) { + switch (id) { + case IDNAME_RIGIDDISK : + return "RDSK"; + case IDNAME_BADBLOCK : + return "BADB"; + case IDNAME_PARTITION : + return "PART"; + case IDNAME_FILESYSHEADER : + return "FSHD"; + case IDNAME_LOADSEG : + return "LSEG"; + case IDNAME_BOOT : + return "BOOT"; + case IDNAME_FREE : + return "<free>"; + default : + return "<unknown>"; + } +} + +struct AmigaIds * +_amiga_add_id (uint32_t id, struct AmigaIds *ids) { + struct AmigaIds *newid; + + if ((newid=ped_malloc(sizeof (struct AmigaIds)))==NULL) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate id list element\n"), __func__); + return 0; + } + newid->ID = id; + newid->next = ids; + return newid; +} + +void +_amiga_free_ids (struct AmigaIds *ids) { + struct AmigaIds *current, *next; + + for (current = ids; current != NULL; current = next) { + next = current->next; + free (current); + } +} +int +_amiga_id_in_list (uint32_t id, struct AmigaIds *ids) { + struct AmigaIds *current; + + for (current = ids; current != NULL; current = current->next) { + if (id == current->ID) + return 1; + } + return 0; +} + +#define AMIGA_RDB_NOT_FOUND ((uint32_t)0xffffffff) + +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)) + +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 AMIGA_MAX_PARTITIONS 128 +#define RDB_LOCATION_LIMIT 16 +#define RDSK(pos) ((struct RigidDiskBlock *)(pos)) + +static int +_amiga_checksum (struct AmigaBlock *blk) { + uint32_t *rdb = (uint32_t *) blk; + uint32_t sum; + int i, end; + + sum = PED_BE32_TO_CPU (rdb[0]); + end = PED_BE32_TO_CPU (rdb[1]); + + if (end > PED_SECTOR_SIZE_DEFAULT) end = PED_SECTOR_SIZE_DEFAULT; + + for (i = 1; i < end; i++) sum += PED_BE32_TO_CPU (rdb[i]); + + return sum; +} + +static void +_amiga_calculate_checksum (struct AmigaBlock *blk) { + + blk->amiga_ChkSum = PED_CPU_TO_BE32( + PED_BE32_TO_CPU(blk->amiga_ChkSum) - + _amiga_checksum((struct AmigaBlock *) blk)); + return; +} + + +static struct AmigaBlock * +_amiga_read_block (PedDevice *dev, struct AmigaBlock *blk, PedSector block, struct AmigaIds *ids) { + if (!ped_device_read (dev, blk, block, 1)) { + switch (ped_exception_throw(PED_EXCEPTION_ERROR, + PED_EXCEPTION_CANCEL, + _("%s : Couldn't read block %llu\n"), __func__, block)) + { + case PED_EXCEPTION_CANCEL : + case PED_EXCEPTION_UNHANDLED : + default : + return NULL; + } + } + if (ids && !_amiga_id_in_list(PED_BE32_TO_CPU(blk->amiga_ID), ids)) + return NULL; + if (_amiga_checksum (blk) != 0) { + switch (ped_exception_throw(PED_EXCEPTION_ERROR, + PED_EXCEPTION_FIX | PED_EXCEPTION_IGNORE | PED_EXCEPTION_CANCEL, + _("%s : Bad checksum on block %llu of type %s\n"), + __func__, block, _amiga_block_id(PED_BE32_TO_CPU(blk->amiga_ID)))) + { + case PED_EXCEPTION_CANCEL : + return NULL; + case PED_EXCEPTION_FIX : + _amiga_calculate_checksum(AMIGA(blk)); + if (!ped_device_write (dev, blk, block, 1)) { + switch (ped_exception_throw(PED_EXCEPTION_FATAL, + PED_EXCEPTION_CANCEL, + _("%s : Couldn't write block %d\n"), __func__, block)) + { + case PED_EXCEPTION_CANCEL : + case PED_EXCEPTION_UNHANDLED : + default : + return NULL; + } + } + /* FALLTHROUGH */ + case PED_EXCEPTION_IGNORE : + case PED_EXCEPTION_UNHANDLED : + default : + return blk; + } + } + return blk; +} + +static uint32_t +_amiga_find_rdb (PedDevice *dev, struct RigidDiskBlock *rdb) { + int i; + struct AmigaIds *ids; + + ids = _amiga_add_id (IDNAME_RIGIDDISK, NULL); + + for (i = 0; i<RDB_LOCATION_LIMIT; i++) { + if (!_amiga_read_block (dev, AMIGA(rdb), i, ids)) { + continue; + } + if (PED_BE32_TO_CPU (rdb->rdb_ID) == IDNAME_RIGIDDISK) { + _amiga_free_ids (ids); + return i; + } + } + _amiga_free_ids (ids); + return AMIGA_RDB_NOT_FOUND; +} + +static int +_amiga_loop_check (uint32_t block, uint32_t * blocklist, uint32_t max) +{ + uint32_t i; + + 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 */ +struct PartitionBlock * +amiga_find_part (PedGeometry *geom, struct PartitionBlock *part) +{ + struct RigidDiskBlock *rdb; + uint32_t partblock; + uint32_t partlist[AMIGA_MAX_PARTITIONS]; + int i; + + PED_ASSERT(geom!= NULL); + PED_ASSERT(geom->dev!= NULL); + + if (!(rdb = ped_malloc (PED_SECTOR_SIZE_DEFAULT))) { + 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 : + return NULL; + } + } + if (_amiga_find_rdb (geom->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 : + free(rdb); + return NULL; + } + } + + /* We initialize the hardblock free list to detect loops */ + for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = IDNAME_FREE; + + for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList); + i < AMIGA_MAX_PARTITIONS && partblock != IDNAME_FREE; + i++, partblock = PED_BE32_TO_CPU(part->pb_Next)) + { + PedSector start, end; + PedSector cylblocks; + + /* Let's look for loops in the partition table */ + if (_amiga_loop_check(partblock, partlist, i)) { + free (rdb); + return NULL; + } + /* Let's read a partition block to get its geometry*/ + if (!ped_device_read (geom->dev, part, (PedSector)partblock, 1)) { + switch (ped_exception_throw(PED_EXCEPTION_ERROR, + PED_EXCEPTION_CANCEL, + _("%s : Failed to read partition block %llu\n"), + __func__, (PedSector)partblock)) + { + case PED_EXCEPTION_CANCEL : + case PED_EXCEPTION_UNHANDLED : + default : + free(rdb); + return NULL; + } + } + + /* Current block is not a Partition Block */ + if (part->pb_ID != IDNAME_PARTITION) { + free (rdb); + return NULL; + } + + /* Calculate the geometry of the partition */ + cylblocks = ((PedSector) PED_BE32_TO_CPU (part->de_Surfaces)) * + ((PedSector) PED_BE32_TO_CPU (part->de_BlocksPerTrack)); + start = ((PedSector) PED_BE32_TO_CPU (part->de_LowCyl)) * cylblocks; + end = ((((PedSector) PED_BE32_TO_CPU (part->de_HighCyl))+1) * (cylblocks))-1; + + /* And check if it is the one we are searching for */ + if (start == geom->start && end == geom->end) { + free (rdb); + return part; + } + } + + free (rdb); + return NULL; +} diff --git a/libparted/fs/amiga/amiga.h b/libparted/fs/amiga/amiga.h new file mode 100644 index 0000000..30f5b82 --- /dev/null +++ b/libparted/fs/amiga/amiga.h @@ -0,0 +1,70 @@ +/* + util.h -- amiga partition table headers. + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +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 file system */ + 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) */ + +struct PartitionBlock * amiga_find_part (PedGeometry *geom, struct PartitionBlock *part); + +struct AmigaIds { + uint32_t ID; + struct AmigaIds *next; +}; + +struct AmigaIds * _amiga_add_id (uint32_t id, struct AmigaIds *ids); +void _amiga_free_ids (struct AmigaIds *ids); +int _amiga_id_in_list (uint32_t id, struct AmigaIds *ids) _GL_ATTRIBUTE_PURE; diff --git a/libparted/fs/amiga/apfs.c b/libparted/fs/amiga/apfs.c new file mode 100644 index 0000000..aeaa1f3 --- /dev/null +++ b/libparted/fs/amiga/apfs.c @@ -0,0 +1,128 @@ +/* + apfs.c -- parted support for apfs file systems + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <parted/parted.h> +#include <parted/debug.h> +#include <parted/endian.h> + +#include "amiga.h" +#include "apfs.h" + +#if ENABLE_NLS +# include <libintl.h> +# define _(String) dgettext (PACKAGE, String) +#else +# define _(String) (String) +#endif /* ENABLE_NLS */ + +static int +_apfs_probe_root (uint32_t *block, uint32_t blocksize, uint32_t kind) { + if (PED_BE32_TO_CPU (block[0]) != kind) return 0; + return 1; +} + +static PedGeometry* +_generic_apfs_probe (PedGeometry* geom, uint32_t kind) +{ + uint32_t *block; + PedSector root; + struct PartitionBlock * part; + uint32_t blocksize = 1, reserved = 2; + + PED_ASSERT (geom != NULL); + PED_ASSERT (geom->dev != NULL); + if (geom->dev->sector_size != 512) + return NULL; + + /* Finds the blocksize and reserved values of the partition block */ + if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate partition block\n"), __func__); + goto error_part; + } + if (amiga_find_part(geom, part) != NULL) { + reserved = PED_BE32_TO_CPU (part->de_Reserved); + blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) + * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; + } + free (part); + + /* Test boot block */ + if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate block\n"), __func__); + goto error_block; + } + if (!ped_device_read (geom->dev, block, geom->start, blocksize)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Couldn't read boot block %llu\n"), __func__, geom->start); + goto error; + } + if (PED_BE32_TO_CPU (block[0]) != kind) { + goto error; + } + + /* Find and test the root block */ + root = geom->start+reserved*blocksize; + if (!ped_device_read (geom->dev, block, root, blocksize)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Couldn't read root block %llu\n"), __func__, root); + goto error; + } + if (_apfs_probe_root(block, blocksize, kind) == 1) { + free(block); + return ped_geometry_duplicate (geom); + } + +error: + free (block); +error_block: +error_part: + return NULL; +} + +static PedGeometry* +_apfs1_probe (PedGeometry* geom) { + return _generic_apfs_probe (geom, 0x50463101); +} + +static PedGeometry* +_apfs2_probe (PedGeometry* geom) { + return _generic_apfs_probe (geom, 0x50463102); +} + +static PedFileSystemOps _apfs1_ops = { + probe: _apfs1_probe, +}; +static PedFileSystemOps _apfs2_ops = { + probe: _apfs2_probe, +}; + +PedFileSystemType _apfs1_type = { + next: NULL, + ops: &_apfs1_ops, + name: "apfs1", +}; +PedFileSystemType _apfs2_type = { + next: NULL, + ops: &_apfs2_ops, + name: "apfs2", +}; diff --git a/libparted/fs/amiga/apfs.h b/libparted/fs/amiga/apfs.h new file mode 100644 index 0000000..972941b --- /dev/null +++ b/libparted/fs/amiga/apfs.h @@ -0,0 +1,18 @@ +/* + apfs.h -- parted support for apfs file systems header files + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ diff --git a/libparted/fs/amiga/asfs.c b/libparted/fs/amiga/asfs.c new file mode 100644 index 0000000..c4c65e5 --- /dev/null +++ b/libparted/fs/amiga/asfs.c @@ -0,0 +1,130 @@ +/* + asfs.c -- parted asfs filesystem support + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ + +#include <config.h> + +#include <parted/parted.h> +#include <parted/debug.h> +#include <parted/endian.h> + +#include "amiga.h" +#include "asfs.h" + +#if ENABLE_NLS +# include <libintl.h> +# define _(String) dgettext (PACKAGE, String) +#else +# define _(String) (String) +#endif /* ENABLE_NLS */ + +static int +_asfs_probe_root (PedGeometry *geom, uint32_t *block, int blocksize, PedSector root) { + int i, sum; + PedSector start, end; + + if (PED_BE32_TO_CPU (block[0]) != 0x53465300) return 0; + for (i = 0, sum = 1; i < 128*blocksize; i++) sum += PED_BE32_TO_CPU (block[i]); + if (sum != 0) return 0; + if (PED_BE32_TO_CPU (block[2]) * blocksize + geom->start != root) { + return 0; + } + start = ((((PedSector) PED_BE32_TO_CPU (block[8])) << 32) + + (PedSector) PED_BE32_TO_CPU (block[9])) / 512; + end = (((((PedSector) PED_BE32_TO_CPU (block[10])) << 32) + + (PedSector) PED_BE32_TO_CPU (block[11])) / 512) - 1; + if (start != geom->start || end != geom->end) return 0; + return 1; +} + +static PedGeometry* +_asfs_probe (PedGeometry* geom) +{ + uint32_t *block; + struct PartitionBlock * part; + int blocksize = 1; + PedSector root; + int found = 0; + + PED_ASSERT (geom != NULL); + PED_ASSERT (geom->dev != NULL); + if (geom->dev->sector_size != 512) + return NULL; + + /* Finds the blocksize of the partition block */ + if (!(part = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate partition block\n"), __func__); + goto error_part; + } + if (amiga_find_part(geom, part) != NULL) { + blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) + * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; + } + free (part); + + /* Test boot block */ + if (!(block = ped_malloc (PED_SECTOR_SIZE_DEFAULT*blocksize))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate block\n"), __func__); + goto error_block; + } + root = geom->start; + if (!ped_device_read (geom->dev, block, root, blocksize)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Couldn't read root block %llu\n"), __func__, root); + goto error; + } + if (PED_BE32_TO_CPU (block[0]) != 0x53465300) { + goto error; + } + + /* Find and test the root blocks */ + if (_asfs_probe_root(geom, block, blocksize, root)) { + found++; + } + root = geom->end - blocksize - (geom->length % blocksize) + 1; + if (!ped_device_read (geom->dev, block, root, 1)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Couldn't read root block %llu\n"), __func__, root); + goto error; + } + if (_asfs_probe_root(geom, block, blocksize, root)) { + found++; + } + if (found != 0) { + free (block); + return ped_geometry_duplicate (geom); + } + +error: + free (block); +error_block: +error_part: + return NULL; +} + +static PedFileSystemOps _asfs_ops = { + probe: _asfs_probe, +}; + +PedFileSystemType _asfs_type = { + next: NULL, + ops: &_asfs_ops, + name: "asfs", +}; diff --git a/libparted/fs/amiga/asfs.h b/libparted/fs/amiga/asfs.h new file mode 100644 index 0000000..2b70a94 --- /dev/null +++ b/libparted/fs/amiga/asfs.h @@ -0,0 +1,18 @@ +/* + asfs.h -- parted asfs filesystem support header files + Copyright (C) 1998-2000, 2007, 2009-2014, 2019-2023 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 3 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, see <http://www.gnu.org/licenses/>. +*/ |