6921e7890be64255ebe78fd05768270965b71663
[cascardo/linux.git] / fs / partitions / acorn.c
1 /*
2  *  linux/fs/partitions/acorn.c
3  *
4  *  Copyright (c) 1996-2000 Russell King.
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License version 2 as
8  * published by the Free Software Foundation.
9  *
10  *  Scan ADFS partitions on hard disk drives.  Unfortunately, there
11  *  isn't a standard for partitioning drives on Acorn machines, so
12  *  every single manufacturer of SCSI and IDE cards created their own
13  *  method.
14  */
15 #include <linux/buffer_head.h>
16 #include <linux/adfs_fs.h>
17
18 #include "check.h"
19 #include "acorn.h"
20
21 /*
22  * Partition types. (Oh for reusability)
23  */
24 #define PARTITION_RISCIX_MFM    1
25 #define PARTITION_RISCIX_SCSI   2
26 #define PARTITION_LINUX         9
27
28 #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
29         defined(CONFIG_ACORN_PARTITION_ADFS)
30 static struct adfs_discrecord *
31 adfs_partition(struct parsed_partitions *state, char *name, char *data,
32                unsigned long first_sector, int slot)
33 {
34         struct adfs_discrecord *dr;
35         unsigned int nr_sects;
36
37         if (adfs_checkbblk(data))
38                 return NULL;
39
40         dr = (struct adfs_discrecord *)(data + 0x1c0);
41
42         if (dr->disc_size == 0 && dr->disc_size_high == 0)
43                 return NULL;
44
45         nr_sects = (le32_to_cpu(dr->disc_size_high) << 23) |
46                    (le32_to_cpu(dr->disc_size) >> 9);
47
48         if (name)
49                 printk(" [%s]", name);
50         put_partition(state, slot, first_sector, nr_sects);
51         return dr;
52 }
53 #endif
54
55 #ifdef CONFIG_ACORN_PARTITION_RISCIX
56
57 struct riscix_part {
58         __le32  start;
59         __le32  length;
60         __le32  one;
61         char    name[16];
62 };
63
64 struct riscix_record {
65         __le32  magic;
66 #define RISCIX_MAGIC    cpu_to_le32(0x4a657320)
67         __le32  date;
68         struct riscix_part part[8];
69 };
70
71 #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
72         defined(CONFIG_ACORN_PARTITION_ADFS)
73 static int riscix_partition(struct parsed_partitions *state,
74                             unsigned long first_sect, int slot,
75                             unsigned long nr_sects)
76 {
77         Sector sect;
78         struct riscix_record *rr;
79         
80         rr = read_part_sector(state, first_sect, &sect);
81         if (!rr)
82                 return -1;
83
84         printk(" [RISCiX]");
85
86
87         if (rr->magic == RISCIX_MAGIC) {
88                 unsigned long size = nr_sects > 2 ? 2 : nr_sects;
89                 int part;
90
91                 printk(" <");
92
93                 put_partition(state, slot++, first_sect, size);
94                 for (part = 0; part < 8; part++) {
95                         if (rr->part[part].one &&
96                             memcmp(rr->part[part].name, "All\0", 4)) {
97                                 put_partition(state, slot++,
98                                         le32_to_cpu(rr->part[part].start),
99                                         le32_to_cpu(rr->part[part].length));
100                                 printk("(%s)", rr->part[part].name);
101                         }
102                 }
103
104                 printk(" >\n");
105         } else {
106                 put_partition(state, slot++, first_sect, nr_sects);
107         }
108
109         put_dev_sector(sect);
110         return slot;
111 }
112 #endif
113 #endif
114
115 #define LINUX_NATIVE_MAGIC 0xdeafa1de
116 #define LINUX_SWAP_MAGIC   0xdeafab1e
117
118 struct linux_part {
119         __le32 magic;
120         __le32 start_sect;
121         __le32 nr_sects;
122 };
123
124 #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
125         defined(CONFIG_ACORN_PARTITION_ADFS)
126 static int linux_partition(struct parsed_partitions *state,
127                            unsigned long first_sect, int slot,
128                            unsigned long nr_sects)
129 {
130         Sector sect;
131         struct linux_part *linuxp;
132         unsigned long size = nr_sects > 2 ? 2 : nr_sects;
133
134         printk(" [Linux]");
135
136         put_partition(state, slot++, first_sect, size);
137
138         linuxp = read_part_sector(state, first_sect, &sect);
139         if (!linuxp)
140                 return -1;
141
142         printk(" <");
143         while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) ||
144                linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) {
145                 if (slot == state->limit)
146                         break;
147                 put_partition(state, slot++, first_sect +
148                                  le32_to_cpu(linuxp->start_sect),
149                                  le32_to_cpu(linuxp->nr_sects));
150                 linuxp ++;
151         }
152         printk(" >");
153
154         put_dev_sector(sect);
155         return slot;
156 }
157 #endif
158
159 #ifdef CONFIG_ACORN_PARTITION_CUMANA
160 int adfspart_check_CUMANA(struct parsed_partitions *state)
161 {
162         unsigned long first_sector = 0;
163         unsigned int start_blk = 0;
164         Sector sect;
165         unsigned char *data;
166         char *name = "CUMANA/ADFS";
167         int first = 1;
168         int slot = 1;
169
170         /*
171          * Try Cumana style partitions - sector 6 contains ADFS boot block
172          * with pointer to next 'drive'.
173          *
174          * There are unknowns in this code - is the 'cylinder number' of the
175          * next partition relative to the start of this one - I'm assuming
176          * it is.
177          *
178          * Also, which ID did Cumana use?
179          *
180          * This is totally unfinished, and will require more work to get it
181          * going. Hence it is totally untested.
182          */
183         do {
184                 struct adfs_discrecord *dr;
185                 unsigned int nr_sects;
186
187                 data = read_part_sector(state, start_blk * 2 + 6, &sect);
188                 if (!data)
189                         return -1;
190
191                 if (slot == state->limit)
192                         break;
193
194                 dr = adfs_partition(state, name, data, first_sector, slot++);
195                 if (!dr)
196                         break;
197
198                 name = NULL;
199
200                 nr_sects = (data[0x1fd] + (data[0x1fe] << 8)) *
201                            (dr->heads + (dr->lowsector & 0x40 ? 1 : 0)) *
202                            dr->secspertrack;
203
204                 if (!nr_sects)
205                         break;
206
207                 first = 0;
208                 first_sector += nr_sects;
209                 start_blk += nr_sects >> (BLOCK_SIZE_BITS - 9);
210                 nr_sects = 0; /* hmm - should be partition size */
211
212                 switch (data[0x1fc] & 15) {
213                 case 0: /* No partition / ADFS? */
214                         break;
215
216 #ifdef CONFIG_ACORN_PARTITION_RISCIX
217                 case PARTITION_RISCIX_SCSI:
218                         /* RISCiX - we don't know how to find the next one. */
219                         slot = riscix_partition(state, first_sector, slot,
220                                                 nr_sects);
221                         break;
222 #endif
223
224                 case PARTITION_LINUX:
225                         slot = linux_partition(state, first_sector, slot,
226                                                nr_sects);
227                         break;
228                 }
229                 put_dev_sector(sect);
230                 if (slot == -1)
231                         return -1;
232         } while (1);
233         put_dev_sector(sect);
234         return first ? 0 : 1;
235 }
236 #endif
237
238 #ifdef CONFIG_ACORN_PARTITION_ADFS
239 /*
240  * Purpose: allocate ADFS partitions.
241  *
242  * Params : hd          - pointer to gendisk structure to store partition info.
243  *          dev         - device number to access.
244  *
245  * Returns: -1 on error, 0 for no ADFS boot sector, 1 for ok.
246  *
247  * Alloc  : hda  = whole drive
248  *          hda1 = ADFS partition on first drive.
249  *          hda2 = non-ADFS partition.
250  */
251 int adfspart_check_ADFS(struct parsed_partitions *state)
252 {
253         unsigned long start_sect, nr_sects, sectscyl, heads;
254         Sector sect;
255         unsigned char *data;
256         struct adfs_discrecord *dr;
257         unsigned char id;
258         int slot = 1;
259
260         data = read_part_sector(state, 6, &sect);
261         if (!data)
262                 return -1;
263
264         dr = adfs_partition(state, "ADFS", data, 0, slot++);
265         if (!dr) {
266                 put_dev_sector(sect);
267                 return 0;
268         }
269
270         heads = dr->heads + ((dr->lowsector >> 6) & 1);
271         sectscyl = dr->secspertrack * heads;
272         start_sect = ((data[0x1fe] << 8) + data[0x1fd]) * sectscyl;
273         id = data[0x1fc] & 15;
274         put_dev_sector(sect);
275
276         /*
277          * Work out start of non-adfs partition.
278          */
279         nr_sects = (state->bdev->bd_inode->i_size >> 9) - start_sect;
280
281         if (start_sect) {
282                 switch (id) {
283 #ifdef CONFIG_ACORN_PARTITION_RISCIX
284                 case PARTITION_RISCIX_SCSI:
285                 case PARTITION_RISCIX_MFM:
286                         slot = riscix_partition(state, start_sect, slot,
287                                                 nr_sects);
288                         break;
289 #endif
290
291                 case PARTITION_LINUX:
292                         slot = linux_partition(state, start_sect, slot,
293                                                nr_sects);
294                         break;
295                 }
296         }
297         printk("\n");
298         return 1;
299 }
300 #endif
301
302 #ifdef CONFIG_ACORN_PARTITION_ICS
303
304 struct ics_part {
305         __le32 start;
306         __le32 size;
307 };
308
309 static int adfspart_check_ICSLinux(struct parsed_partitions *state,
310                                    unsigned long block)
311 {
312         Sector sect;
313         unsigned char *data = read_part_sector(state, block, &sect);
314         int result = 0;
315
316         if (data) {
317                 if (memcmp(data, "LinuxPart", 9) == 0)
318                         result = 1;
319                 put_dev_sector(sect);
320         }
321
322         return result;
323 }
324
325 /*
326  * Check for a valid ICS partition using the checksum.
327  */
328 static inline int valid_ics_sector(const unsigned char *data)
329 {
330         unsigned long sum;
331         int i;
332
333         for (i = 0, sum = 0x50617274; i < 508; i++)
334                 sum += data[i];
335
336         sum -= le32_to_cpu(*(__le32 *)(&data[508]));
337
338         return sum == 0;
339 }
340
341 /*
342  * Purpose: allocate ICS partitions.
343  * Params : hd          - pointer to gendisk structure to store partition info.
344  *          dev         - device number to access.
345  * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
346  * Alloc  : hda  = whole drive
347  *          hda1 = ADFS partition 0 on first drive.
348  *          hda2 = ADFS partition 1 on first drive.
349  *              ..etc..
350  */
351 int adfspart_check_ICS(struct parsed_partitions *state)
352 {
353         const unsigned char *data;
354         const struct ics_part *p;
355         int slot;
356         Sector sect;
357
358         /*
359          * Try ICS style partitions - sector 0 contains partition info.
360          */
361         data = read_part_sector(state, 0, &sect);
362         if (!data)
363                 return -1;
364
365         if (!valid_ics_sector(data)) {
366                 put_dev_sector(sect);
367                 return 0;
368         }
369
370         printk(" [ICS]");
371
372         for (slot = 1, p = (const struct ics_part *)data; p->size; p++) {
373                 u32 start = le32_to_cpu(p->start);
374                 s32 size = le32_to_cpu(p->size); /* yes, it's signed. */
375
376                 if (slot == state->limit)
377                         break;
378
379                 /*
380                  * Negative sizes tell the RISC OS ICS driver to ignore
381                  * this partition - in effect it says that this does not
382                  * contain an ADFS filesystem.
383                  */
384                 if (size < 0) {
385                         size = -size;
386
387                         /*
388                          * Our own extension - We use the first sector
389                          * of the partition to identify what type this
390                          * partition is.  We must not make this visible
391                          * to the filesystem.
392                          */
393                         if (size > 1 && adfspart_check_ICSLinux(state, start)) {
394                                 start += 1;
395                                 size -= 1;
396                         }
397                 }
398
399                 if (size)
400                         put_partition(state, slot++, start, size);
401         }
402
403         put_dev_sector(sect);
404         printk("\n");
405         return 1;
406 }
407 #endif
408
409 #ifdef CONFIG_ACORN_PARTITION_POWERTEC
410 struct ptec_part {
411         __le32 unused1;
412         __le32 unused2;
413         __le32 start;
414         __le32 size;
415         __le32 unused5;
416         char type[8];
417 };
418
419 static inline int valid_ptec_sector(const unsigned char *data)
420 {
421         unsigned char checksum = 0x2a;
422         int i;
423
424         /*
425          * If it looks like a PC/BIOS partition, then it
426          * probably isn't PowerTec.
427          */
428         if (data[510] == 0x55 && data[511] == 0xaa)
429                 return 0;
430
431         for (i = 0; i < 511; i++)
432                 checksum += data[i];
433
434         return checksum == data[511];
435 }
436
437 /*
438  * Purpose: allocate ICS partitions.
439  * Params : hd          - pointer to gendisk structure to store partition info.
440  *          dev         - device number to access.
441  * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
442  * Alloc  : hda  = whole drive
443  *          hda1 = ADFS partition 0 on first drive.
444  *          hda2 = ADFS partition 1 on first drive.
445  *              ..etc..
446  */
447 int adfspart_check_POWERTEC(struct parsed_partitions *state)
448 {
449         Sector sect;
450         const unsigned char *data;
451         const struct ptec_part *p;
452         int slot = 1;
453         int i;
454
455         data = read_part_sector(state, 0, &sect);
456         if (!data)
457                 return -1;
458
459         if (!valid_ptec_sector(data)) {
460                 put_dev_sector(sect);
461                 return 0;
462         }
463
464         printk(" [POWERTEC]");
465
466         for (i = 0, p = (const struct ptec_part *)data; i < 12; i++, p++) {
467                 u32 start = le32_to_cpu(p->start);
468                 u32 size = le32_to_cpu(p->size);
469
470                 if (size)
471                         put_partition(state, slot++, start, size);
472         }
473
474         put_dev_sector(sect);
475         printk("\n");
476         return 1;
477 }
478 #endif
479
480 #ifdef CONFIG_ACORN_PARTITION_EESOX
481 struct eesox_part {
482         char    magic[6];
483         char    name[10];
484         __le32  start;
485         __le32  unused6;
486         __le32  unused7;
487         __le32  unused8;
488 };
489
490 /*
491  * Guess who created this format?
492  */
493 static const char eesox_name[] = {
494         'N', 'e', 'i', 'l', ' ',
495         'C', 'r', 'i', 't', 'c', 'h', 'e', 'l', 'l', ' ', ' '
496 };
497
498 /*
499  * EESOX SCSI partition format.
500  *
501  * This is a goddamned awful partition format.  We don't seem to store
502  * the size of the partition in this table, only the start addresses.
503  *
504  * There are two possibilities where the size comes from:
505  *  1. The individual ADFS boot block entries that are placed on the disk.
506  *  2. The start address of the next entry.
507  */
508 int adfspart_check_EESOX(struct parsed_partitions *state)
509 {
510         Sector sect;
511         const unsigned char *data;
512         unsigned char buffer[256];
513         struct eesox_part *p;
514         sector_t start = 0;
515         int i, slot = 1;
516
517         data = read_part_sector(state, 7, &sect);
518         if (!data)
519                 return -1;
520
521         /*
522          * "Decrypt" the partition table.  God knows why...
523          */
524         for (i = 0; i < 256; i++)
525                 buffer[i] = data[i] ^ eesox_name[i & 15];
526
527         put_dev_sector(sect);
528
529         for (i = 0, p = (struct eesox_part *)buffer; i < 8; i++, p++) {
530                 sector_t next;
531
532                 if (memcmp(p->magic, "Eesox", 6))
533                         break;
534
535                 next = le32_to_cpu(p->start);
536                 if (i)
537                         put_partition(state, slot++, start, next - start);
538                 start = next;
539         }
540
541         if (i != 0) {
542                 sector_t size;
543
544                 size = get_capacity(state->bdev->bd_disk);
545                 put_partition(state, slot++, start, size - start);
546                 printk("\n");
547         }
548
549         return i ? 1 : 0;
550 }
551 #endif