Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/hid/hid
[linux-block.git] / block / partitions / acorn.c
1 // SPDX-License-Identifier: GPL-2.0
2 /*
3  *  Copyright (c) 1996-2000 Russell King.
4  *
5  *  Scan ADFS partitions on hard disk drives.  Unfortunately, there
6  *  isn't a standard for partitioning drives on Acorn machines, so
7  *  every single manufacturer of SCSI and IDE cards created their own
8  *  method.
9  */
10 #include <linux/buffer_head.h>
11 #include <linux/adfs_fs.h>
12
13 #include "check.h"
14 #include "acorn.h"
15
16 /*
17  * Partition types. (Oh for reusability)
18  */
19 #define PARTITION_RISCIX_MFM    1
20 #define PARTITION_RISCIX_SCSI   2
21 #define PARTITION_LINUX         9
22
23 #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
24         defined(CONFIG_ACORN_PARTITION_ADFS)
25 static struct adfs_discrecord *
26 adfs_partition(struct parsed_partitions *state, char *name, char *data,
27                unsigned long first_sector, int slot)
28 {
29         struct adfs_discrecord *dr;
30         unsigned int nr_sects;
31
32         if (adfs_checkbblk(data))
33                 return NULL;
34
35         dr = (struct adfs_discrecord *)(data + 0x1c0);
36
37         if (dr->disc_size == 0 && dr->disc_size_high == 0)
38                 return NULL;
39
40         nr_sects = (le32_to_cpu(dr->disc_size_high) << 23) |
41                    (le32_to_cpu(dr->disc_size) >> 9);
42
43         if (name) {
44                 strlcat(state->pp_buf, " [", PAGE_SIZE);
45                 strlcat(state->pp_buf, name, PAGE_SIZE);
46                 strlcat(state->pp_buf, "]", PAGE_SIZE);
47         }
48         put_partition(state, slot, first_sector, nr_sects);
49         return dr;
50 }
51 #endif
52
53 #ifdef CONFIG_ACORN_PARTITION_RISCIX
54
55 struct riscix_part {
56         __le32  start;
57         __le32  length;
58         __le32  one;
59         char    name[16];
60 };
61
62 struct riscix_record {
63         __le32  magic;
64 #define RISCIX_MAGIC    cpu_to_le32(0x4a657320)
65         __le32  date;
66         struct riscix_part part[8];
67 };
68
69 #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
70         defined(CONFIG_ACORN_PARTITION_ADFS)
71 static int riscix_partition(struct parsed_partitions *state,
72                             unsigned long first_sect, int slot,
73                             unsigned long nr_sects)
74 {
75         Sector sect;
76         struct riscix_record *rr;
77         
78         rr = read_part_sector(state, first_sect, &sect);
79         if (!rr)
80                 return -1;
81
82         strlcat(state->pp_buf, " [RISCiX]", PAGE_SIZE);
83
84
85         if (rr->magic == RISCIX_MAGIC) {
86                 unsigned long size = nr_sects > 2 ? 2 : nr_sects;
87                 int part;
88
89                 strlcat(state->pp_buf, " <", PAGE_SIZE);
90
91                 put_partition(state, slot++, first_sect, size);
92                 for (part = 0; part < 8; part++) {
93                         if (rr->part[part].one &&
94                             memcmp(rr->part[part].name, "All\0", 4)) {
95                                 put_partition(state, slot++,
96                                         le32_to_cpu(rr->part[part].start),
97                                         le32_to_cpu(rr->part[part].length));
98                                 strlcat(state->pp_buf, "(", PAGE_SIZE);
99                                 strlcat(state->pp_buf, rr->part[part].name, PAGE_SIZE);
100                                 strlcat(state->pp_buf, ")", PAGE_SIZE);
101                         }
102                 }
103
104                 strlcat(state->pp_buf, " >\n", PAGE_SIZE);
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         strlcat(state->pp_buf, " [Linux]", PAGE_SIZE);
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         strlcat(state->pp_buf, " <", PAGE_SIZE);
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         strlcat(state->pp_buf, " >", PAGE_SIZE);
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         strlcat(state->pp_buf, "\n", PAGE_SIZE);
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         strlcat(state->pp_buf, " [ICS]", PAGE_SIZE);
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         strlcat(state->pp_buf, "\n", PAGE_SIZE);
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         strlcat(state->pp_buf, " [POWERTEC]", PAGE_SIZE);
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         strlcat(state->pp_buf, "\n", PAGE_SIZE);
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                 strlcat(state->pp_buf, "\n", PAGE_SIZE);
547         }
548
549         return i ? 1 : 0;
550 }
551 #endif