/*
 * atari partitions parsing code
 *
 * Copyright (C) 2018 Vaclav Dolezal <vdolezal@redhat.com>
 *
 * This file may be redistributed under the terms of the
 * GNU Lesser General Public License.
 *
 * Based on Linux kernel implementation and atari-fdisk
 */

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <stdint.h>

#include "partitions.h"

struct atari_part_def {
	/*
	 * flags:
	 * 0 (LSB): active
	 * 1-6:     (reserved)
	 * 7 (MSB): bootable
	 */
	unsigned char flags;
	char id[3];
	uint32_t start;
	uint32_t size;
} __attribute__((packed));

struct atari_rootsector {
	char unused0[0x156]; /* boot code */
	struct atari_part_def icd_part[8]; /* ICD partition entries */
	char unused1[0xc];
	uint32_t hd_size;
	struct atari_part_def part[4]; /* primary partition entries */
	uint32_t bsl_start; /* bad sector list start */
	uint32_t bsl_len; /* bad sector list length */
	uint16_t checksum;
} __attribute__((packed));


/*
 * Generated using linux kernel ctype.{c,h}
 *
 * Since kernel uses isalnum() to detect whether it is Atari PT, we need same
 * definition of alnum character to be consistent with kernel.
 */
static const unsigned char _linux_isalnum[] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
1,1,1,1,1,1,1,0,1,1,1,1,1,1,1,1
};

static int linux_isalnum(unsigned char c) {
	return _linux_isalnum[c];
}

#define isalnum linux_isalnum

#define IS_ACTIVE(partdef) ((partdef).flags & 1)

#define IS_PARTDEF_VALID(partdef, hdsize) \
	( \
		(partdef).flags & 1 && \
		isalnum((partdef).id[0]) && \
		isalnum((partdef).id[1]) && \
		isalnum((partdef).id[2]) && \
		be32_to_cpu((partdef).start) <= (hdsize) && \
		be32_to_cpu((partdef).start) + \
			be32_to_cpu((partdef).size) <= (hdsize) \
	)

static int is_id_common(char *id)
{
	const char *ids[] = {"GEM", "BGM", "LNX", "SWP", "RAW", };
	unsigned i;

	for (i = 0; i < ARRAY_SIZE(ids); i++) {
		if (!memcmp(ids[i], id, 3))
			return 1;
	}
	return 0;
}

static int parse_partition(blkid_partlist ls, blkid_parttable tab,
	struct atari_part_def *part, uint32_t offset)
{
	blkid_partition par;
	uint32_t start;
	uint32_t size;

	start = be32_to_cpu(part->start) + offset;
	size = be32_to_cpu(part->size);

	if (blkid_partlist_get_partition_by_start(ls, start)) {
		/* Don't increment partno for extended parts */
		if (!offset)
			blkid_partlist_increment_partno(ls);
		return 0;
	}

	par = blkid_partlist_add_partition(ls, tab, start, size);
	if (!par)
		return -ENOMEM;

	blkid_partition_set_type_string(par, (unsigned char *) part->id,
					sizeof(part->id));
	return 1;
}

/*
 * \return 1: OK, 0: bad format or -errno
 */
static int parse_extended(blkid_probe pr, blkid_partlist ls,
	blkid_parttable tab, struct atari_part_def *part)
{
	uint32_t x0start, xstart;
	unsigned i = 0;
	int rc;

	x0start = xstart = be32_to_cpu(part->start);
	while (1) {
		struct atari_rootsector *xrs;
		xrs = (struct atari_rootsector *) blkid_probe_get_sector(pr, xstart);
		if (!xrs) {
			if (errno)
				return -errno;
			return 0;
		}

		/*
		 * There must be data partition followed by reference to next
		 * XGM or inactive entry.
		 */
		for (i=0; ; i++) {
			if (i >= ARRAY_SIZE(xrs->part) - 1)
				return 0;
			if (IS_ACTIVE(xrs->part[i]))
				break;
		}

		if (!memcmp(xrs->part[i].id, "XGM", 3))
			return 0;

		rc = parse_partition(ls, tab, &xrs->part[i], xstart);
		if (rc <= 0)
			return rc;

		if (!IS_ACTIVE(xrs->part[i+1]))
			break;

		if (memcmp(xrs->part[i+1].id, "XGM", 3))
			return 0;

		xstart = x0start + be32_to_cpu(xrs->part[i+1].start);
	}

	return 1;
}

static int probe_atari_pt(blkid_probe pr,
		const struct blkid_idmag *mag __attribute__((__unused__)))
{
	struct atari_rootsector *rs;

	blkid_parttable tab = NULL;
	blkid_partlist ls;

	unsigned i;
	int has_xgm = 0;
	int rc = 0;
	off_t hdsize;

	/* Atari partition is not defined for other sector sizes */
	if (blkid_probe_get_sectorsize(pr) != 512)
		goto nothing;

	rs = (struct atari_rootsector *) blkid_probe_get_sector(pr, 0);
	if (!rs) {
		if (errno)
			return -errno;
		goto nothing;
	}

	hdsize = blkid_probe_get_size(pr) / 512;

	/* Look for validly looking primary partition */
	for (i = 0; ; i++) {
		if (i >= ARRAY_SIZE(rs->part))
			goto nothing;

		if (IS_PARTDEF_VALID(rs->part[i], hdsize)) {
			blkid_probe_set_magic(pr,
				offsetof(struct atari_rootsector, part[i]),
				sizeof(rs->part[i].flags) + sizeof(rs->part[i].id),
				(unsigned char *) &rs->part[i]);
			break;
		}
	}

	if (blkid_partitions_need_typeonly(pr))
		/* caller does not ask for details about partitions */
		return BLKID_PROBE_OK;

	ls = blkid_probe_get_partlist(pr);
	if (!ls)
		goto nothing;

	tab = blkid_partlist_new_parttable(ls, "atari", 0);
	if (!tab)
		goto err;

	for (i = 0; i < ARRAY_SIZE(rs->part); i++) {
		struct atari_part_def *p = &rs->part[i];

		if (!IS_ACTIVE(*p)) {
			blkid_partlist_increment_partno(ls);
			continue;
		}

		if (!memcmp(p->id, "XGM", 3)) {
			has_xgm = 1;
			rc = parse_extended(pr, ls, tab, p);
		} else {
			rc = parse_partition(ls, tab, p, 0);
		}
		if (rc < 0)
			return rc;
	}

	/* if there are no XGM partitions, we can try ICD format */
	/* if first ICD partition ID is not valid, assume no ICD format */
	if (!has_xgm && is_id_common(rs->icd_part[0].id)) {
		for (i = 0; i < ARRAY_SIZE(rs->icd_part); i++) {
			struct atari_part_def *p = &rs->icd_part[i];

			if (!IS_ACTIVE(*p) || !is_id_common(p->id)) {
				blkid_partlist_increment_partno(ls);
				continue;
			}

			rc = parse_partition(ls, tab, p, 0);
			if (rc < 0)
				return rc;
		}
	}

	return BLKID_PROBE_OK;

nothing:
	return BLKID_PROBE_NONE;
err:
	return -ENOMEM;
}

const struct blkid_idinfo atari_pt_idinfo =
{
	.name		= "atari",
	.probefunc	= probe_atari_pt,
	.magics		= BLKID_NONE_MAGIC
};
