From a73832d9e795dba05770c0aec8af728cd78fcd8c Mon Sep 17 00:00:00 2001 From: Sebastian Huber Date: Fri, 7 Feb 2020 09:03:41 +1300 Subject: [PATCH] Import rtems wrapper from rtems git https://git.rtems.org/sebh/rtems-yaffs2.git/ Commit: 23be2ac372173ecf701a0a Most of this work was authored by Sebastian Huber Sebastien Bourdeauducq Note that the RTEMS licencing applies to all the rtems wrapper code. Signed-off-by: Charles Manning --- Makefile.rtems | 76 ++++ rtems/rtems_yaffs.c | 705 +++++++++++++++++++++++++++++++++ rtems/rtems_yaffs.h | 126 ++++++ rtems/rtems_yaffs_os_context.c | 89 +++++ rtems/rtems_yaffs_os_glue.c | 45 +++ 5 files changed, 1041 insertions(+) create mode 100644 Makefile.rtems create mode 100644 rtems/rtems_yaffs.c create mode 100644 rtems/rtems_yaffs.h create mode 100644 rtems/rtems_yaffs_os_context.c create mode 100644 rtems/rtems_yaffs_os_glue.c diff --git a/Makefile.rtems b/Makefile.rtems new file mode 100644 index 0000000..6c8e140 --- /dev/null +++ b/Makefile.rtems @@ -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 index 0000000..b067f53 --- /dev/null +++ b/rtems/rtems_yaffs.c @@ -0,0 +1,705 @@ +/* + * YAFFS port to RTEMS + * + * Copyright (C) 2010, 2011 Sebastien Bourdeauducq + * Copyright (C) 2011 Stephan Hoffmann + * Copyright (C) 2011-2012 embedded brains GmbH + * + * 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 +#include +#include +#include +#include +#include +#include +#include +#include + +#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 index 0000000..e94fba7 --- /dev/null +++ b/rtems/rtems_yaffs.h @@ -0,0 +1,126 @@ +/* + * YAFFS port to RTEMS + * + * Copyright (C) 2010 Sebastien Bourdeauducq + * Copyright (C) 2011 Stephan Hoffmann + * Copyright (C) 2011 embedded brains GmbH + * + * 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 +#include + +#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 index 0000000..1885b9b --- /dev/null +++ b/rtems/rtems_yaffs_os_context.c @@ -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 + * + * + * 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 +#include + +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 index 0000000..467d8b1 --- /dev/null +++ b/rtems/rtems_yaffs_os_glue.c @@ -0,0 +1,45 @@ +/* + * YAFFS port to RTEMS + * + * Copyright (C) 2010, 2011 Sebastien Bourdeauducq + * Copyright (C) 2011 Stephan Hoffmann + * Copyright (C) 2011 embedded brains GmbH + * + * 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 +#include + +#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); +} -- 2.30.2