18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci *  fs/partitions/atari.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 <linux/ctype.h>
128c2ecf20Sopenharmony_ci#include "check.h"
138c2ecf20Sopenharmony_ci#include "atari.h"
148c2ecf20Sopenharmony_ci
158c2ecf20Sopenharmony_ci/* ++guenther: this should be settable by the user ("make config")?.
168c2ecf20Sopenharmony_ci */
178c2ecf20Sopenharmony_ci#define ICD_PARTS
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci/* check if a partition entry looks valid -- Atari format is assumed if at
208c2ecf20Sopenharmony_ci   least one of the primary entries is ok this way */
218c2ecf20Sopenharmony_ci#define	VALID_PARTITION(pi,hdsiz)					     \
228c2ecf20Sopenharmony_ci    (((pi)->flg & 1) &&							     \
238c2ecf20Sopenharmony_ci     isalnum((pi)->id[0]) && isalnum((pi)->id[1]) && isalnum((pi)->id[2]) && \
248c2ecf20Sopenharmony_ci     be32_to_cpu((pi)->st) <= (hdsiz) &&				     \
258c2ecf20Sopenharmony_ci     be32_to_cpu((pi)->st) + be32_to_cpu((pi)->siz) <= (hdsiz))
268c2ecf20Sopenharmony_ci
278c2ecf20Sopenharmony_cistatic inline int OK_id(char *s)
288c2ecf20Sopenharmony_ci{
298c2ecf20Sopenharmony_ci	return  memcmp (s, "GEM", 3) == 0 || memcmp (s, "BGM", 3) == 0 ||
308c2ecf20Sopenharmony_ci		memcmp (s, "LNX", 3) == 0 || memcmp (s, "SWP", 3) == 0 ||
318c2ecf20Sopenharmony_ci		memcmp (s, "RAW", 3) == 0 ;
328c2ecf20Sopenharmony_ci}
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ciint atari_partition(struct parsed_partitions *state)
358c2ecf20Sopenharmony_ci{
368c2ecf20Sopenharmony_ci	Sector sect;
378c2ecf20Sopenharmony_ci	struct rootsector *rs;
388c2ecf20Sopenharmony_ci	struct partition_info *pi;
398c2ecf20Sopenharmony_ci	u32 extensect;
408c2ecf20Sopenharmony_ci	u32 hd_size;
418c2ecf20Sopenharmony_ci	int slot;
428c2ecf20Sopenharmony_ci#ifdef ICD_PARTS
438c2ecf20Sopenharmony_ci	int part_fmt = 0; /* 0:unknown, 1:AHDI, 2:ICD/Supra */
448c2ecf20Sopenharmony_ci#endif
458c2ecf20Sopenharmony_ci
468c2ecf20Sopenharmony_ci	/*
478c2ecf20Sopenharmony_ci	 * ATARI partition scheme supports 512 lba only.  If this is not
488c2ecf20Sopenharmony_ci	 * the case, bail early to avoid miscalculating hd_size.
498c2ecf20Sopenharmony_ci	 */
508c2ecf20Sopenharmony_ci	if (bdev_logical_block_size(state->bdev) != 512)
518c2ecf20Sopenharmony_ci		return 0;
528c2ecf20Sopenharmony_ci
538c2ecf20Sopenharmony_ci	rs = read_part_sector(state, 0, &sect);
548c2ecf20Sopenharmony_ci	if (!rs)
558c2ecf20Sopenharmony_ci		return -1;
568c2ecf20Sopenharmony_ci
578c2ecf20Sopenharmony_ci	/* Verify this is an Atari rootsector: */
588c2ecf20Sopenharmony_ci	hd_size = state->bdev->bd_inode->i_size >> 9;
598c2ecf20Sopenharmony_ci	if (!VALID_PARTITION(&rs->part[0], hd_size) &&
608c2ecf20Sopenharmony_ci	    !VALID_PARTITION(&rs->part[1], hd_size) &&
618c2ecf20Sopenharmony_ci	    !VALID_PARTITION(&rs->part[2], hd_size) &&
628c2ecf20Sopenharmony_ci	    !VALID_PARTITION(&rs->part[3], hd_size)) {
638c2ecf20Sopenharmony_ci		/*
648c2ecf20Sopenharmony_ci		 * if there's no valid primary partition, assume that no Atari
658c2ecf20Sopenharmony_ci		 * format partition table (there's no reliable magic or the like
668c2ecf20Sopenharmony_ci	         * :-()
678c2ecf20Sopenharmony_ci		 */
688c2ecf20Sopenharmony_ci		put_dev_sector(sect);
698c2ecf20Sopenharmony_ci		return 0;
708c2ecf20Sopenharmony_ci	}
718c2ecf20Sopenharmony_ci
728c2ecf20Sopenharmony_ci	pi = &rs->part[0];
738c2ecf20Sopenharmony_ci	strlcat(state->pp_buf, " AHDI", PAGE_SIZE);
748c2ecf20Sopenharmony_ci	for (slot = 1; pi < &rs->part[4] && slot < state->limit; slot++, pi++) {
758c2ecf20Sopenharmony_ci		struct rootsector *xrs;
768c2ecf20Sopenharmony_ci		Sector sect2;
778c2ecf20Sopenharmony_ci		ulong partsect;
788c2ecf20Sopenharmony_ci
798c2ecf20Sopenharmony_ci		if ( !(pi->flg & 1) )
808c2ecf20Sopenharmony_ci			continue;
818c2ecf20Sopenharmony_ci		/* active partition */
828c2ecf20Sopenharmony_ci		if (memcmp (pi->id, "XGM", 3) != 0) {
838c2ecf20Sopenharmony_ci			/* we don't care about other id's */
848c2ecf20Sopenharmony_ci			put_partition (state, slot, be32_to_cpu(pi->st),
858c2ecf20Sopenharmony_ci					be32_to_cpu(pi->siz));
868c2ecf20Sopenharmony_ci			continue;
878c2ecf20Sopenharmony_ci		}
888c2ecf20Sopenharmony_ci		/* extension partition */
898c2ecf20Sopenharmony_ci#ifdef ICD_PARTS
908c2ecf20Sopenharmony_ci		part_fmt = 1;
918c2ecf20Sopenharmony_ci#endif
928c2ecf20Sopenharmony_ci		strlcat(state->pp_buf, " XGM<", PAGE_SIZE);
938c2ecf20Sopenharmony_ci		partsect = extensect = be32_to_cpu(pi->st);
948c2ecf20Sopenharmony_ci		while (1) {
958c2ecf20Sopenharmony_ci			xrs = read_part_sector(state, partsect, &sect2);
968c2ecf20Sopenharmony_ci			if (!xrs) {
978c2ecf20Sopenharmony_ci				printk (" block %ld read failed\n", partsect);
988c2ecf20Sopenharmony_ci				put_dev_sector(sect);
998c2ecf20Sopenharmony_ci				return -1;
1008c2ecf20Sopenharmony_ci			}
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_ci			/* ++roman: sanity check: bit 0 of flg field must be set */
1038c2ecf20Sopenharmony_ci			if (!(xrs->part[0].flg & 1)) {
1048c2ecf20Sopenharmony_ci				printk( "\nFirst sub-partition in extended partition is not valid!\n" );
1058c2ecf20Sopenharmony_ci				put_dev_sector(sect2);
1068c2ecf20Sopenharmony_ci				break;
1078c2ecf20Sopenharmony_ci			}
1088c2ecf20Sopenharmony_ci
1098c2ecf20Sopenharmony_ci			put_partition(state, slot,
1108c2ecf20Sopenharmony_ci				   partsect + be32_to_cpu(xrs->part[0].st),
1118c2ecf20Sopenharmony_ci				   be32_to_cpu(xrs->part[0].siz));
1128c2ecf20Sopenharmony_ci
1138c2ecf20Sopenharmony_ci			if (!(xrs->part[1].flg & 1)) {
1148c2ecf20Sopenharmony_ci				/* end of linked partition list */
1158c2ecf20Sopenharmony_ci				put_dev_sector(sect2);
1168c2ecf20Sopenharmony_ci				break;
1178c2ecf20Sopenharmony_ci			}
1188c2ecf20Sopenharmony_ci			if (memcmp( xrs->part[1].id, "XGM", 3 ) != 0) {
1198c2ecf20Sopenharmony_ci				printk("\nID of extended partition is not XGM!\n");
1208c2ecf20Sopenharmony_ci				put_dev_sector(sect2);
1218c2ecf20Sopenharmony_ci				break;
1228c2ecf20Sopenharmony_ci			}
1238c2ecf20Sopenharmony_ci
1248c2ecf20Sopenharmony_ci			partsect = be32_to_cpu(xrs->part[1].st) + extensect;
1258c2ecf20Sopenharmony_ci			put_dev_sector(sect2);
1268c2ecf20Sopenharmony_ci			if (++slot == state->limit) {
1278c2ecf20Sopenharmony_ci				printk( "\nMaximum number of partitions reached!\n" );
1288c2ecf20Sopenharmony_ci				break;
1298c2ecf20Sopenharmony_ci			}
1308c2ecf20Sopenharmony_ci		}
1318c2ecf20Sopenharmony_ci		strlcat(state->pp_buf, " >", PAGE_SIZE);
1328c2ecf20Sopenharmony_ci	}
1338c2ecf20Sopenharmony_ci#ifdef ICD_PARTS
1348c2ecf20Sopenharmony_ci	if ( part_fmt!=1 ) { /* no extended partitions -> test ICD-format */
1358c2ecf20Sopenharmony_ci		pi = &rs->icdpart[0];
1368c2ecf20Sopenharmony_ci		/* sanity check: no ICD format if first partition invalid */
1378c2ecf20Sopenharmony_ci		if (OK_id(pi->id)) {
1388c2ecf20Sopenharmony_ci			strlcat(state->pp_buf, " ICD<", PAGE_SIZE);
1398c2ecf20Sopenharmony_ci			for (; pi < &rs->icdpart[8] && slot < state->limit; slot++, pi++) {
1408c2ecf20Sopenharmony_ci				/* accept only GEM,BGM,RAW,LNX,SWP partitions */
1418c2ecf20Sopenharmony_ci				if (!((pi->flg & 1) && OK_id(pi->id)))
1428c2ecf20Sopenharmony_ci					continue;
1438c2ecf20Sopenharmony_ci				part_fmt = 2;
1448c2ecf20Sopenharmony_ci				put_partition (state, slot,
1458c2ecf20Sopenharmony_ci						be32_to_cpu(pi->st),
1468c2ecf20Sopenharmony_ci						be32_to_cpu(pi->siz));
1478c2ecf20Sopenharmony_ci			}
1488c2ecf20Sopenharmony_ci			strlcat(state->pp_buf, " >", PAGE_SIZE);
1498c2ecf20Sopenharmony_ci		}
1508c2ecf20Sopenharmony_ci	}
1518c2ecf20Sopenharmony_ci#endif
1528c2ecf20Sopenharmony_ci	put_dev_sector(sect);
1538c2ecf20Sopenharmony_ci
1548c2ecf20Sopenharmony_ci	strlcat(state->pp_buf, "\n", PAGE_SIZE);
1558c2ecf20Sopenharmony_ci
1568c2ecf20Sopenharmony_ci	return 1;
1578c2ecf20Sopenharmony_ci}
158