diff options
| author | Charles Manning <cdhmanning@gmail.com> | 2012-05-09 16:55:17 +0000 | 
|---|---|---|
| committer | Wolfgang Denk <wd@denx.de> | 2012-08-09 23:39:18 +0200 | 
| commit | 753ac610880e6e563d0384bb114f8b41df89e520 (patch) | |
| tree | 049dc45790bc6f66dd696d4cd671fd6a2cae4473 /fs/yaffs2/yaffs_uboot_glue.c | |
| parent | 3874a377451e4d1f45710f5bf801dd96e8b8f67e (diff) | |
| download | olio-uboot-2014.01-753ac610880e6e563d0384bb114f8b41df89e520.tar.xz olio-uboot-2014.01-753ac610880e6e563d0384bb114f8b41df89e520.zip | |
u-boot: Update yaffs2 file system
This patch updates the yaffs2 in u-boot to correspond to
git://www.aleph1.co.uk/yaffs2
commit id 9ee5d0643e559568dbe62215f76e0a7bd5a63d93
Signed-off-by: Charles Manning <cdhmanning@gmail.com>
Diffstat (limited to 'fs/yaffs2/yaffs_uboot_glue.c')
| -rw-r--r-- | fs/yaffs2/yaffs_uboot_glue.c | 464 | 
1 files changed, 464 insertions, 0 deletions
| diff --git a/fs/yaffs2/yaffs_uboot_glue.c b/fs/yaffs2/yaffs_uboot_glue.c new file mode 100644 index 000000000..e113e4039 --- /dev/null +++ b/fs/yaffs2/yaffs_uboot_glue.c @@ -0,0 +1,464 @@ +/* + * 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 <common.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 + +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"; +	} +} + +extern nand_info_t nand_info[]; + +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; + +	dev = calloc(1, sizeof(*dev)); +	mp = strdup(_mp); + +	mtd = &nand_info[flash_dev]; + +	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 = mtd->size / mtd->erasesize - 1; + +	if (end_block < start_block) { +		printf("Bad start/end\n"); +		goto err; +	} + +	chip =  mtd->priv; + +	/* 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 = +			((unsigned) dev->driver_context - (unsigned) nand_info)/ +				sizeof(nand_info[0]); +		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()); +} |