/*
 * (C) Copyright 2011 - 2012 Samsung Electronics
 * EXT4 filesystem implementation in Uboot by
 * Uma Shankar <uma.shankar@samsung.com>
 * Manjunatha C Achar <a.manjunatha@samsung.com>
 *
 * made from existing ext2/dev.c file of Uboot
 * (C) Copyright 2004
 * esd gmbh <www.esd-electronics.com>
 * Reinhard Arlt <reinhard.arlt@esd-electronics.com>
 *
 * based on code of fs/reiserfs/dev.c by
 *
 * (C) Copyright 2003 - 2004
 * Sysgo AG, <www.elinos.com>, Pavel Bartusek <pba@sysgo.com>
 *
 * SPDX-License-Identifier:	GPL-2.0+
 */

/*
 * Changelog:
 *	0.1 - Newly created file for ext4fs support. Taken from
 *		fs/ext2/dev.c file in uboot.
 */

#include "com_type_local.h"
#include "ext4_typedefs.h"
#include "ext4fs.h"
#include "ext_common.h"
#include "ext4_common.h"

#include "ext4_pt_info.h"

#include "flash_adaptor.h"

#include "lgpl_printf.h"

lbaint_t part_offset;

static struct ext4_pt_info pt_info;

#define EMMC_BLOCK_SIZE (512)

#define min(a, b) (((a) < (b)) ? (a) : (b))

struct ext4_pt_info * get_ext4_pt_info()
{
	return &pt_info;
}

void ext4fs_set_pt(unsigned int start, unsigned int size)
{
	pt_info.start= (lbaint_t)start;  //# of first block in partition
	pt_info.size = (lbaint_t)size;  //number of blocks in partition
}

void ext4fs_set_blk_dev()
{
	pt_info.blksz = EMMC_BLOCK_SIZE;
	pt_info.log2blksz = 9;
}

int ext4fs_devread(lbaint_t sector, int byte_offset, int byte_len, char *buf)
{
	unsigned block_len;
	int log2blksz = pt_info.log2blksz;

	char t_buf[EMMC_BLOCK_SIZE + 63];
	char * sec_buf = (char *)(((unsigned long int)t_buf + 63)& (~0x3F));

	debug("%d, %d, %d, %x, %x\n", sector, byte_offset, byte_len, t_buf, sec_buf);

	/* Check partition boundaries */
	if ((sector + ((byte_offset + byte_len - 1) >> log2blksz))
	     >= pt_info.size) {
		printf("%s read outside partition %llu\n", __func__,
		       sector);
		return 0;
	}

	/* Get the read to the beginning of a partition */
	sector += byte_offset >> log2blksz;
	byte_offset &= pt_info.blksz - 1;

	debug(" <%llu, %d, %d>\n", sector, byte_offset, byte_len);

	if (byte_offset != 0) {
		int readlen;
		/* read first part which isn't aligned with start of sector */
		if (read_flash((pt_info.start + sector) * pt_info.blksz , pt_info.blksz,
			      (unsigned char *)sec_buf) != 0) {
			printf(" ** ext2fs_devread() read error **\n");
			return 0;
		}
		readlen = min((int)pt_info.blksz - byte_offset,
			      byte_len);
		memcpy(buf, sec_buf + byte_offset, readlen);
		buf += readlen;
		byte_len -= readlen;
		sector++;
	}

	if (byte_len == 0)
		return 1;

	/* read sector aligned part */
	block_len = byte_len & ~(pt_info.blksz - 1);

	if (block_len == 0) {

		block_len = pt_info.blksz;
		read_flash((pt_info.start + sector) * pt_info.blksz, pt_info.blksz,
			  (unsigned char *)sec_buf);
		memcpy(buf, sec_buf, byte_len);
		return 1;
	}

	// considering the alignment of the address buf',
	// we continue to use sec_buf and read one blk each time
	do {
		if (read_flash((pt_info.start + sector) * pt_info.blksz,
			      pt_info.blksz, (unsigned char *)sec_buf) != 0) {
			printf(" ** %s read error - block\n", __func__);
			return 0;
		}
		memcpy(buf, sec_buf, pt_info.blksz);
		buf += pt_info.blksz;
		byte_len -= pt_info.blksz;
		sector ++;
		block_len -= pt_info.blksz;
	}while(block_len);

	if (byte_len != 0) {
		/* read rest of data which are not in whole sector */
		if (read_flash((pt_info.start + sector) * pt_info.blksz, pt_info.blksz,
			      (unsigned char *)sec_buf) != 0) {
			printf("* %s read error - last part\n", __func__);
			return 0;
		}
		memcpy(buf, sec_buf, byte_len);
	}

	return 1;
}

int ext4_read_superblock(char *buffer)
{
	int sect = SUPERBLOCK_START >> pt_info.log2blksz;
	int off = SUPERBLOCK_START % pt_info.blksz;

	return ext4fs_devread(sect, off, SUPERBLOCK_SIZE,
				buffer);
}
