summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--Makefile.rtems76
-rw-r--r--direct/yaffsfs.h4
-rw-r--r--direct/yportenv.h15
-rw-r--r--rtems/rtems_yaffs.c890
-rw-r--r--rtems/rtems_yaffs.h119
-rw-r--r--rtems/rtems_yaffs_os_context.c89
-rw-r--r--rtems/rtems_yaffs_os_glue.c45
-rw-r--r--utils/Makefile6
-rw-r--r--utils/mkyaffs2image.c84
-rw-r--r--yaffs_packedtags2.c9
11 files changed, 1319 insertions, 20 deletions
diff --git a/.gitignore b/.gitignore
index 97f1da3..c0df74f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,4 +5,4 @@
*.pyc
DEADJOE
*.mod.c
-
+build-*
diff --git a/Makefile.rtems b/Makefile.rtems
new file mode 100644
index 0000000..7137c04
--- /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 -t $(INSTALL_BASE) $(LIB)
+ install -m 644 -t $(INSTALL_BASE)/include/yaffs $(INCLUDES)
+
+.PHONY: clean install
+
+-include $(LIB_DEPS)
diff --git a/direct/yaffsfs.h b/direct/yaffsfs.h
index 6b6b328..57caca0 100644
--- a/direct/yaffsfs.h
+++ b/direct/yaffsfs.h
@@ -25,6 +25,10 @@
#include "yaffscfg.h"
#include "yportenv.h"
+#ifdef __rtems__
+#include <sys/types.h>
+typedef __loff_t loff_t;
+#endif
//typedef long off_t;
//typedef long dev_t;
diff --git a/direct/yportenv.h b/direct/yportenv.h
index 0d0d0fa..69509e0 100644
--- a/direct/yportenv.h
+++ b/direct/yportenv.h
@@ -23,6 +23,21 @@ typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned u32;
+#ifdef __rtems__
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <errno.h>
+
+#define CONFIG_YAFFS_DIRECT 1
+#define CONFIG_YAFFS_SHORT_NAMES_IN_RAM 1
+#define CONFIG_YAFFS_YAFFS2 1
+#define CONFIG_YAFFS_PROVIDE_DEFS 1
+#define CONFIG_YAFFSFS_PROVIDE_VALUES 1
+#define NO_Y_INLINE 1
+
+#endif /* __rtems__ */
#ifdef CONFIG_YAFFS_PROVIDE_DEFS
/* File types */
diff --git a/rtems/rtems_yaffs.c b/rtems/rtems_yaffs.c
new file mode 100644
index 0000000..b9ae049
--- /dev/null
+++ b/rtems/rtems_yaffs.c
@@ -0,0 +1,890 @@
+/*
+ * 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 <rtems.h>
+#include <rtems/libio_.h>
+#include <rtems/seterr.h>
+#include <rtems/userenv.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"
+
+#define MAX_SIZE 0x7fffffff
+
+/* 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);
+}
+
+/* Helper functions */
+
+static int is_valid_offset(rtems_off64_t offset)
+{
+ return (0 <= offset && offset <= MAX_SIZE);
+}
+
+static int is_path_divider(YCHAR ch)
+{
+ const YCHAR *str = YAFFS_PATH_DIVIDERS;
+
+ while(*str){
+ if(*str == ch)
+ return 1;
+ str++;
+ }
+
+ return 0;
+}
+
+static struct yaffs_obj *h_find_object(struct yaffs_dev *dev, struct yaffs_obj *dir, const char *pathname, const char **out_of_fs);
+
+static struct yaffs_obj *h_follow_link(struct yaffs_obj *obj, const char **out_of_fs)
+{
+ if(obj)
+ obj = yaffs_get_equivalent_obj(obj);
+
+ while(obj && obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK) {
+ YCHAR *alias = obj->variant.symlink_variant.alias;
+
+ if(is_path_divider(*alias))
+ /* Starts with a /, need to scan from root up */
+ obj = h_find_object(obj->my_dev, NULL, alias, out_of_fs);
+ else
+ /* Relative to here, so use the parent of the symlink as a start */
+ obj = h_find_object(obj->my_dev, obj->parent, alias, out_of_fs);
+ }
+ return obj;
+}
+
+
+static struct yaffs_obj *h_find_object(struct yaffs_dev *dev, struct yaffs_obj *dir, const char *pathname, const char **out_of_fs)
+{
+ YCHAR str[YAFFS_MAX_NAME_LENGTH+1];
+ int i;
+ char sux[NAME_MAX];
+
+ /* RTEMS sometimes calls eval_path with pathloc already pointing to the file to look for
+ * and name being the name of the file. Deal with this case.
+ * And no, I have no idea either.
+ */
+ if(strchr(pathname, '/') == NULL) {
+ yaffs_get_obj_name(dir, sux, NAME_MAX);
+ if(strcmp(sux, pathname) == 0)
+ return dir;
+ }
+
+ *out_of_fs = NULL;
+
+ if(!dev->is_mounted)
+ return NULL;
+
+ if(dir == NULL)
+ dir = dev->root_dir;
+
+ while(dir) {
+ /*
+ * parse off /.
+ * curve ball: also throw away surplus '/'
+ * eg. "/ram/x////ff" gets treated the same as "/ram/x/ff"
+ */
+ while(is_path_divider(*pathname))
+ pathname++; /* get rid of '/' */
+
+ i = 0;
+ str[0] = 0;
+
+ while(*pathname && !is_path_divider(*pathname)) {
+ if (i < YAFFS_MAX_NAME_LENGTH) {
+ str[i] = *pathname;
+ str[i+1] = '\0';
+ i++;
+ }
+ pathname++;
+ }
+
+ if(strcmp(str, _Y(".")) == 0) {
+ /* Do nothing */
+ } else if(strcmp(str, _Y("..")) == 0) {
+ if(dir->parent != NULL)
+ dir = dir->parent;
+ else {
+ while(is_path_divider(*pathname))
+ pathname++; /* get rid of '/' */
+ *out_of_fs = pathname;
+ return NULL;
+ }
+ }
+ else {
+ if(str[0] != 0) {
+ if(dir->variant_type != YAFFS_OBJECT_TYPE_DIRECTORY)
+ return NULL;
+ dir = yaffs_find_by_name(dir, str);
+ }
+ dir = h_follow_link(dir, out_of_fs);
+ }
+
+ if(!*pathname)
+ /* got to the end of the string */
+ return dir;
+ }
+
+ return NULL;
+}
+
+/* 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;
+
+//#define VERBOSE_DEBUG
+
+static int ycb_eval_path(const char *pathname, size_t pathnamelen, int flags, rtems_filesystem_location_info_t *pathloc)
+{
+ const char *out_of_fs;
+ struct yaffs_dev *dev;
+ struct yaffs_obj *obj;
+
+ dev = pathloc->mt_entry->fs_info;
+
+ /* The RTEMS eval path system is not a good idea. */
+ ylock(dev);
+ obj = h_find_object(dev, pathloc->node_access, pathname, &out_of_fs);
+ yunlock(dev);
+ if(obj == NULL) {
+ /* Really. It is not. */
+ int extra;
+
+ if(out_of_fs == NULL) {
+#ifdef VERBOSE_DEBUG
+ printf("newnode: ENOENT (%s)\n", pathname);
+#endif
+ rtems_set_errno_and_return_minus_one(ENOENT);
+ }
+#ifdef VERBOSE_DEBUG
+ printf("newnode: out of fs (%s -> %s) we@%p callback@%p\n", pathname, out_of_fs, ycb_eval_path, pathloc->mt_entry->mt_point_node.ops->evalpath_h);
+#endif
+ *pathloc = pathloc->mt_entry->mt_point_node;
+ extra = 0;
+ while(is_path_divider(*(out_of_fs-1))) {
+ out_of_fs--;
+ extra++;
+ }
+ return pathloc->ops->evalpath_h(out_of_fs-2, pathnamelen - (out_of_fs - pathname) + 2 + extra, flags, pathloc);
+ }
+ pathloc->node_access = obj;
+ pathloc->ops = &yaffs_ops;
+ if(obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
+ pathloc->handlers = &yaffs_directory_handlers;
+ else if(obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
+ pathloc->handlers = &yaffs_file_handlers;
+ else {
+ errno = ENOSYS;
+ return -1;
+ }
+#ifdef VERBOSE_DEBUG
+ printf("newnode: %p (path: %s, flags: %x)\n", pathloc->node_access, pathname, flags);
+#endif
+ return 0;
+}
+
+static int ycb_eval_path_for_make(const char *path, rtems_filesystem_location_info_t *pathloc, const char **name)
+{
+ char *s;
+ char *path1, *path2;
+ int r, i;
+
+ path1 = strdup(path);
+ if(path1 == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ i = strlen(path1) - 1;
+ while((i >= 0) && (path1[i] == '/')) {
+ path1[i] = '\0';
+ i--;
+ }
+
+ s = strrchr(path1, '/');
+ if(s == NULL) {
+ *name = path;
+ free(path1);
+ return ycb_eval_path(".", strlen(path), 0, pathloc);
+ }
+
+ *name = path + (s - path1) + 1;
+
+ path2 = strdup(path);
+ if(path2 == NULL) {
+ errno = ENOMEM;
+ free(path1);
+ return -1;
+ }
+ s = path2 + (s - path1);
+ *s = 0;
+ r = ycb_eval_path(path2, strlen(path2), 0, pathloc);
+ free(path1);
+ free(path2);
+
+ if(r == 0) {
+ if(pathloc->handlers != &yaffs_directory_handlers) {
+ pathloc->ops->freenod_h(pathloc);
+ errno = EINVAL;
+ return -1;
+ }
+ }
+
+ return r;
+}
+
+static int ycb_link(rtems_filesystem_location_info_t *to_loc, rtems_filesystem_location_info_t *parent_loc, const char *name)
+{
+ /* TODO */
+ errno = ENOSYS;
+ return -1;
+}
+
+static int ycb_dir_rmnod(rtems_filesystem_location_info_t *parent_loc, rtems_filesystem_location_info_t *pathloc);
+
+static int ycb_unlink(rtems_filesystem_location_info_t *parent_pathloc, rtems_filesystem_location_info_t *pathloc)
+{
+ return ycb_dir_rmnod(parent_pathloc, pathloc);
+}
+
+static rtems_filesystem_node_types_t ycb_node_type(rtems_filesystem_location_info_t *pathloc)
+{
+ struct yaffs_obj *obj;
+
+ obj = pathloc->node_access;
+ switch(obj->variant_type) {
+ case YAFFS_OBJECT_TYPE_FILE:
+ return RTEMS_FILESYSTEM_MEMORY_FILE;
+ case YAFFS_OBJECT_TYPE_SYMLINK:
+ return RTEMS_FILESYSTEM_SYM_LINK;
+ case YAFFS_OBJECT_TYPE_DIRECTORY:
+ return RTEMS_FILESYSTEM_DIRECTORY;
+ case YAFFS_OBJECT_TYPE_HARDLINK:
+ return RTEMS_FILESYSTEM_HARD_LINK;
+ case YAFFS_OBJECT_TYPE_SPECIAL:
+ return RTEMS_FILESYSTEM_DEVICE;
+ default: /* YAFFS_OBJECT_TYPE_UNKNOWN */
+ errno = EINVAL;
+ return -1;
+ }
+}
+
+static int ycb_mknod(const char *path, mode_t mode, dev_t the_dev, rtems_filesystem_location_info_t *pathloc)
+{
+ char *name, *s;
+ int ret = 0;
+
+ struct yaffs_obj *parent = pathloc->node_access;
+ struct yaffs_dev *dev = parent->my_dev;
+
+ name = strdup(path);
+ if(name == NULL) {
+ errno = ENOMEM;
+ return -1;
+ }
+ s = strchr(name, '/');
+ if(s != NULL)
+ *s = '\0';
+
+ if(parent->my_dev->read_only) {
+ errno = EROFS;
+ free(name);
+ return -1;
+ }
+
+ ylock(dev);
+
+ if(yaffs_find_by_name(parent, name)) {
+ errno = EEXIST;
+ ret = -1;
+ goto free;
+ }
+
+ if(S_ISDIR(mode)) {
+ struct yaffs_obj *dir;
+
+ dir = yaffs_create_dir(parent, name, mode, 0, 0);
+ if(dir == NULL) {
+ errno = ENOSPC; /* just assume no space */
+ ret = -1;
+ goto free;
+ }
+ } else if(S_ISREG(mode)) {
+ struct yaffs_obj *file;
+
+ file = yaffs_create_file(parent, name, mode, 0, 0);
+ if(file == NULL) {
+ errno = ENOSPC; /* just assume no space */
+ ret = -1;
+ goto free;
+ }
+ } else {
+ printf("mknod of unsupported type\n");
+ errno = ENOSYS;
+ ret = -1;
+ goto free;
+ }
+free:
+ yunlock(dev);
+ free(name);
+ return ret;
+}
+
+static int ycb_chown(rtems_filesystem_location_info_t *pathloc, uid_t owner, gid_t group)
+{
+ /* not implemented */
+ errno = 0;
+ return 0;
+}
+
+static int ycb_freenod(rtems_filesystem_location_info_t *pathloc)
+{
+#ifdef VERBOSE_DEBUG
+ printf("freenode: %p\n", pathloc->node_access);
+#endif
+ return 0;
+}
+
+static int ycb_mount(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ /* not implemented */
+ errno = ENOSYS;
+ return -1;
+}
+
+static int ycb_unmount(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ /* not implemented */
+ errno = ENOSYS;
+ return -1;
+}
+
+static int ycb_fsunmount(rtems_filesystem_mount_table_entry_t *mt_entry)
+{
+ struct yaffs_dev *dev = mt_entry->fs_info;
+
+ ylock(dev);
+ yaffs_flush_whole_cache(dev);
+ yaffs_deinitialise(dev);
+ yunlock(dev);
+ rtems_yaffs_os_unmount(dev);
+
+ return 0;
+}
+
+static int ycb_utime(rtems_filesystem_location_info_t *pathloc, time_t actime, time_t modtime)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+
+ obj = pathloc->node_access;
+ dev = obj->my_dev;
+
+ ylock(dev);
+ obj = yaffs_get_equivalent_obj(obj);
+ if(obj != NULL) {
+ obj->dirty = 1;
+ obj->yst_atime = obj->yst_ctime = (u32)actime;
+ obj->yst_mtime = (u32)modtime;
+ }
+ yunlock(dev);
+ return 0;
+}
+
+static int ycb_evaluate_link(rtems_filesystem_location_info_t *pathloc, int flags)
+{
+ /* TODO */
+ errno = ENOSYS;
+ return -1;
+}
+
+static int ycb_symlink(rtems_filesystem_location_info_t *loc, const char *link_name, const char *node_name)
+{
+ /* TODO */
+ errno = ENOSYS;
+ return -1;
+}
+
+static ssize_t ycb_readlink(rtems_filesystem_location_info_t *loc, char *buf, size_t bufsize)
+{
+ /* TODO */
+ errno = ENOSYS;
+ return -1;
+}
+
+static int ycb_rename(rtems_filesystem_location_info_t *old_parent_loc, rtems_filesystem_location_info_t *old_loc, rtems_filesystem_location_info_t *new_parent_loc, const char *name)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ int r;
+ char oldname[NAME_MAX];
+
+ obj = old_loc->node_access;
+ dev = obj->my_dev;
+
+ if(obj->my_dev->read_only) {
+ errno = EROFS;
+ return -1;
+ }
+
+ ylock(dev);
+ yaffs_get_obj_name(obj, oldname, NAME_MAX);
+ r = yaffs_rename_obj(obj->parent, oldname, new_parent_loc->node_access, name);
+ if(r == YAFFS_FAIL) {
+ yunlock(dev);
+ errno = EIO;
+ return -1;
+ }
+ yunlock(dev);
+ return 0;
+}
+
+static int ycb_statvfs(rtems_filesystem_location_info_t *loc, struct statvfs *buf)
+{
+ /* TODO */
+ printf("%s\n", __func__);
+ errno = ENOSYS;
+ return -1;
+}
+
+static int ycb_dir_open(rtems_libio_t *iop, const char *pathname, uint32_t flag, uint32_t mode)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static int ycb_dir_close(rtems_libio_t *iop)
+{
+ /* nothing to do */
+ return 0;
+}
+
+static ssize_t ycb_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 rtems_off64_t ycb_dir_lseek(rtems_libio_t *iop, rtems_off64_t length, int whence)
+{
+ /* We support only rewinding */
+ if (whence == SEEK_SET && length == 0) {
+ return 0;
+ } else {
+ rtems_set_errno_and_return_minus_one(EINVAL);
+ }
+}
+
+static int ycb_fstat(rtems_filesystem_location_info_t *loc, struct stat *buf)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+
+ obj = (struct yaffs_obj *)loc->node_access;
+ dev = (struct yaffs_dev *)obj->my_dev;
+
+ ylock(dev);
+
+ obj = yaffs_get_equivalent_obj(obj);
+
+ buf->st_ino = obj->obj_id;
+ buf->st_mode = obj->yst_mode & ~(unsigned)S_IFMT; /* clear out file type bits */
+
+ if(obj->variant_type == YAFFS_OBJECT_TYPE_DIRECTORY)
+ buf->st_mode |= S_IFDIR;
+ else if(obj->variant_type == YAFFS_OBJECT_TYPE_SYMLINK)
+ buf->st_mode |= S_IFLNK;
+ else if(obj->variant_type == YAFFS_OBJECT_TYPE_FILE)
+ buf->st_mode |= S_IFREG;
+
+ buf->st_rdev = 0ll;
+ buf->st_nlink = (nlink_t)yaffs_get_obj_link_count(obj);
+ buf->st_uid = 0;
+ buf->st_gid = 0;
+ 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_atime = (time_t)obj->yst_atime;
+ buf->st_ctime = (time_t)obj->yst_ctime;
+ buf->st_mtime = (time_t)obj->yst_mtime;
+
+ yunlock(dev);
+
+ return 0;
+}
+
+static int ycb_fchmod(rtems_filesystem_location_info_t *loc, mode_t mode)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ int result;
+
+ if(mode & ~(0777u)){
+ errno = EINVAL;
+ return -1;
+ }
+
+ obj = loc->node_access;
+ if(obj->my_dev->read_only) {
+ errno = EROFS;
+ return -1;
+ }
+
+ dev = obj->my_dev;
+
+ ylock(dev);
+
+ obj = yaffs_get_equivalent_obj(obj);
+
+ result = YAFFS_FAIL;
+ if(obj) {
+ obj->yst_mode = (obj->yst_mode & ~0777u) | mode;
+ obj->dirty = 1;
+ result = yaffs_flush_file(obj, 0, 0);
+ }
+ if(result != YAFFS_OK) {
+ yunlock(dev);
+ errno = EIO;
+ return -1;
+ }
+ yunlock(dev);
+ return 0;
+}
+
+static int ycb_fdatasync(rtems_libio_t *iop)
+{
+ const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo;
+ struct yaffs_obj *obj = pathinfo->node_access;
+ struct yaffs_dev *dev = obj->my_dev;
+ int yc = YAFFS_OK;
+
+ ylock(dev);
+ yc = yaffs_flush_file(obj, 0, 1);
+ if (rtems_filesystem_is_root_location(pathinfo)) {
+ yaffs_flush_whole_cache(dev);
+ }
+ yunlock(dev);
+
+ if (yc == YAFFS_OK) {
+ return 0;
+ } else {
+ rtems_set_errno_and_return_minus_one(EIO);
+ }
+}
+
+static int ycb_dir_rmnod(rtems_filesystem_location_info_t *parent_loc, rtems_filesystem_location_info_t *pathloc)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ int r;
+
+ obj = pathloc->node_access;
+ if(obj->my_dev->read_only) {
+ errno = EROFS;
+ return -1;
+ }
+ dev = obj->my_dev;
+ ylock(dev);
+ r = yaffs_del_obj(obj);
+ yunlock(dev);
+ if(r == YAFFS_FAIL) {
+ errno = ENOTEMPTY;
+ return -1;
+ }
+ return 0;
+}
+
+static int ycb_file_open(rtems_libio_t *iop, const char *pathname, uint32_t flag, uint32_t mode)
+{
+ const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo;
+ struct yaffs_obj *obj = pathinfo->node_access;
+ struct yaffs_dev *dev = obj->my_dev;
+ int length = 0;
+
+ ylock(dev);
+ length = yaffs_get_obj_length(obj);
+ iop->size = length;
+ if ((iop->flags & LIBIO_FLAGS_APPEND) != 0) {
+ iop->offset = length;
+ }
+ yunlock(dev);
+
+ return 0;
+}
+
+static int ycb_file_close(rtems_libio_t *iop)
+{
+ const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo;
+ struct yaffs_obj *obj = pathinfo->node_access;
+ struct yaffs_dev *dev = obj->my_dev;
+
+ ylock(dev);
+ yaffs_flush_file(obj, 1, 0);
+ yunlock(dev);
+
+ return 0;
+}
+
+static ssize_t ycb_file_read(rtems_libio_t *iop, void *buffer, size_t count)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ ssize_t nr;
+ int ol;
+ size_t maxread;
+
+ obj = iop->pathinfo.node_access;
+ dev = obj->my_dev;
+
+ 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);
+
+ yunlock(dev);
+
+ if(nr < 0) {
+ errno = ENOSPC;
+ return -1;
+ }
+ return nr;
+}
+
+static ssize_t ycb_file_write(rtems_libio_t *iop, const void *buffer, size_t count)
+{
+ const rtems_filesystem_location_info_t *pathinfo = &iop->pathinfo;
+ struct yaffs_obj *obj = pathinfo->node_access;
+ struct yaffs_dev *dev = obj->my_dev;
+ rtems_off64_t offset = 0;
+ rtems_off64_t new_offset = 0;
+ ssize_t rv = -1;
+
+ if (count == 0) {
+ return 0;
+ }
+
+ ylock(dev);
+ offset = iop->offset;
+ new_offset = offset + count;
+ if (is_valid_offset(new_offset)) {
+ rv = yaffs_wr_file(obj, buffer, offset, (int) count, 0);
+ if (rv > 0) {
+ iop->size = yaffs_get_obj_length(obj);
+ } else {
+ errno = ENOSPC;
+ }
+ } else {
+ errno = EINVAL;
+ }
+ yunlock(dev);
+
+ return rv;
+}
+
+static rtems_off64_t ycb_file_lseek(rtems_libio_t *iop, rtems_off64_t offset, int whence)
+{
+ if (is_valid_offset(iop->offset)) {
+ return iop->offset;
+ } else {
+ rtems_set_errno_and_return_minus_one(EINVAL);
+ }
+}
+
+int ycb_file_ftruncate(rtems_libio_t *iop, rtems_off64_t length)
+{
+ struct yaffs_obj *obj;
+ struct yaffs_dev *dev;
+ int r;
+
+ obj = iop->pathinfo.node_access;
+ dev = obj->my_dev;
+ ylock(dev);
+ r = yaffs_resize_file(obj, length);
+ yunlock(dev);
+ if(r == YAFFS_FAIL) {
+ errno = EIO;
+ return -1;
+ }
+ iop->size = length;
+ return 0;
+}
+
+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->options & RTEMS_FILESYSTEM_READ_WRITE) != 0) {
+ errno = EACCES;
+ return -1;
+ }
+
+ ylock(dev);
+ if (yaffs_guts_initialise(dev) == YAFFS_FAIL) {
+ yunlock(dev);
+ errno = ENOMEM;
+ return -1;
+ }
+
+ mt_entry->mt_fs_root.node_access = dev->root_dir;
+ mt_entry->mt_fs_root.handlers = &yaffs_directory_handlers;
+ mt_entry->mt_fs_root.ops = &yaffs_ops;
+ mt_entry->fs_info = dev;
+
+ yaffs_flush_whole_cache(dev);
+ yunlock(dev);
+
+ return 0;
+}
+
+static const rtems_filesystem_file_handlers_r yaffs_directory_handlers = {
+ .open_h = ycb_dir_open,
+ .close_h = ycb_dir_close,
+ .read_h = ycb_dir_read,
+ .write_h = rtems_filesystem_default_write, /* write */
+ .ioctl_h = rtems_filesystem_default_ioctl, /* ioctl */
+ .lseek_h = ycb_dir_lseek,
+ .fstat_h = ycb_fstat,
+ .fchmod_h = ycb_fchmod,
+ .ftruncate_h = rtems_filesystem_default_ftruncate, /* ftruncate */
+ .fpathconf_h = rtems_filesystem_default_fpathconf, /* fpathconf */
+ .fsync_h = ycb_fdatasync, /* fsync */
+ .fdatasync_h = ycb_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl, /* fcntl */
+ .rmnod_h = ycb_dir_rmnod
+};
+
+static const rtems_filesystem_file_handlers_r yaffs_file_handlers = {
+ .open_h = ycb_file_open,
+ .close_h = ycb_file_close,
+ .read_h = ycb_file_read,
+ .write_h = ycb_file_write,
+ .ioctl_h = rtems_filesystem_default_ioctl, /* ioctl */
+ .lseek_h = ycb_file_lseek,
+ .fstat_h = ycb_fstat,
+ .fchmod_h = rtems_filesystem_default_fchmod, /* fchmod */
+ .ftruncate_h = ycb_file_ftruncate,
+ .fpathconf_h = rtems_filesystem_default_fpathconf, /* fpathconf */
+ .fsync_h = ycb_fdatasync, /* fsync */
+ .fdatasync_h = ycb_fdatasync,
+ .fcntl_h = rtems_filesystem_default_fcntl, /* fcntl */
+ .rmnod_h = rtems_filesystem_default_rmnod /* rmnod */
+};
+
+static const rtems_filesystem_operations_table yaffs_ops = {
+ .evalpath_h = ycb_eval_path,
+ .evalformake_h = ycb_eval_path_for_make,
+ .link_h = ycb_link,
+ .unlink_h = ycb_unlink,
+ .node_type_h = ycb_node_type,
+ .mknod_h = ycb_mknod,
+ .chown_h = ycb_chown,
+ .freenod_h = ycb_freenod,
+ .mount_h = ycb_mount,
+ .fsmount_me_h = rtems_yaffs_mount_handler,
+ .unmount_h = ycb_unmount,
+ .fsunmount_me_h = ycb_fsunmount,
+ .utime_h = ycb_utime,
+ .eval_link_h = ycb_evaluate_link,
+ .symlink_h = ycb_symlink,
+ .readlink_h = ycb_readlink,
+ .rename_h = ycb_rename,
+ .statvfs_h = ycb_statvfs
+};
+
+/* Yeah, who thought writing filesystem glue code could ever be so complicated? */
diff --git a/rtems/rtems_yaffs.h b/rtems/rtems_yaffs.h
new file mode 100644
index 0000000..dce8204
--- /dev/null
+++ b/rtems/rtems_yaffs.h
@@ -0,0 +1,119 @@
+/*
+ * 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;
+} 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 initizialized
+ * 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 occured. 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 inheritence 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 occured. 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
+ * <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
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 <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);
+}
diff --git a/utils/Makefile b/utils/Makefile
index 710ebbf..ef02aec 100644
--- a/utils/Makefile
+++ b/utils/Makefile
@@ -16,7 +16,7 @@
#KERNELDIR = /usr/src/kernel-headers-2.4.18
-CFLAGS = -O2 -Wall -DCONFIG_YAFFS_UTIL
+CFLAGS = -O2 -Wall -DCONFIG_YAFFS_UTIL
CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
@@ -62,6 +62,10 @@ mkyaffsimage: $(MKYAFFSIMAGEOBJS) $(COMMONOBJS)
mkyaffs2image: $(MKYAFFS2IMAGEOBJS) $(COMMONOBJS)
$(CC) -o $@ $^
+nor-mkyaffs2image: CFLAGS:= $(CFLAGS) -DNOR_MKYAFFS2IMAGE
+nor-mkyaffs2image: $(MKYAFFS2IMAGEOBJS)
+ $(CC) -o $@ $(MKYAFFS2IMAGEOBJS)
clean:
rm -f $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) $(ALL_LINKS) mkyaffsimage mkyaffs2image core
+ rm -f rtems-mkyaffs2image
diff --git a/utils/mkyaffs2image.c b/utils/mkyaffs2image.c
index 5292b66..2e62708 100644
--- a/utils/mkyaffs2image.c
+++ b/utils/mkyaffs2image.c
@@ -31,9 +31,12 @@
#include <unistd.h>
#include <errno.h>
#include <assert.h>
-#include "yaffs_ecc.h"
#include "yaffs_guts.h"
+#ifndef NOR_MKYAFFS2IMAGE
+#include "yaffs_ecc.h"
+#endif
+
#include "yaffs_packedtags2.h"
unsigned yaffs_trace_mask=0;
@@ -41,11 +44,26 @@ unsigned yaffs_trace_mask=0;
#define MAX_OBJECTS 10000
// Adjust these to match your NAND LAYOUT:
-#define chunkSize 2048
-#define spareSize 64
-#define pagesPerBlock 64
+#ifdef NOR_MKYAFFS2IMAGE
+ #define chunkSize 512
+ #define spareSize 16
+ #define blockSize (128*1024)
+ #define pagesPerBlock (blockSize/(chunkSize+spareSize))
+ #define remainderSize (blockSize%(chunkSize+spareSize))
+ static int write_chunk_count = 0;
+#else
+ #define chunkSize 2048
+ #define spareSize 64
+ #define pagesPerBlock 64
+#endif
+#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \
+ (((x) & 0x0000FF00) << 8 ) | \
+ (((x) & 0x00FF0000) >> 8 ) | \
+ (((x) & 0xFF000000) >> 24))
+#define SWAP16(x) ((((x) & 0x00FF) << 8) | \
+ (((x) & 0xFF00) >> 8))
typedef struct
{
@@ -171,7 +189,15 @@ static void little_to_big_endian(struct yaffs_ext_tags *tagsPtr)
#endif
}
-static void shuffle_oob(char *spareData, struct yaffs_packed_tags2 *pt)
+static void yaffs_packed_tags2_tags_only_to_big_endian(struct yaffs_packed_tags2_tags_only *ptt)
+{
+ ptt->seq_number = SWAP32(ptt->seq_number);
+ ptt->obj_id = SWAP32(ptt->obj_id);
+ ptt->chunk_id = SWAP32(ptt->chunk_id);
+ ptt->n_bytes = SWAP32(ptt->n_bytes);
+}
+
+static void shuffle_oob(char *spareData, struct yaffs_packed_tags2_tags_only *pt)
{
assert(sizeof(*pt) <= spareSize);
// NAND LAYOUT: For non-trivial OOB orderings, here would be a good place to shuffle.
@@ -180,8 +206,15 @@ static void shuffle_oob(char *spareData, struct yaffs_packed_tags2 *pt)
static int write_chunk(u8 *data, u32 id, u32 chunk_id, u32 n_bytes)
{
+#ifdef NOR_MKYAFFS2IMAGE
+ u8 remainder[remainderSize];
+#endif
struct yaffs_ext_tags t;
+#ifdef NOR_MKYAFFS2IMAGE
+ struct yaffs_packed_tags2_tags_only pt;
+#else
struct yaffs_packed_tags2 pt;
+#endif
char spareData[spareSize];
if (write(outFile,data,chunkSize) != chunkSize)
@@ -200,32 +233,40 @@ static int write_chunk(u8 *data, u32 id, u32 chunk_id, u32 n_bytes)
// added NCB **CHECK**
t.chunk_used = 1;
+ nPages++;
+
+ memset(&pt, 0, sizeof(pt));
+
+#ifdef NOR_MKYAFFS2IMAGE
+ yaffs_pack_tags2_tags_only(&pt,&t);
+
+ if (convert_endian)
+ yaffs_packed_tags2_tags_only_to_big_endian(&pt);
+#else
if (convert_endian)
{
little_to_big_endian(&t);
}
-
- nPages++;
-
- memset(&pt, 0, sizeof(pt));
yaffs_pack_tags2(&pt,&t,1);
+#endif
memset(spareData, 0xff, sizeof(spareData));
shuffle_oob(spareData, &pt);
if (write(outFile,spareData,sizeof(spareData)) != sizeof(spareData))
fatal("write");
+#ifdef NOR_MKYAFFS2IMAGE
+ write_chunk_count++;
+ if (write_chunk_count == pagesPerBlock) {
+ write_chunk_count = 0;
+ memset(remainder, 0xff, sizeof(remainder));
+ if (write(outFile,remainder,sizeof(remainder)) != sizeof(remainder))
+ fatal("write");
+ }
+#endif
return 0;
}
-#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \
- (((x) & 0x0000FF00) << 8 ) | \
- (((x) & 0x00FF0000) >> 8 ) | \
- (((x) & 0xFF000000) >> 24))
-
-#define SWAP16(x) ((((x) & 0x00FF) << 8) | \
- (((x) & 0xFF00) >> 8))
-
// This one is easier, since the types are more standard. No funky shifts here.
static void object_header_little_to_big_endian(struct yaffs_obj_hdr* oh)
{
@@ -331,6 +372,9 @@ static int write_object_header(int id, enum yaffs_obj_type t, struct stat *s, in
static void pad_image(void)
{
u8 data[chunkSize + spareSize];
+#ifdef NOR_MKYAFFS2IMAGE
+ u8 remainder[remainderSize];
+#endif
int padPages = (nPages % pagesPerBlock);
if (padPages)
@@ -342,6 +386,12 @@ static void pad_image(void)
fatal("write");
}
}
+
+#ifdef NOR_MKYAFFS2IMAGE
+ memset(remainder, 0xff, sizeof(remainder));
+ if (write(outFile,remainder,sizeof(remainder)) != sizeof(remainder))
+ fatal("write");
+#endif
}
static int process_directory(int parent, const char *path)
diff --git a/yaffs_packedtags2.c b/yaffs_packedtags2.c
index 820bc41..18ff48b 100644
--- a/yaffs_packedtags2.c
+++ b/yaffs_packedtags2.c
@@ -97,10 +97,12 @@ void yaffs_pack_tags2(struct yaffs_packed_tags2 *pt,
{
yaffs_pack_tags2_tags_only(&pt->t, t);
+#ifndef NOR_MKYAFFS2IMAGE
if (tags_ecc)
yaffs_ecc_calc_other((unsigned char *)&pt->t,
sizeof(struct yaffs_packed_tags2_tags_only),
&pt->ecc);
+#endif
}
void yaffs_unpack_tags2_tags_only(struct yaffs_ext_tags *t,
@@ -149,8 +151,12 @@ void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
if (pt->t.seq_number != 0xffffffff && tags_ecc) {
/* Chunk is in use and we need to do ECC */
- struct yaffs_ecc_other ecc;
int result;
+
+#ifdef NOR_MKYAFFS2IMAGE
+ result = 0;
+#else
+ struct yaffs_ecc_other ecc;
yaffs_ecc_calc_other((unsigned char *)&pt->t,
sizeof(struct yaffs_packed_tags2_tags_only),
&ecc);
@@ -158,6 +164,7 @@ void yaffs_unpack_tags2(struct yaffs_ext_tags *t, struct yaffs_packed_tags2 *pt,
yaffs_ecc_correct_other((unsigned char *)&pt->t,
sizeof(struct yaffs_packed_tags2_tags_only),
&pt->ecc, &ecc);
+#endif
switch (result) {
case 0:
ecc_result = YAFFS_ECC_RESULT_NO_ERROR;