rtems support: Rudimentary test harness now working.
authorCharles Manning <cdhmanning@gmail.com>
Fri, 13 Mar 2020 03:33:23 +0000 (16:33 +1300)
committerCharles Manning <cdhmanning@gmail.com>
Fri, 13 Mar 2020 03:33:23 +0000 (16:33 +1300)
Lots more test cases to add.

Signed-off-by: Charles Manning <cdhmanning@gmail.com>
rtems/rtems-y-test/Makefile [new file with mode: 0644]
rtems/rtems-y-test/yaffs-rtems-flashsim.c [new file with mode: 0644]
rtems/rtems-y-test/yaffs-rtems-flashsim.h [new file with mode: 0644]
rtems/rtems-y-test/yaffs-rtems-test.c [new file with mode: 0644]

diff --git a/rtems/rtems-y-test/Makefile b/rtems/rtems-y-test/Makefile
new file mode 100644 (file)
index 0000000..4018051
--- /dev/null
@@ -0,0 +1,45 @@
+#
+#  Makefile for yaffs-rtems-test.exe
+#
+
+#
+#  RTEMS_MAKEFILE_PATH is typically set in an environment variable
+#
+
+EXEC=yaffs-rtems-test.exe
+PGM=${ARCH}/$(EXEC)
+
+# optional managers required
+MANAGERS=all
+
+# C source names
+CSRCS = yaffs-rtems-test.c yaffs-rtems-flashsim.c
+COBJS_ = $(CSRCS:.c=.o)
+COBJS = $(COBJS_:%=${ARCH}/%)
+
+# C++ source names
+CXXSRCS =
+CXXOBJS_ = $(CXXSRCS:.cc=.o)
+CXXOBJS = $(CXXOBJS_:%=${ARCH}/%)
+
+# AS source names
+ASSRCS =
+ASOBJS_ = $(ASSRCS:.s=.o)
+ASOBJS = $(ASOBJS_:%=${ARCH}/%)
+
+# Libraries
+#LIBS = -lrtemsall -lc  -lyaffs2
+LINK_LIBS = -lyaffs2
+
+include $(RTEMS_MAKEFILE_PATH)/Makefile.inc
+
+include $(RTEMS_CUSTOM)
+include $(PROJECT_ROOT)/make/leaf.cfg
+
+OBJS= $(COBJS) $(CXXOBJS) $(ASOBJS)
+
+all:    ${ARCH} $(PGM)
+
+$(PGM): $(OBJS)
+       $(make-exe)
+
diff --git a/rtems/rtems-y-test/yaffs-rtems-flashsim.c b/rtems/rtems-y-test/yaffs-rtems-flashsim.c
new file mode 100644 (file)
index 0000000..a49ff44
--- /dev/null
@@ -0,0 +1,301 @@
+/*
+ * Modified verion of yramsim.c.
+ */
+#include "yaffs-rtems-flashsim.h"
+
+#include <string.h>
+#include "../yaffs_guts.h"
+
+
+
+#define N_RAM_SIM_DEVS 1
+
+#define DATA_SIZE      2048
+#define SPARE_SIZE     64
+#define PAGE_SIZE      (DATA_SIZE + SPARE_SIZE)
+#define PAGES_PER_BLOCK        64
+
+
+typedef struct {
+       unsigned char page[PAGES_PER_BLOCK][PAGE_SIZE];
+       unsigned blockOk;
+} Block;
+
+typedef struct {
+       Block **blockList;
+       int nBlocks;
+} SimData;
+
+
+SimData *simDevs[N_RAM_SIM_DEVS];
+
+static SimData *DevToSim(struct yaffs_dev *dev)
+{
+       return (SimData*)(dev->driver_context);
+}
+
+
+static void CheckInitialised(void)
+{
+
+}
+
+static int yramsim_erase_internal(SimData *sim, unsigned blockId,int force)
+{
+       if(blockId < 0 || blockId >= sim->nBlocks){
+               return 0;
+       }
+
+       if(!sim->blockList[blockId]){
+               return 0;
+       }
+
+       if(!force && !sim->blockList[blockId]->blockOk){
+               return 0;
+       }
+
+       memset(sim->blockList[blockId],0xff,sizeof(Block));
+       sim->blockList[blockId]->blockOk = 1;
+
+       return 1;
+}
+
+
+
+
+static int yramsim_initialise(struct yaffs_dev *dev)
+{
+       SimData *sim = DevToSim(dev);
+       Block **blockList = sim->blockList;
+       return blockList != NULL;
+}
+
+
+static int yramsim_deinitialise(struct yaffs_dev *dev)
+{
+       return 1;
+}
+
+static int yramsim_rd_chunk (struct yaffs_dev *dev, int pageId,
+                                         u8 *data, int dataLength,
+                                         u8 *spare, int spareLength,
+                                         enum yaffs_ecc_result *ecc_result)
+{
+       SimData *sim = DevToSim(dev);
+       Block **blockList = sim->blockList;
+
+       unsigned blockId = pageId / PAGES_PER_BLOCK;
+       unsigned pageOffset = pageId % PAGES_PER_BLOCK;
+       unsigned char * d;
+       unsigned char *s;
+       if(blockId >= sim->nBlocks ||
+          pageOffset >= PAGES_PER_BLOCK ||
+          dataLength >DATA_SIZE ||
+          spareLength > SPARE_SIZE ||
+          !blockList[blockId]->blockOk){
+                  return YAFFS_FAIL;
+       }
+
+       d = blockList[blockId]->page[pageOffset];
+       s = d + DATA_SIZE;
+
+       if(data)
+               memcpy(data,d,dataLength);
+
+       if(spare)
+               memcpy(spare,s,spareLength);
+
+       if (ecc_result)
+               *ecc_result  = YAFFS_ECC_RESULT_NO_ERROR;
+
+       return YAFFS_OK;
+}
+
+static int yramsim_wr_chunk (struct yaffs_dev *dev, int pageId,
+                                          const u8 *data, int dataLength,
+                                          const u8 *spare, int spareLength)
+{
+       SimData *sim = DevToSim(dev);
+       Block **blockList = sim->blockList;
+
+       unsigned blockId = pageId / PAGES_PER_BLOCK;
+       unsigned pageOffset = pageId % PAGES_PER_BLOCK;
+       unsigned char * d;
+       unsigned char *s;
+       if(blockId >= sim->nBlocks ||
+          pageOffset >= PAGES_PER_BLOCK ||
+          dataLength >DATA_SIZE ||
+          spareLength > SPARE_SIZE ||
+          !blockList[blockId]->blockOk){
+                  return YAFFS_FAIL;
+       }
+
+       d = blockList[blockId]->page[pageOffset];
+       s = d + DATA_SIZE;
+
+       if(data)
+               memcpy(d,data,dataLength);
+
+       if(spare)
+               memcpy(s,spare,spareLength);
+
+       return YAFFS_OK;
+}
+
+
+static int yramsim_erase(struct yaffs_dev *dev, int blockId)
+{
+       SimData *sim = DevToSim(dev);
+
+       CheckInitialised();
+       return yramsim_erase_internal(sim,blockId,0);
+}
+
+static int yramsim_check_block_bad(struct yaffs_dev *dev, int blockId)
+{
+       SimData *sim = DevToSim(dev);
+       Block **blockList = sim->blockList;
+       if(blockId >= sim->nBlocks){
+               return YAFFS_FAIL;
+       }
+
+       return blockList[blockId]->blockOk ? YAFFS_OK : YAFFS_FAIL;
+}
+
+static int yramsim_mark_block_bad(struct yaffs_dev *dev, int blockId)
+{
+       SimData *sim = DevToSim(dev);
+       Block **blockList = sim->blockList;
+       if(blockId >= sim->nBlocks){
+               return YAFFS_FAIL;
+       }
+
+       blockList[blockId]->blockOk = 0;
+
+       return YAFFS_OK;
+}
+
+
+static SimData *yramsim_alloc_sim_data(u32 devId, u32 nBlocks)
+{
+       int ok = 1;
+
+       Block **blockList;
+       SimData *sim;
+       Block *b;
+       u32 i;
+
+       if(devId >= N_RAM_SIM_DEVS)
+               return NULL;
+
+       sim = simDevs[devId];
+
+       if(sim)
+               return sim;
+
+       sim = malloc(sizeof (SimData));
+       if(!sim)
+               return NULL;
+
+       simDevs[devId] = sim;
+
+       blockList = malloc(nBlocks * sizeof(Block *));
+
+       sim->blockList = blockList;
+       sim->nBlocks = nBlocks;
+       if(!blockList){
+               free(sim);
+               return NULL;
+       }
+
+       for(i = 0; i < nBlocks; i++)
+               blockList[i] = NULL;
+
+       for(i = 0; i < nBlocks && ok; i++){
+               b=  malloc(sizeof(Block));
+               if(b){
+                       blockList[i] = b;
+                       yramsim_erase_internal(sim,i,1);
+               }
+               else
+                       ok = 0;
+       }
+
+       if(!ok){
+               for(i = 0; i < nBlocks; i++)
+                       if(blockList[i]){
+                               free(blockList[i]);
+                               blockList[i] = NULL;
+                       }
+               free(blockList);
+               blockList = NULL;
+               free(sim);
+               sim = NULL;
+       }
+
+       return sim;
+}
+
+
+struct yaffs_dev *yramsim_CreateRamSim(const YCHAR *name,
+                               u32 devId, u32 nBlocks,
+                               u32 start_block, u32 end_block)
+{
+       SimData *sim;
+       struct yaffs_dev *dev;
+       struct yaffs_param *p;
+       struct yaffs_driver *d;
+
+       sim = yramsim_alloc_sim_data(devId, nBlocks);
+
+       dev = malloc(sizeof(*dev));
+
+       if(!sim || !dev){
+               free(sim);
+               free(dev);
+               printf("Flash Sim creation failed. sim = %p, dev = %p\n",
+                               sim, dev);
+               return NULL;
+       }
+
+       memset(dev, 0, sizeof(*dev));
+
+       if(start_block >= sim->nBlocks)
+               start_block = 0;
+       if(end_block == 0 || end_block >= sim->nBlocks)
+               end_block = sim->nBlocks - 1;
+
+       p = &dev->param;
+       p->name = strdup(name);
+       p->start_block = start_block;
+       p->end_block = end_block;
+       p->total_bytes_per_chunk = DATA_SIZE;
+       p->spare_bytes_per_chunk= SPARE_SIZE;
+       p->chunks_per_block = PAGES_PER_BLOCK;
+       p->n_reserved_blocks = 2;
+       p->use_nand_ecc = 1;
+       p->inband_tags = 0;
+       p->is_yaffs2 = 1;
+
+       d= &dev->drv;
+       d->drv_initialise_fn = yramsim_initialise;
+       d->drv_deinitialise_fn = yramsim_deinitialise;
+       d->drv_read_chunk_fn = yramsim_rd_chunk;
+       d->drv_write_chunk_fn = yramsim_wr_chunk;
+       d->drv_erase_fn = yramsim_erase;
+       d->drv_check_bad_fn = yramsim_check_block_bad;
+       d->drv_mark_bad_fn = yramsim_mark_block_bad;
+
+       dev->driver_context= (void *)sim;
+
+       printf("Created simulated flash device %p\n", dev);
+       return dev;
+}
+
+struct yaffs_dev *yaffs_rtems_flashsim_setup(void)
+{
+       return yramsim_CreateRamSim("ramsim",
+                               0, 100,
+                               0, 99);
+}
+
diff --git a/rtems/rtems-y-test/yaffs-rtems-flashsim.h b/rtems/rtems-y-test/yaffs-rtems-flashsim.h
new file mode 100644 (file)
index 0000000..d9b5e41
--- /dev/null
@@ -0,0 +1,9 @@
+#ifndef __YAFFS_FLASH_SIM_H__
+#define __YAFFS_FLASH_SIM_H__
+
+struct yaffs_dev;
+
+struct yaffs_dev *yaffs_rtems_flashsim_setup(void);
+
+#endif
+
diff --git a/rtems/rtems-y-test/yaffs-rtems-test.c b/rtems/rtems-y-test/yaffs-rtems-test.c
new file mode 100644 (file)
index 0000000..8e1c620
--- /dev/null
@@ -0,0 +1,191 @@
+/*
+ *  Simple test program -- demonstrating use of IMFS
+ */
+
+#include <bsp.h>
+
+#include <fcntl.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <rtems/libio.h>
+#include <yaffs/rtems_yaffs.h>
+
+#include "yaffs-rtems-flashsim.h"
+
+//#define YPATH "/yaffs_mount_pt/"
+#define YPATH ""
+
+void yaffs_bug_fn(const char *file_name, int line_no)
+{
+       printf("Yaffs bug at %s:%d\n", file_name, line_no);
+}
+
+int filesystem_init(const char *mount_target)
+{
+       struct yaffs_dev *device;
+       rtems_yaffs_default_os_context *os_context;
+       rtems_yaffs_mount_data mount_args;
+
+
+       rtems_filesystem_register(RTEMS_FILESYSTEM_TYPE_YAFFS,
+                                 rtems_yaffs_mount_handler);
+
+       // We mount the filesystem by passing an appropriate
+       // rtems_yaffs_mount_data as the last argument to mount(). mount_data is
+       // used to pass a yaffs_dev pointer by-value.
+
+
+       device = yaffs_rtems_flashsim_setup();
+
+       // Initialize callback storage for RTEMS's VFS inside the yaffs_dev.
+       os_context = malloc(sizeof(rtems_yaffs_default_os_context));
+       rtems_yaffs_initialize_default_os_context(os_context);
+
+       device->os_context = os_context;
+
+       mount_args.dev = device;
+
+       if (mount_and_make_target_path(NULL,
+                              NULL /*mount_target */,
+                              RTEMS_FILESYSTEM_TYPE_YAFFS,
+                              RTEMS_FILESYSTEM_READ_WRITE,
+                              &mount_args) < 0) {
+               return errno;
+       } else {
+               return 0;
+       }
+}
+
+
+void set_uint8_t_buffer(uint8_t *buf, uint32_t n, uint8_t start, uint8_t inc)
+{
+       while (n) {
+               *buf = start;
+               buf++;
+               start += inc;
+               n--;
+       }
+}
+
+int run_basic_file_test(void)
+{
+       int fd;
+       int ret;
+       uint8_t buf[100];
+       uint8_t buf2[100];
+
+       fd = open(YPATH"/test", O_RDWR | O_CREAT | O_TRUNC, 0666);
+       printf("open = %d\n", fd);
+
+       set_uint8_t_buffer(buf, sizeof(buf), 0xAA, 1);
+
+       ret = write(fd, buf, sizeof(buf));
+
+       printf("write returned %d\n", ret);
+
+       if (ret == -1)
+               perror("writing file");
+
+       ret = lseek(fd, 0, SEEK_END);
+
+       printf("lseek end ret = %d\n", ret);
+
+       ret = lseek(fd, 0, SEEK_SET);
+       printf("lseek start ret = %d\n", ret);
+
+       ret = read(fd, buf2, sizeof(buf2));
+
+       printf("reading file ret = %d\n", ret);
+
+       if (ret == -1)
+               perror("reading file");
+
+
+       return ret;
+
+#if 0
+
+
+   fd = open("test1", O_CREAT);
+   printf( "fcntl flags =0x%x\n", fcntl( fd, F_GETFL ) );
+   close(fd);
+
+   fd = open("test", O_RDONLY);
+   if (fd == -1) {
+     printf("Starting on the wrong foot....\n");
+     exit(-1);
+   }
+
+   printf( "fcntl flags =0x%x\n", fcntl( fd, F_GETFL ) );
+
+   fp = fdopen(fd, "r");
+   if (fp == NULL) {
+      printf("Nothing ever goes my way!\n");
+      close(fd);
+      exit(-1);
+   } else {
+      printf("Soon, I will be able to take over the world!\n");
+      fgets(str, 200, fp);
+      printf("%s\n", str);
+      fclose(fp);
+   }
+#endif
+}
+
+
+rtems_task Init(
+  rtems_task_argument ignored
+)
+{
+       int err;
+
+        printf("Starting\n");
+
+       err = filesystem_init(YPATH);
+
+       printf("filesystem_init(\"%s\") returned %d\n", YPATH, err);
+
+       run_basic_file_test();
+
+
+   exit(0);
+}
+
+
+
+
+#if 0
+So basically, we are registering our NAND-specific callbacks with YAFFS
+and registering the RTEMS-YAFFS filesystem callbacks with RTEMS.
+The rtems_filesystem_register() associates the mount() system call with
+a callback function to handle that system call, in this case
+rtems_yaffs_mount_handler().  rtems_yaffs_mount_handler() and
+RTEMS_FILESYSTEM_TYPE_YAFFS (just a string) are provided
+by the rtems-yaffs fork.
+
+mount_and_make_target_path() is provided by RTEMS: it combines a
+mkdir -p` with mount(), passing the mount_args to the
+previously-registered handler.
+#endif
+
+
+/* configuration information */
+
+/* NOTICE: the clock driver is explicitly disabled */
+#define CONFIGURE_APPLICATION_DOES_NOT_NEED_CLOCK_DRIVER
+#define CONFIGURE_APPLICATION_NEEDS_CONSOLE_DRIVER
+
+#define CONFIGURE_USE_IMFS_AS_BASE_FILESYSTEM
+#define CONFIGURE_MAXIMUM_FILE_DESCRIPTORS 6
+
+#define CONFIGURE_RTEMS_INIT_TASKS_TABLE
+#define CONFIGURE_MAXIMUM_TASKS 1
+
+#define CONFIGURE_MAXIMUM_SEMAPHORES        20
+
+#define CONFIGURE_INIT
+
+#include <rtems/confdefs.h>
+/* end of file */