18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  fs/partitions/sun.c
48c2ecf20Sopenharmony_ci *
58c2ecf20Sopenharmony_ci *  Code extracted from drivers/block/genhd.c
68c2ecf20Sopenharmony_ci *
78c2ecf20Sopenharmony_ci *  Copyright (C) 1991-1998  Linus Torvalds
88c2ecf20Sopenharmony_ci *  Re-organised Feb 1998 Russell King
98c2ecf20Sopenharmony_ci */
108c2ecf20Sopenharmony_ci
118c2ecf20Sopenharmony_ci#include "check.h"
128c2ecf20Sopenharmony_ci
138c2ecf20Sopenharmony_ci#define SUN_LABEL_MAGIC          0xDABE
148c2ecf20Sopenharmony_ci#define SUN_VTOC_SANITY          0x600DDEEE
158c2ecf20Sopenharmony_ci
168c2ecf20Sopenharmony_cienum {
178c2ecf20Sopenharmony_ci	SUN_WHOLE_DISK = 5,
188c2ecf20Sopenharmony_ci	LINUX_RAID_PARTITION = 0xfd,	/* autodetect RAID partition */
198c2ecf20Sopenharmony_ci};
208c2ecf20Sopenharmony_ci
218c2ecf20Sopenharmony_ciint sun_partition(struct parsed_partitions *state)
228c2ecf20Sopenharmony_ci{
238c2ecf20Sopenharmony_ci	int i;
248c2ecf20Sopenharmony_ci	__be16 csum;
258c2ecf20Sopenharmony_ci	int slot = 1;
268c2ecf20Sopenharmony_ci	__be16 *ush;
278c2ecf20Sopenharmony_ci	Sector sect;
288c2ecf20Sopenharmony_ci	struct sun_disklabel {
298c2ecf20Sopenharmony_ci		unsigned char info[128];   /* Informative text string */
308c2ecf20Sopenharmony_ci		struct sun_vtoc {
318c2ecf20Sopenharmony_ci		    __be32 version;     /* Layout version */
328c2ecf20Sopenharmony_ci		    char   volume[8];   /* Volume name */
338c2ecf20Sopenharmony_ci		    __be16 nparts;      /* Number of partitions */
348c2ecf20Sopenharmony_ci		    struct sun_info {           /* Partition hdrs, sec 2 */
358c2ecf20Sopenharmony_ci			__be16 id;
368c2ecf20Sopenharmony_ci			__be16 flags;
378c2ecf20Sopenharmony_ci		    } infos[8];
388c2ecf20Sopenharmony_ci		    __be16 padding;     /* Alignment padding */
398c2ecf20Sopenharmony_ci		    __be32 bootinfo[3];  /* Info needed by mboot */
408c2ecf20Sopenharmony_ci		    __be32 sanity;       /* To verify vtoc sanity */
418c2ecf20Sopenharmony_ci		    __be32 reserved[10]; /* Free space */
428c2ecf20Sopenharmony_ci		    __be32 timestamp[8]; /* Partition timestamp */
438c2ecf20Sopenharmony_ci		} vtoc;
448c2ecf20Sopenharmony_ci		__be32 write_reinstruct; /* sectors to skip, writes */
458c2ecf20Sopenharmony_ci		__be32 read_reinstruct;  /* sectors to skip, reads */
468c2ecf20Sopenharmony_ci		unsigned char spare[148]; /* Padding */
478c2ecf20Sopenharmony_ci		__be16 rspeed;     /* Disk rotational speed */
488c2ecf20Sopenharmony_ci		__be16 pcylcount;  /* Physical cylinder count */
498c2ecf20Sopenharmony_ci		__be16 sparecyl;   /* extra sects per cylinder */
508c2ecf20Sopenharmony_ci		__be16 obs1;       /* gap1 */
518c2ecf20Sopenharmony_ci		__be16 obs2;       /* gap2 */
528c2ecf20Sopenharmony_ci		__be16 ilfact;     /* Interleave factor */
538c2ecf20Sopenharmony_ci		__be16 ncyl;       /* Data cylinder count */
548c2ecf20Sopenharmony_ci		__be16 nacyl;      /* Alt. cylinder count */
558c2ecf20Sopenharmony_ci		__be16 ntrks;      /* Tracks per cylinder */
568c2ecf20Sopenharmony_ci		__be16 nsect;      /* Sectors per track */
578c2ecf20Sopenharmony_ci		__be16 obs3;       /* bhead - Label head offset */
588c2ecf20Sopenharmony_ci		__be16 obs4;       /* ppart - Physical Partition */
598c2ecf20Sopenharmony_ci		struct sun_partition {
608c2ecf20Sopenharmony_ci			__be32 start_cylinder;
618c2ecf20Sopenharmony_ci			__be32 num_sectors;
628c2ecf20Sopenharmony_ci		} partitions[8];
638c2ecf20Sopenharmony_ci		__be16 magic;      /* Magic number */
648c2ecf20Sopenharmony_ci		__be16 csum;       /* Label xor'd checksum */
658c2ecf20Sopenharmony_ci	} * label;
668c2ecf20Sopenharmony_ci	struct sun_partition *p;
678c2ecf20Sopenharmony_ci	unsigned long spc;
688c2ecf20Sopenharmony_ci	char b[BDEVNAME_SIZE];
698c2ecf20Sopenharmony_ci	int use_vtoc;
708c2ecf20Sopenharmony_ci	int nparts;
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	label = read_part_sector(state, 0, &sect);
738c2ecf20Sopenharmony_ci	if (!label)
748c2ecf20Sopenharmony_ci		return -1;
758c2ecf20Sopenharmony_ci
768c2ecf20Sopenharmony_ci	p = label->partitions;
778c2ecf20Sopenharmony_ci	if (be16_to_cpu(label->magic) != SUN_LABEL_MAGIC) {
788c2ecf20Sopenharmony_ci/*		printk(KERN_INFO "Dev %s Sun disklabel: bad magic %04x\n",
798c2ecf20Sopenharmony_ci		       bdevname(bdev, b), be16_to_cpu(label->magic)); */
808c2ecf20Sopenharmony_ci		put_dev_sector(sect);
818c2ecf20Sopenharmony_ci		return 0;
828c2ecf20Sopenharmony_ci	}
838c2ecf20Sopenharmony_ci	/* Look at the checksum */
848c2ecf20Sopenharmony_ci	ush = ((__be16 *) (label+1)) - 1;
858c2ecf20Sopenharmony_ci	for (csum = 0; ush >= ((__be16 *) label);)
868c2ecf20Sopenharmony_ci		csum ^= *ush--;
878c2ecf20Sopenharmony_ci	if (csum) {
888c2ecf20Sopenharmony_ci		printk("Dev %s Sun disklabel: Csum bad, label corrupted\n",
898c2ecf20Sopenharmony_ci		       bdevname(state->bdev, b));
908c2ecf20Sopenharmony_ci		put_dev_sector(sect);
918c2ecf20Sopenharmony_ci		return 0;
928c2ecf20Sopenharmony_ci	}
938c2ecf20Sopenharmony_ci
948c2ecf20Sopenharmony_ci	/* Check to see if we can use the VTOC table */
958c2ecf20Sopenharmony_ci	use_vtoc = ((be32_to_cpu(label->vtoc.sanity) == SUN_VTOC_SANITY) &&
968c2ecf20Sopenharmony_ci		    (be32_to_cpu(label->vtoc.version) == 1) &&
978c2ecf20Sopenharmony_ci		    (be16_to_cpu(label->vtoc.nparts) <= 8));
988c2ecf20Sopenharmony_ci
998c2ecf20Sopenharmony_ci	/* Use 8 partition entries if not specified in validated VTOC */
1008c2ecf20Sopenharmony_ci	nparts = (use_vtoc) ? be16_to_cpu(label->vtoc.nparts) : 8;
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci	/*
1038c2ecf20Sopenharmony_ci	 * So that old Linux-Sun partitions continue to work,
1048c2ecf20Sopenharmony_ci	 * alow the VTOC to be used under the additional condition ...
1058c2ecf20Sopenharmony_ci	 */
1068c2ecf20Sopenharmony_ci	use_vtoc = use_vtoc || !(label->vtoc.sanity ||
1078c2ecf20Sopenharmony_ci				 label->vtoc.version || label->vtoc.nparts);
1088c2ecf20Sopenharmony_ci	spc = be16_to_cpu(label->ntrks) * be16_to_cpu(label->nsect);
1098c2ecf20Sopenharmony_ci	for (i = 0; i < nparts; i++, p++) {
1108c2ecf20Sopenharmony_ci		unsigned long st_sector;
1118c2ecf20Sopenharmony_ci		unsigned int num_sectors;
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci		st_sector = be32_to_cpu(p->start_cylinder) * spc;
1148c2ecf20Sopenharmony_ci		num_sectors = be32_to_cpu(p->num_sectors);
1158c2ecf20Sopenharmony_ci		if (num_sectors) {
1168c2ecf20Sopenharmony_ci			put_partition(state, slot, st_sector, num_sectors);
1178c2ecf20Sopenharmony_ci			state->parts[slot].flags = 0;
1188c2ecf20Sopenharmony_ci			if (use_vtoc) {
1198c2ecf20Sopenharmony_ci				if (be16_to_cpu(label->vtoc.infos[i].id) == LINUX_RAID_PARTITION)
1208c2ecf20Sopenharmony_ci					state->parts[slot].flags |= ADDPART_FLAG_RAID;
1218c2ecf20Sopenharmony_ci				else if (be16_to_cpu(label->vtoc.infos[i].id) == SUN_WHOLE_DISK)
1228c2ecf20Sopenharmony_ci					state->parts[slot].flags |= ADDPART_FLAG_WHOLEDISK;
1238c2ecf20Sopenharmony_ci			}
1248c2ecf20Sopenharmony_ci		}
1258c2ecf20Sopenharmony_ci		slot++;
1268c2ecf20Sopenharmony_ci	}
1278c2ecf20Sopenharmony_ci	strlcat(state->pp_buf, "\n", PAGE_SIZE);
1288c2ecf20Sopenharmony_ci	put_dev_sector(sect);
1298c2ecf20Sopenharmony_ci	return 1;
1308c2ecf20Sopenharmony_ci}
131