// SPDX-License-Identifier: GPL-2.0
/*
 *  fs/partitions/amiga.c
 *
 *  Code extracted from drivers/block/genhd.c
 *
 *  Copyright (C) 1991-1998  Linus Torvalds
 *  Re-organised Feb 1998 Russell King
 */

#define pr_fmt(fmt) fmt

#include <linux/types.h>
#include <linux/mm_types.h>
#include <linux/overflow.h>
#include <linux/affs_hardblocks.h>

#include "check.h"
#include "amiga.h"

/* magic offsets in partition DosEnvVec */
#define NR_HD	3
#define NR_SECT	5
#define LO_CYL	9
#define HI_CYL	10

static __inline__ u32
checksum_block(__be32 *m, int size)
{
	u32 sum = 0;

	while (size--)
		sum += be32_to_cpu(*m++);
	return sum;
}

int amiga_partition(struct parsed_partitions *state)
{
	Sector sect;
	unsigned char *data;
	struct RigidDiskBlock *rdb;
	struct PartitionBlock *pb;
	u64 start_sect, nr_sects;
	sector_t blk, end_sect;
	u32 cylblk;		/* rdb_CylBlocks = nr_heads*sect_per_track */
	u32 nr_hd, nr_sect, lo_cyl, hi_cyl;
	int part, res = 0;
	unsigned int blksize = 1;	/* Multiplier for disk block size */
	int slot = 1;
	char b[BDEVNAME_SIZE];

	for (blk = 0; ; blk++, put_dev_sector(sect)) {
		if (blk == RDB_ALLOCATION_LIMIT)
			goto rdb_done;
		data = read_part_sector(state, blk, &sect);
		if (!data) {
			if (warn_no_part)
				pr_err("Dev %s: unable to read RDB block %llu\n",
				       bdevname(state->bdev, b), blk);
			res = -1;
			goto rdb_done;
		}
		if (*(__be32 *)data != cpu_to_be32(IDNAME_RIGIDDISK))
			continue;

		rdb = (struct RigidDiskBlock *)data;
		if (checksum_block((__be32 *)data, be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F) == 0)
			break;
		/* Try again with 0xdc..0xdf zeroed, Windows might have
		 * trashed it.
		 */
		*(__be32 *)(data+0xdc) = 0;
		if (checksum_block((__be32 *)data,
				be32_to_cpu(rdb->rdb_SummedLongs) & 0x7F)==0) {
			pr_err("Trashed word at 0xd0 in block %llu ignored in checksum calculation\n",
			       blk);
			break;
		}

		pr_err("Dev %s: RDB in block %llu has bad checksum\n",
		       bdevname(state->bdev, b), blk);
	}

	/* blksize is blocks per 512 byte standard block */
	blksize = be32_to_cpu( rdb->rdb_BlockBytes ) / 512;

	{
		char tmp[7 + 10 + 1 + 1];

		/* Be more informative */
		snprintf(tmp, sizeof(tmp), " RDSK (%d)", blksize * 512);
		strlcat(state->pp_buf, tmp, PAGE_SIZE);
	}
	blk = be32_to_cpu(rdb->rdb_PartitionList);
	put_dev_sector(sect);
	for (part = 1; (s32) blk>0 && part<=16; part++, put_dev_sector(sect)) {
		/* Read in terms partition table understands */
		if (check_mul_overflow(blk, (sector_t) blksize, &blk)) {
			pr_err("Dev %s: overflow calculating partition block %llu! Skipping partitions %u and beyond\n",
				bdevname(state->bdev, b), blk, part);
			break;
		}
		data = read_part_sector(state, blk, &sect);
		if (!data) {
			if (warn_no_part)
				pr_err("Dev %s: unable to read partition block %llu\n",
				       bdevname(state->bdev, b), blk);
			res = -1;
			goto rdb_done;
		}
		pb  = (struct PartitionBlock *)data;
		blk = be32_to_cpu(pb->pb_Next);
		if (pb->pb_ID != cpu_to_be32(IDNAME_PARTITION))
			continue;
		if (checksum_block((__be32 *)pb, be32_to_cpu(pb->pb_SummedLongs) & 0x7F) != 0 )
			continue;

		/* RDB gives us more than enough rope to hang ourselves with,
		 * many times over (2^128 bytes if all fields max out).
		 * Some careful checks are in order, so check for potential
		 * overflows.
		 * We are multiplying four 32 bit numbers to one sector_t!
		 */

		nr_hd   = be32_to_cpu(pb->pb_Environment[NR_HD]);
		nr_sect = be32_to_cpu(pb->pb_Environment[NR_SECT]);

		/* CylBlocks is total number of blocks per cylinder */
		if (check_mul_overflow(nr_hd, nr_sect, &cylblk)) {
			pr_err("Dev %s: heads*sects %u overflows u32, skipping partition!\n",
				bdevname(state->bdev, b), cylblk);
			continue;
		}

		/* check for consistency with RDB defined CylBlocks */
		if (cylblk > be32_to_cpu(rdb->rdb_CylBlocks)) {
			pr_warn("Dev %s: cylblk %u > rdb_CylBlocks %u!\n",
				bdevname(state->bdev, b), cylblk,
				be32_to_cpu(rdb->rdb_CylBlocks));
		}

		/* RDB allows for variable logical block size -
		 * normalize to 512 byte blocks and check result.
		 */

		if (check_mul_overflow(cylblk, blksize, &cylblk)) {
			pr_err("Dev %s: partition %u bytes per cyl. overflows u32, skipping partition!\n",
				bdevname(state->bdev, b), part);
			continue;
		}

		/* Calculate partition start and end. Limit of 32 bit on cylblk
		 * guarantees no overflow occurs if LBD support is enabled.
		 */

		lo_cyl = be32_to_cpu(pb->pb_Environment[LO_CYL]);
		start_sect = ((u64) lo_cyl * cylblk);

		hi_cyl = be32_to_cpu(pb->pb_Environment[HI_CYL]);
		nr_sects = (((u64) hi_cyl - lo_cyl + 1) * cylblk);

		if (!nr_sects)
			continue;

		/* Warn user if partition end overflows u32 (AmigaDOS limit) */

		if ((start_sect + nr_sects) > UINT_MAX) {
			pr_warn("Dev %s: partition %u (%llu-%llu) needs 64 bit device support!\n",
				bdevname(state->bdev, b), part,
				start_sect, start_sect + nr_sects);
		}

		if (check_add_overflow(start_sect, nr_sects, &end_sect)) {
			pr_err("Dev %s: partition %u (%llu-%llu) needs LBD device support, skipping partition!\n",
				bdevname(state->bdev, b), part,
				start_sect, end_sect);
			continue;
		}

		/* Tell Kernel about it */

		put_partition(state,slot++,start_sect,nr_sects);
		{
			/* Be even more informative to aid mounting */
			char dostype[4];
			char tmp[42];

			__be32 *dt = (__be32 *)dostype;
			*dt = pb->pb_Environment[16];
			if (dostype[3] < ' ')
				snprintf(tmp, sizeof(tmp), " (%c%c%c^%c)",
					dostype[0], dostype[1],
					dostype[2], dostype[3] + '@' );
			else
				snprintf(tmp, sizeof(tmp), " (%c%c%c%c)",
					dostype[0], dostype[1],
					dostype[2], dostype[3]);
			strlcat(state->pp_buf, tmp, PAGE_SIZE);
			snprintf(tmp, sizeof(tmp), "(res %d spb %d)",
				be32_to_cpu(pb->pb_Environment[6]),
				be32_to_cpu(pb->pb_Environment[4]));
			strlcat(state->pp_buf, tmp, PAGE_SIZE);
		}
		res = 1;
	}
	strlcat(state->pp_buf, "\n", PAGE_SIZE);

rdb_done:
	return res;
}
