/*
 * Copyright (c) 2012, NVIDIA CORPORATION.  All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms and conditions of the GNU General Public License,
 * version 2, as published by the Free Software Foundation.
 *
 * This program is distributed in the hope it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <config.h>
#include <common.h>
#include <part.h>
#include <ext4fs.h>
#include <fat.h>
#include <fs.h>

DECLARE_GLOBAL_DATA_PTR;

static block_dev_desc_t *fs_dev_desc;
static disk_partition_t fs_partition;
static int fs_type = FS_TYPE_ANY;

static inline int fs_ls_unsupported(const char *dirname)
{
	printf("** Unrecognized filesystem type **\n");
	return -1;
}

static inline int fs_read_unsupported(const char *filename, ulong addr,
				      int offset, int len)
{
	printf("** Unrecognized filesystem type **\n");
	return -1;
}

#ifdef CONFIG_FS_FAT
static int fs_probe_fat(void)
{
	return fat_set_blk_dev(fs_dev_desc, &fs_partition);
}

static void fs_close_fat(void)
{
}

#define fs_ls_fat file_fat_ls

static int fs_read_fat(const char *filename, ulong addr, int offset, int len)
{
	int len_read;

	len_read = file_fat_read_at(filename, offset,
				    (unsigned char *)addr, len);
	if (len_read == -1) {
		printf("** Unable to read file %s **\n", filename);
		return -1;
	}

	return len_read;
}
#else
static inline int fs_probe_fat(void)
{
	return -1;
}

static inline void fs_close_fat(void)
{
}

#define fs_ls_fat fs_ls_unsupported
#define fs_read_fat fs_read_unsupported
#endif

#ifdef CONFIG_FS_EXT4
static int fs_probe_ext(void)
{
	ext4fs_set_blk_dev(fs_dev_desc, &fs_partition);

	if (!ext4fs_mount(fs_partition.size)) {
		ext4fs_close();
		return -1;
	}

	return 0;
}

static void fs_close_ext(void)
{
	ext4fs_close();
}

#define fs_ls_ext ext4fs_ls

static int fs_read_ext(const char *filename, ulong addr, int offset, int len)
{
	int file_len;
	int len_read;

	if (offset != 0) {
		printf("** Cannot support non-zero offset **\n");
		return -1;
	}

	file_len = ext4fs_open(filename);
	if (file_len < 0) {
		printf("** File not found %s **\n", filename);
		ext4fs_close();
		return -1;
	}

	if (len == 0)
		len = file_len;

	len_read = ext4fs_read((char *)addr, len);
	ext4fs_close();

	if (len_read != len) {
		printf("** Unable to read file %s **\n", filename);
		return -1;
	}

	return len_read;
}
#else
static inline int fs_probe_ext(void)
{
	return -1;
}

static inline void fs_close_ext(void)
{
}

#define fs_ls_ext fs_ls_unsupported
#define fs_read_ext fs_read_unsupported
#endif

static struct {
	int fstype;
	int (*probe)(void);
} fstypes[] = {
	{
		.fstype = FS_TYPE_FAT,
		.probe = fs_probe_fat,
	},
	{
		.fstype = FS_TYPE_EXT,
		.probe = fs_probe_ext,
	},
};

int fs_set_blk_dev(const char *ifname, const char *dev_part_str, int fstype)
{
	int part, i;
#ifdef CONFIG_NEEDS_MANUAL_RELOC
	static int relocated;

	if (!relocated) {
		for (i = 0; i < ARRAY_SIZE(fstypes); i++)
			fstypes[i].probe += gd->reloc_off;
		relocated = 1;
	}
#endif

	part = get_device_and_partition(ifname, dev_part_str, &fs_dev_desc,
					&fs_partition, 1);
	if (part < 0)
		return -1;

	for (i = 0; i < ARRAY_SIZE(fstypes); i++) {
		if ((fstype != FS_TYPE_ANY) && (fstype != fstypes[i].fstype))
			continue;

		if (!fstypes[i].probe()) {
			fs_type = fstypes[i].fstype;
			return 0;
		}
	}

	printf("** Unrecognized filesystem type **\n");
	return -1;
}

static void fs_close(void)
{
	switch (fs_type) {
	case FS_TYPE_FAT:
		fs_close_fat();
		break;
	case FS_TYPE_EXT:
		fs_close_ext();
		break;
	default:
		break;
	}

	fs_type = FS_TYPE_ANY;
}

int fs_ls(const char *dirname)
{
	int ret;

	switch (fs_type) {
	case FS_TYPE_FAT:
		ret = fs_ls_fat(dirname);
		break;
	case FS_TYPE_EXT:
		ret = fs_ls_ext(dirname, NULL, 0);
		break;
	default:
		ret = fs_ls_unsupported(dirname);
		break;
	}

	fs_close();

	return ret;
}

int fs_read(const char *filename, ulong addr, int offset, int len)
{
	int ret;

	switch (fs_type) {
	case FS_TYPE_FAT:
		ret = fs_read_fat(filename, addr, offset, len);
		break;
	case FS_TYPE_EXT:
		ret = fs_read_ext(filename, addr, offset, len);
		break;
	default:
		ret = fs_read_unsupported(filename, addr, offset, len);
		break;
	}

	fs_close();

	return ret;
}

int do_load(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
		int fstype, int cmdline_base)
{
	unsigned long addr;
	const char *addr_str;
	const char *filename;
	unsigned long bytes;
	unsigned long pos;
	int len_read;
	char buf[12];
	unsigned long time;

	if (argc < 2)
		return CMD_RET_USAGE;
	if (argc > 7)
		return CMD_RET_USAGE;

	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
		return 1;

	if (argc >= 4) {
		addr = simple_strtoul(argv[3], NULL, cmdline_base);
	} else {
		addr_str = getenv("loadaddr");
		if (addr_str != NULL)
			addr = simple_strtoul(addr_str, NULL, 16);
		else
			addr = CONFIG_SYS_LOAD_ADDR;
	}
	if (argc >= 5) {
		filename = argv[4];
	} else {
		filename = getenv("bootfile");
		if (!filename) {
			puts("** No boot file defined **\n");
			return 1;
		}
	}
	if (argc >= 6)
		bytes = simple_strtoul(argv[5], NULL, cmdline_base);
	else
		bytes = 0;
	if (argc >= 7)
		pos = simple_strtoul(argv[6], NULL, cmdline_base);
	else
		pos = 0;

	time = get_timer(0);
	len_read = fs_read(filename, addr, pos, bytes);
	time = get_timer(time);
	if (len_read <= 0)
		return 1;

	printf("%d bytes read in %lu ms", len_read, time);
	if (time > 0) {
		puts(" (");
		print_size(len_read / time * 1000, "/s");
		puts(")");
	}
	puts("\n");

	sprintf(buf, "0x%x", len_read);
	setenv("filesize", buf);

	return 0;
}

int do_ls(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
	int fstype)
{
	if (argc < 2)
		return CMD_RET_USAGE;
	if (argc > 4)
		return CMD_RET_USAGE;

	if (fs_set_blk_dev(argv[1], (argc >= 3) ? argv[2] : NULL, fstype))
		return 1;

	if (fs_ls(argc >= 4 ? argv[3] : "/"))
		return 1;

	return 0;
}
