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