162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  fs/partitions/sgi.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Code extracted from drivers/block/genhd.c
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include "check.h"
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#define SGI_LABEL_MAGIC 0x0be5a941
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_cienum {
1362306a36Sopenharmony_ci	LINUX_RAID_PARTITION = 0xfd,	/* autodetect RAID partition */
1462306a36Sopenharmony_ci};
1562306a36Sopenharmony_ci
1662306a36Sopenharmony_cistruct sgi_disklabel {
1762306a36Sopenharmony_ci	__be32 magic_mushroom;		/* Big fat spliff... */
1862306a36Sopenharmony_ci	__be16 root_part_num;		/* Root partition number */
1962306a36Sopenharmony_ci	__be16 swap_part_num;		/* Swap partition number */
2062306a36Sopenharmony_ci	s8 boot_file[16];		/* Name of boot file for ARCS */
2162306a36Sopenharmony_ci	u8 _unused0[48];		/* Device parameter useless crapola.. */
2262306a36Sopenharmony_ci	struct sgi_volume {
2362306a36Sopenharmony_ci		s8 name[8];		/* Name of volume */
2462306a36Sopenharmony_ci		__be32 block_num;		/* Logical block number */
2562306a36Sopenharmony_ci		__be32 num_bytes;		/* How big, in bytes */
2662306a36Sopenharmony_ci	} volume[15];
2762306a36Sopenharmony_ci	struct sgi_partition {
2862306a36Sopenharmony_ci		__be32 num_blocks;		/* Size in logical blocks */
2962306a36Sopenharmony_ci		__be32 first_block;	/* First logical block */
3062306a36Sopenharmony_ci		__be32 type;		/* Type of this partition */
3162306a36Sopenharmony_ci	} partitions[16];
3262306a36Sopenharmony_ci	__be32 csum;			/* Disk label checksum */
3362306a36Sopenharmony_ci	__be32 _unused1;			/* Padding */
3462306a36Sopenharmony_ci};
3562306a36Sopenharmony_ci
3662306a36Sopenharmony_ciint sgi_partition(struct parsed_partitions *state)
3762306a36Sopenharmony_ci{
3862306a36Sopenharmony_ci	int i, csum;
3962306a36Sopenharmony_ci	__be32 magic;
4062306a36Sopenharmony_ci	int slot = 1;
4162306a36Sopenharmony_ci	unsigned int start, blocks;
4262306a36Sopenharmony_ci	__be32 *ui, cs;
4362306a36Sopenharmony_ci	Sector sect;
4462306a36Sopenharmony_ci	struct sgi_disklabel *label;
4562306a36Sopenharmony_ci	struct sgi_partition *p;
4662306a36Sopenharmony_ci
4762306a36Sopenharmony_ci	label = read_part_sector(state, 0, &sect);
4862306a36Sopenharmony_ci	if (!label)
4962306a36Sopenharmony_ci		return -1;
5062306a36Sopenharmony_ci	p = &label->partitions[0];
5162306a36Sopenharmony_ci	magic = label->magic_mushroom;
5262306a36Sopenharmony_ci	if(be32_to_cpu(magic) != SGI_LABEL_MAGIC) {
5362306a36Sopenharmony_ci		/*printk("Dev %s SGI disklabel: bad magic %08x\n",
5462306a36Sopenharmony_ci		       state->disk->disk_name, be32_to_cpu(magic));*/
5562306a36Sopenharmony_ci		put_dev_sector(sect);
5662306a36Sopenharmony_ci		return 0;
5762306a36Sopenharmony_ci	}
5862306a36Sopenharmony_ci	ui = ((__be32 *) (label + 1)) - 1;
5962306a36Sopenharmony_ci	for(csum = 0; ui >= ((__be32 *) label);) {
6062306a36Sopenharmony_ci		cs = *ui--;
6162306a36Sopenharmony_ci		csum += be32_to_cpu(cs);
6262306a36Sopenharmony_ci	}
6362306a36Sopenharmony_ci	if(csum) {
6462306a36Sopenharmony_ci		printk(KERN_WARNING "Dev %s SGI disklabel: csum bad, label corrupted\n",
6562306a36Sopenharmony_ci		       state->disk->disk_name);
6662306a36Sopenharmony_ci		put_dev_sector(sect);
6762306a36Sopenharmony_ci		return 0;
6862306a36Sopenharmony_ci	}
6962306a36Sopenharmony_ci	/* All SGI disk labels have 16 partitions, disks under Linux only
7062306a36Sopenharmony_ci	 * have 15 minor's.  Luckily there are always a few zero length
7162306a36Sopenharmony_ci	 * partitions which we don't care about so we never overflow the
7262306a36Sopenharmony_ci	 * current_minor.
7362306a36Sopenharmony_ci	 */
7462306a36Sopenharmony_ci	for(i = 0; i < 16; i++, p++) {
7562306a36Sopenharmony_ci		blocks = be32_to_cpu(p->num_blocks);
7662306a36Sopenharmony_ci		start  = be32_to_cpu(p->first_block);
7762306a36Sopenharmony_ci		if (blocks) {
7862306a36Sopenharmony_ci			put_partition(state, slot, start, blocks);
7962306a36Sopenharmony_ci			if (be32_to_cpu(p->type) == LINUX_RAID_PARTITION)
8062306a36Sopenharmony_ci				state->parts[slot].flags = ADDPART_FLAG_RAID;
8162306a36Sopenharmony_ci		}
8262306a36Sopenharmony_ci		slot++;
8362306a36Sopenharmony_ci	}
8462306a36Sopenharmony_ci	strlcat(state->pp_buf, "\n", PAGE_SIZE);
8562306a36Sopenharmony_ci	put_dev_sector(sect);
8662306a36Sopenharmony_ci	return 1;
8762306a36Sopenharmony_ci}
88