/*
 * (C) Copyright 2000
 * Wolfgang Denk, DENX Software Engineering, wd@denx.de.
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*
 * Support for harddisk partitions.
 *
 * To be compatible with LinuxPPC and Apple we use the standard Apple
 * SCSI disk partitioning scheme. For more information see:
 * http://developer.apple.com/techpubs/mac/Devices/Devices-126.html#MARKER-14-92
 */

#include <common.h>
#include <command.h>
#include <ide.h>
#include "part_mac.h"

#ifdef HAVE_BLOCK_DEVICE

/* stdlib.h causes some compatibility problems; should fixe these! -- wd */
#ifndef __ldiv_t_defined
typedef struct {
	long int quot;		/* Quotient	*/
	long int rem;		/* Remainder	*/
} ldiv_t;
extern ldiv_t ldiv (long int __numer, long int __denom);
# define __ldiv_t_defined	1
#endif


static int part_mac_read_ddb (block_dev_desc_t *dev_desc, mac_driver_desc_t *ddb_p);
static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partition_t *pdb_p);

/*
 * Test for a valid MAC partition
 */
int test_part_mac (block_dev_desc_t *dev_desc)
{
	ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
	ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);
	ulong i, n;

	if (part_mac_read_ddb (dev_desc, ddesc)) {
		/* error reading Driver Desriptor Block, or no valid Signature */
		return (-1);
	}

	n = 1;	/* assuming at least one partition */
	for (i=1; i<=n; ++i) {
		if ((dev_desc->block_read(dev_desc->dev, i, 1, (ulong *)mpart) != 1) ||
		    (mpart->signature != MAC_PARTITION_MAGIC) ) {
			return (-1);
		}
		/* update partition count */
		n = mpart->map_count;
	}
	return (0);
}


void print_part_mac (block_dev_desc_t *dev_desc)
{
	ulong i, n;
	ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
	ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);
	ldiv_t mb, gb;

	if (part_mac_read_ddb (dev_desc, ddesc)) {
		/* error reading Driver Desriptor Block, or no valid Signature */
		return;
	}

	n  = ddesc->blk_count;

	mb = ldiv(n, ((1024 * 1024) / ddesc->blk_size)); /* MB */
	/* round to 1 digit */
	mb.rem *= 10 * ddesc->blk_size;
	mb.rem += 512 * 1024;
	mb.rem /= 1024 * 1024;

	gb = ldiv(10 * mb.quot + mb.rem, 10240);
	gb.rem += 512;
	gb.rem /= 1024;


	printf ("Block Size=%d, Number of Blocks=%d, "
		"Total Capacity: %ld.%ld MB = %ld.%ld GB\n"
		"DeviceType=0x%x, DeviceId=0x%x\n\n"
		"   #:                 type name"
		"                   length   base       (size)\n",
		ddesc->blk_size,
		ddesc->blk_count,
		mb.quot, mb.rem, gb.quot, gb.rem,
		ddesc->dev_type, ddesc->dev_id
		);

	n = 1;	/* assuming at least one partition */
	for (i=1; i<=n; ++i) {
		ulong bytes;
		char c;

		printf ("%4ld: ", i);
		if (dev_desc->block_read (dev_desc->dev, i, 1, (ulong *)mpart) != 1) {
			printf ("** Can't read Partition Map on %d:%ld **\n",
				dev_desc->dev, i);
			return;
		}

		if (mpart->signature != MAC_PARTITION_MAGIC) {
			printf ("** Bad Signature on %d:%ld - "
				"expected 0x%04x, got 0x%04x\n",
				dev_desc->dev, i, MAC_PARTITION_MAGIC, mpart->signature);
			return;
		}

		/* update partition count */
		n = mpart->map_count;

		c      = 'k';
		bytes  = mpart->block_count;
		bytes /= (1024 / ddesc->blk_size);  /* kB; assumes blk_size == 512 */
		if (bytes >= 1024) {
			bytes >>= 10;
			c = 'M';
		}
		if (bytes >= 1024) {
			bytes >>= 10;
			c = 'G';
		}

		printf ("%20.32s %-18.32s %10u @ %-10u (%3ld%c)\n",
			mpart->type,
			mpart->name,
			mpart->block_count,
			mpart->start_block,
			bytes, c
			);
	}

	return;
}


/*
 * Read Device Descriptor Block
 */
static int part_mac_read_ddb (block_dev_desc_t *dev_desc, mac_driver_desc_t *ddb_p)
{
	if (dev_desc->block_read(dev_desc->dev, 0, 1, (ulong *)ddb_p) != 1) {
		printf ("** Can't read Driver Desriptor Block **\n");
		return (-1);
	}

	if (ddb_p->signature != MAC_DRIVER_MAGIC) {
#if 0
		printf ("** Bad Signature: expected 0x%04x, got 0x%04x\n",
			MAC_DRIVER_MAGIC, ddb_p->signature);
#endif
		return (-1);
	}
	return (0);
}

/*
 * Read Partition Descriptor Block
 */
static int part_mac_read_pdb (block_dev_desc_t *dev_desc, int part, mac_partition_t *pdb_p)
{
	int n = 1;

	for (;;) {
		/*
		 * We must always read the descritpor block for
		 * partition 1 first since this is the only way to
		 * know how many partitions we have.
		 */
		if (dev_desc->block_read (dev_desc->dev, n, 1, (ulong *)pdb_p) != 1) {
			printf ("** Can't read Partition Map on %d:%d **\n",
				dev_desc->dev, n);
			return (-1);
		}

		if (pdb_p->signature != MAC_PARTITION_MAGIC) {
			printf ("** Bad Signature on %d:%d: "
				"expected 0x%04x, got 0x%04x\n",
				dev_desc->dev, n, MAC_PARTITION_MAGIC, pdb_p->signature);
			return (-1);
		}

		if (n == part)
			return (0);

		if ((part < 1) || (part > pdb_p->map_count)) {
			printf ("** Invalid partition %d:%d [%d:1...%d:%d only]\n",
				dev_desc->dev, part,
				dev_desc->dev,
				dev_desc->dev, pdb_p->map_count);
			return (-1);
		}

		/* update partition count */
		n = part;
	}

	/* NOTREACHED */
}

int get_partition_info_mac (block_dev_desc_t *dev_desc, int part, disk_partition_t *info)
{
	ALLOC_CACHE_ALIGN_BUFFER(mac_driver_desc_t, ddesc, 1);
	ALLOC_CACHE_ALIGN_BUFFER(mac_partition_t, mpart, 1);

	if (part_mac_read_ddb (dev_desc, ddesc)) {
		return (-1);
	}

	info->blksz = ddesc->blk_size;

	if (part_mac_read_pdb (dev_desc, part, mpart)) {
		return (-1);
	}

	info->start = mpart->start_block;
	info->size  = mpart->block_count;
	memcpy (info->type, mpart->type, sizeof(info->type));
	memcpy (info->name, mpart->name, sizeof(info->name));

	return (0);
}

#endif
