This source file includes following definitions.
- adfs_partition
- riscix_partition
- linux_partition
- adfspart_check_CUMANA
- adfspart_check_ADFS
- adfspart_check_ICSLinux
- valid_ics_sector
- adfspart_check_ICS
- valid_ptec_sector
- adfspart_check_POWERTEC
- adfspart_check_EESOX
1
2
3
4
5
6
7
8
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
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, §);
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, §);
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
172
173
174
175
176
177
178
179
180
181
182
183 do {
184 struct adfs_discrecord *dr;
185 unsigned int nr_sects;
186
187 data = read_part_sector(state, start_blk * 2 + 6, §);
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;
211
212 switch (data[0x1fc] & 15) {
213 case 0:
214 break;
215
216 #ifdef CONFIG_ACORN_PARTITION_RISCIX
217 case PARTITION_RISCIX_SCSI:
218
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
241
242
243
244
245
246
247
248
249
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, §);
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
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, §);
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
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
343
344
345
346
347
348
349
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
360
361 data = read_part_sector(state, 0, §);
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);
375
376 if (slot == state->limit)
377 break;
378
379
380
381
382
383
384 if (size < 0) {
385 size = -size;
386
387
388
389
390
391
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
426
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
439
440
441
442
443
444
445
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, §);
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
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
500
501
502
503
504
505
506
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, §);
518 if (!data)
519 return -1;
520
521
522
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