// SPDX-License-Identifier: GPL-2.0+
/*
 * (C) Copyright 2001
 * Denis Peter, MPL AG Switzerland, d.peter@mpl.ch.
 */

#include <common.h>
#include <blk.h>
#include <command.h>
#include <part.h>
#include <asm/cache.h>
#include <asm/unaligned.h>
#include "part_iso.h"

/* #define	ISO_PART_DEBUG */

#ifdef	ISO_PART_DEBUG
#define	PRINTF(fmt,args...)	printf (fmt ,##args)
#else
#define PRINTF(fmt,args...)
#endif

/* enable this if CDs are written with the PowerPC Platform ID */
#undef CHECK_FOR_POWERPC_PLATTFORM
#define CD_SECTSIZE 2048

static unsigned char tmpbuf[CD_SECTSIZE] __aligned(ARCH_DMA_MINALIGN);

unsigned long iso_dread(struct blk_desc *block_dev, lbaint_t start,
                        lbaint_t blkcnt, void *buffer)
{
	unsigned long ret;

	if (block_dev->blksz == 512) {
		/* Convert from 2048 to 512 sector size */
		start *= 4;
		blkcnt *= 4;
	}

	ret = blk_dread(block_dev, start, blkcnt, buffer);

	if (block_dev->blksz == 512)
		ret /= 4;

	return ret;
}

/* only boot records will be listed as valid partitions */
int part_get_info_iso_verb(struct blk_desc *desc, int part_num,
			   struct disk_partition *info, int verb)
{
	int i,offset,entry_num;
	unsigned short *chksumbuf;
	unsigned short chksum;
	unsigned long newblkaddr,blkaddr,lastsect,bootaddr;
	iso_boot_rec_t *pbr = (iso_boot_rec_t	*)tmpbuf; /* boot record */
	iso_pri_rec_t *ppr = (iso_pri_rec_t	*)tmpbuf;	/* primary desc */
	iso_val_entry_t *pve = (iso_val_entry_t *)tmpbuf;
	iso_init_def_entry_t *pide;

	if (desc->blksz != CD_SECTSIZE && desc->blksz != 512)
		return -1;

