18c16567dSChristoph Hellwig // SPDX-License-Identifier: GPL-2.0
29be96f3fSAl Viro /*
39be96f3fSAl Viro * Copyright (c) 1996-2000 Russell King.
49be96f3fSAl Viro *
59be96f3fSAl Viro * Scan ADFS partitions on hard disk drives. Unfortunately, there
69be96f3fSAl Viro * isn't a standard for partitioning drives on Acorn machines, so
79be96f3fSAl Viro * every single manufacturer of SCSI and IDE cards created their own
89be96f3fSAl Viro * method.
99be96f3fSAl Viro */
109be96f3fSAl Viro #include <linux/buffer_head.h>
119be96f3fSAl Viro #include <linux/adfs_fs.h>
129be96f3fSAl Viro
139be96f3fSAl Viro #include "check.h"
149be96f3fSAl Viro
159be96f3fSAl Viro /*
169be96f3fSAl Viro * Partition types. (Oh for reusability)
179be96f3fSAl Viro */
189be96f3fSAl Viro #define PARTITION_RISCIX_MFM 1
199be96f3fSAl Viro #define PARTITION_RISCIX_SCSI 2
209be96f3fSAl Viro #define PARTITION_LINUX 9
219be96f3fSAl Viro
229be96f3fSAl Viro #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
239be96f3fSAl Viro defined(CONFIG_ACORN_PARTITION_ADFS)
249be96f3fSAl Viro static struct adfs_discrecord *
adfs_partition(struct parsed_partitions * state,char * name,char * data,unsigned long first_sector,int slot)259be96f3fSAl Viro adfs_partition(struct parsed_partitions *state, char *name, char *data,
269be96f3fSAl Viro unsigned long first_sector, int slot)
279be96f3fSAl Viro {
289be96f3fSAl Viro struct adfs_discrecord *dr;
299be96f3fSAl Viro unsigned int nr_sects;
309be96f3fSAl Viro
319be96f3fSAl Viro if (adfs_checkbblk(data))
329be96f3fSAl Viro return NULL;
339be96f3fSAl Viro
349be96f3fSAl Viro dr = (struct adfs_discrecord *)(data + 0x1c0);
359be96f3fSAl Viro
369be96f3fSAl Viro if (dr->disc_size == 0 && dr->disc_size_high == 0)
379be96f3fSAl Viro return NULL;
389be96f3fSAl Viro
399be96f3fSAl Viro nr_sects = (le32_to_cpu(dr->disc_size_high) << 23) |
409be96f3fSAl Viro (le32_to_cpu(dr->disc_size) >> 9);
419be96f3fSAl Viro
429be96f3fSAl Viro if (name) {
439be96f3fSAl Viro strlcat(state->pp_buf, " [", PAGE_SIZE);
449be96f3fSAl Viro strlcat(state->pp_buf, name, PAGE_SIZE);
459be96f3fSAl Viro strlcat(state->pp_buf, "]", PAGE_SIZE);
469be96f3fSAl Viro }
479be96f3fSAl Viro put_partition(state, slot, first_sector, nr_sects);
489be96f3fSAl Viro return dr;
499be96f3fSAl Viro }
509be96f3fSAl Viro #endif
519be96f3fSAl Viro
529be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_RISCIX
539be96f3fSAl Viro
549be96f3fSAl Viro struct riscix_part {
559be96f3fSAl Viro __le32 start;
569be96f3fSAl Viro __le32 length;
579be96f3fSAl Viro __le32 one;
589be96f3fSAl Viro char name[16];
599be96f3fSAl Viro };
609be96f3fSAl Viro
619be96f3fSAl Viro struct riscix_record {
629be96f3fSAl Viro __le32 magic;
639be96f3fSAl Viro #define RISCIX_MAGIC cpu_to_le32(0x4a657320)
649be96f3fSAl Viro __le32 date;
659be96f3fSAl Viro struct riscix_part part[8];
669be96f3fSAl Viro };
679be96f3fSAl Viro
689be96f3fSAl Viro #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
699be96f3fSAl Viro defined(CONFIG_ACORN_PARTITION_ADFS)
riscix_partition(struct parsed_partitions * state,unsigned long first_sect,int slot,unsigned long nr_sects)709be96f3fSAl Viro static int riscix_partition(struct parsed_partitions *state,
719be96f3fSAl Viro unsigned long first_sect, int slot,
729be96f3fSAl Viro unsigned long nr_sects)
739be96f3fSAl Viro {
749be96f3fSAl Viro Sector sect;
759be96f3fSAl Viro struct riscix_record *rr;
769be96f3fSAl Viro
779be96f3fSAl Viro rr = read_part_sector(state, first_sect, §);
789be96f3fSAl Viro if (!rr)
799be96f3fSAl Viro return -1;
809be96f3fSAl Viro
819be96f3fSAl Viro strlcat(state->pp_buf, " [RISCiX]", PAGE_SIZE);
829be96f3fSAl Viro
839be96f3fSAl Viro
849be96f3fSAl Viro if (rr->magic == RISCIX_MAGIC) {
859be96f3fSAl Viro unsigned long size = nr_sects > 2 ? 2 : nr_sects;
869be96f3fSAl Viro int part;
879be96f3fSAl Viro
889be96f3fSAl Viro strlcat(state->pp_buf, " <", PAGE_SIZE);
899be96f3fSAl Viro
909be96f3fSAl Viro put_partition(state, slot++, first_sect, size);
919be96f3fSAl Viro for (part = 0; part < 8; part++) {
929be96f3fSAl Viro if (rr->part[part].one &&
939be96f3fSAl Viro memcmp(rr->part[part].name, "All\0", 4)) {
949be96f3fSAl Viro put_partition(state, slot++,
959be96f3fSAl Viro le32_to_cpu(rr->part[part].start),
969be96f3fSAl Viro le32_to_cpu(rr->part[part].length));
979be96f3fSAl Viro strlcat(state->pp_buf, "(", PAGE_SIZE);
989be96f3fSAl Viro strlcat(state->pp_buf, rr->part[part].name, PAGE_SIZE);
999be96f3fSAl Viro strlcat(state->pp_buf, ")", PAGE_SIZE);
1009be96f3fSAl Viro }
1019be96f3fSAl Viro }
1029be96f3fSAl Viro
1039be96f3fSAl Viro strlcat(state->pp_buf, " >\n", PAGE_SIZE);
1049be96f3fSAl Viro } else {
1059be96f3fSAl Viro put_partition(state, slot++, first_sect, nr_sects);
1069be96f3fSAl Viro }
1079be96f3fSAl Viro
1089be96f3fSAl Viro put_dev_sector(sect);
1099be96f3fSAl Viro return slot;
1109be96f3fSAl Viro }
1119be96f3fSAl Viro #endif
1129be96f3fSAl Viro #endif
1139be96f3fSAl Viro
1149be96f3fSAl Viro #define LINUX_NATIVE_MAGIC 0xdeafa1de
1159be96f3fSAl Viro #define LINUX_SWAP_MAGIC 0xdeafab1e
1169be96f3fSAl Viro
1179be96f3fSAl Viro struct linux_part {
1189be96f3fSAl Viro __le32 magic;
1199be96f3fSAl Viro __le32 start_sect;
1209be96f3fSAl Viro __le32 nr_sects;
1219be96f3fSAl Viro };
1229be96f3fSAl Viro
1239be96f3fSAl Viro #if defined(CONFIG_ACORN_PARTITION_CUMANA) || \
1249be96f3fSAl Viro defined(CONFIG_ACORN_PARTITION_ADFS)
linux_partition(struct parsed_partitions * state,unsigned long first_sect,int slot,unsigned long nr_sects)1259be96f3fSAl Viro static int linux_partition(struct parsed_partitions *state,
1269be96f3fSAl Viro unsigned long first_sect, int slot,
1279be96f3fSAl Viro unsigned long nr_sects)
1289be96f3fSAl Viro {
1299be96f3fSAl Viro Sector sect;
1309be96f3fSAl Viro struct linux_part *linuxp;
1319be96f3fSAl Viro unsigned long size = nr_sects > 2 ? 2 : nr_sects;
1329be96f3fSAl Viro
1339be96f3fSAl Viro strlcat(state->pp_buf, " [Linux]", PAGE_SIZE);
1349be96f3fSAl Viro
1359be96f3fSAl Viro put_partition(state, slot++, first_sect, size);
1369be96f3fSAl Viro
1379be96f3fSAl Viro linuxp = read_part_sector(state, first_sect, §);
1389be96f3fSAl Viro if (!linuxp)
1399be96f3fSAl Viro return -1;
1409be96f3fSAl Viro
1419be96f3fSAl Viro strlcat(state->pp_buf, " <", PAGE_SIZE);
1429be96f3fSAl Viro while (linuxp->magic == cpu_to_le32(LINUX_NATIVE_MAGIC) ||
1439be96f3fSAl Viro linuxp->magic == cpu_to_le32(LINUX_SWAP_MAGIC)) {
1449be96f3fSAl Viro if (slot == state->limit)
1459be96f3fSAl Viro break;
1469be96f3fSAl Viro put_partition(state, slot++, first_sect +
1479be96f3fSAl Viro le32_to_cpu(linuxp->start_sect),
1489be96f3fSAl Viro le32_to_cpu(linuxp->nr_sects));
1499be96f3fSAl Viro linuxp ++;
1509be96f3fSAl Viro }
1519be96f3fSAl Viro strlcat(state->pp_buf, " >", PAGE_SIZE);
1529be96f3fSAl Viro
1539be96f3fSAl Viro put_dev_sector(sect);
1549be96f3fSAl Viro return slot;
1559be96f3fSAl Viro }
1569be96f3fSAl Viro #endif
1579be96f3fSAl Viro
1589be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_CUMANA
adfspart_check_CUMANA(struct parsed_partitions * state)1599be96f3fSAl Viro int adfspart_check_CUMANA(struct parsed_partitions *state)
1609be96f3fSAl Viro {
1619be96f3fSAl Viro unsigned long first_sector = 0;
1629be96f3fSAl Viro unsigned int start_blk = 0;
1639be96f3fSAl Viro Sector sect;
1649be96f3fSAl Viro unsigned char *data;
1659be96f3fSAl Viro char *name = "CUMANA/ADFS";
1669be96f3fSAl Viro int first = 1;
1679be96f3fSAl Viro int slot = 1;
1689be96f3fSAl Viro
1699be96f3fSAl Viro /*
1709be96f3fSAl Viro * Try Cumana style partitions - sector 6 contains ADFS boot block
1719be96f3fSAl Viro * with pointer to next 'drive'.
1729be96f3fSAl Viro *
1739be96f3fSAl Viro * There are unknowns in this code - is the 'cylinder number' of the
1749be96f3fSAl Viro * next partition relative to the start of this one - I'm assuming
1759be96f3fSAl Viro * it is.
1769be96f3fSAl Viro *
1779be96f3fSAl Viro * Also, which ID did Cumana use?
1789be96f3fSAl Viro *
1799be96f3fSAl Viro * This is totally unfinished, and will require more work to get it
1809be96f3fSAl Viro * going. Hence it is totally untested.
1819be96f3fSAl Viro */
1829be96f3fSAl Viro do {
1839be96f3fSAl Viro struct adfs_discrecord *dr;
1849be96f3fSAl Viro unsigned int nr_sects;
1859be96f3fSAl Viro
1869be96f3fSAl Viro data = read_part_sector(state, start_blk * 2 + 6, §);
1879be96f3fSAl Viro if (!data)
1889be96f3fSAl Viro return -1;
1899be96f3fSAl Viro
1909be96f3fSAl Viro if (slot == state->limit)
1919be96f3fSAl Viro break;
1929be96f3fSAl Viro
1939be96f3fSAl Viro dr = adfs_partition(state, name, data, first_sector, slot++);
1949be96f3fSAl Viro if (!dr)
1959be96f3fSAl Viro break;
1969be96f3fSAl Viro
1979be96f3fSAl Viro name = NULL;
1989be96f3fSAl Viro
1999be96f3fSAl Viro nr_sects = (data[0x1fd] + (data[0x1fe] << 8)) *
2009be96f3fSAl Viro (dr->heads + (dr->lowsector & 0x40 ? 1 : 0)) *
2019be96f3fSAl Viro dr->secspertrack;
2029be96f3fSAl Viro
2039be96f3fSAl Viro if (!nr_sects)
2049be96f3fSAl Viro break;
2059be96f3fSAl Viro
2069be96f3fSAl Viro first = 0;
2079be96f3fSAl Viro first_sector += nr_sects;
2089be96f3fSAl Viro start_blk += nr_sects >> (BLOCK_SIZE_BITS - 9);
2099be96f3fSAl Viro nr_sects = 0; /* hmm - should be partition size */
2109be96f3fSAl Viro
2119be96f3fSAl Viro switch (data[0x1fc] & 15) {
2129be96f3fSAl Viro case 0: /* No partition / ADFS? */
2139be96f3fSAl Viro break;
2149be96f3fSAl Viro
2159be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_RISCIX
2169be96f3fSAl Viro case PARTITION_RISCIX_SCSI:
2179be96f3fSAl Viro /* RISCiX - we don't know how to find the next one. */
2189be96f3fSAl Viro slot = riscix_partition(state, first_sector, slot,
2199be96f3fSAl Viro nr_sects);
2209be96f3fSAl Viro break;
2219be96f3fSAl Viro #endif
2229be96f3fSAl Viro
2239be96f3fSAl Viro case PARTITION_LINUX:
2249be96f3fSAl Viro slot = linux_partition(state, first_sector, slot,
2259be96f3fSAl Viro nr_sects);
2269be96f3fSAl Viro break;
2279be96f3fSAl Viro }
2289be96f3fSAl Viro put_dev_sector(sect);
2299be96f3fSAl Viro if (slot == -1)
2309be96f3fSAl Viro return -1;
2319be96f3fSAl Viro } while (1);
2329be96f3fSAl Viro put_dev_sector(sect);
2339be96f3fSAl Viro return first ? 0 : 1;
2349be96f3fSAl Viro }
2359be96f3fSAl Viro #endif
2369be96f3fSAl Viro
2379be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_ADFS
2389be96f3fSAl Viro /*
2399be96f3fSAl Viro * Purpose: allocate ADFS partitions.
2409be96f3fSAl Viro *
2419be96f3fSAl Viro * Params : hd - pointer to gendisk structure to store partition info.
2429be96f3fSAl Viro * dev - device number to access.
2439be96f3fSAl Viro *
2449be96f3fSAl Viro * Returns: -1 on error, 0 for no ADFS boot sector, 1 for ok.
2459be96f3fSAl Viro *
2469be96f3fSAl Viro * Alloc : hda = whole drive
2479be96f3fSAl Viro * hda1 = ADFS partition on first drive.
2489be96f3fSAl Viro * hda2 = non-ADFS partition.
2499be96f3fSAl Viro */
adfspart_check_ADFS(struct parsed_partitions * state)2509be96f3fSAl Viro int adfspart_check_ADFS(struct parsed_partitions *state)
2519be96f3fSAl Viro {
2529be96f3fSAl Viro unsigned long start_sect, nr_sects, sectscyl, heads;
2539be96f3fSAl Viro Sector sect;
2549be96f3fSAl Viro unsigned char *data;
2559be96f3fSAl Viro struct adfs_discrecord *dr;
2569be96f3fSAl Viro unsigned char id;
2579be96f3fSAl Viro int slot = 1;
2589be96f3fSAl Viro
2599be96f3fSAl Viro data = read_part_sector(state, 6, §);
2609be96f3fSAl Viro if (!data)
2619be96f3fSAl Viro return -1;
2629be96f3fSAl Viro
2639be96f3fSAl Viro dr = adfs_partition(state, "ADFS", data, 0, slot++);
2649be96f3fSAl Viro if (!dr) {
2659be96f3fSAl Viro put_dev_sector(sect);
2669be96f3fSAl Viro return 0;
2679be96f3fSAl Viro }
2689be96f3fSAl Viro
2699be96f3fSAl Viro heads = dr->heads + ((dr->lowsector >> 6) & 1);
2709be96f3fSAl Viro sectscyl = dr->secspertrack * heads;
2719be96f3fSAl Viro start_sect = ((data[0x1fe] << 8) + data[0x1fd]) * sectscyl;
2729be96f3fSAl Viro id = data[0x1fc] & 15;
2739be96f3fSAl Viro put_dev_sector(sect);
2749be96f3fSAl Viro
2759be96f3fSAl Viro /*
2769be96f3fSAl Viro * Work out start of non-adfs partition.
2779be96f3fSAl Viro */
278a08aa9bcSChristoph Hellwig nr_sects = get_capacity(state->disk) - start_sect;
2799be96f3fSAl Viro
2809be96f3fSAl Viro if (start_sect) {
2819be96f3fSAl Viro switch (id) {
2829be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_RISCIX
2839be96f3fSAl Viro case PARTITION_RISCIX_SCSI:
2849be96f3fSAl Viro case PARTITION_RISCIX_MFM:
285*83472682SMichal Orzel riscix_partition(state, start_sect, slot,
2869be96f3fSAl Viro nr_sects);
2879be96f3fSAl Viro break;
2889be96f3fSAl Viro #endif
2899be96f3fSAl Viro
2909be96f3fSAl Viro case PARTITION_LINUX:
291*83472682SMichal Orzel linux_partition(state, start_sect, slot,
2929be96f3fSAl Viro nr_sects);
2939be96f3fSAl Viro break;
2949be96f3fSAl Viro }
2959be96f3fSAl Viro }
2969be96f3fSAl Viro strlcat(state->pp_buf, "\n", PAGE_SIZE);
2979be96f3fSAl Viro return 1;
2989be96f3fSAl Viro }
2999be96f3fSAl Viro #endif
3009be96f3fSAl Viro
3019be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_ICS
3029be96f3fSAl Viro
3039be96f3fSAl Viro struct ics_part {
3049be96f3fSAl Viro __le32 start;
3059be96f3fSAl Viro __le32 size;
3069be96f3fSAl Viro };
3079be96f3fSAl Viro
adfspart_check_ICSLinux(struct parsed_partitions * state,unsigned long block)3089be96f3fSAl Viro static int adfspart_check_ICSLinux(struct parsed_partitions *state,
3099be96f3fSAl Viro unsigned long block)
3109be96f3fSAl Viro {
3119be96f3fSAl Viro Sector sect;
3129be96f3fSAl Viro unsigned char *data = read_part_sector(state, block, §);
3139be96f3fSAl Viro int result = 0;
3149be96f3fSAl Viro
3159be96f3fSAl Viro if (data) {
3169be96f3fSAl Viro if (memcmp(data, "LinuxPart", 9) == 0)
3179be96f3fSAl Viro result = 1;
3189be96f3fSAl Viro put_dev_sector(sect);
3199be96f3fSAl Viro }
3209be96f3fSAl Viro
3219be96f3fSAl Viro return result;
3229be96f3fSAl Viro }
3239be96f3fSAl Viro
3249be96f3fSAl Viro /*
3259be96f3fSAl Viro * Check for a valid ICS partition using the checksum.
3269be96f3fSAl Viro */
valid_ics_sector(const unsigned char * data)3279be96f3fSAl Viro static inline int valid_ics_sector(const unsigned char *data)
3289be96f3fSAl Viro {
3299be96f3fSAl Viro unsigned long sum;
3309be96f3fSAl Viro int i;
3319be96f3fSAl Viro
3329be96f3fSAl Viro for (i = 0, sum = 0x50617274; i < 508; i++)
3339be96f3fSAl Viro sum += data[i];
3349be96f3fSAl Viro
3359be96f3fSAl Viro sum -= le32_to_cpu(*(__le32 *)(&data[508]));
3369be96f3fSAl Viro
3379be96f3fSAl Viro return sum == 0;
3389be96f3fSAl Viro }
3399be96f3fSAl Viro
3409be96f3fSAl Viro /*
3419be96f3fSAl Viro * Purpose: allocate ICS partitions.
3429be96f3fSAl Viro * Params : hd - pointer to gendisk structure to store partition info.
3439be96f3fSAl Viro * dev - device number to access.
3449be96f3fSAl Viro * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
3459be96f3fSAl Viro * Alloc : hda = whole drive
3469be96f3fSAl Viro * hda1 = ADFS partition 0 on first drive.
3479be96f3fSAl Viro * hda2 = ADFS partition 1 on first drive.
3489be96f3fSAl Viro * ..etc..
3499be96f3fSAl Viro */
adfspart_check_ICS(struct parsed_partitions * state)3509be96f3fSAl Viro int adfspart_check_ICS(struct parsed_partitions *state)
3519be96f3fSAl Viro {
3529be96f3fSAl Viro const unsigned char *data;
3539be96f3fSAl Viro const struct ics_part *p;
3549be96f3fSAl Viro int slot;
3559be96f3fSAl Viro Sector sect;
3569be96f3fSAl Viro
3579be96f3fSAl Viro /*
3589be96f3fSAl Viro * Try ICS style partitions - sector 0 contains partition info.
3599be96f3fSAl Viro */
3609be96f3fSAl Viro data = read_part_sector(state, 0, §);
3619be96f3fSAl Viro if (!data)
3629be96f3fSAl Viro return -1;
3639be96f3fSAl Viro
3649be96f3fSAl Viro if (!valid_ics_sector(data)) {
3659be96f3fSAl Viro put_dev_sector(sect);
3669be96f3fSAl Viro return 0;
3679be96f3fSAl Viro }
3689be96f3fSAl Viro
3699be96f3fSAl Viro strlcat(state->pp_buf, " [ICS]", PAGE_SIZE);
3709be96f3fSAl Viro
3719be96f3fSAl Viro for (slot = 1, p = (const struct ics_part *)data; p->size; p++) {
3729be96f3fSAl Viro u32 start = le32_to_cpu(p->start);
3739be96f3fSAl Viro s32 size = le32_to_cpu(p->size); /* yes, it's signed. */
3749be96f3fSAl Viro
3759be96f3fSAl Viro if (slot == state->limit)
3769be96f3fSAl Viro break;
3779be96f3fSAl Viro
3789be96f3fSAl Viro /*
3799be96f3fSAl Viro * Negative sizes tell the RISC OS ICS driver to ignore
3809be96f3fSAl Viro * this partition - in effect it says that this does not
3819be96f3fSAl Viro * contain an ADFS filesystem.
3829be96f3fSAl Viro */
3839be96f3fSAl Viro if (size < 0) {
3849be96f3fSAl Viro size = -size;
3859be96f3fSAl Viro
3869be96f3fSAl Viro /*
3879be96f3fSAl Viro * Our own extension - We use the first sector
3889be96f3fSAl Viro * of the partition to identify what type this
3899be96f3fSAl Viro * partition is. We must not make this visible
3909be96f3fSAl Viro * to the filesystem.
3919be96f3fSAl Viro */
3929be96f3fSAl Viro if (size > 1 && adfspart_check_ICSLinux(state, start)) {
3939be96f3fSAl Viro start += 1;
3949be96f3fSAl Viro size -= 1;
3959be96f3fSAl Viro }
3969be96f3fSAl Viro }
3979be96f3fSAl Viro
3989be96f3fSAl Viro if (size)
3999be96f3fSAl Viro put_partition(state, slot++, start, size);
4009be96f3fSAl Viro }
4019be96f3fSAl Viro
4029be96f3fSAl Viro put_dev_sector(sect);
4039be96f3fSAl Viro strlcat(state->pp_buf, "\n", PAGE_SIZE);
4049be96f3fSAl Viro return 1;
4059be96f3fSAl Viro }
4069be96f3fSAl Viro #endif
4079be96f3fSAl Viro
4089be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_POWERTEC
4099be96f3fSAl Viro struct ptec_part {
4109be96f3fSAl Viro __le32 unused1;
4119be96f3fSAl Viro __le32 unused2;
4129be96f3fSAl Viro __le32 start;
4139be96f3fSAl Viro __le32 size;
4149be96f3fSAl Viro __le32 unused5;
4159be96f3fSAl Viro char type[8];
4169be96f3fSAl Viro };
4179be96f3fSAl Viro
valid_ptec_sector(const unsigned char * data)4189be96f3fSAl Viro static inline int valid_ptec_sector(const unsigned char *data)
4199be96f3fSAl Viro {
4209be96f3fSAl Viro unsigned char checksum = 0x2a;
4219be96f3fSAl Viro int i;
4229be96f3fSAl Viro
4239be96f3fSAl Viro /*
4249be96f3fSAl Viro * If it looks like a PC/BIOS partition, then it
4259be96f3fSAl Viro * probably isn't PowerTec.
4269be96f3fSAl Viro */
4279be96f3fSAl Viro if (data[510] == 0x55 && data[511] == 0xaa)
4289be96f3fSAl Viro return 0;
4299be96f3fSAl Viro
4309be96f3fSAl Viro for (i = 0; i < 511; i++)
4319be96f3fSAl Viro checksum += data[i];
4329be96f3fSAl Viro
4339be96f3fSAl Viro return checksum == data[511];
4349be96f3fSAl Viro }
4359be96f3fSAl Viro
4369be96f3fSAl Viro /*
4379be96f3fSAl Viro * Purpose: allocate ICS partitions.
4389be96f3fSAl Viro * Params : hd - pointer to gendisk structure to store partition info.
4399be96f3fSAl Viro * dev - device number to access.
4409be96f3fSAl Viro * Returns: -1 on error, 0 for no ICS table, 1 for partitions ok.
4419be96f3fSAl Viro * Alloc : hda = whole drive
4429be96f3fSAl Viro * hda1 = ADFS partition 0 on first drive.
4439be96f3fSAl Viro * hda2 = ADFS partition 1 on first drive.
4449be96f3fSAl Viro * ..etc..
4459be96f3fSAl Viro */
adfspart_check_POWERTEC(struct parsed_partitions * state)4469be96f3fSAl Viro int adfspart_check_POWERTEC(struct parsed_partitions *state)
4479be96f3fSAl Viro {
4489be96f3fSAl Viro Sector sect;
4499be96f3fSAl Viro const unsigned char *data;
4509be96f3fSAl Viro const struct ptec_part *p;
4519be96f3fSAl Viro int slot = 1;
4529be96f3fSAl Viro int i;
4539be96f3fSAl Viro
4549be96f3fSAl Viro data = read_part_sector(state, 0, §);
4559be96f3fSAl Viro if (!data)
4569be96f3fSAl Viro return -1;
4579be96f3fSAl Viro
4589be96f3fSAl Viro if (!valid_ptec_sector(data)) {
4599be96f3fSAl Viro put_dev_sector(sect);
4609be96f3fSAl Viro return 0;
4619be96f3fSAl Viro }
4629be96f3fSAl Viro
4639be96f3fSAl Viro strlcat(state->pp_buf, " [POWERTEC]", PAGE_SIZE);
4649be96f3fSAl Viro
4659be96f3fSAl Viro for (i = 0, p = (const struct ptec_part *)data; i < 12; i++, p++) {
4669be96f3fSAl Viro u32 start = le32_to_cpu(p->start);
4679be96f3fSAl Viro u32 size = le32_to_cpu(p->size);
4689be96f3fSAl Viro
4699be96f3fSAl Viro if (size)
4709be96f3fSAl Viro put_partition(state, slot++, start, size);
4719be96f3fSAl Viro }
4729be96f3fSAl Viro
4739be96f3fSAl Viro put_dev_sector(sect);
4749be96f3fSAl Viro strlcat(state->pp_buf, "\n", PAGE_SIZE);
4759be96f3fSAl Viro return 1;
4769be96f3fSAl Viro }
4779be96f3fSAl Viro #endif
4789be96f3fSAl Viro
4799be96f3fSAl Viro #ifdef CONFIG_ACORN_PARTITION_EESOX
4809be96f3fSAl Viro struct eesox_part {
4819be96f3fSAl Viro char magic[6];
4829be96f3fSAl Viro char name[10];
4839be96f3fSAl Viro __le32 start;
4849be96f3fSAl Viro __le32 unused6;
4859be96f3fSAl Viro __le32 unused7;
4869be96f3fSAl Viro __le32 unused8;
4879be96f3fSAl Viro };
4889be96f3fSAl Viro
4899be96f3fSAl Viro /*
4909be96f3fSAl Viro * Guess who created this format?
4919be96f3fSAl Viro */
4929be96f3fSAl Viro static const char eesox_name[] = {
4939be96f3fSAl Viro 'N', 'e', 'i', 'l', ' ',
4949be96f3fSAl Viro 'C', 'r', 'i', 't', 'c', 'h', 'e', 'l', 'l', ' ', ' '
4959be96f3fSAl Viro };
4969be96f3fSAl Viro
4979be96f3fSAl Viro /*
4989be96f3fSAl Viro * EESOX SCSI partition format.
4999be96f3fSAl Viro *
5009be96f3fSAl Viro * This is a goddamned awful partition format. We don't seem to store
5019be96f3fSAl Viro * the size of the partition in this table, only the start addresses.
5029be96f3fSAl Viro *
5039be96f3fSAl Viro * There are two possibilities where the size comes from:
5049be96f3fSAl Viro * 1. The individual ADFS boot block entries that are placed on the disk.
5059be96f3fSAl Viro * 2. The start address of the next entry.
5069be96f3fSAl Viro */
adfspart_check_EESOX(struct parsed_partitions * state)5079be96f3fSAl Viro int adfspart_check_EESOX(struct parsed_partitions *state)
5089be96f3fSAl Viro {
5099be96f3fSAl Viro Sector sect;
5109be96f3fSAl Viro const unsigned char *data;
5119be96f3fSAl Viro unsigned char buffer[256];
5129be96f3fSAl Viro struct eesox_part *p;
5139be96f3fSAl Viro sector_t start = 0;
5149be96f3fSAl Viro int i, slot = 1;
5159be96f3fSAl Viro
5169be96f3fSAl Viro data = read_part_sector(state, 7, §);
5179be96f3fSAl Viro if (!data)
5189be96f3fSAl Viro return -1;
5199be96f3fSAl Viro
5209be96f3fSAl Viro /*
5219be96f3fSAl Viro * "Decrypt" the partition table. God knows why...
5229be96f3fSAl Viro */
5239be96f3fSAl Viro for (i = 0; i < 256; i++)
5249be96f3fSAl Viro buffer[i] = data[i] ^ eesox_name[i & 15];
5259be96f3fSAl Viro
5269be96f3fSAl Viro put_dev_sector(sect);
5279be96f3fSAl Viro
5289be96f3fSAl Viro for (i = 0, p = (struct eesox_part *)buffer; i < 8; i++, p++) {
5299be96f3fSAl Viro sector_t next;
5309be96f3fSAl Viro
5319be96f3fSAl Viro if (memcmp(p->magic, "Eesox", 6))
5329be96f3fSAl Viro break;
5339be96f3fSAl Viro
5349be96f3fSAl Viro next = le32_to_cpu(p->start);
5359be96f3fSAl Viro if (i)
5369be96f3fSAl Viro put_partition(state, slot++, start, next - start);
5379be96f3fSAl Viro start = next;
5389be96f3fSAl Viro }
5399be96f3fSAl Viro
5409be96f3fSAl Viro if (i != 0) {
5419be96f3fSAl Viro sector_t size;
5429be96f3fSAl Viro
543a08aa9bcSChristoph Hellwig size = get_capacity(state->disk);
5449be96f3fSAl Viro put_partition(state, slot++, start, size - start);
5459be96f3fSAl Viro strlcat(state->pp_buf, "\n", PAGE_SIZE);
5469be96f3fSAl Viro }
5479be96f3fSAl Viro
5489be96f3fSAl Viro return i ? 1 : 0;
5499be96f3fSAl Viro }
5509be96f3fSAl Viro #endif
551