/*
 * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
 *
 * Copyright (C) 2002-2007 Aleph One Ltd.
 *   for Toby Churchill Ltd and Brightstar Engineering
 *
 * Created by Charles Manning <charles@aleph1.co.uk>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

/*
 * yaffscfg.c  The configuration for the "direct" use of yaffs.
 *
 * This is set up for u-boot.
 *
 * This version now uses the ydevconfig mechanism to set up partitions.
 */

#include <div64.h>
#include <malloc.h>
#include <linux/printk.h>

#include <config.h>
#include "nand.h"
#include "yaffscfg.h"
#include "yaffsfs.h"
#include "yaffs_packedtags2.h"
#include "yaffs_mtdif.h"
#include "yaffs_mtdif2.h"
#if 0
#include <errno.h>
#else
#include "malloc.h"
#endif
#include <linux/mtd/rawnand.h>

unsigned yaffs_trace_mask = 0x0; /* Disable logging */
static int yaffs_errno;


void yaffs_bug_fn(const char *fn, int n)
{
	printf("yaffs bug at %s:%d\n", fn, n);
}

void *yaffsfs_malloc(size_t x)
{
	return malloc(x);
}

void yaffsfs_free(void *x)
{
	free(x);
}

void yaffsfs_SetError(int err)
{
	yaffs_errno = err;
}

int yaffsfs_GetLastError(void)
{
	return yaffs_errno;
}


int yaffsfs_GetError(void)
{
	return yaffs_errno;
}

void yaffsfs_Lock(void)
{
}

void yaffsfs_Unlock(void)
{
}

__u32 yaffsfs_CurrentTime(void)
{
	return 0;
}

void *yaffs_malloc(size_t size)
{
	return malloc(size);
}

void yaffs_free(void *ptr)
{
	free(ptr);
}

void yaffsfs_LocalInitialisation(void)
{
	/* No locking used */
}


static const char *yaffs_file_type_str(struct yaffs_stat *stat)
{
	switch (stat->st_mode & S_IFMT) {
	case S_IFREG: return "regular file";
	case S_IFDIR: return "directory";
	case S_IFLNK: return "symlink";
	default: return "unknown";
	}
}

static const char *yaffs_error_str(void)
{
	int error = yaffsfs_GetLastError();

	if (error < 0)
		error = -error;

	switch (error) {
	case EBUSY: return "Busy";
	case ENODEV: return "No such device";
	case EINVAL: return "Invalid parameter";
	case ENFILE: return "Too many open files";
	case EBADF:  return "Bad handle";
	case EACCES: return "Wrong permissions";
	case EXDEV:  return "Not on same device";
	case ENOENT: return "No such entry";
	case ENOSPC: return "Device full";
	case EROFS:  return "Read only file system";
	case ERANGE: return "Range error";
	case ENOTEMPTY: return "Not empty";
	case ENAMETOOLONG: return "Name too long";
	case ENOMEM: return "Out of memory";
	case EFAULT: return "Fault";
	case EEXIST: return "Name exists";
	case ENOTDIR: return "Not a directory";
	case EISDIR: return "Not permitted on a directory";
	case ELOOP:  return "Symlink loop";
	case 0: return "No error";
	default: return "Unknown error";
	}
}

void cmd_yaffs_tracemask(unsigned set, unsigned mask)
{
	if (set)
		yaffs_trace_mask = mask;

	printf("yaffs trace mask: %08x\n", yaffs_trace_mask);
}

static int yaffs_regions_overlap(int a, int b, int x, int y)
{
	return	(a <= x && x <= b) ||
		(a <= y && y <= b) ||
		(x <= a && a <= y) ||
		(x <= b && b <= y);
}

