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