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