Import rtems wrapper from rtems git
authorSebastian Huber <sebastian.huber@embedded-brains.de>
Thu, 6 Feb 2020 20:03:41 +0000 (09:03 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Thu, 6 Feb 2020 20:03:41 +0000 (09:03 +1300)
https://git.rtems.org/sebh/rtems-yaffs2.git/
Commit:  23be2ac372173ecf701a0a

Most of this work was authored by

Sebastian Huber <sebastian.huber@embedded-brains.de>
Sebastien Bourdeauducq <sebastien@milkymist.org>

Note that the RTEMS licencing applies to all the rtems wrapper code.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
Makefile.rtems [new file with mode: 0644]
rtems/rtems_yaffs.c [new file with mode: 0644]
rtems/rtems_yaffs.h [new file with mode: 0644]
rtems/rtems_yaffs_os_context.c [new file with mode: 0644]
rtems/rtems_yaffs_os_glue.c [new file with mode: 0644]

diff --git a/Makefile.rtems b/Makefile.rtems
new file mode 100644 (file)
index 0000000..6c8e140
--- /dev/null
@@ -0,0 +1,76 @@
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+include $(RTEMS_MAKEFILE_PATH)/make/target.cfg
+
+INSTALL_BASE = $(RTEMS_MAKEFILE_PATH)/lib
+
+BUILDDIR = build-$(RTEMS_BSP)
+
+CPPFLAGS += -I. -Idirect -Idirect/rtems
+
+DEPFLAGS = -MT $@ -MD -MP -MF $(basename $@).d
+
+GCCFLAGS = -g -I . -B $(INSTALL_BASE) -specs bsp_specs -qrtems
+
+CFLAGS += $(DEPFLAGS) $(GCCFLAGS)
+
+INCLUDES = rtems/rtems_yaffs.h \
+       direct/yportenv.h \
+       direct/ydirectenv.h \
+       direct/yaffs_osglue.h \
+       direct/yaffs_hweight.h \
+       direct/yaffscfg.h \
+       direct/yaffs_list.h \
+       direct/yaffsfs.h \
+       yaffs_guts.h \
+       yaffs_packedtags2.h \
+       yaffs_ecc.h
+
+LIB = $(BUILDDIR)/libyaffs2.a
+LIB_PIECES = yaffs_ecc \
+       yaffs_guts \
+       yaffs_packedtags1 \
+       yaffs_tagscompat \
+       yaffs_packedtags2 \
+       yaffs_nand \
+       yaffs_checkptrw \
+       direct/yaffs_qsort \
+       yaffs_nameval \
+       yaffs_attribs \
+       yaffs_allocator \
+       yaffs_bitmap \
+       yaffs_yaffs1 \
+       yaffs_yaffs2 \
+       yaffs_verify \
+       yaffs_summary \
+       direct/yaffs_hweight \
+       rtems/rtems_yaffs \
+       rtems/rtems_yaffs_os_context \
+       rtems/rtems_yaffs_os_glue
+LIB_OBJS = $(LIB_PIECES:%=$(BUILDDIR)/%.o)
+LIB_DEPS = $(LIB_PIECES:%=$(BUILDDIR)/%.d)
+
+all: $(BUILDDIR) $(LIB)
+
+$(BUILDDIR):
+       mkdir $(BUILDDIR)
+       mkdir $(BUILDDIR)/direct
+       mkdir $(BUILDDIR)/rtems
+
+$(LIB): $(LIB_OBJS)
+       $(AR) rcu $@ $^
+       $(RANLIB) $@
+
+$(BUILDDIR)/%.o: %.c
+       $(CC) $(CPPFLAGS) $(CFLAGS) -c $< -o $@
+
+clean:
+       rm -rf $(BUILDDIR)
+
+install:  all
+       mkdir -p $(INSTALL_BASE)/include/yaffs
+       install -m 644 $(LIB) $(INSTALL_BASE)
+       install -m 644 $(INCLUDES) $(INSTALL_BASE)/include/yaffs
+
+.PHONY: clean install
+
+-include $(LIB_DEPS)
diff --git a/rtems/rtems_yaffs.c b/rtems/rtems_yaffs.c
new file mode 100644 (file)
index 0000000..b067f53
--- /dev/null
@@ -0,0 +1,705 @@
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ * Copyright (C) 2011 Stephan Hoffmann <sho@reLinux.de>
+ * Copyright (C) 2011-2012 embedded brains GmbH <rtems@embedded-brains.de>
+ *
+ * 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.
+ *
+ * As a special exception, linking other files with the object code from
+ * this one to produce an executable application does not by itself cause
+ * the resulting executable application to be covered by the GNU General
+ * Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#include <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.h>
+#include <sys/stat.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdlib.h>
+#include <dirent.h>
+
+#include "yportenv.h"
+
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yaffs_packedtags2.h"
+
+#include "rtems_yaffs.h"
+
+/* RTEMS interface */
+
+static const rtems_filesystem_file_handlers_r yaffs_directory_handlers;
+static const rtems_filesystem_file_handlers_r yaffs_file_handlers;
+static const rtems_filesystem_operations_table yaffs_ops;
+
+/* locking */
+
+static void ylock(struct yaffs_dev *dev)
+{
+       rtems_yaffs_os_context *os_context = dev->os_context;
+       (*os_context->lock)(dev, os_context);
+}
+
+static void yunlock(struct yaffs_dev *dev)
+{
+       rtems_yaffs_os_context *os_context = dev->os_context;
+       (*os_context->unlock)(dev, os_context);
+}
+
+static void rtems_yaffs_os_unmount(struct yaffs_dev *dev)
+{
+       rtems_yaffs_os_context *os_context = dev->os_context;
+       (*os_context->unmount)(dev, os_context);
+}
+
+static struct yaffs_obj *ryfs_get_object_by_location(
+       const rtems_filesystem_location_info_t *loc
+)
+{
+       return loc->node_access;
+}
+
+static struct yaffs_obj *ryfs_get_object_by_iop(
+       const rtems_libio_t *iop
+)
+{
+       return iop->pathinfo.node_access;
+}
+
+static struct yaffs_dev *ryfs_get_device_by_mt_entry(
+       const rtems_filesystem_mount_table_entry_t *mt_entry
+)
+{
+       return mt_entry->fs_info;
+}
+
+static void ryfs_set_location(rtems_filesystem_location_info_t *loc, struct yaffs_obj *obj)
+{
+       loc->node_access = obj;
+
+       switch (obj->variant_type) {
+               case YAFFS_OBJECT_TYPE_FILE:
+                       loc->handlers = &yaffs_file_handlers;
+                       break;
+               case YAFFS_OBJECT_TYPE_DIRECTORY:
+                       loc->handlers = &yaffs_directory_handlers;
+                       break;
+               default:
+                       loc->handlers = &rtems_filesystem_handlers_default;
+                       break;
+       };
+}
+
+static bool ryfs_eval_is_directory(
+       rtems_filesystem_eval_path_context_t *ctx,
+       void *arg
+)
+{
+       rtems_filesystem_location_info_t *currentloc =
+               rtems_filesystem_eval_path_get_currentloc(ctx);
+       struct yaffs_obj *obj = ryfs_get_object_by_location(currentloc);
+
+       obj = yaffs_get_equivalent_obj(obj);
+
+       return obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY;
+}
+
+static const char *ryfs_make_string(char *buf, const char *src, size_t len)
+{
+       buf [len] = '\0';
+
+       return memcpy(buf, src, len);
+}
+
+static struct yaffs_obj *ryfs_search_in_directory(
+       struct yaffs_obj *dir,
+       const char *token,
+       size_t tokenlen
+)
+{
+       if (rtems_filesystem_is_parent_directory(token, tokenlen)) {
+               dir = dir->parent;
+       } else if (!rtems_filesystem_is_current_directory(token, tokenlen)) {
+               if (tokenlen < YAFFS_MAX_NAME_LENGTH) {
+                       char buf [YAFFS_MAX_NAME_LENGTH + 1];
+
+                       dir = yaffs_find_by_name(
+                               dir,
+                               ryfs_make_string(buf, token, tokenlen)
+                       );
+               } else {
+                       dir = NULL;
+               }
+       }
+
+       return dir;
+}
+
+static rtems_filesystem_eval_path_generic_status ryfs_eval_token(
+       rtems_filesystem_eval_path_context_t *ctx,
+       void *arg,
+       const char *token,
+       size_t tokenlen
+)
+{
+       rtems_filesystem_eval_path_generic_status status =
+               RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_DONE;
+       rtems_filesystem_location_info_t *currentloc =
+               rtems_filesystem_eval_path_get_currentloc(ctx);
+       struct yaffs_obj *dir = ryfs_get_object_by_location(currentloc);
+       bool access_ok = rtems_filesystem_eval_path_check_access(
+               ctx,
+               RTEMS_FS_PERMS_EXEC,
+               dir->yst_mode,
+               (uid_t) dir->yst_uid,
+               (gid_t) dir->yst_gid
+       );
+
+       if (access_ok) {
+               struct yaffs_obj *entry = ryfs_search_in_directory(dir, token, tokenlen);
+
+               if (entry != NULL) {
+                       bool terminal = !rtems_filesystem_eval_path_has_path(ctx);
+                       int eval_flags = rtems_filesystem_eval_path_get_flags(ctx);
+                       bool follow_hard_link = (eval_flags & RTEMS_FS_FOLLOW_HARD_LINK) != 0;
+                       bool follow_sym_link = (eval_flags & RTEMS_FS_FOLLOW_SYM_LINK) != 0;
+                       enum yaffs_obj_type type = entry->variant_type;
+
+                       rtems_filesystem_eval_path_clear_token(ctx);
+
+                       if (type == YAFFS_OBJECT_TYPE_HARDLINK && (follow_hard_link || !terminal)) {
+                               entry = yaffs_get_equivalent_obj(entry);
+                       }
+
+                       if (type == YAFFS_OBJECT_TYPE_SYMLINK && (follow_sym_link || !terminal)) {
+                               const char *target = entry->variant.symlink_variant.alias;
+
+                               rtems_filesystem_eval_path_recursive(ctx, target, strlen(target));
+                       } else {
+                               ryfs_set_location(currentloc, entry);
+
+                               if (!terminal) {
+                                       status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_CONTINUE;
+                               }
+                       }
+               } else {
+                       status = RTEMS_FILESYSTEM_EVAL_PATH_GENERIC_NO_ENTRY;
+               }
+       }
+
+       return status;
+}
+
+static const rtems_filesystem_eval_path_generic_config ryfs_eval_config = {
+       .is_directory = ryfs_eval_is_directory,
+       .eval_token = ryfs_eval_token
+};
+
+static void ryfs_eval_path(rtems_filesystem_eval_path_context_t *ctx)
+{
+       rtems_filesystem_eval_path_generic(ctx, NULL, &ryfs_eval_config);
+}
+
+/* Helper functions */
+
+static int ryfs_mknod(
+       const rtems_filesystem_location_info_t *parentloc,
+       const char *name,
+       size_t namelen,
+       mode_t mode,
+       dev_t dev
+)
+{
+       int rv = 0;
+       struct yaffs_obj *parent = ryfs_get_object_by_location(parentloc);
+       struct yaffs_obj *(*create)(
+               struct yaffs_obj *parent,
+               const YCHAR *name,
+               u32 mode,
+               u32 uid,
+               u32 gid
+       );
+
+       switch (mode & S_IFMT) {
+               case S_IFREG:
+                       create = yaffs_create_file;
+                       break;
+               case S_IFDIR:
+                       create = yaffs_create_dir;
+                       break;
+               default:
+                       errno = EINVAL;
+                       rv = -1;
+                       break;
+       }
+
+       if (rv == 0) {
+               char buf [YAFFS_MAX_NAME_LENGTH + 1];
+               struct yaffs_obj *entry = (*create)(
+                       parent,
+                       ryfs_make_string(buf, name, namelen),
+                       mode,
+                       geteuid(),
+                       getegid()
+               );
+
+               if (entry == NULL) {
+                       errno = ENOSPC;
+                       rv = -1;
+               }
+       }
+
+       return rv;
+}
+
+static int ryfs_utime(
+       const rtems_filesystem_location_info_t *loc,
+       time_t actime,
+       time_t modtime
+)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+
+       obj = yaffs_get_equivalent_obj(obj);
+       if (obj != NULL) {
+               obj->dirty = 1;
+               obj->yst_atime = (u32) actime;
+               obj->yst_mtime = (u32) modtime;
+               obj->yst_ctime = (u32) time(NULL);
+       } else {
+               errno = EIO;
+               rv = -1;
+       }
+
+       return rv;
+}
+
+static int ryfs_rename(
+       const rtems_filesystem_location_info_t *old_parent_loc,
+       const rtems_filesystem_location_info_t *old_loc,
+       const rtems_filesystem_location_info_t *new_parent_loc,
+       const char *name,
+       size_t namelen
+)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_location(old_loc);
+       char old_name_buf [YAFFS_MAX_NAME_LENGTH + 1];
+       char new_name_buf [YAFFS_MAX_NAME_LENGTH + 1];
+       int yc;
+
+       yaffs_get_obj_name(obj, old_name_buf, sizeof(old_name_buf));
+       yc = yaffs_rename_obj(
+               obj->parent,
+               old_name_buf,
+               ryfs_get_object_by_location(new_parent_loc),
+               ryfs_make_string(new_name_buf, name, namelen)
+       );
+       if (yc != YAFFS_OK) {
+               errno = EIO;
+               rv = -1;
+       }
+
+       return rv;
+}
+
+static ssize_t ryfs_dir_read(rtems_libio_t *iop, void *buffer, size_t count)
+{
+       struct yaffs_obj *obj;
+       struct yaffs_dev *dev;
+       struct dirent *de = (struct dirent *)buffer;
+       size_t i;
+       size_t maxcount;
+       struct list_head *next;
+       ssize_t readlen;
+
+       obj = (struct yaffs_obj *)iop->pathinfo.node_access;
+       dev = obj->my_dev;
+       maxcount = count / sizeof(struct dirent);
+
+       ylock(dev);
+
+       if(iop->offset == 0) {
+               if(list_empty(&obj->variant.dir_variant.children))
+                       iop->data1 = NULL;
+               else
+                       iop->data1 = list_entry(obj->variant.dir_variant.children.next, struct yaffs_obj, siblings);
+       }
+
+       i = 0;
+       while((i < maxcount) && (iop->data1 != NULL)) {
+               de[i].d_ino = (long)yaffs_get_equivalent_obj((struct yaffs_obj *)iop->data1)->obj_id;
+               de[i].d_off = 0;
+               yaffs_get_obj_name((struct yaffs_obj *)iop->data1, de[i].d_name, NAME_MAX);
+               de[i].d_reclen = sizeof(struct dirent);
+               de[i].d_namlen = (unsigned short)strnlen(de[i].d_name, NAME_MAX);
+
+               i++;
+               next = ((struct yaffs_obj *)iop->data1)->siblings.next;
+               if(next == &obj->variant.dir_variant.children)
+                       iop->data1 = NULL; /* end of list */
+               else
+                       iop->data1 = list_entry(next, struct yaffs_obj, siblings);
+       }
+
+       readlen = (ssize_t)(i * sizeof(struct dirent));
+       iop->offset = iop->offset + readlen;
+
+       yunlock(dev);
+
+       return readlen;
+}
+
+static int ryfs_fstat(const rtems_filesystem_location_info_t *loc, struct stat *buf)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+       struct yaffs_dev *dev = obj->my_dev;
+       rtems_yaffs_os_context *os_context = dev->os_context;
+
+       ylock(dev);
+
+       obj = yaffs_get_equivalent_obj(obj);
+       if (obj != NULL) {
+               buf->st_dev = os_context->dev;
+               buf->st_ino = obj->obj_id;
+               buf->st_mode = obj->yst_mode;
+               buf->st_nlink = (nlink_t) yaffs_get_obj_link_count(obj);
+               buf->st_rdev = obj->yst_rdev;
+               buf->st_size = yaffs_get_obj_length(obj);
+               buf->st_blksize = obj->my_dev->data_bytes_per_chunk;
+               buf->st_blocks = (blkcnt_t)
+                       ((buf->st_size + buf->st_blksize - 1) / buf->st_blksize);
+               buf->st_uid = (uid_t) obj->yst_uid;
+               buf->st_gid = (gid_t) obj->yst_gid;
+               buf->st_atime = (time_t) obj->yst_atime;
+               buf->st_ctime = (time_t) obj->yst_ctime;
+               buf->st_mtime = (time_t) obj->yst_mtime;
+       } else {
+               errno = EIO;
+               rv = -1;
+       }
+
+       yunlock(dev);
+
+       return rv;
+}
+
+static int ryfs_fchmod(const rtems_filesystem_location_info_t *loc, mode_t mode)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+       int yc;
+
+       obj = yaffs_get_equivalent_obj(obj);
+       if (obj != NULL) {
+               obj->yst_mode = mode;
+               obj->dirty = 1;
+               yc = yaffs_flush_file(obj, 0, 0);
+       } else {
+               yc = YAFFS_FAIL;
+       }
+
+       if (yc != YAFFS_OK) {
+               errno = EIO;
+               rv = -1;
+       }
+
+       return rv;
+}
+
+static int ryfs_chown(
+       const rtems_filesystem_location_info_t *loc,
+       uid_t owner,
+       gid_t group
+)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+       int yc;
+
+       obj = yaffs_get_equivalent_obj(obj);
+       if (obj != NULL) {
+               obj->yst_uid = owner;
+               obj->yst_gid = group;
+               obj->dirty = 1;
+               yc = yaffs_flush_file(obj, 0, 0);
+       } else {
+               yc = YAFFS_FAIL;
+       }
+
+       if (yc != YAFFS_OK) {
+               errno = EIO;
+               rv = -1;
+       }
+
+       return rv;
+}
+
+static int ryfs_fsync_or_fdatasync(rtems_libio_t *iop)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+       struct yaffs_dev *dev = obj->my_dev;
+       int yc;
+
+       ylock(dev);
+       yc = yaffs_flush_file(obj, 0, 1);
+       if (rtems_filesystem_location_is_instance_root(&iop->pathinfo)) {
+               yaffs_flush_whole_cache(dev);
+       }
+       yunlock(dev);
+
+       if (yc != YAFFS_OK) {
+               errno = EIO;
+               rv = -1;
+       }
+
+       return rv;
+}
+
+static int ryfs_rmnod(
+       const rtems_filesystem_location_info_t *parentloc,
+       const rtems_filesystem_location_info_t *loc
+)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_location(loc);
+       int yc = yaffs_del_obj(obj);
+
+       if (yc != YAFFS_OK) {
+               errno = ENOTEMPTY;
+               rv = -1;
+       }
+
+       return rv;
+}
+
+static int ryfs_file_open(rtems_libio_t *iop, const char *pathname, int oflag, mode_t mode)
+{
+       struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+       struct yaffs_dev *dev = obj->my_dev;
+       int length = 0;
+
+       ylock(dev);
+       length = yaffs_get_obj_length(obj);
+       if ((iop->flags & LIBIO_FLAGS_APPEND) != 0) {
+               iop->offset = length;
+       }
+       yunlock(dev);
+
+       return 0;
+}
+
+static int ryfs_file_close(rtems_libio_t *iop)
+{
+       struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+       struct yaffs_dev *dev = obj->my_dev;
+
+       ylock(dev);
+       yaffs_flush_file(obj, 1, 0);
+       yunlock(dev);
+
+       return 0;
+}
+
+static ssize_t ryfs_file_read(rtems_libio_t *iop, void *buffer, size_t count)
+{
+       struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+       struct yaffs_dev *dev = obj->my_dev;
+       ssize_t nr;
+       int ol;
+       size_t maxread;
+
+       ylock(dev);
+
+       ol = yaffs_get_obj_length(obj);
+       if(iop->offset >= ol)
+               maxread = 0;
+       else
+               maxread = (size_t)(ol - (int)iop->offset);
+       if(count > maxread)
+               count = maxread;
+
+       nr = yaffs_file_rd(obj, buffer, iop->offset, (int)count);
+       if (nr >= 0) {
+               iop->offset += nr;
+       } else {
+               errno = EIO;
+               nr = -1;
+       }
+
+       yunlock(dev);
+
+       return nr;
+}
+
+static ssize_t ryfs_file_write(rtems_libio_t *iop, const void *buffer, size_t count)
+{
+       struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+       struct yaffs_dev *dev = obj->my_dev;
+       ssize_t rv = -1;
+       int max_size = INT_MAX;
+       off_t offset;
+
+       if (count == 0) {
+               return 0;
+       }
+
+       ylock(dev);
+       offset = iop->offset;
+       if (offset < max_size) {
+               size_t max_count = max_size - (size_t) offset;
+
+               if (count > max_count) {
+                       count = max_count;
+               }
+
+               rv = yaffs_wr_file(obj, buffer, offset, (int) count, 0);
+               if (rv > 0) {
+                       iop->offset += rv;
+               } else {
+                       errno = ENOSPC;
+                       rv = -1;
+               }
+       } else {
+               errno = EFBIG;
+       }
+       yunlock(dev);
+
+       return rv;
+}
+
+static int ryfs_file_ftruncate(rtems_libio_t *iop, off_t length)
+{
+       int rv = 0;
+       struct yaffs_obj *obj = ryfs_get_object_by_iop(iop);
+       struct yaffs_dev *dev = obj->my_dev;
+       int yc;
+
+       ylock(dev);
+       yc = yaffs_resize_file(obj, length);
+       yunlock(dev);
+
+       if (yc != YAFFS_OK) {
+               errno = EIO;
+               rv = -1;
+       }
+
+       return rv;
+}
+
+int rtems_yaffs_mount_handler(rtems_filesystem_mount_table_entry_t *mt_entry, const void *data)
+{
+       const rtems_yaffs_mount_data *mount_data = data;
+       struct yaffs_dev *dev = mount_data->dev;
+
+       if (dev->read_only && mt_entry->writeable) {
+               errno = EACCES;
+               return -1;
+       }
+
+       ylock(dev);
+       if (yaffs_guts_initialise(dev) == YAFFS_FAIL) {
+               yunlock(dev);
+               errno = ENOMEM;
+               return -1;
+       }
+
+       mt_entry->fs_info = dev;
+       mt_entry->ops = &yaffs_ops;
+       mt_entry->mt_fs_root->location.node_access = dev->root_dir;
+       mt_entry->mt_fs_root->location.handlers = &yaffs_directory_handlers;
+
+       yaffs_flush_whole_cache(dev);
+       yunlock(dev);
+
+       return 0;
+}
+
+static void ryfs_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+       struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry);
+
+       ylock(dev);
+       yaffs_flush_whole_cache(dev);
+       yaffs_deinitialise(dev);
+       yunlock(dev);
+       rtems_yaffs_os_unmount(dev);
+}
+
+static void ryfs_lock(const rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+       struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry);
+
+       ylock(dev);
+}
+
+static void ryfs_unlock(const rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+       struct yaffs_dev *dev = ryfs_get_device_by_mt_entry(mt_entry);
+
+       yunlock(dev);
+}
+
+static const rtems_filesystem_file_handlers_r yaffs_directory_handlers = {
+       .open_h = rtems_filesystem_default_open,
+       .close_h = rtems_filesystem_default_close,
+       .read_h = ryfs_dir_read,
+       .write_h = rtems_filesystem_default_write,
+       .ioctl_h = rtems_filesystem_default_ioctl,
+       .lseek_h = rtems_filesystem_default_lseek_directory,
+       .fstat_h = ryfs_fstat,
+       .ftruncate_h = rtems_filesystem_default_ftruncate_directory,
+       .fsync_h = ryfs_fsync_or_fdatasync,
+       .fdatasync_h = ryfs_fsync_or_fdatasync,
+       .fcntl_h = rtems_filesystem_default_fcntl
+};
+
+static const rtems_filesystem_file_handlers_r yaffs_file_handlers = {
+       .open_h = ryfs_file_open,
+       .close_h = ryfs_file_close,
+       .read_h = ryfs_file_read,
+       .write_h = ryfs_file_write,
+       .ioctl_h = rtems_filesystem_default_ioctl,
+       .lseek_h = rtems_filesystem_default_lseek_file,
+       .fstat_h = ryfs_fstat,
+       .ftruncate_h = ryfs_file_ftruncate,
+       .fsync_h = ryfs_fsync_or_fdatasync,
+       .fdatasync_h = ryfs_fsync_or_fdatasync,
+       .fcntl_h = rtems_filesystem_default_fcntl
+};
+
+static const rtems_filesystem_operations_table yaffs_ops = {
+       .lock_h = ryfs_lock,
+       .unlock_h = ryfs_unlock,
+       .eval_path_h = ryfs_eval_path,
+       .link_h = rtems_filesystem_default_link,
+       .are_nodes_equal_h = rtems_filesystem_default_are_nodes_equal,
+       .mknod_h = ryfs_mknod,
+       .rmnod_h = ryfs_rmnod,
+       .fchmod_h = ryfs_fchmod,
+       .chown_h = ryfs_chown,
+       .clonenod_h = rtems_filesystem_default_clonenode,
+       .freenod_h = rtems_filesystem_default_freenode,
+       .mount_h = rtems_filesystem_default_mount,
+       .unmount_h = rtems_filesystem_default_unmount,
+       .fsunmount_me_h = ryfs_fsunmount,
+       .utime_h = ryfs_utime,
+       .symlink_h = rtems_filesystem_default_symlink,
+       .readlink_h = rtems_filesystem_default_readlink,
+       .rename_h = ryfs_rename,
+       .statvfs_h = rtems_filesystem_default_statvfs
+};
diff --git a/rtems/rtems_yaffs.h b/rtems/rtems_yaffs.h
new file mode 100644 (file)
index 0000000..e94fba7
--- /dev/null
@@ -0,0 +1,126 @@
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (C) 2010 Sebastien Bourdeauducq
+ * Copyright (C) 2011 Stephan Hoffmann <sho@reLinux.de>
+ * Copyright (C) 2011 embedded brains GmbH <rtems@embedded-brains.de>
+ *
+ * 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.
+ * 
+ * As a special exception, including this header in a file does not by
+ * itself cause the resulting executable application to be covered by the
+ * GNU General Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#ifndef __RTEMS_YAFFS_H
+#define __RTEMS_YAFFS_H
+
+#include <rtems.h>
+#include <rtems/fs.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/* Must be inside the extern "C" */
+#include "yportenv.h"
+#include "yaffs_guts.h"
+
+/**
+ * @defgroup rtems_yaffs YAFFS Support for RTEMS
+ *
+ *
+ * @{
+ */
+
+#define RTEMS_FILESYSTEM_TYPE_YAFFS "yaffs"
+
+typedef void (*rtems_yaffs_os_handler)(
+  struct yaffs_dev *dev,
+  void *os_context
+);
+
+/**
+ * @brief Per YAFFS file system instance context.
+ */
+typedef struct {
+  rtems_yaffs_os_handler lock;
+  rtems_yaffs_os_handler unlock;
+  rtems_yaffs_os_handler unmount;
+
+  /**
+   * @brief The device containing the file system instance.
+   *
+   * This will be used for the st_dev field in stat().
+   */
+  dev_t dev;
+} rtems_yaffs_os_context;
+
+/**
+ * @brief Default per YAFFS file system instance context.
+ */
+typedef struct {
+  rtems_yaffs_os_context os_context;
+  rtems_id semaphore_id;
+} rtems_yaffs_default_os_context;
+
+/**
+ * @brief Data for YAFFS mount handler.
+ *
+ * @see rtems_yaffs_mount_handler()
+ */
+typedef struct {
+  /**
+   * @brief YAFFS device of the file system instance.
+   *
+   * The @a param field has to be completely set up.  The
+   * @a driver_context can point to arbitrary driver specific
+   * information.  The @a os_context must point to an initialized
+   * structure that begins with a rtems_yaffs_os_context structure.
+   */
+  struct yaffs_dev *dev;
+} rtems_yaffs_mount_data;
+
+/**
+ * @brief YAFFS mount handler.
+ *
+ * The @a data pointer must point to a completely initialized
+ * rtems_yaffs_mount_data structure.  The ownership of the YAFFS device
+ * structure changes.  This structure is now owned by the file system layer.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occurred.  The @c errno indicates the error.
+ */
+int rtems_yaffs_mount_handler(
+  rtems_filesystem_mount_table_entry_t *mt_entry,
+  const void *data
+);
+
+/**
+ * @brief Initializes the default per file system context @a os_context.
+ *
+ * A binary semaphore with priority inheritance will be used to ensure mutual
+ * exclusion.
+ *
+ * The umount handler will release all resources of the default context.
+ *
+ * @retval 0 Successful operation.
+ * @retval -1 An error occurred.  The @c errno indicates the error.
+ */
+int rtems_yaffs_initialize_default_os_context(
+  rtems_yaffs_default_os_context *os_context
+);
+
+/** @} */
+
+#ifdef __cplusplus
+}
+#endif /* __cplusplus */
+
+#endif /* __RTEMS_YAFFS_H */
diff --git a/rtems/rtems_yaffs_os_context.c b/rtems/rtems_yaffs_os_context.c
new file mode 100644 (file)
index 0000000..1885b9b
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (c) 2011 embedded brains GmbH.  All rights reserved.
+ *
+ *  embedded brains GmbH
+ *  Obere Lagerstr. 30
+ *  82178 Puchheim
+ *  Germany
+ *  <rtems@embedded-brains.de>
+ *
+ * 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.
+ *
+ * As a special exception, linking other files with the object code from
+ * this one to produce an executable application does not by itself cause
+ * the resulting executable application to be covered by the GNU General
+ * Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#include "rtems_yaffs.h"
+
+#include <assert.h>
+#include <errno.h>
+
+static void rtems_yaffs_default_lock(struct yaffs_dev *dev, void *arg)
+{
+       rtems_status_code sc = RTEMS_SUCCESSFUL;
+       rtems_yaffs_default_os_context *os_context = arg;
+
+        sc = rtems_semaphore_obtain(
+               os_context->semaphore_id,
+               RTEMS_WAIT,
+               RTEMS_NO_TIMEOUT
+       );
+       assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void rtems_yaffs_default_unlock(struct yaffs_dev *dev, void *arg)
+{
+       rtems_status_code sc = RTEMS_SUCCESSFUL;
+       rtems_yaffs_default_os_context *os_context = arg;
+
+        sc = rtems_semaphore_release(os_context->semaphore_id);
+       assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void rtems_yaffs_default_unmount(struct yaffs_dev *dev, void *arg)
+{
+       rtems_status_code sc = RTEMS_SUCCESSFUL;
+       rtems_yaffs_default_os_context *os_context = arg;
+
+        sc = rtems_semaphore_delete(os_context->semaphore_id);
+       assert(sc == RTEMS_SUCCESSFUL);
+}
+
+int rtems_yaffs_initialize_default_os_context(
+       rtems_yaffs_default_os_context *os_context
+)
+{
+       rtems_status_code sc = RTEMS_SUCCESSFUL;
+
+       os_context->os_context.lock = rtems_yaffs_default_lock;
+       os_context->os_context.unlock = rtems_yaffs_default_unlock;
+       os_context->os_context.unmount = rtems_yaffs_default_unmount;
+
+       sc = rtems_semaphore_create(
+               rtems_build_name('Y', 'A', 'F', 'S'),
+               1,
+               RTEMS_LOCAL
+                       | RTEMS_BINARY_SEMAPHORE
+                       | RTEMS_INHERIT_PRIORITY
+                       | RTEMS_PRIORITY,
+               0,
+               &os_context->semaphore_id
+       );
+       if (sc == RTEMS_SUCCESSFUL) {
+               return 0;
+       } else {
+               errno = ENOMEM;
+
+               return -1;
+       }
+}
diff --git a/rtems/rtems_yaffs_os_glue.c b/rtems/rtems_yaffs_os_glue.c
new file mode 100644 (file)
index 0000000..467d8b1
--- /dev/null
@@ -0,0 +1,45 @@
+/*
+ * YAFFS port to RTEMS
+ *
+ * Copyright (C) 2010, 2011 Sebastien Bourdeauducq
+ * Copyright (C) 2011 Stephan Hoffmann <sho@reLinux.de>
+ * Copyright (C) 2011 embedded brains GmbH <rtems@embedded-brains.de>
+ *
+ * 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.
+ *
+ * As a special exception, linking other files with the object code from
+ * this one to produce an executable application does not by itself cause
+ * the resulting executable application to be covered by the GNU General
+ * Public License.
+ * This exception does not however invalidate any other reasons why the
+ * executable file might be covered by the GNU Public License. In particular,
+ * the other YAFFS files are not covered by this exception, and using them
+ * in a proprietary application requires a paid license from Aleph One.
+ */
+
+#include <stdlib.h>
+#include <time.h>
+
+#include "yaffs_trace.h"
+#include "yaffs_osglue.h"
+
+unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS;
+
+unsigned int yaffs_wr_attempts;
+
+void *yaffsfs_malloc(size_t size)
+{
+       return malloc(size);
+}
+
+void yaffsfs_free(void *ptr)
+{
+       free(ptr);
+}
+
+u32 yaffsfs_CurrentTime(void)
+{
+       return time(NULL);
+}