#! /bin/sh -e ## amiga.dpatch by Sven Luther ## ## All lines beginning with `## DP:' are a description of the patch. ## DP: No description. [ -f debian/patches/00patch-opts ] && . debian/patches/00patch-opts patch_opts="${patch_opts:--f --no-backup-if-mismatch}" if [ $# -ne 1 ]; then echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1 fi case "$1" in -patch) patch $patch_opts -p1 < $0;; -unpatch) patch $patch_opts -p1 -R < $0;; *) echo >&2 "`basename $0`: script expects -patch|-unpatch as argument" exit 1;; esac exit 0 @DPATCH@ Fixes bug #219947, adding support for amiga file system. diff -urN parted-1.6.6/configure parted-1.6.6-amiga/configure --- parted-1.6.6/configure 2003-07-26 02:02:18.000000000 +0200 +++ parted-1.6.6-amiga/configure 2004-01-22 12:36:45.000000000 +0100 @@ -13714,8 +13714,7 @@ if test "$enable_Werror" = yes; then CFLAGS="$CFLAGS -Werror" fi - - ac_config_files="$ac_config_files Makefile include/Makefile include/parted/Makefile libparted/Makefile libparted/fs_ext2/Makefile libparted/fs_fat/Makefile libparted/fs_hfs/Makefile libparted/fs_jfs/Makefile libparted/fs_linux_swap/Makefile libparted/fs_ntfs/Makefile libparted/fs_reiserfs/Makefile libparted/fs_ufs/Makefile libparted/fs_xfs/Makefile parted/Makefile partprobe/Makefile intl/Makefile doc/Makefile debug/Makefile debug/clearfat/Makefile debug/test/Makefile po/Makefile.in parted.spec" +ac_config_files="$ac_config_files Makefile include/Makefile include/parted/Makefile libparted/Makefile libparted/fs_ext2/Makefile libparted/fs_fat/Makefile libparted/fs_hfs/Makefile libparted/fs_jfs/Makefile libparted/fs_linux_swap/Makefile libparted/fs_ntfs/Makefile libparted/fs_reiserfs/Makefile libparted/fs_ufs/Makefile libparted/fs_xfs/Makefile libparted/fs_amiga/Makefile parted/Makefile partprobe/Makefile intl/Makefile doc/Makefile debug/Makefile debug/clearfat/Makefile debug/test/Makefile po/Makefile.in parted.spec" cat >confcache <<\_ACEOF # This file is a shell script that caches the results of configure # tests run on this system so they can be shared between configure @@ -14264,6 +14263,7 @@ "libparted/fs_reiserfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES libparted/fs_reiserfs/Makefile" ;; "libparted/fs_ufs/Makefile" ) CONFIG_FILES="$CONFIG_FILES libparted/fs_ufs/Makefile" ;; "libparted/fs_xfs/Makefile" ) CONFIG_FILES="$CONFIG_FILES libparted/fs_xfs/Makefile" ;; + "libparted/fs_amiga/Makefile" ) CONFIG_FILES="$CONFIG_FILES libparted/fs_amiga/Makefile" ;; "parted/Makefile" ) CONFIG_FILES="$CONFIG_FILES parted/Makefile" ;; "partprobe/Makefile" ) CONFIG_FILES="$CONFIG_FILES partprobe/Makefile" ;; "intl/Makefile" ) CONFIG_FILES="$CONFIG_FILES intl/Makefile" ;; diff -urN parted-1.6.6/libparted/Makefile.am parted-1.6.6-amiga/libparted/Makefile.am --- parted-1.6.6/libparted/Makefile.am 2002-12-31 01:19:17.000000000 +0100 +++ parted-1.6.6-amiga/libparted/Makefile.am 2004-01-22 12:36:45.000000000 +0100 @@ -11,7 +11,8 @@ fs_ntfs \ fs_reiserfs \ fs_ufs \ - fs_xfs + fs_xfs \ + fs_amiga LIBS = @INTLLIBS@ @LIBS@ @@ -41,6 +42,7 @@ disk_dvh.c \ disk_pc98.c \ disk_sun.c \ + disk_amiga.c \ @OS@.c EXTRA_libparted_la_SOURCES = linux.c \ @@ -57,7 +59,8 @@ fs_ntfs/libntfs.la \ fs_reiserfs/libreiserfs.la \ fs_ufs/libufs.la \ - fs_xfs/libxfs.la + fs_xfs/libxfs.la \ + fs_amiga/libamigafs.la EXTRA_DIST = mbr.s diff -urN parted-1.6.6/libparted/Makefile.in parted-1.6.6-amiga/libparted/Makefile.in --- parted-1.6.6/libparted/Makefile.in 2003-07-26 02:38:27.000000000 +0200 +++ parted-1.6.6-amiga/libparted/Makefile.in 2004-01-22 12:36:45.000000000 +0100 @@ -110,7 +110,7 @@ UUID_LIBS = @UUID_LIBS@ VERSION = @VERSION@ -SUBDIRS = fs_ext2 fs_fat fs_hfs fs_jfs fs_linux_swap fs_ntfs fs_reiserfs fs_ufs fs_xfs +SUBDIRS = fs_ext2 fs_fat fs_hfs fs_jfs fs_linux_swap fs_ntfs fs_reiserfs fs_ufs fs_xfs fs_amiga LIBS = @INTLLIBS@ @LIBS@ @@ -120,13 +120,13 @@ libparted_la_LDFLAGS = -version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE) -release $(LT_RELEASE) -libparted_la_SOURCES = blkpg.h dvh.h crc32.c constraint.c debug.c device.c exception.c filesys.c geom.c libparted.c natmath.c timer.c disk.c disk_bsd.c disk_dos.c disk_gpt.c disk_loop.c disk_mac.c disk_dvh.c disk_pc98.c disk_sun.c @OS@.c +libparted_la_SOURCES = blkpg.h dvh.h crc32.c constraint.c debug.c device.c exception.c filesys.c geom.c libparted.c natmath.c timer.c disk.c disk_bsd.c disk_dos.c disk_gpt.c disk_loop.c disk_mac.c disk_dvh.c disk_pc98.c disk_sun.c disk_amiga.c @OS@.c EXTRA_libparted_la_SOURCES = linux.c gnu.c -libparted_la_LIBADD = @UUID_LIBS@ @OS_LIBS@ @REISER_LIBS@ fs_ext2/libext2.la fs_fat/libfat.la fs_hfs/libhfs.la fs_jfs/libjfs.la fs_linux_swap/liblinuxswap.la fs_ntfs/libntfs.la fs_reiserfs/libreiserfs.la fs_ufs/libufs.la fs_xfs/libxfs.la +libparted_la_LIBADD = @UUID_LIBS@ @OS_LIBS@ @REISER_LIBS@ fs_ext2/libext2.la fs_fat/libfat.la fs_hfs/libhfs.la fs_jfs/libjfs.la fs_linux_swap/liblinuxswap.la fs_ntfs/libntfs.la fs_reiserfs/libreiserfs.la fs_ufs/libufs.la fs_xfs/libxfs.la fs_amiga/libamigafs.la EXTRA_DIST = mbr.s @@ -144,11 +144,11 @@ libparted_la_DEPENDENCIES = fs_ext2/libext2.la fs_fat/libfat.la \ fs_hfs/libhfs.la fs_jfs/libjfs.la fs_linux_swap/liblinuxswap.la \ fs_ntfs/libntfs.la fs_reiserfs/libreiserfs.la fs_ufs/libufs.la \ -fs_xfs/libxfs.la +fs_xfs/libxfs.la fs_amiga/libamigafs.la libparted_la_OBJECTS = crc32.lo constraint.lo debug.lo device.lo \ exception.lo filesys.lo geom.lo libparted.lo natmath.lo timer.lo \ disk.lo disk_bsd.lo disk_dos.lo disk_gpt.lo disk_loop.lo disk_mac.lo \ -disk_dvh.lo disk_pc98.lo disk_sun.lo @OS@.lo +disk_dvh.lo disk_pc98.lo disk_sun.lo disk_amiga.lo @OS@.lo CFLAGS = @CFLAGS@ COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) @@ -361,131 +361,6 @@ || exit 1; \ fi; \ done -constraint.lo constraint.o : constraint.c ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h ../config.h -crc32.lo crc32.o : crc32.c -debug.lo debug.o : debug.c ../config.h ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h -device.lo device.o : device.c ../config.h ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h -disk.lo disk.o : disk.c ../config.h ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h -disk_bsd.lo disk_bsd.o : disk_bsd.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/endian.h -disk_dos.lo disk_dos.o : disk_dos.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/endian.h -disk_dvh.lo disk_dvh.o : disk_dvh.c ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h ../config.h \ - ../include/parted/endian.h dvh.h -disk_gpt.lo disk_gpt.o : disk_gpt.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/endian.h ../include/parted/crc32.h -disk_loop.lo disk_loop.o : disk_loop.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/endian.h -disk_mac.lo disk_mac.o : disk_mac.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/endian.h -disk_mips.lo disk_mips.o : ../config.h -disk_pc98.lo disk_pc98.o : disk_pc98.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/endian.h -disk_sun.lo disk_sun.o : disk_sun.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/endian.h -exception.lo exception.o : exception.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h -filesys.lo filesys.o : filesys.c ../config.h ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h -geom.lo geom.o : geom.c ../config.h ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h -libparted.lo libparted.o : libparted.c ../config.h \ - ../include/parted/parted.h ../include/parted/constraint.h \ - ../include/parted/device.h ../include/parted/timer.h \ - ../include/parted/natmath.h ../include/parted/disk.h \ - ../include/parted/filesys.h ../include/parted/geom.h \ - ../include/parted/exception.h ../include/parted/debug.h \ - ../include/parted/linux.h -linux.lo linux.o : linux.c ../config.h ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h ../include/parted/linux.h blkpg.h -natmath.lo natmath.o : natmath.c ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h ../config.h -timer.lo timer.o : timer.c ../include/parted/parted.h \ - ../include/parted/constraint.h ../include/parted/device.h \ - ../include/parted/timer.h ../include/parted/natmath.h \ - ../include/parted/disk.h ../include/parted/filesys.h \ - ../include/parted/geom.h ../include/parted/exception.h \ - ../include/parted/debug.h ../config.h - info-am: info: info-recursive dvi-am: diff -urN parted-1.6.6/libparted/disk_amiga.c parted-1.6.6-amiga/libparted/disk_amiga.c --- parted-1.6.6/libparted/disk_amiga.c 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/disk_amiga.c 2004-01-23 13:17:04.000000000 +0100 @@ -0,0 +1,1260 @@ +/* -*- Mode: c; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + + libparted - a library for manipulating disk partitions + disk_amiga.c - libparted module to manipulate amiga RDB partition tables. + 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 */ + +/* String manipulation */ +static void _amiga_set_bstr (const char *cstr, char *bstr, int maxsize) { + int size = strlen (cstr); + int i; + + if (size >= maxsize) return; + bstr[0] = size; + for (i = 0; i"; + default : + return ""; + } +} +static int +_amiga_valid_block_id (uint32_t id) { + 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 AmigaIds { + uint32_t ID; + struct AmigaIds *next; +}; + +static 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; +} + +static void +_amiga_free_ids (struct AmigaIds *ids) { + struct AmigaIds *current, *next; + + for (current = ids; current != NULL; current = next) { + next = current->next; + ped_free (current); + } +} +static 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; +} + +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; + + 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) { + 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)) { + ped_exception_throw(PED_EXCEPTION_ERROR, + PED_EXCEPTION_CANCEL, + _("%s : Couldn't read block %llu\n"), __func__, block); + 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)) { + ped_exception_throw(PED_EXCEPTION_FATAL, PED_EXCEPTION_CANCEL, + _("%s : Couldn't write block %d\n"), __func__, block); + return NULL; + } + case PED_EXCEPTION_IGNORE : + case PED_EXCEPTION_UNHANDLED : + default : + return blk; + } + } + return blk; +} + +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 RDSK(pos) ((struct RigidDiskBlock *)(pos)) + +#define AMIGA_RDB_NOT_FOUND ((uint32_t)0xffffffff) +#define RDB_LOCATION_LIMIT 16 +#define AMIGA_MAX_PARTITIONS 128 +#define MAX_RDB_BLOCK (RDB_LOCATION_LIMIT + 2 * AMIGA_MAX_PARTITIONS + 2) + +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; irdb_ID) == IDNAME_RIGIDDISK) { + _amiga_free_ids (ids); + return i; + } + } + _amiga_free_ids (ids); + 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) */ + + +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)) + + +static PedDiskType amiga_disk_type; + +static int +amiga_probe (PedDevice *dev) +{ + struct RigidDiskBlock *rdb; + uint32_t found; + PED_ASSERT(dev!= NULL, return 0); + + if ((rdb=RDSK(ped_malloc(PED_SECTOR_SIZE)))==NULL) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate rdb block\n"), __func__); + 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; + PED_ASSERT(dev!= NULL, return NULL); + + if (!(disk = _ped_disk_alloc (dev, &amiga_disk_type))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate disk structure\n"), __func__); + return NULL; + } + + if (!(disk->disk_specific = ped_malloc (PED_SECTOR_SIZE))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate disk_specific rdb block\n"), __func__); + 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 (LINK_END); + rdb->rdb_PartitionList = PED_CPU_TO_BE32 (LINK_END); + rdb->rdb_FileSysHeaderList = PED_CPU_TO_BE32 (LINK_END); + rdb->rdb_DriveInit = PED_CPU_TO_BE32 (LINK_END); + rdb->rdb_BootBlockList = PED_CPU_TO_BE32 (LINK_END); + + /* 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; + 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))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate a new disk structure\n"), __func__); + 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) +{ + 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; + PED_ASSERT(dev!= NULL, return 0); + + if ((rdb=RDSK(ped_malloc(PED_SECTOR_SIZE)))==NULL) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate rdb block\n"), __func__); + 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; + + 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; + + 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) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Didn't find rdb block, should never happen\n"), __func__); + return 0; + } + + /* 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))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate partition block\n"), __func__); + return 0; + } + + /* We initialize the hardblock free list to detect loops */ + for (i = 0; i < AMIGA_MAX_PARTITIONS; i++) partlist[i] = LINK_END; + + for (i = 1, partblock = PED_BE32_TO_CPU(rdb->rdb_PartitionList); + i < AMIGA_MAX_PARTITIONS && partblock != LINK_END; + 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 (!_amiga_read_block (disk->dev, AMIGA(partition), (PedSector)partblock, NULL)) { + ped_free(partition); + return 0; + } + + 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))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate new partition (%llu -> %llu)\n"), + __func__, start, end); + 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)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to add new partition\n"), __func__); + 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; + + 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 : + /* TODO : Need to add fixing code */ + case PED_EXCEPTION_IGNORE : + case PED_EXCEPTION_UNHANDLED : + default : + return 1; + } + } + + if (!_amiga_read_block (disk->dev, AMIGA(block), next, NULL)) { + return 0; + } + 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)) + { + /* TODO : to more subtile things here */ + 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; + + 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; + + 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; + + 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))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate rdb block\n"), __func__); + 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); + + /* 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)))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate free block table\n"), __func__); + 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))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate partition block\n"), __func__); + 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; + } + } + + 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; + + 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))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate a partition structure (%llu, %llu)"), + __func__, start, end); + return NULL; + } + + + if (ped_partition_is_active (part)) { + if (!(part->disk_specific = ped_malloc (PED_SECTOR_SIZE))) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate a partition disk_specific block\n"), __func__); + 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); + + } 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; + + 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) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to allocate a new partition structure\n"), __func__); + 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) +{ + 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; + + 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; + + 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; + + 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) +{ + 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; + + 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; + + 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; + + if (!ped_alignment_init(&start_align, 0, cyl)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to initialize the start constraint\n"), __func__); + return NULL; + } + if (!ped_alignment_init(&end_align, -1, cyl)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to initialize the end constraint\n"), __func__); + return NULL; + } + if (!ped_geometry_init(&max_geom, dev, start, length)) { + ped_exception_throw(PED_EXCEPTION_ERROR, PED_EXCEPTION_CANCEL, + _("%s : Failed to initialize the max constraint\n"), __func__); + return NULL; + } + + return ped_constraint_new (&start_align, &end_align, + &max_geom, &max_geom, cyl, max_part); +} + +static int +amiga_partition_align (PedPartition* part, const PedConstraint* constraint) +{ + + PED_ASSERT (part != NULL, return 0); + PED_ASSERT (part->disk != NULL, return 0); + + 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; + + 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; + + 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) +{ + 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 () +{ + 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 () +{ + + ped_unregister_disk_type (&amiga_disk_type); +} diff -urN parted-1.6.6/libparted/disk_amiga.c.2 parted-1.6.6-amiga/libparted/disk_amiga.c.2 --- parted-1.6.6/libparted/disk_amiga.c.2 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/disk_amiga.c.2 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,1524 @@ +/* -*- 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; +} + +static struct AmigaBlock * +_amiga_read_block (PedDevice *dev, struct AmigaBlock *blk, PedSector block) { + 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 (_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; + } + } + case PED_EXCEPTION_IGNORE : + case PED_EXCEPTION_UNHANDLED : + default : + return blk; + } + } + return blk; +} + +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) { + 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 (!_amiga_read_block (disk->dev, AMIGA(partition), (PedSector)partblock)) { + 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 (!_amiga_read_block (disk->dev, AMIGA(block), next)) { + 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/libparted/fs_amiga/Makefile.am parted-1.6.6-amiga/libparted/fs_amiga/Makefile.am --- parted-1.6.6/libparted/fs_amiga/Makefile.am 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/Makefile.am 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,14 @@ +partedincludedir = -I$(top_srcdir)/include + +noinst_LTLIBRARIES = libamigafs.la +libext2_la_SOURCES = amiga.h \ + amiga.c \ + affs.h \ + affs.c \ + asfs.h \ + asfs.c \ + apfs.h \ + apfs.c \ + interface.c + +INCLUDES = $(partedincludedir) @INTLINCS@ diff -urN parted-1.6.6/libparted/fs_amiga/Makefile.in parted-1.6.6-amiga/libparted/fs_amiga/Makefile.in --- parted-1.6.6/libparted/fs_amiga/Makefile.in 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/Makefile.in 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,340 @@ +# Makefile.in generated automatically by automake 1.4-p6 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999, 2001 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = ../.. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +host_alias = @host_alias@ +host_triplet = @host@ +AS = @AS@ +BUILD_INCLUDED_LIBINTL = @BUILD_INCLUDED_LIBINTL@ +CATALOGS = @CATALOGS@ +CATOBJEXT = @CATOBJEXT@ +CC = @CC@ +DATADIRNAME = @DATADIRNAME@ +DLLTOOL = @DLLTOOL@ +ECHO = @ECHO@ +EXEEXT = @EXEEXT@ +GENCAT = @GENCAT@ +GLIBC21 = @GLIBC21@ +GMOFILES = @GMOFILES@ +GMSGFMT = @GMSGFMT@ +INSTOBJEXT = @INSTOBJEXT@ +INTLBISON = @INTLBISON@ +INTLINCS = @INTLINCS@ +INTLLIBS = @INTLLIBS@ +INTLOBJS = @INTLOBJS@ +INTL_LIBTOOL_SUFFIX_PREFIX = @INTL_LIBTOOL_SUFFIX_PREFIX@ +LIBICONV = @LIBICONV@ +LIBTOOL = @LIBTOOL@ +LN_S = @LN_S@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_RELEASE = @LT_RELEASE@ +LT_REVISION = @LT_REVISION@ +MAKEINFO = @MAKEINFO@ +MKINSTALLDIRS = @MKINSTALLDIRS@ +MSGFMT = @MSGFMT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OS = @OS@ +OS_LIBS = @OS_LIBS@ +PACKAGE = @PACKAGE@ +PARTEDLDFLAGS = @PARTEDLDFLAGS@ +PARTED_LIBS = @PARTED_LIBS@ +POFILES = @POFILES@ +POSUB = @POSUB@ +RANLIB = @RANLIB@ +REISER_LIBS = @REISER_LIBS@ +STRIP = @STRIP@ +USE_INCLUDED_LIBINTL = @USE_INCLUDED_LIBINTL@ +USE_NLS = @USE_NLS@ +UUID_LIBS = @UUID_LIBS@ +VERSION = @VERSION@ + +partedincludedir = -I$(top_srcdir)/include + +noinst_LTLIBRARIES = libamigafs.la +libamiga_la_SOURCES = amiga.h amiga.c affs.h affs.c asfs.h asfs.c apfs.h apfs.c interface.c + +INCLUDES = $(partedincludedir) @INTLINCS@ +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../../config.h +CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I../.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +libamigafs_la_LDFLAGS = +libamigafs_la_LIBADD = +libamigafs_la_OBJECTS = amiga.lo affs.lo asfs.lo apfs.lo interface.lo +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) --mode=compile $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(LIBTOOL) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(libamigafs_la_SOURCES) +OBJECTS = $(libamigafs_la_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .lo .o .obj .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps libparted/fs_amiga/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-noinstLTLIBRARIES: + +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + +distclean-noinstLTLIBRARIES: + +maintainer-clean-noinstLTLIBRARIES: + +.c.o: + $(COMPILE) -c $< + +# FIXME: We should only use cygpath when building on Windows, +# and only if it is available. +.c.obj: + $(COMPILE) -c `cygpath -w $<` + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + -rm -f *.$(OBJEXT) + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +.c.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.s.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +.S.lo: + $(LIBTOOL) --mode=compile $(COMPILE) -c $< + +mostlyclean-libtool: + -rm -f *.lo + +clean-libtool: + -rm -rf .libs _libs + +distclean-libtool: + +maintainer-clean-libtool: + +libamigafs.la: $(libamigafs_la_OBJECTS) $(libamigafs_la_DEPENDENCIES) + $(LINK) $(libamigafs_la_LDFLAGS) $(libamigafs_la_OBJECTS) $(libamigafs_la_LIBADD) $(LIBS) + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags -o $$here/TAGS $(ETAGS_ARGS) $$tags $$unique $(LISP)) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = libparted/fs_amiga + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$d/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +amigafs.lo amiga.o affs.o asfs.o apfs.o interface.o : \ + amiga.c affs.c asfs.c apfs.c interface.c \ + amiga.h affs.h asfs.h apfs.h \ + ../../config.h ../../include/parted/parted.h \ + ../../include/parted/constraint.h ../../include/parted/device.h \ + ../../include/parted/timer.h ../../include/parted/natmath.h \ + ../../include/parted/disk.h ../../include/parted/filesys.h \ + ../../include/parted/geom.h ../../include/parted/exception.h \ + ../../include/parted/endian.h platform_defs.h + +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: +install-exec: install-exec-am + +install-data-am: +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: +uninstall: uninstall-am +all-am: Makefile $(LTLIBRARIES) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-noinstLTLIBRARIES mostlyclean-compile \ + mostlyclean-libtool mostlyclean-tags \ + mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-noinstLTLIBRARIES clean-compile clean-libtool \ + clean-tags clean-generic mostlyclean-am + +clean: clean-am + +distclean-am: distclean-noinstLTLIBRARIES distclean-compile \ + distclean-libtool distclean-tags distclean-generic \ + clean-am + -rm -f libtool + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-noinstLTLIBRARIES \ + maintainer-clean-compile maintainer-clean-libtool \ + maintainer-clean-tags maintainer-clean-generic \ + distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-noinstLTLIBRARIES distclean-noinstLTLIBRARIES \ +clean-noinstLTLIBRARIES maintainer-clean-noinstLTLIBRARIES \ +mostlyclean-compile distclean-compile clean-compile \ +maintainer-clean-compile mostlyclean-libtool distclean-libtool \ +clean-libtool maintainer-clean-libtool tags mostlyclean-tags \ +distclean-tags clean-tags maintainer-clean-tags distdir info-am info \ +dvi-am dvi check check-am installcheck-am installcheck install-exec-am \ +install-exec install-data-am install-data install-am install \ +uninstall-am uninstall all-redirect all-am all installdirs \ +mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff -urN parted-1.6.6/libparted/fs_amiga/affs.c parted-1.6.6-amiga/libparted/fs_amiga/affs.c --- parted-1.6.6/libparted/fs_amiga/affs.c 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/affs.c 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,447 @@ +/* + affs.c -- parted suppoer for affs filesystems + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "amiga.h" +#include "affs.h" + +#if ENABLE_NLS +# include +# 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; + int32_t i; + PedSector root, len, pos; + struct PartitionBlock * part; + int blocksize = 1, reserved = 2, prealloc = 0; + + PED_ASSERT (geom != NULL, return NULL); + PED_ASSERT (geom->dev != NULL, return NULL); + + /* Finds the blocksize, prealloc and reserved values of the partition block */ + if (!(part = ped_malloc (PED_SECTOR_SIZE*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) { + prealloc = PED_BE32_TO_CPU (part->de_PreAlloc); + 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; + } + ped_free (part); + + /* Test boot block */ + if (!(block = ped_malloc (PED_SECTOR_SIZE*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; + printf ("Pralloc = %d, Reserved = %d, blocksize = %d, root block at %llu\n", + prealloc, reserved, blocksize, root); + + 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) { + ped_free (block); + return ped_geometry_duplicate (geom); + } + +error: + ped_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, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _affs1_ops = { + probe: _affs1_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _affs2_ops = { + probe: _affs2_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _affs3_ops = { + probe: _affs3_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _affs4_ops = { + probe: _affs4_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _affs5_ops = { + probe: _affs5_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _affs6_ops = { + probe: _affs6_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _affs7_ops = { + probe: _affs7_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _amufs_ops = { + probe: _amufs_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _amufs0_ops = { + probe: _amufs0_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _amufs1_ops = { + probe: _amufs1_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _amufs2_ops = { + probe: _amufs2_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _amufs3_ops = { + probe: _amufs3_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _amufs4_ops = { + probe: _amufs4_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _amufs5_ops = { + probe: _amufs5_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; + +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 -urN parted-1.6.6/libparted/fs_amiga/affs.h parted-1.6.6-amiga/libparted/fs_amiga/affs.h --- parted-1.6.6/libparted/fs_amiga/affs.h 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/affs.h 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,20 @@ + +/* + affs.h -- parted suppoer for affs filesystems header files + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + diff -urN parted-1.6.6/libparted/fs_amiga/amiga.c parted-1.6.6-amiga/libparted/fs_amiga/amiga.c --- parted-1.6.6/libparted/fs_amiga/amiga.c 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/amiga.c 2004-01-23 13:17:18.000000000 +0100 @@ -0,0 +1,382 @@ +/* + libparted/fs_amiga - amiga filesystem support. + 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 +#include +#include +#include + +#include "amiga.h" + +#if ENABLE_NLS +# include +# define _(String) dgettext (PACKAGE, String) +#else +# define _(String) (String) +#endif /* ENABLE_NLS */ + +/* String manipulation */ +static void _amiga_set_bstr (const char *cstr, char *bstr, int maxsize) { + int size = strlen (cstr); + int i; + + if (size >= maxsize) return; + bstr[0] = size; + for (i = 0; i"; + default : + return ""; + } +} +static int +_amiga_valid_block_id (uint32_t id) { + 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 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; + ped_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) 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) { + + 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; + } + } + 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; irdb_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, return NULL); + PED_ASSERT(geom->dev!= NULL, return NULL); + + if (!(rdb = 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 : + 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 : + ped_free(rdb); + return NULL; + } + } + + /* 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(part->pb_Next)) + { + PedSector start, end; + PedSector cylblocks; + + /* Let's look for loops in the partition table */ + if (_amiga_loop_check(partblock, partlist, i)) { + ped_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 to read partition block %llu\n"), + __func__, (PedSector)partblock)) + { + case PED_EXCEPTION_CANCEL : + case PED_EXCEPTION_UNHANDLED : + default : + ped_free(rdb); + return NULL; + } + } + + /* Current block is not a Partition Block */ + if (part->pb_ID != IDNAME_PARTITION) { + ped_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) { + ped_free (rdb); + return part; + } + } + + ped_free (rdb); + return NULL; +} diff -urN parted-1.6.6/libparted/fs_amiga/amiga.h parted-1.6.6-amiga/libparted/fs_amiga/amiga.h --- parted-1.6.6/libparted/fs_amiga/amiga.h 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/amiga.h 2004-01-22 20:35:02.000000000 +0100 @@ -0,0 +1,71 @@ +/* + util.h -- amiga partition table headers. + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +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) */ + +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); + diff -urN parted-1.6.6/libparted/fs_amiga/apfs.c parted-1.6.6-amiga/libparted/fs_amiga/apfs.c --- parted-1.6.6/libparted/fs_amiga/apfs.c 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/apfs.c 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,150 @@ +/* + apfs.c -- parted support for apfs filesystems + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "amiga.h" +#include "apfs.h" + +#if ENABLE_NLS +# include +# 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; + int32_t i, sum; + PedSector root; + struct PartitionBlock * part; + uint32_t blocksize = 1, reserved = 2, prealloc = 0; + + PED_ASSERT (geom != NULL, return NULL); + PED_ASSERT (geom->dev != NULL, return NULL); + + /* Finds the blocksize, prealloc and reserved values of the partition block */ + if (!(part = ped_malloc (PED_SECTOR_SIZE*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) { + prealloc = PED_BE32_TO_CPU (part->de_PreAlloc); + reserved = PED_BE32_TO_CPU (part->de_Reserved); + blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) + * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; + } + ped_free (part); + + /* Test boot block */ + if (!(block = ped_malloc (PED_SECTOR_SIZE*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) { + ped_free(block); + return ped_geometry_duplicate (geom); + } + +error: + ped_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, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; +static PedFileSystemOps _apfs2_ops = { + probe: _apfs2_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; + +PedFileSystemType _apfs1_type = { + next: NULL, + ops: &_apfs1_ops, + name: "apfs1" +}; +PedFileSystemType _apfs2_type = { + next: NULL, + ops: &_apfs2_ops, + name: "apfs2" +}; diff -urN parted-1.6.6/libparted/fs_amiga/apfs.h parted-1.6.6-amiga/libparted/fs_amiga/apfs.h --- parted-1.6.6/libparted/fs_amiga/apfs.h 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/apfs.h 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,19 @@ + +/* + apfs.h -- parted support for apfs filesystems header files + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ diff -urN parted-1.6.6/libparted/fs_amiga/asfs.c parted-1.6.6-amiga/libparted/fs_amiga/asfs.c --- parted-1.6.6/libparted/fs_amiga/asfs.c 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/asfs.c 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,144 @@ +/* + asfs.c -- parted asfs filesystem support + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "config.h" + +#include +#include +#include +#include +#include + +#include "amiga.h" +#include "asfs.h" + +#if ENABLE_NLS +# include +# 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, reserved = 1, prealloc = 1; + PedSector root, root2; + int found = 0; + + PED_ASSERT (geom != NULL, return NULL); + PED_ASSERT (geom->dev != NULL, return NULL); + + /* Finds the blocksize, prealloc and reserved values of the partition block */ + if (!(part = ped_malloc (PED_SECTOR_SIZE*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) { + prealloc = PED_BE32_TO_CPU (part->de_PreAlloc) == 0 ? + 1 : PED_BE32_TO_CPU (part->de_PreAlloc); + reserved = PED_BE32_TO_CPU (part->de_Reserved) == 0 ? + 1 : PED_BE32_TO_CPU (part->de_Reserved); + blocksize = PED_BE32_TO_CPU (part->de_SizeBlock) + * PED_BE32_TO_CPU (part->de_SectorPerBlock) / 128; + } + ped_free (part); + + /* Test boot block */ + if (!(block = ped_malloc (PED_SECTOR_SIZE*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) { + ped_free (block); + return ped_geometry_duplicate (geom); + } + +error: + ped_free (block); +error_block: +error_part: + return NULL; +} + +static PedFileSystemOps _asfs_ops = { + probe: _asfs_probe, + clobber: NULL, + open: NULL, + create: NULL, + close: NULL, + check: NULL, + resize: NULL, + copy: NULL, + get_create_constraint: NULL, + get_copy_constraint: NULL, + get_resize_constraint: NULL +}; + +PedFileSystemType _asfs_type = { + next: NULL, + ops: &_asfs_ops, + name: "asfs" +}; diff -urN parted-1.6.6/libparted/fs_amiga/asfs.h parted-1.6.6-amiga/libparted/fs_amiga/asfs.h --- parted-1.6.6/libparted/fs_amiga/asfs.h 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/asfs.h 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,19 @@ + +/* + asfs.h -- parted asfs filesystem support header files + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ diff -urN parted-1.6.6/libparted/fs_amiga/interface.c parted-1.6.6-amiga/libparted/fs_amiga/interface.c --- parted-1.6.6/libparted/fs_amiga/interface.c 1970-01-01 01:00:00.000000000 +0100 +++ parted-1.6.6-amiga/libparted/fs_amiga/interface.c 2004-01-22 12:36:45.000000000 +0100 @@ -0,0 +1,90 @@ +/* + interface.c -- parted support amiga filesystems + Copyright (C) 1998-2000 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., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + + +#include "config.h" + +#include +#include +#include +#include +#include + +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 -urN parted-1.6.6/libparted/libparted.c parted-1.6.6-amiga/libparted/libparted.c --- parted-1.6.6/libparted/libparted.c 2002-12-31 01:21:45.000000000 +0100 +++ parted-1.6.6-amiga/libparted/libparted.c 2004-01-22 12:36:45.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 (); @@ -104,6 +106,7 @@ } #ifdef ENABLE_FS +extern void ped_file_system_amiga_init (void); extern void ped_file_system_xfs_init (void); extern void ped_file_system_ufs_init (void); extern void ped_file_system_reiserfs_init (void); @@ -117,6 +120,7 @@ static void init_file_system_types () { + ped_file_system_amiga_init (); ped_file_system_xfs_init (); ped_file_system_ufs_init (); ped_file_system_reiserfs_init (); @@ -137,10 +141,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 (); @@ -190,6 +196,7 @@ extern void ped_file_system_reiserfs_done (void); extern void ped_file_system_ufs_done (void); extern void ped_file_system_xfs_done (void); +extern void ped_file_system_amiga_done (void); static void done_file_system_types () @@ -203,6 +210,7 @@ ped_file_system_reiserfs_done (); ped_file_system_ufs_done (); ped_file_system_xfs_done (); + ped_file_system_amiga_done (); } #endif /* ENABLE_FS */