162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci *  fs/partitions/atari.c
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci *  Code extracted from drivers/block/genhd.c
662306a36Sopenharmony_ci *
762306a36Sopenharmony_ci *  Copyright (C) 1991-1998  Linus Torvalds
862306a36Sopenharmony_ci *  Re-organised Feb 1998 Russell King
962306a36Sopenharmony_ci */
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci#include <linux/ctype.h>
1262306a36Sopenharmony_ci#include "check.h"
1362306a36Sopenharmony_ci#include "atari.h"
1462306a36Sopenharmony_ci
1562306a36Sopenharmony_ci/* ++guenther: this should be settable by the user ("make config")?.
1662306a36Sopenharmony_ci */
1762306a36Sopenharmony_ci#define ICD_PARTS
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci/* check if a partition entry looks valid -- Atari format is assumed if at
2062306a36Sopenharmony_ci   least one of the primary entries is ok this way */
2162306a36Sopenharmony_ci#define	VALID_PARTITION(pi,hdsiz)					     \
2262306a36Sopenharmony_ci    (((pi)->flg & 1) &&							     \
2362306a36Sopenharmony_ci     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
2462306a36Sopenharmony_ci     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
2562306a36Sopenharmony_ci     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
2662306a36Sopenharmony_ci
2762306a36Sopenharmony_cistatic inline int OK_id(char *s)
2862306a36Sopenharmony_ci{
2962306a36Sopenharmony_ci	return  memcmp (s, "GEM", 3) == 0 || memcmp (s, "BGM", 3) == 0 ||
3062306a36Sopenharmony_ci		memcmp (s, "LNX", 3) == 0 || memcmp (s, "SWP", 3) == 0 ||
3162306a36Sopenharmony_ci		memcmp (s, "RAW", 3) == 0 ;
3262306a36Sopenharmony_ci}
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ciint atari_partition(struct parsed_partitions *state)
3562306a36Sopenharmony_ci{
3662306a36Sopenharmony_ci	Sector sect;
3762306a36Sopenharmony_ci	struct rootsector *rs;
3862306a36Sopenharmony_ci	struct partition_info *pi;
3962306a36Sopenharmony_ci	u32 extensect;
4062306a36Sopenharmony_ci	u32 hd_size;
4162306a36Sopenharmony_ci	int slot;
4262306a36Sopenharmony_ci#ifdef ICD_PARTS
4362306a36Sopenharmony_ci	int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
4462306a36Sopenharmony_ci#endif
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_ci	/*
4762306a36Sopenharmony_ci	 * ATARI partition scheme supports 512 lba only.  If this is not
4862306a36Sopenharmony_ci	 * the case, bail early to avoid miscalculating hd_size.
4962306a36Sopenharmony_ci	 */
5062306a36Sopenharmony_ci	if (queue_logical_block_size(state->disk->queue) != 512)
5162306a36Sopenharmony_ci		return 0;
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_ci	rs = read_part_sector(state, 0, &sect);
5462306a36Sopenharmony_ci	if (!rs)
5562306a36Sopenharmony_ci		return -1;
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	/* Verify this is an Atari rootsector: */
5862306a36Sopenharmony_ci	hd_size = get_capacity(state->disk);
5962306a36Sopenharmony_ci	if (!VALID_PARTITION(&rs->part[0], hd_size) &&
6062306a36Sopenharmony_ci	    !VALID_PARTITION(&rs->part[1], hd_size) &&
6162306a36Sopenharmony_ci	    !VALID_PARTITION(&rs->part[2], hd_size) &&
6262306a36Sopenharmony_ci	    !VALID_PARTITION(&rs->part[3], hd_size)) {
6362306a36Sopenharmony_ci		/*
6462306a36Sopenharmony_ci		 * if there's no valid primary partition, assume that no Atari
6562306a36Sopenharmony_ci		 * format partition table (there's no reliable magic or the like
6662306a36Sopenharmony_ci	         * :-()
6762306a36Sopenharmony_ci		 */
6862306a36Sopenharmony_ci		put_dev_sector(sect);
6962306a36Sopenharmony_ci		return 0;
7062306a36Sopenharmony_ci	}
7162306a36Sopenharmony_ci
7262306a36Sopenharmony_ci	pi = &rs->part[0];
7362306a36Sopenharmony_ci	strlcat(state->pp_buf, " AHDI", PAGE_SIZE);
7462306a36Sopenharmony_ci	for (slot = 1; pi < &rs->part[4] && slot < state->limit; slot++, pi++) {
7562306a36Sopenharmony_ci		struct rootsector *xrs;
7662306a36Sopenharmony_ci		Sector sect2;
7762306a36Sopenharmony_ci		ulong partsect;
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci		if ( !(pi->flg & 1) )
8062306a36Sopenharmony_ci			continue;
8162306a36Sopenharmony_ci		/* active partition */
8262306a36Sopenharmony_ci		if (memcmp (pi->id, "XGM", 3) != 0) {
8362306a36Sopenharmony_ci			/* we don't care about other id's */
8462306a36Sopenharmony_ci			put_partition (state, slot, be32_to_cpu(pi->st),
8562306a36Sopenharmony_ci					be32_to_cpu(pi->siz));
8662306a36Sopenharmony_ci			continue;
8762306a36Sopenharmony_ci		}
8862306a36Sopenharmony_ci		/* extension partition */
8962306a36Sopenharmony_ci#ifdef ICD_PARTS
9062306a36Sopenharmony_ci		part_fmt = 1;
9162306a36Sopenharmony_ci#endif
9262306a36Sopenharmony_ci		strlcat(state->pp_buf, " XGM<", PAGE_SIZE);
9362306a36Sopenharmony_ci		partsect = extensect = be32_to_cpu(pi->st);
9462306a36Sopenharmony_ci		while (1) {
9562306a36Sopenharmony_ci			xrs = read_part_sector(state, partsect, &sect2);
9662306a36Sopenharmony_ci			if (!xrs) {
9762306a36Sopenharmony_ci				printk (" block %ld read failed\n", partsect);
9862306a36Sopenharmony_ci				put_dev_sector(sect);
9962306a36Sopenharmony_ci				return -1;
10062306a36Sopenharmony_ci			}
10162306a36Sopenharmony_ci
10262306a36Sopenharmony_ci			/* ++roman: sanity check: bit 0 of flg field must be set */
10362306a36Sopenharmony_ci			if (!(xrs->part[0].flg & 1)) {
10462306a36Sopenharmony_ci				printk( "\nFirst sub-partition in extended partition is not valid!\n" );
10562306a36Sopenharmony_ci				put_dev_sector(sect2);
10662306a36Sopenharmony_ci				break;
10762306a36Sopenharmony_ci			}
10862306a36Sopenharmony_ci
10962306a36Sopenharmony_ci			put_partition(state, slot,
11062306a36Sopenharmony_ci				   partsect + be32_to_cpu(xrs->part[0].st),
11162306a36Sopenharmony_ci				   be32_to_cpu(xrs->part[0].siz));
11262306a36Sopenharmony_ci
11362306a36Sopenharmony_ci			if (!(xrs->part[1].flg & 1)) {
11462306a36Sopenharmony_ci				/* end of linked partition list */
11562306a36Sopenharmony_ci				put_dev_sector(sect2);
11662306a36Sopenharmony_ci				break;
11762306a36Sopenharmony_ci			}
11862306a36Sopenharmony_ci			if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
11962306a36Sopenharmony_ci				printk("\nID of extended partition is not XGM!\n");
12062306a36Sopenharmony_ci				put_dev_sector(sect2);
12162306a36Sopenharmony_ci				break;
12262306a36Sopenharmony_ci			}
12362306a36Sopenharmony_ci
12462306a36Sopenharmony_ci			partsect = be32_to_cpu(xrs->part[1].st) + extensect;
12562306a36Sopenharmony_ci			put_dev_sector(sect2);
12662306a36Sopenharmony_ci			if (++slot == state->limit) {
12762306a36Sopenharmony_ci				printk( "\nMaximum number of partitions reached!\n" );
12862306a36Sopenharmony_ci				break;
12962306a36Sopenharmony_ci			}
13062306a36Sopenharmony_ci		}
13162306a36Sopenharmony_ci		strlcat(state->pp_buf, " >", PAGE_SIZE);
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci#ifdef ICD_PARTS
13462306a36Sopenharmony_ci	if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */
13562306a36Sopenharmony_ci		pi = &rs->icdpart[0];
13662306a36Sopenharmony_ci		/* sanity check: no ICD format if first partition invalid */
13762306a36Sopenharmony_ci		if (OK_id(pi->id)) {
13862306a36Sopenharmony_ci			strlcat(state->pp_buf, " ICD<", PAGE_SIZE);
13962306a36Sopenharmony_ci			for (; pi < &rs->icdpart[8] && slot < state->limit; slot++, pi++) {
14062306a36Sopenharmony_ci				/* accept only GEM,BGM,RAW,LNX,SWP partitions */
14162306a36Sopenharmony_ci				if (!((pi->flg & 1) && OK_id(pi->id)))
14262306a36Sopenharmony_ci					continue;
14362306a36Sopenharmony_ci				put_partition (state, slot,
14462306a36Sopenharmony_ci						be32_to_cpu(pi->st),
14562306a36Sopenharmony_ci						be32_to_cpu(pi->siz));
14662306a36Sopenharmony_ci			}
14762306a36Sopenharmony_ci			strlcat(state->pp_buf, " >", PAGE_SIZE);
14862306a36Sopenharmony_ci		}
14962306a36Sopenharmony_ci	}
15062306a36Sopenharmony_ci#endif
15162306a36Sopenharmony_ci	put_dev_sector(sect);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	strlcat(state->pp_buf, "\n", PAGE_SIZE);
15462306a36Sopenharmony_ci
15562306a36Sopenharmony_ci	return 1;
15662306a36Sopenharmony_ci}
157