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

/*
 * 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 <command.h>
#include <log.h>
#include <memalign.h>
#include "part_mac.h"
#include <part.h>

/* 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(struct blk_desc *desc, mac_driver_desc_t *ddb_p);
static int part_mac_read_pdb(struct blk_desc *desc, int part,
			     mac_partition_t *pdb_p);

/*
 * Test for a valid MAC partition
 */
static int part_test_mac(struct blk_desc *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(desc, ddesc)) {
		/*
		 * error reading Driver Descriptor Block,
		 * or no valid Signature
		 */
		return (-1);
	}

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

static void part_print_mac(struct blk_desc *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(desc, ddesc)) {
		/*
		 * error reading Driver Descriptor 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 (blk_dread(desc, i, 1, (ulong *)mpart) != 1) {
			printf ("** Can't read Partition Map on %d:%ld **\n",
				desc->devnum, i);
			return;
		}

		if (mpart->signature != MAC_PARTITION_MAGIC) {
			printf("** Bad Signature on %d:%ld - expected 0x%04x, got 0x%04x\n",
			       desc->devnum, 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(struct blk_desc *desc, mac_driver_desc_t *ddb_p)
{
	if (blk_dread(desc, 0, 1, (ulong *)ddb_p) != 1) {
		debug("** Can't read Driver Descriptor Block **\n");
		return (-1);
	}

	if (ddb_p->signature != MAC_DRIVER_MAGIC) {
		return (-1);
	}
	return (0);
}

/*
 * Read Partition Descriptor Block
 */
static int part_mac_read_pdb(struct blk_desc *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 (blk_dread(desc, n, 1, (ulong *)pdb_p) != 1) {
			printf("** Can't read Partition Map on %d:%d **\n",
			       desc->devnum, n);
			return (-1);
		}

		if (pdb_p->signature != MAC_PARTITION_MAGIC) {
			printf("** Bad Signature on %d:%d: expected 0x%04x, got 0x%04x\n",
			       desc->devnum, 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",
			       desc->devnum, part, desc->devnum, desc->devnum,
			       pdb_p->map_count);
			return (-1);
		}

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

	/* NOTREACHED */
}

static int part_get_info_mac(struct blk_desc *desc, int part,
			     struct disk_partition *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(desc, ddesc))
		return -1;

	info->blksz = ddesc->blk_size;

	if (part_mac_read_pdb(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);
}

U_BOOT_PART_TYPE(mac) = {
	.name		= "MAC",
	.part_type	= PART_TYPE_MAC,
	.max_entries	= MAC_ENTRY_NUMBERS,
	.get_info	= part_get_info_mac,
	.print		= part_print_mac,
	.test		= part_test_mac,
};
