Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
amiga.c
Go to the documentation of this file.
1 /*
2  * fs/partitions/amiga.c
3  *
4  * Code extracted from drivers/block/genhd.c
5  *
6  * Copyright (C) 1991-1998 Linus Torvalds
7  * Re-organised Feb 1998 Russell King
8  */
9 
10 #include <linux/types.h>
11 #include <linux/affs_hardblocks.h>
12 
13 #include "check.h"
14 #include "amiga.h"
15 
16 static __inline__ u32
17 checksum_block(__be32 *m, int size)
18 {
19  u32 sum = 0;
20 
21  while (size--)
22  sum += be32_to_cpu(*m++);
23  return sum;
24 }
25 
27 {
28  Sector sect;
29  unsigned char *data;
30  struct RigidDiskBlock *rdb;
31  struct PartitionBlock *pb;
32  int start_sect, nr_sects, blk, part, res = 0;
33  int blksize = 1; /* Multiplier for disk block size */
34  int slot = 1;
35  char b[BDEVNAME_SIZE];
36 
37  for (blk = 0; ; blk++, put_dev_sector(sect)) {
38  if (blk == RDB_ALLOCATION_LIMIT)
39  goto rdb_done;
40  data = read_part_sector(state, blk, &sect);
41  if (!data) {
42  if (warn_no_part)
43  printk("Dev %s: unable to read RDB block %d\n",
44  bdevname(state->bdev, b), blk);
45  res = -1;
46  goto rdb_done;
47  }
48  if (*(__be32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
49  continue;
50 
51  rdb = (struct RigidDiskBlock *)data;
52  if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
53  break;
54  /* Try again with 0xdc..0xdf zeroed, Windows might have
55  * trashed it.
56  */
57  *(__be32 *)(data+0xdc) = 0;
58  if (checksum_block((__be32 *)data,
59  be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
60  printk("Warning: Trashed word at 0xd0 in block %d "
61  "ignored in checksum calculation\n",blk);
62  break;
63  }
64 
65  printk("Dev %s: RDB in block %d has bad checksum\n",
66  bdevname(state->bdev, b), blk);
67  }
68 
69  /* blksize is blocks per 512 byte standard block */
70  blksize = be32_to_cpu( rdb->rdb_BlockBytes ) / 512;
71 
72  {
73  char tmp[7 + 10 + 1 + 1];
74 
75  /* Be more informative */
76  snprintf(tmp, sizeof(tmp), " RDSK (%d)", blksize * 512);
77  strlcat(state->pp_buf, tmp, PAGE_SIZE);
78  }
79  blk = be32_to_cpu(rdb->rdb_PartitionList);
80  put_dev_sector(sect);
81  for (part = 1; blk>0 && part<=16; part++, put_dev_sector(sect)) {
82  blk *= blksize; /* Read in terms partition table understands */
83  data = read_part_sector(state, blk, &sect);
84  if (!data) {
85  if (warn_no_part)
86  printk("Dev %s: unable to read partition block %d\n",
87  bdevname(state->bdev, b), blk);
88  res = -1;
89  goto rdb_done;
90  }
91  pb = (struct PartitionBlock *)data;
92  blk = be32_to_cpu(pb->pb_Next);
94  continue;
95  if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
96  continue;
97 
98  /* Tell Kernel about it */
99 
100  nr_sects = (be32_to_cpu(pb->pb_Environment[10]) + 1 -
101  be32_to_cpu(pb->pb_Environment[9])) *
102  be32_to_cpu(pb->pb_Environment[3]) *
103  be32_to_cpu(pb->pb_Environment[5]) *
104  blksize;
105  if (!nr_sects)
106  continue;
107  start_sect = be32_to_cpu(pb->pb_Environment[9]) *
108  be32_to_cpu(pb->pb_Environment[3]) *
109  be32_to_cpu(pb->pb_Environment[5]) *
110  blksize;
111  put_partition(state,slot++,start_sect,nr_sects);
112  {
113  /* Be even more informative to aid mounting */
114  char dostype[4];
115  char tmp[42];
116 
117  __be32 *dt = (__be32 *)dostype;
118  *dt = pb->pb_Environment[16];
119  if (dostype[3] < ' ')
120  snprintf(tmp, sizeof(tmp), " (%c%c%c^%c)",
121  dostype[0], dostype[1],
122  dostype[2], dostype[3] + '@' );
123  else
124  snprintf(tmp, sizeof(tmp), " (%c%c%c%c)",
125  dostype[0], dostype[1],
126  dostype[2], dostype[3]);
127  strlcat(state->pp_buf, tmp, PAGE_SIZE);
128  snprintf(tmp, sizeof(tmp), "(res %d spb %d)",
129  be32_to_cpu(pb->pb_Environment[6]),
130  be32_to_cpu(pb->pb_Environment[4]));
131  strlcat(state->pp_buf, tmp, PAGE_SIZE);
132  }
133  res = 1;
134  }
135  strlcat(state->pp_buf, "\n", PAGE_SIZE);
136 
137 rdb_done:
138  return res;
139 }