2005-04-17 02:20:36 +04:00
/*
* fs / partitions / amiga . c
*
* Code extracted from drivers / block / genhd . c
*
* Copyright ( C ) 1991 - 1998 Linus Torvalds
* Re - organised Feb 1998 Russell King
*/
# include <linux/types.h>
# include <linux/affs_hardblocks.h>
# include "check.h"
# include "amiga.h"
static __inline__ u32
checksum_block ( __be32 * m , int size )
{
u32 sum = 0 ;
while ( size - - )
sum + = be32_to_cpu ( * m + + ) ;
return sum ;
}
2010-05-15 22:09:30 +04:00
int amiga_partition ( struct parsed_partitions * state )
2005-04-17 02:20:36 +04:00
{
Sector sect ;
unsigned char * data ;
struct RigidDiskBlock * rdb ;
struct PartitionBlock * pb ;
int start_sect , nr_sects , blk , part , res = 0 ;
int blksize = 1 ; /* Multiplier for disk block size */
int slot = 1 ;
char b [ BDEVNAME_SIZE ] ;
for ( blk = 0 ; ; blk + + , put_dev_sector ( sect ) ) {
if ( blk = = RDB_ALLOCATION_LIMIT )
goto rdb_done ;
2010-05-15 22:09:30 +04:00
data = read_part_sector ( state , blk , & sect ) ;
2005-04-17 02:20:36 +04:00
if ( ! data ) {
if ( warn_no_part )
printk ( " Dev %s: unable to read RDB block %d \n " ,
2010-05-15 22:09:30 +04:00
bdevname ( state - > bdev , b ) , blk ) ;
2006-12-07 07:35:16 +03:00
res = - 1 ;
2005-04-17 02:20:36 +04:00
goto rdb_done ;
}
if ( * ( __be32 * ) data ! = cpu_to_be32 ( IDNAME_RIGIDDISK ) )
continue ;
rdb = ( struct RigidDiskBlock * ) data ;
if ( checksum_block ( ( __be32 * ) data , be32_to_cpu ( rdb - > rdb_SummedLongs ) & 0x7F ) = = 0 )
break ;
/* Try again with 0xdc..0xdf zeroed, Windows might have
* trashed it .
*/
* ( __be32 * ) ( data + 0xdc ) = 0 ;
if ( checksum_block ( ( __be32 * ) data ,
be32_to_cpu ( rdb - > rdb_SummedLongs ) & 0x7F ) = = 0 ) {
printk ( " Warning: Trashed word at 0xd0 in block %d "
" ignored in checksum calculation \n " , blk ) ;
break ;
}
printk ( " Dev %s: RDB in block %d has bad checksum \n " ,
2010-05-15 22:09:30 +04:00
bdevname ( state - > bdev , b ) , blk ) ;
2005-04-17 02:20:36 +04:00
}
/* blksize is blocks per 512 byte standard block */
blksize = be32_to_cpu ( rdb - > rdb_BlockBytes ) / 512 ;
2010-08-11 05:03:14 +04:00
{
char tmp [ 7 + 10 + 1 + 1 ] ;
/* Be more informative */
snprintf ( tmp , sizeof ( tmp ) , " RDSK (%d) " , blksize * 512 ) ;
strlcat ( state - > pp_buf , tmp , PAGE_SIZE ) ;
}
2005-04-17 02:20:36 +04:00
blk = be32_to_cpu ( rdb - > rdb_PartitionList ) ;
put_dev_sector ( sect ) ;
for ( part = 1 ; blk > 0 & & part < = 16 ; part + + , put_dev_sector ( sect ) ) {
blk * = blksize ; /* Read in terms partition table understands */
2010-05-15 22:09:30 +04:00
data = read_part_sector ( state , blk , & sect ) ;
2005-04-17 02:20:36 +04:00
if ( ! data ) {
if ( warn_no_part )
printk ( " Dev %s: unable to read partition block %d \n " ,
2010-05-15 22:09:30 +04:00
bdevname ( state - > bdev , b ) , blk ) ;
2006-12-07 07:35:16 +03:00
res = - 1 ;
2005-04-17 02:20:36 +04:00
goto rdb_done ;
}
pb = ( struct PartitionBlock * ) data ;
blk = be32_to_cpu ( pb - > pb_Next ) ;
if ( pb - > pb_ID ! = cpu_to_be32 ( IDNAME_PARTITION ) )
continue ;
if ( checksum_block ( ( __be32 * ) pb , be32_to_cpu ( pb - > pb_SummedLongs ) & 0x7F ) ! = 0 )
continue ;
/* Tell Kernel about it */
nr_sects = ( be32_to_cpu ( pb - > pb_Environment [ 10 ] ) + 1 -
be32_to_cpu ( pb - > pb_Environment [ 9 ] ) ) *
be32_to_cpu ( pb - > pb_Environment [ 3 ] ) *
be32_to_cpu ( pb - > pb_Environment [ 5 ] ) *
blksize ;
if ( ! nr_sects )
continue ;
start_sect = be32_to_cpu ( pb - > pb_Environment [ 9 ] ) *
be32_to_cpu ( pb - > pb_Environment [ 3 ] ) *
be32_to_cpu ( pb - > pb_Environment [ 5 ] ) *
blksize ;
put_partition ( state , slot + + , start_sect , nr_sects ) ;
{
/* Be even more informative to aid mounting */
char dostype [ 4 ] ;
2010-08-11 05:03:14 +04:00
char tmp [ 42 ] ;
2005-04-17 02:20:36 +04:00
__be32 * dt = ( __be32 * ) dostype ;
* dt = pb - > pb_Environment [ 16 ] ;
if ( dostype [ 3 ] < ' ' )
2010-08-11 05:03:14 +04:00
snprintf ( tmp , sizeof ( tmp ) , " (%c%c%c^%c) " ,
2005-04-17 02:20:36 +04:00
dostype [ 0 ] , dostype [ 1 ] ,
dostype [ 2 ] , dostype [ 3 ] + ' @ ' ) ;
else
2010-08-11 05:03:14 +04:00
snprintf ( tmp , sizeof ( tmp ) , " (%c%c%c%c) " ,
2005-04-17 02:20:36 +04:00
dostype [ 0 ] , dostype [ 1 ] ,
dostype [ 2 ] , dostype [ 3 ] ) ;
2010-08-11 05:03:14 +04:00
strlcat ( state - > pp_buf , tmp , PAGE_SIZE ) ;
snprintf ( tmp , sizeof ( tmp ) , " (res %d spb %d) " ,
2005-04-17 02:20:36 +04:00
be32_to_cpu ( pb - > pb_Environment [ 6 ] ) ,
be32_to_cpu ( pb - > pb_Environment [ 4 ] ) ) ;
2010-08-11 05:03:14 +04:00
strlcat ( state - > pp_buf , tmp , PAGE_SIZE ) ;
2005-04-17 02:20:36 +04:00
}
res = 1 ;
}
2010-08-11 05:03:14 +04:00
strlcat ( state - > pp_buf , " \n " , PAGE_SIZE ) ;
2005-04-17 02:20:36 +04:00
rdb_done :
return res ;
}