void cmd_yaffs_devconfig(char *_mp, int flash_dev,
			int start_block, int end_block)
{
	struct mtd_info *mtd = NULL;
	struct yaffs_dev *dev = NULL;
	struct yaffs_dev *chk;
	char *mp = NULL;
	struct nand_chip *chip;

	mtd = get_nand_dev_by_index(flash_dev);
	if (!mtd) {
		pr_err("\nno NAND devices available\n");
		return;
	}

	dev = calloc(1, sizeof(*dev));
	mp = strdup(_mp);

	if (!dev || !mp) {
		/* Alloc error */
		printf("Failed to allocate memory\n");
		goto err;
	}

	if (flash_dev >= CONFIG_SYS_MAX_NAND_DEVICE) {
		printf("Flash device invalid\n");
		goto err;
	}

	if (end_block == 0)
		end_block = lldiv(mtd->size, mtd->erasesize - 1);

	if (end_block < start_block) {
		printf("Bad start/end\n");
		goto err;
	}

	chip =  mtd_to_nand(mtd);

	/* Check for any conflicts */
	yaffs_dev_rewind();
	while (1) {
		chk = yaffs_next_dev();
		if (!chk)
			break;
		if (strcmp(chk->param.name, mp) == 0) {
			printf("Mount point name already used\n");
			goto err;
		}
		if (chk->driver_context == mtd &&
			yaffs_regions_overlap(
				chk->param.start_block, chk->param.end_block,
				start_block, end_block)) {
			printf("Region overlaps with partition %s\n",
				chk->param.name);
			goto err;
		}

	}

	/* Seems sane, so configure */
	memset(dev, 0, sizeof(*dev));
	dev->param.name = mp;
	dev->driver_context = mtd;
	dev->param.start_block = start_block;
	dev->param.end_block = end_block;
	dev->param.chunks_per_block = mtd->erasesize / mtd->writesize;
	dev->param.total_bytes_per_chunk = mtd->writesize;
	dev->param.is_yaffs2 = 1;
	dev->param.use_nand_ecc = 1;
	dev->param.n_reserved_blocks = 5;
	if (chip->ecc.layout->oobavail < sizeof(struct yaffs_packed_tags2))
		dev->param.inband_tags = 1;
	dev->param.n_caches = 10;
	dev->param.write_chunk_tags_fn = nandmtd2_write_chunk_tags;
	dev->param.read_chunk_tags_fn = nandmtd2_read_chunk_tags;
	dev->param.erase_fn = nandmtd_EraseBlockInNAND;
	dev->param.initialise_flash_fn = nandmtd_InitialiseNAND;
	dev->param.bad_block_fn = nandmtd2_MarkNANDBlockBad;
	dev->param.query_block_fn = nandmtd2_QueryNANDBlock;

	yaffs_add_device(dev);

	printf("Configures yaffs mount %s: dev %d start block %d, end block %d %s\n",
		mp, flash_dev, start_block, end_block,
		dev->param.inband_tags ? "using inband tags" : "");
	return;

err:
	free(dev);
	free(mp);
}

void cmd_yaffs_dev_ls(void)
{
	struct yaffs_dev *dev;
	int flash_dev;
	int free_space;

	yaffs_dev_rewind();

	while (1) {
		dev = yaffs_next_dev();
		if (!dev)
			return;
		flash_dev = nand_mtd_to_devnum(dev->driver_context);
		printf("%-10s %5d 0x%05x 0x%05x %s",
			dev->param.name, flash_dev,
			dev->param.start_block, dev->param.end_block,
			dev->param.inband_tags ? "using inband tags, " : "");

		free_space = yaffs_freespace(dev->param.name);
		if (free_space < 0)
			printf("not mounted\n");
		else
			printf("free 0x%x\n", free_space);

	}
}

void make_a_file(char *yaffsName, char bval, int sizeOfFile)
{
	int outh;
	int i;
	unsigned char buffer[100];

	outh = yaffs_open(yaffsName,
				O_CREAT | O_RDWR | O_TRUNC,
				S_IREAD | S_IWRITE);
	if (outh < 0) {
		printf("Error opening file: %d. %s\n", outh, yaffs_error_str());
		return;
	}

	memset(buffer, bval, 100);

	do {
		i = sizeOfFile;
		if (i > 100)
			i = 100;
		sizeOfFile -= i;

		yaffs_write(outh, buffer, i);

	} while (sizeOfFile > 0);


	yaffs_close(outh);
}