	/* the first sector (sector 0x10) must be a primary volume desc */
	blkaddr=PVD_OFFSET;
	if (iso_dread(desc, PVD_OFFSET, 1, (ulong *)tmpbuf) != 1)
		return -1;
	if(ppr->desctype!=0x01) {
		if(verb)
			printf ("** First descriptor is NOT a primary desc on %d:%d **\n",
				desc->devnum, part_num);
		return (-1);
	}
	if(strncmp((char *)ppr->stand_ident,"CD001",5)!=0) {
		if(verb)
			printf ("** Wrong ISO Ident: %s on %d:%d **\n",
				ppr->stand_ident, desc->devnum, part_num);
		return (-1);
	}
	lastsect = le32_to_cpu(ppr->firstsek_LEpathtab1_LE);
	/* assuming same block size for all entries */
	info->blksz = be16_to_cpu(ppr->secsize_BE);
	PRINTF(" Lastsect:%08lx\n",lastsect);
	for(i=blkaddr;i<lastsect;i++) {
		PRINTF("Reading block %d\n", i);
		if (iso_dread(desc, i, 1, (ulong *)tmpbuf) != 1)
			return -1;
		if(ppr->desctype==0x00)
			break; /* boot entry found */
		if(ppr->desctype==0xff) {
			if(verb)
				printf ("** No valid boot catalog found on %d:%d **\n",
					desc->devnum, part_num);
			return (-1);
		}
	}
	/* boot entry found */
	if(strncmp(pbr->ident_str,"EL TORITO SPECIFICATION",23)!=0) {
		if(verb)
			printf ("** Wrong El Torito ident: %s on %d:%d **\n",
				pbr->ident_str, desc->devnum, part_num);
		return (-1);
	}
	bootaddr = get_unaligned_le32(pbr->pointer);
	PRINTF(" Boot Entry at: %08lX\n",bootaddr);
	if (iso_dread(desc, bootaddr, 1, (ulong *)tmpbuf) != 1) {
		if(verb)
			printf ("** Can't read Boot Entry at %lX on %d:%d **\n",
				bootaddr, desc->devnum, part_num);
		return (-1);
	}
	chksum=0;
	chksumbuf = (unsigned short *)tmpbuf;
	for(i=0;i<0x10;i++)
		chksum += le16_to_cpu(chksumbuf[i]);
	if(chksum!=0) {
		if(verb)
			printf("** Checksum Error in booting catalog validation entry on %d:%d **\n",
			       desc->devnum, part_num);
		return (-1);
	}
	if((pve->key[0]!=0x55)||(pve->key[1]!=0xAA)) {
		if(verb)
			printf ("** Key 0x55 0xAA error on %d:%d **\n",
				desc->devnum, part_num);
		return(-1);
	}
#ifdef CHECK_FOR_POWERPC_PLATTFORM
	if(pve->platform!=0x01) {
		if(verb)
			printf ("** No PowerPC platform CD on %d:%d **\n",
				desc->devnum, part_num);
		return(-1);
	}
#endif
	/* the validation entry seems to be ok, now search the "partition" */
	entry_num=1;
	offset=0x20;
	strcpy((char *)info->type, "U-Boot");
	part_set_generic_name(desc, part_num, (char *)info->name);
	/* the bootcatalog (including validation Entry) is limited to 2048Bytes
	 * (63 boot entries + validation entry) */
	 while(offset<2048) {
		pide=(iso_init_def_entry_t *)&tmpbuf[offset];
		if ((pide->boot_ind==0x88) ||
		    (pide->boot_ind==0x00)) { /* Header Id for default Sections Entries */
			if(entry_num==part_num) { /* part found */
				goto found;
			}
			entry_num++; /* count partitions Entries (boot and non bootables */
			offset+=0x20;
			continue;
		}
		if ((pide->boot_ind==0x90) ||	/* Section Header Entry */
		    (pide->boot_ind==0x91) ||	/* Section Header Entry (last) */
		    (pide->boot_ind==0x44)) {	/* Extension Indicator */
			offset+=0x20; /* skip unused entries */
		}
		else {
			if(verb)
				printf ("** Partition %d not found on device %d **\n",
					part_num, desc->devnum);
			return(-1);
		}
	}
	/* if we reach this point entire sector has been
	 * searched w/o succsess */
	if(verb)
		printf ("** Partition %d not found on device %d **\n",
			part_num, desc->devnum);
	return(-1);
found:
	if(pide->boot_ind!=0x88) {
		if(verb)
			printf("** Partition %d is not bootable on device %d **\n",
			       part_num, desc->devnum);
		return (-1);
	}
	switch(pide->boot_media) {
		case 0x00: /* no emulation */
			info->size = get_unaligned_le16(pide->sec_cnt)>>2;
			break;
		case 0x01:	info->size=2400>>2; break; /* 1.2MByte Floppy */
		case 0x02:	info->size=2880>>2; break; /* 1.44MByte Floppy */
		case 0x03:	info->size=5760>>2; break; /* 2.88MByte Floppy */
		case 0x04:	info->size=2880>>2; break; /* dummy (HD Emulation) */
		default:	info->size=0; break;
	}
	newblkaddr = get_unaligned_le32(pide->rel_block_addr);
	info->start=newblkaddr;

	if (desc->blksz == 512) {
		info->size *= 4;
		info->start *= 4;
		info->blksz = 512;
	}

	PRINTF(" part %d found @ %lx size %lx\n",part_num,info->start,info->size);
	return 0;
}

static int part_get_info_iso(struct blk_desc *desc, int part_num,
			     struct disk_partition *info)
{
	return part_get_info_iso_verb(desc, part_num, info, 0);
}

static void part_print_iso(struct blk_desc *desc)
{
	struct disk_partition info;
	int i;

	if (part_get_info_iso_verb(desc, 1, &info, 0) == -1) {
		printf("** No boot partition found on device %d **\n",
		       desc->devnum);
		return;
	}
	printf("Part   Start     Sect x Size Type\n");
	i=1;
	do {
		printf(" %2d %8" LBAFlength "u %8" LBAFlength "u %6ld %.32s\n",
		       i, info.start, info.size, info.blksz, info.type);
		i++;
	} while (part_get_info_iso_verb(desc, i, &info, 0) != -1);
}

static int part_test_iso(struct blk_desc *desc)
{
	struct disk_partition info;

	return part_get_info_iso_verb(desc, 1, &info, 0);
}

U_BOOT_PART_TYPE(iso) = {
	.name		= "ISO",
	.part_type	= PART_TYPE_ISO,
	.max_entries	= ISO_ENTRY_NUMBERS,
	.get_info	= part_get_info_iso,
	.print		= part_print_iso,
	.test		= part_test_iso,
};
