/*
 * 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);
		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_fsload(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[],
		int fstype)
{
	unsigned long addr;
	const char *addr_str;
	const char *filename;
	unsigned long bytes;
	unsigned long pos;
	int len_read;
	char buf[12];

	if (argc < 5)
		return CMD_RET_USAGE;

	if (fs_set_blk_dev(argv[1], argv[2], fstype))
		return 1;

	if (argc >= 4) {
		addr = simple_strtoul(argv[3], NULL, 0);
	} 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, 0);
	else
		bytes = 0;
	if (argc >= 7)
		pos = simple_strtoul(argv[6], NULL, 0);
	else
		pos = 0;

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

	printf("%d bytes read\n", len_read);

	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 (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;
}
