Browse Source

update dfs_xxx_mkfs in jffs2 nand uffs.c to use new args

prife 12 years ago
parent
commit
4bc0347b11
2 changed files with 657 additions and 659 deletions
  1. 1 1
      components/dfs/filesystems/jffs2/dfs_jffs2.c
  2. 656 658
      components/dfs/filesystems/uffs/dfs_uffs.c

+ 1 - 1
components/dfs/filesystems/jffs2/dfs_jffs2.c

@@ -222,7 +222,7 @@ static int dfs_jffs2_unmount(struct dfs_filesystem* fs)
 	return -DFS_STATUS_ENOENT;
 }
 
-static int dfs_jffs2_mkfs(const char* device_name)
+static int dfs_jffs2_mkfs(rt_device_t dev_id)
 {
 	/* just erase all blocks on this nand partition */
 	return -DFS_STATUS_ENOSYS; 

+ 656 - 658
components/dfs/filesystems/uffs/dfs_uffs.c

@@ -1,658 +1,656 @@
-/*
- * File      : rtthread.h
- * This file is part of RT-Thread RTOS
- * COPYRIGHT (C) 2006-2012, RT-Thread Development Team
- *
- * The license and distribution terms for this file may be
- * found in the file LICENSE in this distribution or at
- * http://www.rt-thread.org/license/LICENSE.
- *
- * Change Logs:
- * Date           Author       Notes
- * 2011-10-22     prife        the first version
- * 2012-03-28     prife        use mtd device interface
- * 2012-04-05     prife        update uffs with official repo and use uffs_UnMount/Mount
-*/
-#include <rtthread.h>
-
-#include <dfs_fs.h>
-#include <dfs_def.h>
-#include <rtdevice.h>
-#include "dfs_uffs.h"
-
-#include "uffs/uffs_fd.h" /* posix file api is here */
-#include "uffs/uffs_mtb.h"
-#include "uffs/uffs_mem.h"
-#include "uffs/uffs_utils.h"
-
-/*
- * RT-Thread DFS Interface for uffs
- */
-#define UFFS_DEVICE_MAX	        2	 /* the max partions on a nand deivce*/
-#define UFFS_MOUNT_PATH_MAX     128	 /* the mount point max length */
-#define FILE_PATH_MAX	        256	 /* the longest file path */
-
-struct _nand_dev
-{
-	struct rt_mtd_nand_device * dev;
-	struct uffs_StorageAttrSt storage;
-	uffs_Device uffs_dev;
-	uffs_MountTable mount_table;
-	char mount_path[UFFS_MOUNT_PATH_MAX];
-	void * data;  /* when uffs use static buf, it will save ptr here */	
-};
-/* make sure the following struct var had been initilased to 0! */
-static struct _nand_dev nand_part[UFFS_DEVICE_MAX] = {0};
-
-static int uffs_result_to_dfs(int result)
-{
-	int status = -1;
-
-	result = result < 0 ? -result : result;
-	switch (result)
-	{
-	case UENOERR:/** no error */
-		break;
-	case UEACCES:/** Tried to open read-only file for writing, or files sharing mode
-				   does not allow specified operations, or given path is directory */
-		status = -DFS_STATUS_EINVAL;
-		break;/* no suitable */
-	case UEEXIST:   /** _O_CREAT and _O_EXCL flags specified, but filename already exists */
-		status = -DFS_STATUS_EEXIST;
-		break;
-	case UEINVAL:  /** Invalid oflag or pmode argument */
-		status = -DFS_STATUS_EINVAL;
-		break;
-	case UEMFILE: /** No more file handles available(too many open files)  */
-		status = -1;
-		break;
-	case UENOENT: /** file or path not found */
-		status = -DFS_STATUS_ENOENT;
-		break;
-	case UETIME: /** can't set file time */
-		status = -1;
-		break;
-	case UEBADF: /** invalid file handle */
-		status = -DFS_STATUS_EBADF;
-		break;
-	case UENOMEM:/** no enough memory */
-		status = -DFS_STATUS_ENOSPC;
-		break;
-	case UEIOERR: /** I/O error from lower level flash operation */
-		status = -DFS_STATUS_EIO;
-		break;
-	case UENOTDIR: /** Not a directory */
-		status = -DFS_STATUS_ENOTDIR;
-		break;
-	case UEISDIR: /** Is a directory */
-		status = -DFS_STATUS_EISDIR;
-		break;
-	case UEUNKNOWN_ERR:
-	default:
-		status = -1;
-		break; /* unknown error! */
-	}
-
-	return status;
-}
-
-static URET _device_init(uffs_Device *dev)
-{
-	dev->attr->_private = NULL;	// hook nand_chip data structure to attr->_private
-	dev->ops = (struct uffs_FlashOpsSt *)&nand_ops;
-
-	return U_SUCC;
-}
-
-static URET _device_release(uffs_Device *dev)
-{
-	return U_SUCC;
-}
-
-static int init_uffs_fs(
-	struct _nand_dev * nand_part)
-{
-    uffs_MountTable * mtb;
-    struct rt_mtd_nand_device * nand;
-    struct uffs_StorageAttrSt * flash_storage;
-
-    mtb = &nand_part->mount_table;
-    nand = nand_part->dev;
-    flash_storage = &nand_part->storage;
-
-	/* setup nand storage attributes */
-	uffs_setup_storage(flash_storage, nand);
-
-	/* register mount table */
-	if(mtb->dev)
-	{
-		/* set memory allocator for uffs */
-#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0
-		uffs_MemSetupSystemAllocator(&mtb->dev->mem);
-#endif
-		/* setup device init/release entry */
-		mtb->dev->Init = _device_init;
-		mtb->dev->Release = _device_release;
-		mtb->dev->attr = flash_storage;
-
-		uffs_RegisterMountTable(mtb);
-	}
-	/* mount uffs partion on nand device */
-	return uffs_Mount(nand_part->mount_path) == U_SUCC ? 0 : -1;
-}
-
-static int dfs_uffs_mount(
-	struct dfs_filesystem* fs,
-    unsigned long rwflag,
-    const void* data)
-{
-	rt_base_t index;
-	uffs_MountTable * mount_part;
-	struct rt_mtd_nand_device * dev;
-	
-	RT_ASSERT(rt_strlen(fs->path) < (UFFS_MOUNT_PATH_MAX-1));
-	dev = RT_MTD_NAND_DEVICE(fs->dev_id);
-
-	/*1. find a empty entry in partition table */
-	for (index = 0; index < UFFS_DEVICE_MAX ; index ++)
-	{
-		if (nand_part[index].dev == RT_NULL)
-			break;
-	}
-	if (index == UFFS_DEVICE_MAX)
-		return -DFS_STATUS_ENOENT;
-
-	/*2. fill partition structure */
-	nand_part[index].dev = dev;
-
-	/* make a right mount path for uffs, end with '/' */
-	rt_snprintf(nand_part[index].mount_path, UFFS_MOUNT_PATH_MAX, "%s/", fs->path);
-	if (nand_part[index].mount_path[1] == '/')
-		nand_part[index].mount_path[1] = 0;
-
-	mount_part = &(nand_part[index].mount_table);
-	mount_part->mount	= nand_part[index].mount_path;
-	mount_part->dev = &(nand_part[index].uffs_dev);
-	rt_memset(mount_part->dev, 0, sizeof(uffs_Device));//in order to make uffs happy.
-	mount_part->dev->_private = dev;   /* save dev_id into uffs */
-	mount_part->start_block = dev->block_start;
-	mount_part->end_block = dev->block_end;
-	/*3. mount uffs */
-	if (init_uffs_fs(&nand_part[index]) < 0)
-	{
-		return uffs_result_to_dfs(uffs_get_error());
-	}
-	return 0;
-}
-
-static int dfs_uffs_unmount(struct dfs_filesystem* fs)
-{
-	rt_base_t index;
-	int result;
-
-	/* find the device index and then unmount it */
-	for (index = 0; index < UFFS_DEVICE_MAX; index++)
-	{
-		if (nand_part[index].dev == RT_MTD_NAND_DEVICE(fs->dev_id))
-		{
-			nand_part[index].dev = RT_NULL;
-			result = uffs_UnMount(nand_part[index].mount_path);
-			if (result != U_SUCC)
-				break;
-
-			result = uffs_UnRegisterMountTable(& nand_part[index].mount_table);
-			return (result == U_SUCC) ? DFS_STATUS_OK : -1;
-		}
-	}
-	return -DFS_STATUS_ENOENT;
-}
-
-static int dfs_uffs_mkfs(const char* device_name)
-{
-	rt_base_t index;
-	rt_uint32_t block;
-	struct rt_mtd_nand_device * mtd;
-
-	/*1. find the device index */
-	for (index = 0; index < UFFS_DEVICE_MAX; index++)
-	{
-		if (rt_strncmp(nand_part[index].dev->parent.parent.name,
-				       device_name, RT_NAME_MAX) == 0)
-			break;
-	}
-
-	if (index == UFFS_DEVICE_MAX)
-	{
-		/* can't find device driver */
-		rt_kprintf("can not find device driver: %s\n", device_name);
-		return -DFS_STATUS_ENOENT;
-	}
-
-	/*2. then unmount the partition */
-	uffs_Mount(nand_part[index].mount_path);
-	mtd = nand_part[index].dev;
-
-	/*3. erase all blocks on the partition */
-	block = mtd->block_start;
-	for (; block <= mtd->block_end; block++)
-	{
-		rt_mtd_nand_erase_block(mtd, block);
-		if (rt_mtd_nand_check_block(mtd, block) != RT_EOK)
-		{
-			rt_kprintf("found bad block %d\n", block);
-			rt_mtd_nand_mark_badblock(mtd, block);
-		}
-	}
-
-	/*4. remount it */
-	if (init_uffs_fs(&nand_part[index]) < 0)
-	{
-		return uffs_result_to_dfs(uffs_get_error());
-	}
-	return DFS_STATUS_OK;
-}
-
-static int dfs_uffs_statfs(struct dfs_filesystem* fs,
-                    struct statfs *buf)
-{
-	rt_base_t index;
-	struct rt_mtd_nand_device * mtd = RT_MTD_NAND_DEVICE(fs->dev_id);
-
-	RT_ASSERT(mtd != RT_NULL);
-
-	/* find the device index */
-	for (index = 0; index < UFFS_DEVICE_MAX; index++)
-	{
-		if (nand_part[index].dev == (void *)mtd)
-			break;
-	}
-	if (index == UFFS_DEVICE_MAX)
-		return -DFS_STATUS_ENOENT;
-	
-	buf->f_bsize = mtd->page_size;
-	buf->f_blocks = mtd->pages_per_block*
-	                (mtd->block_end - mtd->block_start + 1);
-	buf->f_bfree = uffs_GetDeviceFree(&nand_part[index].uffs_dev) / mtd->page_size;
-	
-	return 0;
-}
-
-static int dfs_uffs_open(struct dfs_fd* file)
-{
-	int fd;
-	int oflag, mode;
-	char * file_path;
-
-	oflag = file->flags;
-	if (oflag & DFS_O_DIRECTORY)   /* operations about dir */
-	{
-		uffs_DIR * dir;
-
-		if (oflag & DFS_O_CREAT)   /* create a dir*/
-		{
-			if (uffs_mkdir(file->path) < 0)
-				return uffs_result_to_dfs(uffs_get_error());
-		}
-		/* open dir */
-		file_path = rt_malloc(FILE_PATH_MAX);
-		if(file_path == RT_NULL)
-			return -DFS_STATUS_ENOMEM;			
-
-		if (file->path[0] == '/' && !(file->path[1] == 0))
-			rt_snprintf(file_path, FILE_PATH_MAX, "%s/", file->path);
-		else
-		{
-			file_path[0] = '/';
-			file_path[1] = 0;
-		}
-
-		dir = uffs_opendir(file_path);
-
-		if (dir == RT_NULL)
-		{
-			rt_free(file_path);			
-			return uffs_result_to_dfs(uffs_get_error());
-		}
-		/* save this pointer,will used by  dfs_uffs_getdents*/
-		file->data = dir;
-		rt_free(file_path);
-		return DFS_STATUS_OK;
-	}
-	/* regular file operations */
-	/* int uffs_open(const char *name, int oflag, ...); what is this?
-	 * uffs_open can open dir!!  **/
-	mode = 0;
-	if (oflag & DFS_O_RDONLY) mode |= UO_RDONLY;
-	if (oflag & DFS_O_WRONLY) mode |= UO_WRONLY;
-	if (oflag & DFS_O_RDWR)   mode |= UO_RDWR;
-	/* Opens the file, if it is existing. If not, a new file is created. */
-	if (oflag & DFS_O_CREAT) mode |= UO_CREATE;
-	/* Creates a new file. If the file is existing, it is truncated and overwritten. */
-	if (oflag & DFS_O_TRUNC) mode |= UO_TRUNC;
-	/* Creates a new file. The function fails if the file is already existing. */
-	if (oflag & DFS_O_EXCL) mode |= UO_EXCL;
-
-	fd = uffs_open(file->path, mode);
-	if (fd < 0)
-	{
-		return uffs_result_to_dfs(uffs_get_error());
-	}
-
-	/* save this pointer, it will be used when calling read()£¬write(),
-	 * flush(), seek(), and will be free when calling close()*/
-
-	file->data = (void *)fd;
-	file->pos  = uffs_seek(fd, 0, USEEK_CUR);
-	file->size = uffs_seek(fd, 0, USEEK_END);
-	uffs_seek(fd, file->pos, USEEK_SET);
-
-	if (oflag & DFS_O_APPEND)
-	{
-		file->pos = uffs_seek(fd, 0, USEEK_END);
-	}
-	return 0;
-}
-
-static int dfs_uffs_close(struct dfs_fd* file)
-{
-	int oflag;
-	int fd;
-
-	oflag = file->flags;
-	if (oflag & DFS_O_DIRECTORY)
-	{
-		/* operations about dir */
-		if (uffs_closedir((uffs_DIR *)(file->data)) < 0)
-			return uffs_result_to_dfs(uffs_get_error());
-
-		return 0;
-	}
-	/* regular file operations */
-	fd = (int)(file->data);
-
-	if (uffs_close(fd) == 0)
-		return 0;
-
-	return uffs_result_to_dfs(uffs_get_error());
-}
-
-static int dfs_uffs_ioctl(struct dfs_fd * file, int cmd, void* args)
-{
-	return -DFS_STATUS_ENOSYS;
-}
-
-static int dfs_uffs_read(struct dfs_fd * file, void* buf, rt_size_t len)
-{
-	int fd;
-	int char_read;
-
-	fd = (int)(file->data);
-	char_read = uffs_read(fd, buf, len);
-	if (char_read < 0)
-		return uffs_result_to_dfs(uffs_get_error());
-
-	/* update position */
-	file->pos = uffs_seek(fd, 0, USEEK_CUR);
-	return char_read;
-}
-
-static int dfs_uffs_write(struct dfs_fd* file,
-                   const void* buf,
-                   rt_size_t len)
-{
-	int fd;
-	int char_write;
-
-	fd = (int)(file->data);
-
-	char_write = uffs_write(fd, buf, len);
-	if (char_write < 0)
-		return uffs_result_to_dfs(uffs_get_error());
-
-	/* update position */
-	file->pos = uffs_seek(fd, 0, USEEK_CUR);
-	return char_write;
-}
-
-static int dfs_uffs_flush(struct dfs_fd* file)
-{
-	int fd;
-	int result;
-
-	fd = (int)(file->data);
-
-	result = uffs_flush(fd);
-	if (result < 0 )
-		return uffs_result_to_dfs(uffs_get_error());
-	return 0;
-}
-
-int uffs_seekdir(uffs_DIR *dir, long offset)
-{
-	int i = 0;
-
-	while(i < offset)
-	{	
-		if (uffs_readdir(dir) == RT_NULL)
-			return -1;
-		i++;
-	} 
-	return 0;
-}
-
-
-static int dfs_uffs_seek(struct dfs_fd* file,
-                  rt_off_t offset)
-{
-	int result;
-
-	/* set offset as current offset */
-	if (file->type == FT_DIRECTORY)
-	{
-		uffs_rewinddir((uffs_DIR *)(file->data));
-		result = uffs_seekdir((uffs_DIR *)(file->data), offset/sizeof(struct dirent));
-		if (result >= 0)
-		{
-			file->pos = offset; 
-			return offset;
-		}
-	}
-	else if (file->type == FT_REGULAR)
-	{
-		result = uffs_seek((int)(file->data), offset, USEEK_SET);
-		if (result >= 0)	
-			return offset;
-	}
-
-	return uffs_result_to_dfs(uffs_get_error());
-}
-
-/* return the size of struct dirent*/
-static int dfs_uffs_getdents(
-    struct dfs_fd* file,
-    struct dirent* dirp,
-    rt_uint32_t count)
-{
-	rt_uint32_t index;
-	char * file_path;
-	struct dirent* d;
-	uffs_DIR* dir;
-	struct uffs_dirent * uffs_d;
-	
-	dir = (uffs_DIR*)(file->data);
-	RT_ASSERT(dir != RT_NULL);
-	
-	/* round count, count is always 1 */
-	count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
-	if (count == 0) return -DFS_STATUS_EINVAL;
-
-	/* allocate file name */
-	file_path = rt_malloc(FILE_PATH_MAX);
-	if (file_path == RT_NULL)
-		return -DFS_STATUS_ENOMEM;
-		
-	index = 0;
-	/* usually, the while loop should only be looped only once! */
-	while (1)
-	{
-		struct uffs_stat s;
-		
-		d = dirp + index;
-
-		uffs_d = uffs_readdir(dir);
-		if (uffs_d == RT_NULL)
-		{
-			rt_free(file_path);
-			return (uffs_result_to_dfs(uffs_get_error()));
-		}
-
-		if (file->path[0] == '/' && !(file->path[1] == 0))
-			rt_snprintf(file_path, FILE_PATH_MAX, "%s/%s", file->path, uffs_d->d_name);
-		else
-			rt_strncpy(file_path, uffs_d->d_name, FILE_PATH_MAX);
-
-		uffs_stat(file_path, &s); 
-		switch(s.st_mode & US_IFMT)   /* file type mark */
-		{
-		case US_IFREG: /* directory */
-			d->d_type = DFS_DT_REG;
-			break;
-		case US_IFDIR: /* regular file */
-			d->d_type = DFS_DT_DIR;
-			break;
-		case US_IFLNK: /* symbolic link */
-		case US_IREAD: /* read permission */
-		case US_IWRITE:/* write permission */
-		default:
-			d->d_type = DFS_DT_UNKNOWN;
-			break;
-		}
-
-		/* write the rest args of struct dirent* dirp  */
-		d->d_namlen = rt_strlen(uffs_d->d_name);
-		d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
-		rt_strncpy(d->d_name, uffs_d->d_name, rt_strlen(uffs_d->d_name) + 1);
-
-		index ++;
-		if (index * sizeof(struct dirent) >= count)
-			break;
-	}
-	
-	/* free file name buf */
-	rt_free(file_path);
-	
-	if (index == 0)
-		return uffs_result_to_dfs(uffs_get_error());
-
-	file->pos += index * sizeof(struct dirent);
-
-	return index * sizeof(struct dirent);
-}
-
-static int dfs_uffs_unlink(struct dfs_filesystem* fs, const char* path)
-{
-	int result;
-	struct uffs_stat s;
-
-	/* judge file type, dir is to be delete by uffs_rmdir, others by uffs_remove */
-	if (uffs_lstat(path, &s) < 0)
-	{
-		return uffs_result_to_dfs(uffs_get_error());
-	}
-
-	switch(s.st_mode & US_IFMT)
-	{
-	case US_IFREG:
-		result = uffs_remove(path);
-		break;
-	case US_IFDIR:
-		result = uffs_rmdir(path);
-		break;
-	default:
-		/* unknown file type */
-		return -1;
-	}
-	if (result < 0)
-		return uffs_result_to_dfs(uffs_get_error());
-
-	return 0;
-}
-
-static int dfs_uffs_rename(
-    struct dfs_filesystem* fs,
-    const char* oldpath,
-    const char* newpath)
-{
-	int result;
-	
-	result = uffs_rename(oldpath, newpath);
-	if (result < 0)
-		return uffs_result_to_dfs(uffs_get_error());
-
-	return 0;
-}
-
-static int dfs_uffs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
-{
-	int result;
-	struct uffs_stat s;
-	struct rt_mtd_nand_device * mtd;
-
-	result = uffs_stat(path, &s);
-	if (result < 0)
-		return uffs_result_to_dfs(uffs_get_error());
-
-	/* convert uffs stat to dfs stat structure */
-	/* FIXME, these field may not be the same */
-	st->st_dev  = 0;
-	st->st_mode = s.st_mode;
-	st->st_size = s.st_size;
-	st->st_mtime = s.st_mtime;
-
-	mtd = RT_MTD_NAND_DEVICE(fs->dev_id);
-	st->st_blksize = mtd->page_size;
-
-	return 0;
-}
-
-static const struct dfs_filesystem_operation dfs_uffs_ops =
-{
-	"uffs", /* file system type: uffs */
-#if RTTHREAD_VERSION >= 10100
-	DFS_FS_FLAG_FULLPATH,
-#else
-#error "uffs can only work with rtthread whose version should >= 1.01\n"
-#endif
-	dfs_uffs_mount,
-	dfs_uffs_unmount,
-	dfs_uffs_mkfs,
-	dfs_uffs_statfs,
-
-	dfs_uffs_open,
-	dfs_uffs_close,
-	dfs_uffs_ioctl,
-	dfs_uffs_read,
-	dfs_uffs_write,
-	dfs_uffs_flush,
-	dfs_uffs_seek,
-	dfs_uffs_getdents,
-	dfs_uffs_unlink,
-	dfs_uffs_stat,
-	dfs_uffs_rename,
-};
-
-int dfs_uffs_init(void)
-{
-	/* register uffs file system */
-	dfs_register(&dfs_uffs_ops);
-
-	if (uffs_InitObjectBuf() == U_SUCC)
-	{
-		if (uffs_DirEntryBufInit() == U_SUCC)
-		{
-			uffs_InitGlobalFsLock();
-			return RT_EOK;
-		}
-	}
-	return -RT_ERROR;
-}
+/*
+ * File      : rtthread.h
+ * This file is part of RT-Thread RTOS
+ * COPYRIGHT (C) 2006-2012, RT-Thread Development Team
+ *
+ * The license and distribution terms for this file may be
+ * found in the file LICENSE in this distribution or at
+ * http://www.rt-thread.org/license/LICENSE.
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2011-10-22     prife        the first version
+ * 2012-03-28     prife        use mtd device interface
+ * 2012-04-05     prife        update uffs with official repo and use uffs_UnMount/Mount
+*/
+#include <rtthread.h>
+
+#include <dfs_fs.h>
+#include <dfs_def.h>
+#include <rtdevice.h>
+#include "dfs_uffs.h"
+
+#include "uffs/uffs_fd.h" /* posix file api is here */
+#include "uffs/uffs_mtb.h"
+#include "uffs/uffs_mem.h"
+#include "uffs/uffs_utils.h"
+
+/*
+ * RT-Thread DFS Interface for uffs
+ */
+#define UFFS_DEVICE_MAX	        2	 /* the max partions on a nand deivce*/
+#define UFFS_MOUNT_PATH_MAX     128	 /* the mount point max length */
+#define FILE_PATH_MAX	        256	 /* the longest file path */
+
+struct _nand_dev
+{
+	struct rt_mtd_nand_device * dev;
+	struct uffs_StorageAttrSt storage;
+	uffs_Device uffs_dev;
+	uffs_MountTable mount_table;
+	char mount_path[UFFS_MOUNT_PATH_MAX];
+	void * data;  /* when uffs use static buf, it will save ptr here */	
+};
+/* make sure the following struct var had been initilased to 0! */
+static struct _nand_dev nand_part[UFFS_DEVICE_MAX] = {0};
+
+static int uffs_result_to_dfs(int result)
+{
+	int status = -1;
+
+	result = result < 0 ? -result : result;
+	switch (result)
+	{
+	case UENOERR:/** no error */
+		break;
+	case UEACCES:/** Tried to open read-only file for writing, or files sharing mode
+				   does not allow specified operations, or given path is directory */
+		status = -DFS_STATUS_EINVAL;
+		break;/* no suitable */
+	case UEEXIST:   /** _O_CREAT and _O_EXCL flags specified, but filename already exists */
+		status = -DFS_STATUS_EEXIST;
+		break;
+	case UEINVAL:  /** Invalid oflag or pmode argument */
+		status = -DFS_STATUS_EINVAL;
+		break;
+	case UEMFILE: /** No more file handles available(too many open files)  */
+		status = -1;
+		break;
+	case UENOENT: /** file or path not found */
+		status = -DFS_STATUS_ENOENT;
+		break;
+	case UETIME: /** can't set file time */
+		status = -1;
+		break;
+	case UEBADF: /** invalid file handle */
+		status = -DFS_STATUS_EBADF;
+		break;
+	case UENOMEM:/** no enough memory */
+		status = -DFS_STATUS_ENOSPC;
+		break;
+	case UEIOERR: /** I/O error from lower level flash operation */
+		status = -DFS_STATUS_EIO;
+		break;
+	case UENOTDIR: /** Not a directory */
+		status = -DFS_STATUS_ENOTDIR;
+		break;
+	case UEISDIR: /** Is a directory */
+		status = -DFS_STATUS_EISDIR;
+		break;
+	case UEUNKNOWN_ERR:
+	default:
+		status = -1;
+		break; /* unknown error! */
+	}
+
+	return status;
+}
+
+static URET _device_init(uffs_Device *dev)
+{
+	dev->attr->_private = NULL;	// hook nand_chip data structure to attr->_private
+	dev->ops = (struct uffs_FlashOpsSt *)&nand_ops;
+
+	return U_SUCC;
+}
+
+static URET _device_release(uffs_Device *dev)
+{
+	return U_SUCC;
+}
+
+static int init_uffs_fs(
+	struct _nand_dev * nand_part)
+{
+    uffs_MountTable * mtb;
+    struct rt_mtd_nand_device * nand;
+    struct uffs_StorageAttrSt * flash_storage;
+
+    mtb = &nand_part->mount_table;
+    nand = nand_part->dev;
+    flash_storage = &nand_part->storage;
+
+	/* setup nand storage attributes */
+	uffs_setup_storage(flash_storage, nand);
+
+	/* register mount table */
+	if(mtb->dev)
+	{
+		/* set memory allocator for uffs */
+#if CONFIG_USE_SYSTEM_MEMORY_ALLOCATOR > 0
+		uffs_MemSetupSystemAllocator(&mtb->dev->mem);
+#endif
+		/* setup device init/release entry */
+		mtb->dev->Init = _device_init;
+		mtb->dev->Release = _device_release;
+		mtb->dev->attr = flash_storage;
+
+		uffs_RegisterMountTable(mtb);
+	}
+	/* mount uffs partion on nand device */
+	return uffs_Mount(nand_part->mount_path) == U_SUCC ? 0 : -1;
+}
+
+static int dfs_uffs_mount(
+	struct dfs_filesystem* fs,
+    unsigned long rwflag,
+    const void* data)
+{
+	rt_base_t index;
+	uffs_MountTable * mount_part;
+	struct rt_mtd_nand_device * dev;
+	
+	RT_ASSERT(rt_strlen(fs->path) < (UFFS_MOUNT_PATH_MAX-1));
+	dev = RT_MTD_NAND_DEVICE(fs->dev_id);
+
+	/*1. find a empty entry in partition table */
+	for (index = 0; index < UFFS_DEVICE_MAX ; index ++)
+	{
+		if (nand_part[index].dev == RT_NULL)
+			break;
+	}
+	if (index == UFFS_DEVICE_MAX)
+		return -DFS_STATUS_ENOENT;
+
+	/*2. fill partition structure */
+	nand_part[index].dev = dev;
+
+	/* make a right mount path for uffs, end with '/' */
+	rt_snprintf(nand_part[index].mount_path, UFFS_MOUNT_PATH_MAX, "%s/", fs->path);
+	if (nand_part[index].mount_path[1] == '/')
+		nand_part[index].mount_path[1] = 0;
+
+	mount_part = &(nand_part[index].mount_table);
+	mount_part->mount	= nand_part[index].mount_path;
+	mount_part->dev = &(nand_part[index].uffs_dev);
+	rt_memset(mount_part->dev, 0, sizeof(uffs_Device));//in order to make uffs happy.
+	mount_part->dev->_private = dev;   /* save dev_id into uffs */
+	mount_part->start_block = dev->block_start;
+	mount_part->end_block = dev->block_end;
+	/*3. mount uffs */
+	if (init_uffs_fs(&nand_part[index]) < 0)
+	{
+		return uffs_result_to_dfs(uffs_get_error());
+	}
+	return 0;
+}
+
+static int dfs_uffs_unmount(struct dfs_filesystem* fs)
+{
+	rt_base_t index;
+	int result;
+
+	/* find the device index and then unmount it */
+	for (index = 0; index < UFFS_DEVICE_MAX; index++)
+	{
+		if (nand_part[index].dev == RT_MTD_NAND_DEVICE(fs->dev_id))
+		{
+			nand_part[index].dev = RT_NULL;
+			result = uffs_UnMount(nand_part[index].mount_path);
+			if (result != U_SUCC)
+				break;
+
+			result = uffs_UnRegisterMountTable(& nand_part[index].mount_table);
+			return (result == U_SUCC) ? DFS_STATUS_OK : -1;
+		}
+	}
+	return -DFS_STATUS_ENOENT;
+}
+
+static int dfs_uffs_mkfs(rt_device_t dev_id)
+{
+	rt_base_t index;
+	rt_uint32_t block;
+	struct rt_mtd_nand_device * mtd;
+
+	/*1. find the device index */
+	for (index = 0; index < UFFS_DEVICE_MAX; index++)
+	{
+		if (nand_part[index].dev == (struct rt_mtd_nand_device *)dev_id)
+			break;
+	}
+
+	if (index == UFFS_DEVICE_MAX)
+	{
+		/* can't find device driver */
+		return -DFS_STATUS_ENOENT;
+	}
+
+	/*2. then unmount the partition */
+	uffs_Mount(nand_part[index].mount_path);
+	mtd = nand_part[index].dev;
+
+	/*3. erase all blocks on the partition */
+	block = mtd->block_start;
+	for (; block <= mtd->block_end; block++)
+	{
+		rt_mtd_nand_erase_block(mtd, block);
+		if (rt_mtd_nand_check_block(mtd, block) != RT_EOK)
+		{
+			rt_kprintf("found bad block %d\n", block);
+			rt_mtd_nand_mark_badblock(mtd, block);
+		}
+	}
+
+	/*4. remount it */
+	if (init_uffs_fs(&nand_part[index]) < 0)
+	{
+		return uffs_result_to_dfs(uffs_get_error());
+	}
+	return DFS_STATUS_OK;
+}
+
+static int dfs_uffs_statfs(struct dfs_filesystem* fs,
+                    struct statfs *buf)
+{
+	rt_base_t index;
+	struct rt_mtd_nand_device * mtd = RT_MTD_NAND_DEVICE(fs->dev_id);
+
+	RT_ASSERT(mtd != RT_NULL);
+
+	/* find the device index */
+	for (index = 0; index < UFFS_DEVICE_MAX; index++)
+	{
+		if (nand_part[index].dev == (void *)mtd)
+			break;
+	}
+	if (index == UFFS_DEVICE_MAX)
+		return -DFS_STATUS_ENOENT;
+	
+	buf->f_bsize = mtd->page_size;
+	buf->f_blocks = mtd->pages_per_block*
+	                (mtd->block_end - mtd->block_start + 1);
+	buf->f_bfree = uffs_GetDeviceFree(&nand_part[index].uffs_dev) / mtd->page_size;
+	
+	return 0;
+}
+
+static int dfs_uffs_open(struct dfs_fd* file)
+{
+	int fd;
+	int oflag, mode;
+	char * file_path;
+
+	oflag = file->flags;
+	if (oflag & DFS_O_DIRECTORY)   /* operations about dir */
+	{
+		uffs_DIR * dir;
+
+		if (oflag & DFS_O_CREAT)   /* create a dir*/
+		{
+			if (uffs_mkdir(file->path) < 0)
+				return uffs_result_to_dfs(uffs_get_error());
+		}
+		/* open dir */
+		file_path = rt_malloc(FILE_PATH_MAX);
+		if(file_path == RT_NULL)
+			return -DFS_STATUS_ENOMEM;			
+
+		if (file->path[0] == '/' && !(file->path[1] == 0))
+			rt_snprintf(file_path, FILE_PATH_MAX, "%s/", file->path);
+		else
+		{
+			file_path[0] = '/';
+			file_path[1] = 0;
+		}
+
+		dir = uffs_opendir(file_path);
+
+		if (dir == RT_NULL)
+		{
+			rt_free(file_path);			
+			return uffs_result_to_dfs(uffs_get_error());
+		}
+		/* save this pointer,will used by  dfs_uffs_getdents*/
+		file->data = dir;
+		rt_free(file_path);
+		return DFS_STATUS_OK;
+	}
+	/* regular file operations */
+	/* int uffs_open(const char *name, int oflag, ...); what is this?
+	 * uffs_open can open dir!!  **/
+	mode = 0;
+	if (oflag & DFS_O_RDONLY) mode |= UO_RDONLY;
+	if (oflag & DFS_O_WRONLY) mode |= UO_WRONLY;
+	if (oflag & DFS_O_RDWR)   mode |= UO_RDWR;
+	/* Opens the file, if it is existing. If not, a new file is created. */
+	if (oflag & DFS_O_CREAT) mode |= UO_CREATE;
+	/* Creates a new file. If the file is existing, it is truncated and overwritten. */
+	if (oflag & DFS_O_TRUNC) mode |= UO_TRUNC;
+	/* Creates a new file. The function fails if the file is already existing. */
+	if (oflag & DFS_O_EXCL) mode |= UO_EXCL;
+
+	fd = uffs_open(file->path, mode);
+	if (fd < 0)
+	{
+		return uffs_result_to_dfs(uffs_get_error());
+	}
+
+	/* save this pointer, it will be used when calling read()£¬write(),
+	 * flush(), seek(), and will be free when calling close()*/
+
+	file->data = (void *)fd;
+	file->pos  = uffs_seek(fd, 0, USEEK_CUR);
+	file->size = uffs_seek(fd, 0, USEEK_END);
+	uffs_seek(fd, file->pos, USEEK_SET);
+
+	if (oflag & DFS_O_APPEND)
+	{
+		file->pos = uffs_seek(fd, 0, USEEK_END);
+	}
+	return 0;
+}
+
+static int dfs_uffs_close(struct dfs_fd* file)
+{
+	int oflag;
+	int fd;
+
+	oflag = file->flags;
+	if (oflag & DFS_O_DIRECTORY)
+	{
+		/* operations about dir */
+		if (uffs_closedir((uffs_DIR *)(file->data)) < 0)
+			return uffs_result_to_dfs(uffs_get_error());
+
+		return 0;
+	}
+	/* regular file operations */
+	fd = (int)(file->data);
+
+	if (uffs_close(fd) == 0)
+		return 0;
+
+	return uffs_result_to_dfs(uffs_get_error());
+}
+
+static int dfs_uffs_ioctl(struct dfs_fd * file, int cmd, void* args)
+{
+	return -DFS_STATUS_ENOSYS;
+}
+
+static int dfs_uffs_read(struct dfs_fd * file, void* buf, rt_size_t len)
+{
+	int fd;
+	int char_read;
+
+	fd = (int)(file->data);
+	char_read = uffs_read(fd, buf, len);
+	if (char_read < 0)
+		return uffs_result_to_dfs(uffs_get_error());
+
+	/* update position */
+	file->pos = uffs_seek(fd, 0, USEEK_CUR);
+	return char_read;
+}
+
+static int dfs_uffs_write(struct dfs_fd* file,
+                   const void* buf,
+                   rt_size_t len)
+{
+	int fd;
+	int char_write;
+
+	fd = (int)(file->data);
+
+	char_write = uffs_write(fd, buf, len);
+	if (char_write < 0)
+		return uffs_result_to_dfs(uffs_get_error());
+
+	/* update position */
+	file->pos = uffs_seek(fd, 0, USEEK_CUR);
+	return char_write;
+}
+
+static int dfs_uffs_flush(struct dfs_fd* file)
+{
+	int fd;
+	int result;
+
+	fd = (int)(file->data);
+
+	result = uffs_flush(fd);
+	if (result < 0 )
+		return uffs_result_to_dfs(uffs_get_error());
+	return 0;
+}
+
+int uffs_seekdir(uffs_DIR *dir, long offset)
+{
+	int i = 0;
+
+	while(i < offset)
+	{	
+		if (uffs_readdir(dir) == RT_NULL)
+			return -1;
+		i++;
+	} 
+	return 0;
+}
+
+
+static int dfs_uffs_seek(struct dfs_fd* file,
+                  rt_off_t offset)
+{
+	int result;
+
+	/* set offset as current offset */
+	if (file->type == FT_DIRECTORY)
+	{
+		uffs_rewinddir((uffs_DIR *)(file->data));
+		result = uffs_seekdir((uffs_DIR *)(file->data), offset/sizeof(struct dirent));
+		if (result >= 0)
+		{
+			file->pos = offset; 
+			return offset;
+		}
+	}
+	else if (file->type == FT_REGULAR)
+	{
+		result = uffs_seek((int)(file->data), offset, USEEK_SET);
+		if (result >= 0)	
+			return offset;
+	}
+
+	return uffs_result_to_dfs(uffs_get_error());
+}
+
+/* return the size of struct dirent*/
+static int dfs_uffs_getdents(
+    struct dfs_fd* file,
+    struct dirent* dirp,
+    rt_uint32_t count)
+{
+	rt_uint32_t index;
+	char * file_path;
+	struct dirent* d;
+	uffs_DIR* dir;
+	struct uffs_dirent * uffs_d;
+	
+	dir = (uffs_DIR*)(file->data);
+	RT_ASSERT(dir != RT_NULL);
+	
+	/* round count, count is always 1 */
+	count = (count / sizeof(struct dirent)) * sizeof(struct dirent);
+	if (count == 0) return -DFS_STATUS_EINVAL;
+
+	/* allocate file name */
+	file_path = rt_malloc(FILE_PATH_MAX);
+	if (file_path == RT_NULL)
+		return -DFS_STATUS_ENOMEM;
+		
+	index = 0;
+	/* usually, the while loop should only be looped only once! */
+	while (1)
+	{
+		struct uffs_stat s;
+		
+		d = dirp + index;
+
+		uffs_d = uffs_readdir(dir);
+		if (uffs_d == RT_NULL)
+		{
+			rt_free(file_path);
+			return (uffs_result_to_dfs(uffs_get_error()));
+		}
+
+		if (file->path[0] == '/' && !(file->path[1] == 0))
+			rt_snprintf(file_path, FILE_PATH_MAX, "%s/%s", file->path, uffs_d->d_name);
+		else
+			rt_strncpy(file_path, uffs_d->d_name, FILE_PATH_MAX);
+
+		uffs_stat(file_path, &s); 
+		switch(s.st_mode & US_IFMT)   /* file type mark */
+		{
+		case US_IFREG: /* directory */
+			d->d_type = DFS_DT_REG;
+			break;
+		case US_IFDIR: /* regular file */
+			d->d_type = DFS_DT_DIR;
+			break;
+		case US_IFLNK: /* symbolic link */
+		case US_IREAD: /* read permission */
+		case US_IWRITE:/* write permission */
+		default:
+			d->d_type = DFS_DT_UNKNOWN;
+			break;
+		}
+
+		/* write the rest args of struct dirent* dirp  */
+		d->d_namlen = rt_strlen(uffs_d->d_name);
+		d->d_reclen = (rt_uint16_t)sizeof(struct dirent);
+		rt_strncpy(d->d_name, uffs_d->d_name, rt_strlen(uffs_d->d_name) + 1);
+
+		index ++;
+		if (index * sizeof(struct dirent) >= count)
+			break;
+	}
+	
+	/* free file name buf */
+	rt_free(file_path);
+	
+	if (index == 0)
+		return uffs_result_to_dfs(uffs_get_error());
+
+	file->pos += index * sizeof(struct dirent);
+
+	return index * sizeof(struct dirent);
+}
+
+static int dfs_uffs_unlink(struct dfs_filesystem* fs, const char* path)
+{
+	int result;
+	struct uffs_stat s;
+
+	/* judge file type, dir is to be delete by uffs_rmdir, others by uffs_remove */
+	if (uffs_lstat(path, &s) < 0)
+	{
+		return uffs_result_to_dfs(uffs_get_error());
+	}
+
+	switch(s.st_mode & US_IFMT)
+	{
+	case US_IFREG:
+		result = uffs_remove(path);
+		break;
+	case US_IFDIR:
+		result = uffs_rmdir(path);
+		break;
+	default:
+		/* unknown file type */
+		return -1;
+	}
+	if (result < 0)
+		return uffs_result_to_dfs(uffs_get_error());
+
+	return 0;
+}
+
+static int dfs_uffs_rename(
+    struct dfs_filesystem* fs,
+    const char* oldpath,
+    const char* newpath)
+{
+	int result;
+	
+	result = uffs_rename(oldpath, newpath);
+	if (result < 0)
+		return uffs_result_to_dfs(uffs_get_error());
+
+	return 0;
+}
+
+static int dfs_uffs_stat(struct dfs_filesystem* fs, const char *path, struct stat *st)
+{
+	int result;
+	struct uffs_stat s;
+	struct rt_mtd_nand_device * mtd;
+
+	result = uffs_stat(path, &s);
+	if (result < 0)
+		return uffs_result_to_dfs(uffs_get_error());
+
+	/* convert uffs stat to dfs stat structure */
+	/* FIXME, these field may not be the same */
+	st->st_dev  = 0;
+	st->st_mode = s.st_mode;
+	st->st_size = s.st_size;
+	st->st_mtime = s.st_mtime;
+
+	mtd = RT_MTD_NAND_DEVICE(fs->dev_id);
+	st->st_blksize = mtd->page_size;
+
+	return 0;
+}
+
+static const struct dfs_filesystem_operation dfs_uffs_ops =
+{
+	"uffs", /* file system type: uffs */
+#if RTTHREAD_VERSION >= 10100
+	DFS_FS_FLAG_FULLPATH,
+#else
+#error "uffs can only work with rtthread whose version should >= 1.01\n"
+#endif
+	dfs_uffs_mount,
+	dfs_uffs_unmount,
+	dfs_uffs_mkfs,
+	dfs_uffs_statfs,
+
+	dfs_uffs_open,
+	dfs_uffs_close,
+	dfs_uffs_ioctl,
+	dfs_uffs_read,
+	dfs_uffs_write,
+	dfs_uffs_flush,
+	dfs_uffs_seek,
+	dfs_uffs_getdents,
+	dfs_uffs_unlink,
+	dfs_uffs_stat,
+	dfs_uffs_rename,
+};
+
+int dfs_uffs_init(void)
+{
+	/* register uffs file system */
+	dfs_register(&dfs_uffs_ops);
+
+	if (uffs_InitObjectBuf() == U_SUCC)
+	{
+		if (uffs_DirEntryBufInit() == U_SUCC)
+		{
+			uffs_InitGlobalFsLock();
+			return RT_EOK;
+		}
+	}
+	return -RT_ERROR;
+}