void read_a_file(char *fn)
{
	int h;
	int i = 0;
	unsigned char b;

	h = yaffs_open(fn, O_RDWR, 0);
	if (h < 0) {
		printf("File not found\n");
		return;
	}

	while (yaffs_read(h, &b, 1) > 0) {
		printf("%02x ", b);
		i++;
		if (i > 32) {
			printf("\n");
			i = 0;
		}
	}
	printf("\n");
	yaffs_close(h);
}

void cmd_yaffs_mount(char *mp)
{
	int retval = yaffs_mount(mp);
	if (retval < 0)
		printf("Error mounting %s, return value: %d, %s\n", mp,
			yaffsfs_GetError(), yaffs_error_str());
}


void cmd_yaffs_umount(char *mp)
{
	if (yaffs_unmount(mp) == -1)
		printf("Error umounting %s, return value: %d, %s\n", mp,
			yaffsfs_GetError(), yaffs_error_str());
}

void cmd_yaffs_write_file(char *yaffsName, char bval, int sizeOfFile)
{
	make_a_file(yaffsName, bval, sizeOfFile);
}


void cmd_yaffs_read_file(char *fn)
{
	read_a_file(fn);
}


void cmd_yaffs_mread_file(char *fn, char *addr)
{
	int h;
	struct yaffs_stat s;

	yaffs_stat(fn, &s);

	printf("Copy %s to 0x%p... ", fn, addr);
	h = yaffs_open(fn, O_RDWR, 0);
	if (h < 0) {
		printf("File not found\n");
		return;
	}

	yaffs_read(h, addr, (int)s.st_size);
	printf("\t[DONE]\n");

	yaffs_close(h);
}


void cmd_yaffs_mwrite_file(char *fn, char *addr, int size)
{
	int outh;

	outh = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
	if (outh < 0)
		printf("Error opening file: %d, %s\n", outh, yaffs_error_str());

	yaffs_write(outh, addr, size);

	yaffs_close(outh);
}


void cmd_yaffs_ls(const char *mountpt, int longlist)
{
	int i;
	yaffs_DIR *d;
	struct yaffs_dirent *de;
	struct yaffs_stat stat;
	char tempstr[255];

	d = yaffs_opendir(mountpt);

	if (!d) {
		printf("opendir failed, %s\n", yaffs_error_str());
		return;
	}

	for (i = 0; (de = yaffs_readdir(d)) != NULL; i++) {
		if (longlist) {
			sprintf(tempstr, "%s/%s", mountpt, de->d_name);
			yaffs_lstat(tempstr, &stat);
			printf("%-25s\t%7ld",
					de->d_name,
					(long)stat.st_size);
			printf(" %5d %s\n",
					stat.st_ino,
					yaffs_file_type_str(&stat));
		} else {
			printf("%s\n", de->d_name);
		}
	}

	yaffs_closedir(d);
}


void cmd_yaffs_mkdir(const char *dir)
{
	int retval = yaffs_mkdir(dir, 0);

	if (retval < 0)
		printf("yaffs_mkdir returning error: %d, %s\n",
			retval, yaffs_error_str());
}

void cmd_yaffs_rmdir(const char *dir)
{
	int retval = yaffs_rmdir(dir);

	if (retval < 0)
		printf("yaffs_rmdir returning error: %d, %s\n",
			retval, yaffs_error_str());
}

void cmd_yaffs_rm(const char *path)
{
	int retval = yaffs_unlink(path);

	if (retval < 0)
		printf("yaffs_unlink returning error: %d, %s\n",
			retval, yaffs_error_str());
}

void cmd_yaffs_mv(const char *oldPath, const char *newPath)
{
	int retval = yaffs_rename(newPath, oldPath);

	if (retval < 0)
		printf("yaffs_unlink returning error: %d, %s\n",
			retval, yaffs_error_str());
}
