From 0d592874019a980b1a32b887be84aaabe7fb0b0c Mon Sep 17 00:00:00 2001 From: Charles Manning Date: Fri, 13 Mar 2020 16:33:23 +1300 Subject: [PATCH] rtems support: Rudimentary test harness now working. Lots more test cases to add. Signed-off-by: Charles Manning --- rtems/rtems-y-test/Makefile | 45 ++++ rtems/rtems-y-test/yaffs-rtems-flashsim.c | 301 ++++++++++++++++++++++ rtems/rtems-y-test/yaffs-rtems-flashsim.h | 9 + rtems/rtems-y-test/yaffs-rtems-test.c | 191 ++++++++++++++ 4 files changed, 546 insertions(+) create mode 100644 rtems/rtems-y-test/Makefile create mode 100644 rtems/rtems-y-test/yaffs-rtems-flashsim.c create mode 100644 rtems/rtems-y-test/yaffs-rtems-flashsim.h create mode 100644 rtems/rtems-y-test/yaffs-rtems-test.c diff --git a/rtems/rtems-y-test/Makefile b/rtems/rtems-y-test/Makefile new file mode 100644 index 0000000..4018051 --- /dev/null +++ b/rtems/rtems-y-test/Makefile @@ -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 index 0000000..a49ff44 --- /dev/null +++ b/rtems/rtems-y-test/yaffs-rtems-flashsim.c @@ -0,0 +1,301 @@ +/* + * Modified verion of yramsim.c. + */ +#include "yaffs-rtems-flashsim.h" + +#include +#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 index 0000000..d9b5e41 --- /dev/null +++ b/rtems/rtems-y-test/yaffs-rtems-flashsim.h @@ -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 index 0000000..8e1c620 --- /dev/null +++ b/rtems/rtems-y-test/yaffs-rtems-test.c @@ -0,0 +1,191 @@ +/* + * Simple test program -- demonstrating use of IMFS + */ + +#include + +#include +#include +#include +#include + +#include +#include + +#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 +/* end of file */ -- 2.30.2