obj-m := $(YAFFS_O)
- yaffs2-objs := yaffs_mtdif.o yaffs_mtdif2_single.o
- yaffs2-objs += yaffs_mtdif1_single.o yaffs_packedtags1.o
+ yaffs2-objs := yaffs_mtdif_single.o
+ yaffs2-objs += yaffs_packedtags1.o
yaffs2-objs += yaffs_ecc.o yaffs_vfs_single.o yaffs_guts.o
yaffs2-objs += yaffs_packedtags2.o
yaffs2-objs += yaffs_tagscompat.o
+ yaffs2-objs += yaffs_tagsmarshall.o
yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o
yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o
yaffs2-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o
yaffs2-objs += yaffs_verify.o
yaffs2-objs += yaffs_summary.o
- yaffs2multi-objs := yaffs_mtdif.o yaffs_mtdif2_multi.o
- yaffs2multi-objs += yaffs_mtdif1_multi.o yaffs_packedtags1.o
+ yaffs2multi-objs := yaffs_mtdif_multi.o
+ yaffs2multi-objs += yaffs_packedtags1.o
yaffs2multi-objs += yaffs_ecc.o yaffs_vfs_multi.o yaffs_guts.o
yaffs2multi-objs += yaffs_packedtags2.o
yaffs2multi-objs += yaffs_tagscompat.o
+ yaffs2multi-objs += yaffs_tagsmarshall.o
yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o
yaffs2multi-objs += yaffs_checkptrw.o yaffs_nand.o yaffs_nameval.o
yaffs2multi-objs += yaffs_allocator.o yaffs_bitmap.o yaffs_attribs.o
yaffs-y := yaffs_ecc.o yaffs_vfs.o yaffs_guts.o yaffs_checkptrw.o
yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o
-yaffs-y += yaffs_tagscompat.o
-yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o
+yaffs-y += yaffs_tagscompat.o yaffs_tagsmarshall.o
+yaffs-y += yaffs_mtdif.o
yaffs-y += yaffs_nameval.o yaffs_attribs.o
yaffs-y += yaffs_allocator.o
yaffs-y += yaffs_yaffs1.o
--- /dev/null
+New Handling for Yaffs Core Code in Yaffs Direct
+
+In the past, the Yaffs core code was joined into the Yaffs direct code by
+means of symbolic links. This had to be changed when some Linux
+kernel-friendly changes were made.
+
+Now, the Yaffs core code needs to be slightly modified before use in Yaffs
+Direct. This is accomplished by a script that copies the code intto the
+Yaffs Direct "workspace" while using sed to modify some of the function
+names etc. For example, strlen() is changed to yaffs_strlen() to allow these
+functions to be twaeked for use with unicode.
+
+This is accomplished by the script called handle_common.sh.
+
+cd yaffs2/direct
+./handle_common.sh copy
+
+++ /dev/null
-# Makefile for YAFFS direct test
-#
-#
-# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
-#
-# Copyright (C) 2003-2010 Aleph One Ltd.
-#
-#
-# Created by Charles Manning <charles@aleph1.co.uk>
-#
-# 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.
-#
-# NB Warning this Makefile does not include header dependencies.
-#
-# $Id: Makefile,v 1.24 2010-02-17 02:18:57 charles Exp $
-
-#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
-
-CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -D CONFIG_YAFFS_DEFINES_TYPES
-CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE
-CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Werror=strict-aliasing
-#CFLAGS += -fno-strict-aliasing
-CFLAGS += -O0
-#CFLAGS += -DVALGRIND_TEST
-#CFLAGS += -DCONFIG_YAFFS_CASE_INSENSITIVE
-
-CFLAGS+= -Wshadow -Werror=pointer-arith -Werror=write-strings
-CFLAGS+= -Werror=strict-prototypes -Werror=missing-parameter-type
-CFLAGS+= -Werror=redundant-decls -Werror=nested-externs -Winline
-CFLAGS+= -Werror=undef
-
-CFLAGS+= -DCONFIG_YAFFS_USE_PTHREADS -lpthread
-
-
-COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o \
- yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
- yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
- yaffs_tagscompat.o yaffs_packedtags2.o yaffs_nand.o \
- yaffs_checkptrw.o yaffs_qsort.o\
- yaffs_nameval.o yaffs_attribs.o \
- yaffs_norif1.o ynorsim.o \
- yaffs_allocator.o \
- yaffs_bitmap.o \
- yaffs_yaffs1.o \
- yaffs_yaffs2.o \
- yaffs_verify.o \
- yaffs_summary.o
-
-# yaffs_checkptrwtest.o\
-
-
-YAFFSDIRECTSYMLINKS = \
- yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h \
- yaffs_tagscompat.c yaffs_tagscompat.h \
- yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h \
- yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
- yaffs_checkptrw.h yaffs_checkptrw.c \
- yaffs_nameval.c yaffs_nameval.h \
- yaffs_trace.h yaffs_attribs.h \
- yaffs_allocator.c yaffs_allocator.h \
- yaffs_yaffs1.c yaffs_yaffs1.h \
- yaffs_yaffs2.c yaffs_yaffs2.h \
- yaffs_bitmap.c yaffs_bitmap.h \
- yaffs_verify.c yaffs_verify.h \
- yaffs_summary.c yaffs_summary.h \
- yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
- yaffsfs.h yaffs_osglue.h ydirectenv.h \
- yaffscfg.h yaffs_list.h \
- yaffs_qsort.c yportenv.h yaffs_attribs.c \
- yaffs_nandif.c yaffs_nandif.h yaffs_nandemul2k.h \
- yaffs_hweight.h yaffs_hweight.c \
-
-
-
-DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o
-
-BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o
-
-ALLOBJS = $(sort $(DIRECTTESTOBJS) $(YAFFSTESTOBJS))
-
-TARGETS = directtest2k
-
-all: $(TARGETS)
-
-$(ALLOBJS): %.o: %.c
- gcc -c $(CFLAGS) -o $@ $<
-
-
-$(YAFFSDIRECTSYMLINKS):
- ln -s ../$@ $@
-
-
-directtest2k: $(YAFFSDIRECTSYMLINKS) $(DIRECTTESTOBJS)
- gcc -o $@ $(DIRECTTESTOBJS)
-
-yaffs_test: $(YAFFSDIRECTSYMLINKS) $(YAFFSTESTOBJS)
- gcc -o $@ $(YAFFSTESTOBJS)
-
-
-boottest: $(YAFFSDIRECTSYMLINKS) $(BOOTTESTOBJS)
- gcc -o $@ $(BOOTTESTOBJS)
-
-
-clean:
- rm -f $(TARGETS) $(ALLOBJS) core $(YAFFSDIRECTSYMLINKS)
+++ /dev/null
-/*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-/*
- * This provides a YAFFS nand emulation on a file for emulating 2kB pages.
- * This is only intended as test code to test persistence etc.
- */
-
-const char *yaffs_flashif2_c_version = "$Id: yaffs_fileem2k.c,v 1.24 2010-02-18 01:18:04 charles Exp $";
-
-
-#include "yportenv.h"
-#include "yaffs_trace.h"
-
-#include "yaffs_flashif2.h"
-#include "yaffs_guts.h"
-#include "yaffs_fileem2k.h"
-#include "yaffs_packedtags2.h"
-
-
-#include <sys/types.h>
-#include <sys/stat.h>
-#include <fcntl.h>
-#include <unistd.h>
-
-
-
-#define REPORT_ERROR 0
-
-typedef struct
-{
- u8 data[PAGE_SIZE]; // Data + spare
-} yflash_Page;
-
-typedef struct
-{
- yflash_Page page[PAGES_PER_BLOCK]; // The pages in the block
-
-} yflash_Block;
-
-
-
-#define MAX_HANDLES 20
-#define BLOCKS_PER_HANDLE (32*8)
-
-typedef struct
-{
- int handle[MAX_HANDLES];
- int nBlocks;
-} yflash_Device;
-
-static yflash_Device filedisk;
-
-int yaffs_test_partial_write = 0;
-
-extern int random_seed;
-extern int simulate_power_failure;
-static int remaining_ops;
-static int nops_so_far;
-
-int ops_multiplier;
-
-
-static void yflash2_MaybePowerFail(unsigned int nand_chunk, int failPoint)
-{
-
- nops_so_far++;
-
-
- remaining_ops--;
- if(simulate_power_failure &&
- remaining_ops < 1){
- printf("Simulated power failure after %d operations\n",nops_so_far);
- printf(" power failed on nand_chunk %d, at fail point %d\n",
- nand_chunk, failPoint);
- exit(0);
- }
-}
-
-
-
-
-
-static u8 localBuffer[PAGE_SIZE];
-
-static char *NToName(char *buf,int n)
-{
- sprintf(buf,"emfile-2k-%d",n);
- return buf;
-}
-
-static char dummyBuffer[BLOCK_SIZE];
-
-static int GetBlockFileHandle(int n)
-{
- int h;
- int requiredSize;
-
- char name[40];
- NToName(name,n);
- int fSize;
- int i;
-
- h = open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
- if(h >= 0){
- fSize = lseek(h,0,SEEK_END);
- requiredSize = BLOCKS_PER_HANDLE * BLOCK_SIZE;
- if(fSize < requiredSize){
- for(i = 0; i < BLOCKS_PER_HANDLE; i++)
- if(write(h,dummyBuffer,BLOCK_SIZE) != BLOCK_SIZE)
- return -1;
-
- }
- }
-
- return h;
-
-}
-
-static int CheckInit(void)
-{
- static int initialised = 0;
- int i;
-
- int blk;
-
-
- if(initialised)
- {
- return YAFFS_OK;
- }
-
- initialised = 1;
-
-
- srand(random_seed);
- remaining_ops = (rand() % 1000) * 5;
- memset(dummyBuffer,0xff,sizeof(dummyBuffer));
-
-
-
- filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB;
-
- for(i = 0; i < MAX_HANDLES; i++)
- filedisk.handle[i] = -1;
-
- for(i = 0,blk = 0; blk < filedisk.nBlocks; blk+=BLOCKS_PER_HANDLE,i++)
- filedisk.handle[i] = GetBlockFileHandle(i);
-
-
- return 1;
-}
-
-
-int yflash2_GetNumberOfBlocks(void)
-{
- CheckInit();
-
- return filedisk.nBlocks;
-}
-
-int yflash2_WriteChunkWithTagsToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_ext_tags *tags)
-{
- int written;
- int pos;
- int h;
- int i;
- int nRead;
- int error;
-
- yaffs_trace(YAFFS_TRACE_MTD, "write chunk %d data %p tags %p",nand_chunk, data, tags);
-
- CheckInit();
-
-
- if(dev->param.inband_tags){
-
- struct yaffs_packed_tags2_tags_only * pt2tp;
- pt2tp = (struct yaffs_packed_tags2_tags_only *)&data[dev->data_bytes_per_chunk];
- yaffs_pack_tags2_tags_only(pt2tp,tags);
-
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-
- lseek(h,pos,SEEK_SET);
- written = write(h,data,dev->param.total_bytes_per_chunk);
-
-
- if(yaffs_test_partial_write){
- close(h);
- exit(1);
- }
-
- if(written != dev->param.total_bytes_per_chunk) return YAFFS_FAIL;
-
-
- }
-
- else {
- /* First do a write of a partial page */
- int n_partials;
- int bpos;
-
- if(data)
- {
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-
-
- memcpy(localBuffer,data, dev->data_bytes_per_chunk);
-
- n_partials = rand()%20;
-
- for(i = 0; i < n_partials; i++){
- bpos = rand() % dev->data_bytes_per_chunk;
-
- localBuffer[bpos] |= (1 << (rand() & 7));
- }
-
- if(REPORT_ERROR && memcmp(localBuffer,data,dev->data_bytes_per_chunk))
- printf("nand simulator: data does not match\n");
-
- lseek(h,pos,SEEK_SET);
- written = write(h,localBuffer,dev->data_bytes_per_chunk);
-
- if(yaffs_test_partial_write){
- close(h);
- exit(1);
- }
-
-
- if(written != dev->data_bytes_per_chunk) return YAFFS_FAIL;
- }
- // yflash2_MaybePowerFail(nand_chunk,1);
-
- if(tags)
- {
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-
- lseek(h,pos,SEEK_SET);
-
- if( 0 && dev->param.is_yaffs2)
- {
-
- written = write(h,tags,sizeof(struct yaffs_ext_tags));
- if(written != sizeof(struct yaffs_ext_tags)) return YAFFS_FAIL;
- }
- else
- {
- struct yaffs_packed_tags2 pt;
- yaffs_pack_tags2(&pt,tags, !dev->param.no_tags_ecc);
- u8 * ptab = (u8 *)&pt;
-
- nRead = read(h,localBuffer,sizeof(pt));
- for(i = error = 0; REPORT_ERROR && i < sizeof(pt) && !error; i++){
- if(localBuffer[i] != 0xFF){
- printf("nand simulation: chunk %d oob byte %d was %0x2\n",
- nand_chunk,i,localBuffer[i]);
- error = 1;
- }
- }
-
- for(i = 0; i < sizeof(pt); i++)
- localBuffer[i] &= ptab[i];
-
- n_partials = rand()% sizeof(pt);
-
- for(i = 0; i < n_partials; i++){
- bpos = rand() % sizeof(pt);
-
- localBuffer[bpos] |= (1 << (rand() & 7));
- }
-
- if(REPORT_ERROR && memcmp(localBuffer,&pt,sizeof(pt)))
- printf("nand sim: tags corruption\n");
-
- lseek(h,pos,SEEK_SET);
-
- written = write(h,localBuffer,sizeof(pt));
- if(written != sizeof(pt)) return YAFFS_FAIL;
- }
- }
-
- //yflash2_MaybePowerFail(nand_chunk,2);
-
- /* Next do the whole write */
- if(data)
- {
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-
-
- memset(localBuffer,0xFF, PAGE_SIZE);
- for(i = 0; i < dev->data_bytes_per_chunk; i++){
- localBuffer[i] &= data[i];
- }
-
- if(REPORT_ERROR && memcmp(localBuffer,data,dev->data_bytes_per_chunk))
- printf("nand simulator: data does not match\n");
-
- lseek(h,pos,SEEK_SET);
- written = write(h,localBuffer,dev->data_bytes_per_chunk);
-
- if(yaffs_test_partial_write){
- close(h);
- exit(1);
- }
-
-
- if(written != dev->data_bytes_per_chunk) return YAFFS_FAIL;
- }
-
- if(tags)
- {
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-
- lseek(h,pos,SEEK_SET);
-
- if( 0 && dev->param.is_yaffs2)
- {
-
- written = write(h,tags,sizeof(struct yaffs_ext_tags));
- if(written != sizeof(struct yaffs_ext_tags)) return YAFFS_FAIL;
- }
- else
- {
- struct yaffs_packed_tags2 pt;
- yaffs_pack_tags2(&pt,tags,!dev->param.no_tags_ecc);
- u8 * ptab = (u8 *)&pt;
-
- nRead = read(h,localBuffer,sizeof(pt));
- for(i = error = 0; REPORT_ERROR && i < sizeof(pt) && !error; i++){
- if(localBuffer[i] != 0xFF){
- printf("nand simulation: chunk %d oob byte %d was %0x2\n",
- nand_chunk,i,localBuffer[i]);
- error = 1;
- }
- }
-
- for(i = 0; i < sizeof(pt); i++)
- localBuffer[i] &= ptab[i];
-
- if(REPORT_ERROR && memcmp(localBuffer,&pt,sizeof(pt)))
- printf("nand sim: tags corruption\n");
-
- lseek(h,pos,SEEK_SET);
-
- written = write(h,localBuffer,sizeof(pt));
- if(written != sizeof(pt)) return YAFFS_FAIL;
- }
- }
-
- yflash2_MaybePowerFail(nand_chunk,3);
-
- }
- return YAFFS_OK;
-
-}
-
-int yaffs_check_all_ff(const u8 *ptr, int n)
-{
- while(n)
- {
- n--;
- if(*ptr!=0xFF) return 0;
- ptr++;
- }
- return 1;
-}
-
-
-static int fail300 = 1;
-static int fail320 = 1;
-
-static int failRead10 = 2;
-
-int yflash2_ReadChunkWithTagsFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_ext_tags *tags)
-{
- int nread;
- int pos;
- int h;
- int localData = 0;
- int retval = YAFFS_OK;
- int nRead;
-
- yaffs_trace(YAFFS_TRACE_MTD,"read chunk %d data %p tags %p",nand_chunk, data, tags);
-
- CheckInit();
-
-
-
-
- if(dev->param.inband_tags){
- /* Got to suck the tags out of the data area */
- if(!data) {
- localData=1;
- data = yaffs_get_temp_buffer(dev);
- }
-
-
- struct yaffs_packed_tags2_tags_only * pt2tp;
- pt2tp = (struct yaffs_packed_tags2_tags_only *)&data[dev->data_bytes_per_chunk];
-
-
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
-
- lseek(h,pos,SEEK_SET);
-
- nRead = read(h, data,dev->param.total_bytes_per_chunk);
-
- yaffs_unpack_tags2_tags_only(tags,pt2tp);
-
- if(nread != dev->param.total_bytes_per_chunk)
- retval = YAFFS_FAIL;
-
- if(localData)
- yaffs_release_temp_buffer(dev, data);
-
-
-
- }
-
- else {
-
- if(data)
- {
-
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
- lseek(h,pos,SEEK_SET);
- nread = read(h,data,dev->data_bytes_per_chunk);
-
-
- if(nread != dev->data_bytes_per_chunk)
- retval = YAFFS_FAIL;
- }
-
- if(tags)
- {
- pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
- h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
- lseek(h,pos,SEEK_SET);
-
- if(0 && dev->param.is_yaffs2)
- {
- nread= read(h,tags,sizeof(struct yaffs_ext_tags));
- if(nread != sizeof(struct yaffs_ext_tags))
- retval = YAFFS_FAIL;
- if(yaffs_check_all_ff((u8 *)tags, sizeof(struct yaffs_ext_tags)))
- memset(tags, 0, sizeof(struct yaffs_ext_tags));
- else
- tags->chunk_used = 1;
- }
- else
- {
- struct yaffs_packed_tags2 pt;
- nread= read(h,&pt,sizeof(pt));
- yaffs_unpack_tags2(tags,&pt, !dev->param.no_tags_ecc);
-#ifdef SIMULATE_FAILURES
- if((nand_chunk >> 6) == 100) {
- if(fail300 && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR){
- tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
- fail300 = 0;
- }
- }
-
- if((nand_chunk >> 6) == 110) {
- if(fail320 && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR){
- tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
- fail320 = 0;
- }
- }
-#endif
- if(failRead10>0 && nand_chunk == 10){
- failRead10--;
- nread = 0;
- }
-
- if(nread != sizeof(pt))
- retval = YAFFS_FAIL;
- }
- }
- }
-
-
-
- return retval;
-
-}
-
-
-int yflash2_MarkNANDBlockBad(struct yaffs_dev *dev, int block_no)
-{
- int written;
- int h;
-
- struct yaffs_packed_tags2 pt;
-
- CheckInit();
-
- memset(&pt,0,sizeof(pt));
- h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))];
- lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET);
- written = write(h,&pt,sizeof(pt));
-
- if(written != sizeof(pt)) return YAFFS_FAIL;
-
-
- return YAFFS_OK;
-
-}
-
-int yflash2_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
-{
-
- int i;
- int h;
-
- CheckInit();
-
- //printf("erase block %d\n",blockNumber);
-
- if(blockNumber == 320)
- fail320 = 1;
-
- if(blockNumber < 0 || blockNumber >= filedisk.nBlocks)
- {
- yaffs_trace(YAFFS_TRACE_ALWAYS,"Attempt to erase non-existant block %d",blockNumber);
- return YAFFS_FAIL;
- }
- else
- {
-
- u8 pg[PAGE_SIZE];
- int syz = PAGE_SIZE;
- int pos;
-
- memset(pg,0xff,syz);
-
-
- h = filedisk.handle[(blockNumber / ( BLOCKS_PER_HANDLE))];
- lseek(h,((blockNumber % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE,SEEK_SET);
- for(i = 0; i < dev->param.chunks_per_block; i++)
- {
- write(h,pg,PAGE_SIZE);
- }
- pos = lseek(h, 0,SEEK_CUR);
-
- return YAFFS_OK;
- }
-
-}
-
-int yflash2_InitialiseNAND(struct yaffs_dev *dev)
-{
- CheckInit();
-
- return YAFFS_OK;
-}
-
-
-
-
-int yflash2_QueryNANDBlock(struct yaffs_dev *dev, int block_no, enum yaffs_block_state *state, u32 *seq_number)
-{
- struct yaffs_ext_tags tags;
- int chunkNo;
-
- *seq_number = 0;
-
- chunkNo = block_no * dev->param.chunks_per_block;
-
- yflash2_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
- if(tags.block_bad)
- {
- *state = YAFFS_BLOCK_STATE_DEAD;
- }
- else if(!tags.chunk_used)
- {
- *state = YAFFS_BLOCK_STATE_EMPTY;
- }
- else if(tags.chunk_used)
- {
- *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
- *seq_number = tags.seq_number;
- }
- return YAFFS_OK;
-}
-
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __FILEEM2K_H__
-#define __FILEEM2K_H__
-
-#if 1
-
-#define SIZE_IN_MB 32
-/* #define SIZE_IN_MB 128 */
-
-#define PAGE_DATA_SIZE (2048)
-#define PAGE_SPARE_SIZE (64)
-#define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
-#define PAGES_PER_BLOCK (64)
-#define BLOCK_DATA_SIZE (PAGE_DATA_SIZE * PAGES_PER_BLOCK)
-#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE))
-#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE)
-#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB)
-
-#else
-
-#define SIZE_IN_MB 128
-#define PAGE_DATA_SIZE (512)
-#define SPARE_SIZE (16)
-#define PAGE_SIZE (PAGE_DATA_SIZE + SPARE_SIZE)
-#define PAGES_PER_BLOCK (32)
-#define BLOCK_DATA_SIZE (PAGE_SIZE * PAGES_PER_BLOCK)
-#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE))
-#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE)
-#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB)
-
-#endif
-
-
-int yflash2_GetNumberOfBlocks(void);
-
-#endif
-
+++ /dev/null
-/*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-/*
- * yaffscfg2k.c The configuration for the "direct" use of yaffs.
- *
- * This file is intended to be modified to your requirements.
- * There is no need to redistribute this file.
- */
-
-#include "yaffscfg.h"
-#include "yaffs_guts.h"
-#include "yaffsfs.h"
-#include "yaffs_fileem2k.h"
-#include "yaffs_nandemul2k.h"
-#include "yaffs_norif1.h"
-#include "yaffs_trace.h"
-#include "yaffs_osglue.h"
-
-
-#include <errno.h>
-
-unsigned yaffs_trace_mask =
-
- YAFFS_TRACE_SCAN |
- YAFFS_TRACE_GC |
- YAFFS_TRACE_ERASE |
- YAFFS_TRACE_ERROR |
- YAFFS_TRACE_TRACING |
- YAFFS_TRACE_ALLOCATE |
- YAFFS_TRACE_BAD_BLOCKS |
- YAFFS_TRACE_VERIFY |
-
- 0;
-
-
-
-// Configuration
-
-#include "yaffs_ramdisk.h"
-#include "yaffs_flashif.h"
-#include "yaffs_flashif2.h"
-#include "yaffs_nandemul2k.h"
-
-struct yaffs_dev ram1Dev;
-struct yaffs_dev flashDev;
-struct yaffs_dev m18_1Dev;
-
-int yaffs_start_up(void)
-{
- static int start_up_called = 0;
-
- if(start_up_called)
- return;
- start_up_called = 1;
-
- // Stuff to configure YAFFS
- // Stuff to initialise anything special (eg lock semaphore).
- yaffsfs_OSInitialisation();
-
- // Set up devices
- // /ram1 ram, yaffs1
- memset(&ram1Dev,0,sizeof(ram1Dev));
- ram1Dev.param.name = "ram1";
- ram1Dev.param.total_bytes_per_chunk = 512;
- ram1Dev.param.chunks_per_block = 32;
- ram1Dev.param.n_reserved_blocks = 2; // Set this smaller for RAM
- ram1Dev.param.start_block = 0; // Can use block 0
- ram1Dev.param.end_block = 127; // Last block in 2MB.
- //ram1Dev.param.use_nand_ecc = 1;
- ram1Dev.param.n_caches = 0; // Disable caching on this device.
- ram1Dev.driver_context = (void *) 0; // Used to identify the device in fstat.
- ram1Dev.param.write_chunk_tags_fn = yramdisk_wr_chunk;
- ram1Dev.param.read_chunk_tags_fn = yramdisk_rd_chunk;
- ram1Dev.param.erase_fn = yramdisk_erase;
- ram1Dev.param.initialise_flash_fn = yramdisk_initialise;
-
- yaffs_add_device(&ram1Dev);
-
- // /M18-1 yaffs1 on M18 nor sim
- memset(&m18_1Dev,0,sizeof(m18_1Dev));
- m18_1Dev.param.name = "M18-1";
- m18_1Dev.param.total_bytes_per_chunk = 1024;
- m18_1Dev.param.chunks_per_block =248;
- m18_1Dev.param.n_reserved_blocks = 2;
- m18_1Dev.param.start_block = 0; // Can use block 0
- m18_1Dev.param.end_block = 31; // Last block
- m18_1Dev.param.use_nand_ecc = 0; // use YAFFS's ECC
- m18_1Dev.param.n_caches = 10; // Use caches
- m18_1Dev.param.disable_soft_del = 1;
- m18_1Dev.driver_context = (void *) 1; // Used to identify the device in fstat.
- m18_1Dev.param.write_chunk_fn = ynorif1_WriteChunkToNAND;
- m18_1Dev.param.read_chunk_fn = ynorif1_ReadChunkFromNAND;
- m18_1Dev.param.erase_fn = ynorif1_EraseBlockInNAND;
- m18_1Dev.param.initialise_flash_fn = ynorif1_InitialiseNAND;
- m18_1Dev.param.deinitialise_flash_fn = ynorif1_Deinitialise_flash_fn;
-
-// m18_1Dev.param.disable_soft_del = 1;
-
- yaffs_add_device(&m18_1Dev);
-
- // /yaffs2 yaffs2 file emulation
- // 2kpage/64chunk per block
- //
- memset(&flashDev,0,sizeof(flashDev));
- flashDev.param.name = "yaffs2";
- flashDev.param.total_bytes_per_chunk = 2048;
- flashDev.param.chunks_per_block = 64;
- flashDev.param.n_reserved_blocks = 5;
- flashDev.param.inband_tags = 0;
- flashDev.param.start_block = 0;
- flashDev.param.end_block = yflash2_GetNumberOfBlocks()-1;
- flashDev.param.is_yaffs2 = 1;
- flashDev.param.use_nand_ecc=1;
- flashDev.param.wide_tnodes_disabled=0;
- flashDev.param.refresh_period = 1000;
- flashDev.param.n_caches = 10; // Use caches
- flashDev.driver_context = (void *) 2; // Used to identify the device in fstat.
- flashDev.param.write_chunk_tags_fn = yflash2_WriteChunkWithTagsToNAND;
- flashDev.param.read_chunk_tags_fn = yflash2_ReadChunkWithTagsFromNAND;
- flashDev.param.erase_fn = yflash2_EraseBlockInNAND;
- flashDev.param.initialise_flash_fn = yflash2_InitialiseNAND;
- flashDev.param.bad_block_fn = yflash2_MarkNANDBlockBad;
- flashDev.param.query_block_fn = yflash2_QueryNANDBlock;
- flashDev.param.enable_xattr = 1;
-
- yaffs_add_device(&flashDev);
-
-// todo yaffs_initialise(yaffsfs_config);
-
- return 0;
-}
-
-
-
+++ /dev/null
-/*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-#include "ynorsim.h"
-
-
-
-#include <stdio.h>
-#include <fcntl.h>
-#include <sys/stat.h>
-#include <unistd.h>
-#include <time.h>
-
-#define YNORSIM_FNAME "emfile-nor"
-
-/* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to
- *simulate bit flipping as the programming happens.
- * A low value results in faster simulation with less chance of encountering a partially programmed
- * word.
- */
-
-//#define YNORSIM_BIT_CHANGES 15
-#define YNORSIM_BIT_CHANGES 2
-
-#if 0
-/* Simulate 32MB of flash in 256k byte blocks.
- * This stuff is x32.
- */
-
-#define YNORSIM_BLOCK_SIZE_U32 (256*1024/4)
-#define YNORSIM_DEV_SIZE_U32 (32*1024 * 1024/4)
-#else
-/* Simulate 8MB of flash in 256k byte blocks.
- * This stuff is x32.
- */
-
-#define YNORSIM_BLOCK_SIZE_U32 (256*1024/4)
-#define YNORSIM_DEV_SIZE_U32 (8*1024 * 1024/4)
-#endif
-
-static u32 word[YNORSIM_DEV_SIZE_U32];
-
-extern int random_seed;
-extern int simulate_power_failure;
-
-static void NorError(void)
-{
- printf("Nor error\n");
- while(1){}
-}
-
-static void ynorsim_save_image(void)
-{
- int h = open(YNORSIM_FNAME, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
- write(h,word,sizeof(word));
- close(h);
-}
-
-static void ynorsim_restore_image(void)
-{
- int h = open(YNORSIM_FNAME, O_RDONLY, S_IREAD | S_IWRITE);
- memset(word,0xFF,sizeof(word));
- read(h,word,sizeof(word));
- close(h);
-}
-
-
-static void ynorsim_power_fail(void)
-{
- ynorsim_save_image();
- exit(1);
-}
-
-static int initialised = 0;
-static int remaining_ops;
-static int nops_so_far;
-
-int ops_multiplier = 500;
-
-static void ynorsim_maybe_power_fail(void)
-{
-
- nops_so_far++;
-
-
- remaining_ops--;
- if(simulate_power_failure &&
- remaining_ops < 1){
- printf("Simulated power failure after %d operations\n",nops_so_far);
- ynorsim_power_fail();
- }
-}
-
-static void ynorsim_ready(void)
-{
- if(initialised)
- return;
- srand(random_seed);
- remaining_ops = 1000000000;
- remaining_ops = (rand() % 10000) * ops_multiplier * YNORSIM_BIT_CHANGES;
- ynorsim_restore_image();
-}
-
-void ynorsim_rd32(u32 *addr,u32 *buf, int nwords)
-{
- while(nwords > 0){
- *buf = *addr;
- buf++;
- addr++;
- nwords--;
- }
-}
-
-void ynorsim_wr_one_word32(u32 *addr,u32 val)
-{
- u32 tmp;
- u32 m;
- int i;
-
- tmp = *addr;
- if(val & ~tmp){
- // Fail due to trying to change a zero into a 1
- printf("attempt to set a zero to one (%x)->(%x)\n",tmp,val);
- NorError();
- }
-
- for(i = 0; i < YNORSIM_BIT_CHANGES; i++){
- m = 1 << (rand() & 31);
- if(!(m & val)){
- tmp &= ~m;
- *addr = tmp;
- ynorsim_maybe_power_fail();
- }
-
- }
-
- *addr = tmp & val;
- ynorsim_maybe_power_fail();
-}
-
-void ynorsim_wr32(u32 *addr, u32 *buf, int nwords)
-{
- while(nwords >0){
- ynorsim_wr_one_word32(addr,*buf);
- addr++;
- buf++;
- nwords--;
- }
-}
-
-void ynorsim_erase(u32 *addr)
-{
- /* Todo... bit flipping */
- memset(addr,0xFF,YNORSIM_BLOCK_SIZE_U32 * 4);
-}
-
-void ynorsim_initialise(void)
-{
- ynorsim_ready();
-}
-
-void ynorsim_shutdown(void)
-{
- ynorsim_save_image();
- initialised=0;
-}
-
-u32 *ynorsim_get_base(void)
-{
- return word;
-}
YAFFS_COMMON_SOURCES="\
yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h \
yaffs_tagscompat.c yaffs_tagscompat.h \
+ yaffs_tagsmarshall.c yaffs_tagsmarshall.h \
yaffs_packedtags1.c yaffs_packedtags1.h \
yaffs_packedtags2.c yaffs_packedtags2.h \
yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
if [ "$1" = "copy" ] ; then
+set -e -x
for i in $YAFFS_COMMON_SOURCES ; do
sed ../$i \
-e "s/strcat/yaffs_strcat/g" \
+++ /dev/null
-# Makefile for YAFFS direct stress tests
-#
-#
-# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
-#
-# Copyright (C) 2003-2010 Aleph One Ltd.
-#
-#
-# Created by Charles Manning <charles@aleph1.co.uk>
-#
-# 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.
-#
-# NB Warning this Makefile does not include header dependencies.
-#
-# $Id: Makefile,v 1.6 2010-02-17 00:51:15 charles Exp $
-
-#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
-
-CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -DCONFIG_YAFFS_DEFINES_TYPES
-CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES -DNO_Y_INLINE
-CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing
-#CFLAGS += -fno-strict-aliasing
-CFLAGS += -O0 -fPIC
-#CFLAGS += -DVALGRIND_TEST
-
-#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
-#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
-
-
-COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\
- yramsim.o yaffs_fileem2k.o\
- yaffs_nandif.o yaffs_attribs.o \
- yaffsfs.o yaffs_ecc.o yaffs_guts.o \
- yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
- yaffs_tagscompat.o yaffs_packedtags2.o yaffs_nand.o \
- yaffs_checkptrw.o yaffs_qsort.o\
- yaffs_nameval.o \
- yaffs_summary.o \
- yaffs_allocator.o \
- yaffs_norif1.o ynorsim.o \
- yaffs_bitmap.o \
- yaffs_verify.o \
- yaffs_yaffs1.o yaffs_yaffs2.o \
- yaffs_error.o
-
-
-YAFFSLIBOBJS = $(COMMONTESTOBJS) yaffs_python_helper.o
-
-
-
-
-
-YAFFSDIRECTSYMLINKS = \
- yaffsfs.c yaffsfs.h yaffscfg.h yaffs_osglue.h ydirectenv.h \
- yaffs_flashif.h yaffs_flashif2.h yaffs_list.h \
- yaffs_nandif.c yaffs_nandif.h yaffs_qsort.c yaffs_nandemul2k.h \
- yportenv.h yaffs_attribs.c \
- yaffs_hweight.c yaffs_hweight.h \
- yaffs_error.c \
- yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffs_tagscompat.c yaffs_tagscompat.h \
- yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h \
- yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
- yaffs_checkptrw.h yaffs_checkptrw.c \
- yaffs_summary.c yaffs_summary.h \
- yaffs_nameval.c yaffs_nameval.h yaffs_attribs.h \
- yaffs_trace.h \
- yaffs_allocator.c yaffs_allocator.h \
- yaffs_yaffs1.c yaffs_yaffs1.h \
- yaffs_yaffs2.c yaffs_yaffs2.h \
- yaffs_bitmap.c yaffs_bitmap.h \
- yaffs_verify.c yaffs_verify.h
-
-DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
- yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \
- yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \
- yaffsnewcfg.c yramsim.c yramsim.h \
- ynorsim.h ynorsim.c yaffs_osglue.c
-
-COPIED_SOURCES = $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS)
-
-all: libyaffsfs.so
-
-
-$(YAFFSLIBOBJS): %.o: %.c
- gcc -c $(CFLAGS) -o $@ $<
-
-
-$(YAFFSDIRECTSYMLINKS):
- ln -s ../$@ $@
-
-$(DIRECTEXTRASYMLINKS):
- ln -s ../basic-test/$@ $@
-
-
-libyaffsfs.so: $(COPIED_SOURCES) $(YAFFSLIBOBJS)
- gcc -shared $(YAFFSLIBOBJS) -o $@
-
-
-clean:
- rm -f $(YAFFSLIBOBJS) core $(COPIED_SOURCES)
- rm -f libyaffsfs.so
- rm -f *.pyc
-# Makefile for YAFFS direct stress tests
+# Makefile rules for building in test framwork
#
#
# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
#
# NB Warning this Makefile does not include header dependencies.
#
-# $Id: Makefile,v 1.7 2010-02-25 22:34:47 charles Exp $
#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
CFLAGS = -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_YAFFS2 -DCONFIG_YAFFS_DEFINES_TYPES
CFLAGS += -DCONFIG_YAFFS_PROVIDE_DEFS -DCONFIG_YAFFSFS_PROVIDE_VALUES
-CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing
+CFLAGS += -Wall -g $(EXTRA_COMPILE_FLAGS) -Wstrict-aliasing
#CFLAGS += -fno-strict-aliasing
CFLAGS += -O0
CFLAGS += -Wextra -Wpointer-arith
COMMONTESTOBJS = yaffscfg2k.o yaffs_osglue.o yaffs_hweight.o\
yaffs_ecc.o yaffs_fileem.o yaffs_fileem2k.o yaffsfs.o yaffs_guts.o \
yaffs_packedtags1.o yaffs_ramdisk.o yaffs_ramem2k.o \
- yaffs_tagscompat.o yaffs_packedtags2.o yaffs_nand.o \
+ yaffs_tagscompat.o yaffs_tagsmarshall.o \
+ yaffs_packedtags2.o yaffs_nand.o \
yaffs_checkptrw.o yaffs_qsort.o\
yaffs_nameval.o yaffs_attribs.o \
- yaffs_norif1.o ynorsim.o nor_stress.o yaffs_fsx.o \
+ yaffs_m18_drv.o yaffs_nor_drv.o ynorsim.o \
yaffs_allocator.o \
yaffs_bitmap.o \
yaffs_yaffs1.o \
yaffs_verify.o \
yaffs_summary.o
-# yaffs_checkptrwtest.o\
-YAFFSTESTOBJS = $(COMMONTESTOBJS) yaffs_test.o
-
-ALLOBJS = $(sort $(YAFFSTESTOBJS))
+ALLOBJS = $(sort $(ALL_UNSORTED_OBJS))
YAFFSDIRECTSYMLINKS = \
yaffsfs.c yaffs_flashif.h yaffs_flashif2.h\
yaffs_hweight.c yaffs_hweight.h \
yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h \
yaffs_tagscompat.c yaffs_tagscompat.h \
+ yaffs_tagsmarshall.c yaffs_tagsmarshall.h \
yaffs_packedtags1.c yaffs_packedtags1.h \
yaffs_packedtags2.c yaffs_packedtags2.h \
yaffs_nand.c yaffs_nand.h yaffs_getblockinfo.h \
yaffs_summary.c yaffs_summary.h
-DIRECTEXTRASYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
- yaffs_fileem.c yaffs_norif1.c yaffs_norif1.h \
- yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \
- ynorsim.h ynorsim.c yaffs_osglue.c
-
-COPIED_SOURCES = $(YAFFSDIRECTSYMLINKS) $(DIRECTEXTRASYMLINKS)
+FRAMEWORKEXTRASYMLINKS = \
+ yaffscfg2k.c yaffs_fileem2k.c yaffs_fileem2k.h\
+ yaffs_fileem.c yaffs_m18_drv.c yaffs_m18_drv.h \
+ yaffs_nor_drv.c yaffs_nor_drv.h \
+ yaffs_ramdisk.c yaffs_ramdisk.h yaffs_ramem2k.c \
+ ynorsim.h ynorsim.c yaffs_osglue.c
-all: yaffs_test fuzzer
-
-$(ALLOBJS): %.o: %.c
- gcc -c $(CFLAGS) -o $@ $<
+FRAMEWORK_SOURCES = $(YAFFSDIRECTSYMLINKS) $(FRAMEWORKEXTRASYMLINKS)
+clean:
+ rm -f $(TARGETS) $(ALLOBJS) core $(FRAMEWORK_SOURCES)
$(YAFFSDIRECTSYMLINKS):
- ln -s ../$@ $@
+ ln -s $(YDI_DIR)/$@ $@
-$(DIRECTEXTRASYMLINKS):
- ln -s ../basic-test/$@ $@
+$(FRAMEWORKEXTRASYMLINKS):
+ ln -s $(YDI_FRAMEWORK_DIR)/$@ $@
-yaffs_test: $(COPIED_SOURCES) $(YAFFSTESTOBJS)
- gcc $(CFLLAG) -o $@ $(YAFFSTESTOBJS)
-
-fuzzer: fuzzer.c
- gcc $(CFLAGS) -o $@ $<
-
-clean:
- rm -f yaffs_test fuzzer fuzzer.o $(ALLOBJS) core $(COPIED_SOURCES)
+$(ALLOBJS): %.o: %.c
+ gcc -c $(CFLAGS) -o $@ $<
--- /dev/null
+# Makefile for YAFFS direct test
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2003-2010 Aleph One Ltd.
+#
+#
+# Created by Charles Manning <charles@aleph1.co.uk>
+#
+# 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.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+
+
+
+
+YDI_DIR = ../../
+YDI_FRAMEWORK_DIR = ../
+
+TARGETS = directtest2k
+
+all: $(TARGETS)
+
+DIRECTTESTOBJS = $(COMMONTESTOBJS) dtest.o
+
+ALL_UNSORTED_OBJS += $(DIRECTTESTOBJS)
+
+include ../FrameworkRules.mk
+
+directtest2k: $(FRAMEWORK_SOURCES) $(DIRECTTESTOBJS)
+ gcc -o $@ $(DIRECTTESTOBJS)
+
--- /dev/null
+# Makefile for YAFFS direct stress tests
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2003-2010 Aleph One Ltd.
+#
+#
+# Created by Charles Manning <charles@aleph1.co.uk>
+#
+# 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.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+
+
+
+
+
+
+
+$(YAFFSLIBOBJS): %.o: %.c
+ gcc -c $(CFLAGS) -o $@ $<
+
+
+$(YAFFSDIRECTSYMLINKS):
+ ln -s ../$@ $@
+
+$(DIRECTEXTRASYMLINKS):
+ ln -s ../basic-test/$@ $@
+
+
+# Makefile for stress tests and fuzzer
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2003-2010 Aleph One Ltd.
+#
+#
+# Created by Charles Manning <charles@aleph1.co.uk>
+#
+# 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.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+
+YDI_DIR = ../../
+YDI_FRAMEWORK_DIR = ../
+
+TARGETS = libyaffsfs.so
+
+
+all: $(TARGETS)
+
+
+YAFFSLIBOBJS = $(COMMONTESTOBJS) yaffs_python_helper.o
+
+ALL_UNSORTED_OBJS += $(YAFFSLIBOBJS)
+
+include ../FrameworkRules.mk
+
+CFLAGS += -O0 -fPIC
+
+
+libyaffsfs.so: $(FRAMEWORK_SOURCES) $(YAFFSLIBOBJS)
+ gcc -shared $(YAFFSLIBOBJS) -o $@
+
--- /dev/null
+# Makefile for stress tests and fuzzer
+#
+#
+# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
+#
+# Copyright (C) 2003-2010 Aleph One Ltd.
+#
+#
+# Created by Charles Manning <charles@aleph1.co.uk>
+#
+# 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.
+#
+# NB Warning this Makefile does not include header dependencies.
+#
+
+YDI_DIR = ../../
+YDI_FRAMEWORK_DIR = ../
+
+TARGETS = yaffs_test fuzzer
+
+all: $(TARGETS)
+
+YAFFS_TEST_OBJS = $(COMMONTESTOBJS) yaffs_test.o nor_stress.o yaffs_fsx.o
+FUZZER_OBJS = fuzzer.o
+
+ALL_UNSORTED_OBJS += $(YAFFS_TEST_OBJS) $(FUZZER_OBJS)
+
+include ../FrameworkRules.mk
+
+
+yaffs_test: $(FRAMEWORK_SOURCES) $(YAFFS_TEST_OBJS)
+ gcc $(CFLLAG) -o $@ $(YAFFS_TEST_OBJS)
+
+fuzzer: $(FUZZER_OBJS)
+ gcc $(CFLAGS) -o $@ $<
--- /dev/null
+#!/bin/bash
+# Run this to initialise the file system for the test runs.
+set -x
+rm seed-m18-*
+rm emfile-m18*
+./yaffs_test -u -i M18-1
# Run this to initialise the file system for the test runs.
rm seed-nor-*
rm emfile-nor*
-./yaffs_test -u -i M18-1
+./yaffs_test -u -i nor
xterm -e "$LAUNCHDIR/manage_nor_test.sh 0 $iterations"&
-xterm -e "$LAUNCHDIR/manage_nand_test.sh 0 $iterations"&
xterm -e "$LAUNCHDIR/manage_nor_test.sh 1 $iterations"&
-xterm -e "$LAUNCHDIR/manage_nand_test.sh 1 $iterations"&
xterm -e "$LAUNCHDIR/manage_nor_test.sh 2 $iterations"&
+
+xterm -e "$LAUNCHDIR/manage_m18_test.sh 0 $iterations"&
+xterm -e "$LAUNCHDIR/manage_m18_test.sh 1 $iterations"&
+xterm -e "$LAUNCHDIR/manage_m18_test.sh 2 $iterations"&
+
+xterm -e "$LAUNCHDIR/manage_nand_test.sh 0 $iterations"&
+xterm -e "$LAUNCHDIR/manage_nand_test.sh 1 $iterations"&
xterm -e "$LAUNCHDIR/manage_nand_test.sh 2 $iterations"&
--- /dev/null
+#! /bin/sh
+
+set -x
+
+dir_id=-none
+[ -z $1 ] || dir_id=$1
+
+
+iterations=100000
+
+[ -z $2 ] || iterations=$2
+
+STARTDIR=`pwd`
+RUNDIR=`pwd`/tmp/m18-$dir_id
+mkdir $RUNDIR
+cd $RUNDIR
+cp $STARTDIR/*sh .
+ln -s $STARTDIR/yaffs_test yaffs_test
+
+./init_fw_update_test_m18.sh
+./run_fw_update_test_m18.sh $iterations
+
+echo "!!!!!!!!!!!"
+echo "Tests done"
+while true
+do
+sleep 10
+done
static int interleave_fsx;
static int no_verification;
-
+
char fullPathName[100];
char fullPowerUpName[100];
char fullStartName[100];
if(ext_fatal)
ext_fatal();
-
+
while(1){
sleep(1);
}
unsigned x[2];
int nread = 0;
int nwritten = 0;
-
+
x[0] = x[1] = 0;
-
+
if(initialise){
- x[0] = 0;
+ x[0] = 0;
x[1] = 1;
} else {
inh = yaffs_open(name,O_RDONLY, S_IREAD | S_IWRITE);
printf("Error reading counter %s handle %d, x[0] %u x[1] %u last error %d\n",
name, inh, x[0], x[1],yaffsfs_GetLastError());
FatalError(__LINE__);
-
+
}
x[0]++;
x[1]++;
}
-
+
FSX();
outh = yaffs_open(fullTempCounterName, O_RDWR | O_TRUNC | O_CREAT, S_IREAD | S_IWRITE);
-
+
if(outh >= 0){
struct yaffs_stat tmpstat, oldstat, tmpfstat;
- FSX();
+ FSX();
yaffs_fstat(outh,&tmpfstat);
printf("\n\n\n*** Writing file %s inode %d\n",fullTempCounterName,tmpfstat.st_ino);
nwritten = yaffs_write(outh,x,sizeof(x));
yaffs_rename(fullTempCounterName,name);
FSX();
}
-
+
if(nwritten != sizeof(x)){
printf("Error writing counter %s handle %d, x[0] %u x[1] %u\n",
name, inh, x[0], x[1]);
FatalError(__LINE__);
}
-
+
*val = x[0];
-
+
printf("##\n"
"## Set counter %s to %u\n"
"##\n", name,x[0]);
char str[1000];
int error_line = 0;
int nentries;
-
+
d = yaffs_opendir(dname);
-
+
if(!d)
{
printf("opendir failed\n");
strcat(str,"/");
strcat(str,de->d_name);
nentries++;
-
+
yaffs_lstat(str,&s);
-
+
printf("%s inode %ld %d obj %x length %d mode %X ",str, de->d_ino, s.st_ino,de->d_dont_use,(int)s.st_size,s.st_mode);\
if(de->d_ino != s.st_ino){
printf(" \n\n!!!! HEY inode mismatch\n\n");
if(yaffs_readlink(str,str,100) < 0)
printf("no alias");
else
- printf("\"%s\"",str);
+ printf("\"%s\"",str);
break;
default: printf("unknown"); break;
}
-
+
printf("\n");
if((s.st_mode & S_IFMT) == S_IFDIR && recursive)
dump_directory_tree_worker(str,1);
-
+
if(s.st_ino > 10000)
error_line = __LINE__;
-
+
}
-
+
if(strstr(dname,"lost+found") && nentries >0){
printf("\n\n!!! HEY lost+found not empty, had %d entries\n\n\n",nentries);
error_line = __LINE__;
if(error_line && !no_verification)
FatalError(error_line);
-
+
yaffs_closedir(d);
}
int i;
struct yaffs_stat st;
unsigned checksum = 0;
-
+
FSX();
h = yaffs_open(fname,O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
yaffs_fstat(h,&st);
printf("\n\n\n**** Open writing file %s inode %d\n",fname, st.st_ino);
-
+
FSX();
if(h < 0){
xx[i] = sz32 + i;
checksum ^= xx[i];
}
-
+
FSX();
if((r = yaffs_write(h,xx,sizeof(xx))) != sizeof(xx)){
goto WRITE_ERROR;
if((r = yaffs_write(h,xx,sizeof(unsigned))) != sizeof(unsigned)){
goto WRITE_ERROR;
}
-
+
FSX();
yaffs_close(h);
printf("File closed\n");
printf("ywrite error at position %d\n",(int)yaffs_lseek(h,0,SEEK_END));
yaffs_close(h);
return -1;
-
+
}
static int y_verify_file(const char *fName)
return 0;
printf("Verifying file %s\n",fName);
-
+
h = yaffs_open(fName, O_RDONLY,S_IREAD | S_IWRITE);
if(h < 0){
yaffs_close(h);
return -1;
}
-
+
recordedSize = sz32 * sizeof(xx) + 8;
printf("verify %s: file size is %d, recorded size is %d\n", fName, totalSize, recordedSize);
yaffs_close(h);
return -1;
}
-
+
checksum ^= xx[0];
if(checksum != 0){
int result;
int sz32;
sz32 = (myrand() % 1000) + 20;
-
+
result = y_wr_file(fullTempMainName,sz32);
FSX();
if(!no_verification && result)
FatalError(__LINE__);
- printf("Raname file %s to %s\n",fullTempMainName,fullMainName);
+ printf("Rename file %s to %s\n",fullTempMainName,fullMainName);
yaffs_rename(fullTempMainName,fullMainName);
FSX();
}
void NorStressTestInitialise(const char *prefix)
{
MakeFullNames(prefix);
-
+
UpdateCounter(fullPowerUpName,&powerUps,1);
UpdateCounter(fullStartName,&cycleStarts,1);
UpdateCounter(fullEndName,&cycleEnds,1);
interleave_fsx = do_fsx;
no_verification = skip_verification;
-
+
MakeFullNames(prefix);
dump_directory_tree(fullPathName);
FSX_INIT(prefix);
-
+
dump_directory_tree(fullPathName);
-
+
UpdateCounter(fullPowerUpName,&powerUps,0);
dump_directory_tree(fullPathName);
-
+
while(n_cycles < 0 || n_cycles > 0){
if(n_cycles > 0)
n_cycles--;
DoVerifyMainFile();
DoUpdateMainFile();
dump_directory_tree(fullPathName);
-
+
UpdateCounter(fullEndName,&cycleEnds,0);
dump_directory_tree(fullPathName);
}
--- /dev/null
+#!/bin/bash
+
+
+set -x
+
+iterations=100000
+
+[ -z $1 ] || iterations=$1
+
+
+rm iteration-max-*
+touch iteration-max-$iterations
+
+echo " Running $iterations iterations"
+sleep 2
+
+for ((i=0; i < $iterations; i++))
+do
+
+ seed=$RANDOM
+ j=$(( $i % 10 ))
+
+ rm seed-m18-*$j
+ echo $seed>seed-m18-for-run-$i
+
+
+ rm emfile-m18-*$j
+ cp emfile-m18 emfile-m18-$i
+
+ rm log-m18-*$j
+
+ echo "#########"
+ echo "#########"
+ echo "#########"
+ echo "######### Run $i of $iterations with seed $seed"
+ echo "#########"
+ echo "#########"
+ echo "#########"
+ ./yaffs_test -u -f -p -s$seed -t0 M18-1
+ #>log-m18-$i
+done
+
echo "#########"
echo "#########"
echo "#########"
- ./yaffs_test -u -f -p -s$seed -t0 M18-1
+ ./yaffs_test -u -f -p -s$seed -t0 nor
#>log-nor-$i
done
* This is only intended as test code to test persistence etc.
*/
-const char *yaffs_flashif_c_version = "$Id: yaffs_fileem.c,v 1.7 2010-02-18 01:18:04 charles Exp $";
-
-
#include "yportenv.h"
#include "yaffs_trace.h"
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+/*
+ * This provides a YAFFS nand emulation on a file for emulating 2kB pages.
+ * This is only intended as test code to test persistence etc.
+ */
+
+#include "yportenv.h"
+#include "yaffs_trace.h"
+
+#include "yaffs_flashif2.h"
+#include "yaffs_guts.h"
+#include "yaffs_fileem2k.h"
+#include "yaffs_packedtags2.h"
+
+
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <unistd.h>
+
+#if 1
+
+#define SIZE_IN_MB 32
+/* #define SIZE_IN_MB 128 */
+
+#define PAGE_DATA_SIZE (2048)
+#define PAGE_SPARE_SIZE (64)
+#define PAGE_SIZE (PAGE_DATA_SIZE + PAGE_SPARE_SIZE)
+#define PAGES_PER_BLOCK (64)
+#define BLOCK_DATA_SIZE (PAGE_DATA_SIZE * PAGES_PER_BLOCK)
+#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE))
+#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE)
+#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB)
+
+#else
+
+#define SIZE_IN_MB 128
+#define PAGE_DATA_SIZE (512)
+#define SPARE_SIZE (16)
+#define PAGE_SIZE (PAGE_DATA_SIZE + SPARE_SIZE)
+#define PAGES_PER_BLOCK (32)
+#define BLOCK_DATA_SIZE (PAGE_SIZE * PAGES_PER_BLOCK)
+#define BLOCK_SIZE (PAGES_PER_BLOCK * (PAGE_SIZE))
+#define BLOCKS_PER_MB ((1024*1024)/BLOCK_DATA_SIZE)
+#define SIZE_IN_BLOCKS (BLOCKS_PER_MB * SIZE_IN_MB)
+
+#endif
+
+#define REPORT_ERROR 0
+
+typedef struct
+{
+ u8 data[PAGE_SIZE]; // Data + spare
+} yflash_Page;
+
+typedef struct
+{
+ yflash_Page page[PAGES_PER_BLOCK]; // The pages in the block
+
+} yflash_Block;
+
+
+
+#define MAX_HANDLES 20
+#define BLOCKS_PER_HANDLE (32*8)
+
+typedef struct
+{
+ int handle[MAX_HANDLES];
+ int nBlocks;
+} yflash_Device;
+
+static yflash_Device filedisk;
+
+int yaffs_test_partial_write = 0;
+
+extern int random_seed;
+extern int simulate_power_failure;
+static int remaining_ops;
+static int nops_so_far;
+
+int ops_multiplier;
+
+
+static void yflash2_MaybePowerFail(unsigned int nand_chunk, int failPoint)
+{
+
+ nops_so_far++;
+
+
+ remaining_ops--;
+ if(simulate_power_failure &&
+ remaining_ops < 1){
+ printf("Simulated power failure after %d operations\n",nops_so_far);
+ printf(" power failed on nand_chunk %d, at fail point %d\n",
+ nand_chunk, failPoint);
+ exit(0);
+ }
+}
+
+
+
+
+
+static u8 localBuffer[PAGE_SIZE];
+
+static char *NToName(char *buf,int n)
+{
+ sprintf(buf,"emfile-2k-%d",n);
+ return buf;
+}
+
+static char dummyBuffer[BLOCK_SIZE];
+
+static int GetBlockFileHandle(int n)
+{
+ int h;
+ int requiredSize;
+
+ char name[40];
+ NToName(name,n);
+ int fSize;
+ int i;
+
+ h = open(name, O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
+ if(h >= 0){
+ fSize = lseek(h,0,SEEK_END);
+ requiredSize = BLOCKS_PER_HANDLE * BLOCK_SIZE;
+ if(fSize < requiredSize){
+ for(i = 0; i < BLOCKS_PER_HANDLE; i++)
+ if(write(h,dummyBuffer,BLOCK_SIZE) != BLOCK_SIZE)
+ return -1;
+
+ }
+ }
+
+ return h;
+
+}
+
+static int CheckInit(void)
+{
+ static int initialised = 0;
+ int i;
+
+ int blk;
+
+
+ if(initialised)
+ {
+ return YAFFS_OK;
+ }
+
+ initialised = 1;
+
+
+ srand(random_seed);
+ remaining_ops = (rand() % 1000) * 5;
+ memset(dummyBuffer,0xff,sizeof(dummyBuffer));
+
+
+
+ filedisk.nBlocks = SIZE_IN_MB * BLOCKS_PER_MB;
+
+ for(i = 0; i < MAX_HANDLES; i++)
+ filedisk.handle[i] = -1;
+
+ for(i = 0,blk = 0; blk < filedisk.nBlocks; blk+=BLOCKS_PER_HANDLE,i++)
+ filedisk.handle[i] = GetBlockFileHandle(i);
+
+
+ return 1;
+}
+
+
+int yflash2_GetNumberOfBlocks(void)
+{
+ CheckInit();
+
+ return filedisk.nBlocks;
+}
+
+
+int yaffs_check_all_ff(const u8 *ptr, int n)
+{
+ while(n)
+ {
+ n--;
+ if(*ptr!=0xFF) return 0;
+ ptr++;
+ }
+ return 1;
+}
+
+
+static int yflash2_WriteChunk(struct yaffs_dev *dev, int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len)
+{
+ int retval = YAFFS_OK;
+ int pos;
+ int h;
+ int nwritten;
+
+ (void) dev;
+
+ if (data && data_len) {
+ pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+ h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ lseek(h,pos,SEEK_SET);
+ nwritten = write(h,data,data_len);
+ if(nwritten != data_len)
+ retval = YAFFS_FAIL;
+ }
+
+ if (oob && oob_len) {
+ pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
+ h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ lseek(h,pos,SEEK_SET);
+ nwritten = write(h,oob,oob_len);
+ if(nwritten != oob_len)
+ retval = YAFFS_FAIL;
+ }
+
+ yflash2_MaybePowerFail(nand_chunk,3);
+
+ return retval;
+}
+
+static int yflash2_ReadChunk(struct yaffs_dev *dev, int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result)
+{
+ int retval = YAFFS_OK;
+ int pos;
+ int h;
+ int nread;
+
+ (void) dev;
+
+ if (data && data_len) {
+ pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
+ h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ lseek(h,pos,SEEK_SET);
+ nread = read(h,data,data_len);
+ if(nread != data_len)
+ retval = YAFFS_FAIL;
+ }
+
+ if (oob && oob_len) {
+ pos = (nand_chunk % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
+ h = filedisk.handle[(nand_chunk / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
+ lseek(h,pos,SEEK_SET);
+ nread = read(h,oob,oob_len);
+ if(nread != oob_len)
+ retval = YAFFS_FAIL;
+ }
+
+ if (ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+ return retval;
+}
+
+static int yflash2_EraseBlock(struct yaffs_dev *dev, int block_no)
+{
+ int i;
+ int h;
+
+ CheckInit();
+
+ if(block_no < 0 || block_no >= filedisk.nBlocks)
+ {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,"Attempt to erase non-existant block %d",block_no);
+ return YAFFS_FAIL;
+ }
+ else
+ {
+
+ u8 pg[PAGE_SIZE];
+ int syz = PAGE_SIZE;
+ int pos;
+
+ memset(pg,0xff,syz);
+
+
+ h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))];
+ lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE,SEEK_SET);
+ for(i = 0; i < dev->param.chunks_per_block; i++)
+ {
+ write(h,pg,PAGE_SIZE);
+ }
+ pos = lseek(h, 0,SEEK_CUR);
+
+ return YAFFS_OK;
+ }
+}
+
+static int yflash2_MarkBad(struct yaffs_dev *dev, int block_no)
+{
+ int written;
+ int h;
+
+ struct yaffs_packed_tags2 pt;
+
+ CheckInit();
+
+ memset(&pt,0,sizeof(pt));
+ h = filedisk.handle[(block_no / ( BLOCKS_PER_HANDLE))];
+ lseek(h,((block_no % BLOCKS_PER_HANDLE) * dev->param.chunks_per_block) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET);
+ written = write(h,&pt,sizeof(pt));
+
+ if(written != sizeof(pt))
+ return YAFFS_FAIL;
+
+ return YAFFS_OK;
+
+}
+
+static int yflash2_CheckBad(struct yaffs_dev *dev, int block_no)
+{
+ (void) dev;
+ (void) block_no;
+
+ return YAFFS_OK;
+}
+
+static int yflash2_Initialise(struct yaffs_dev *dev)
+{
+ (void) dev;
+
+ CheckInit();
+
+ return YAFFS_OK;
+}
+
+struct yaffs_dev *yflash2_install_drv(const char *name)
+{
+ struct yaffs_dev *dev = NULL;
+ struct yaffs_param *param;
+ struct yaffs_driver *drv;
+
+ dev = malloc(sizeof(*dev));
+
+ if(!dev)
+ return NULL;
+
+ memset(dev, 0, sizeof(*dev));
+
+ dev->param.name = strdup(name);
+
+ if(!dev->param.name) {
+ free(dev);
+ return NULL;
+ }
+
+ drv = &dev->drv;
+
+ drv->drv_write_chunk_fn = yflash2_WriteChunk;
+ drv->drv_read_chunk_fn = yflash2_ReadChunk;
+ drv->drv_erase_fn = yflash2_EraseBlock;
+ drv->drv_mark_bad_fn = yflash2_MarkBad;
+ drv->drv_check_bad_fn = yflash2_CheckBad;
+ drv->drv_initialise_fn = yflash2_Initialise;
+
+ param = &dev->param;
+
+ param->total_bytes_per_chunk = 2048;
+ param->chunks_per_block = 64;
+ param->start_block = 0;
+ param->end_block = yflash2_GetNumberOfBlocks()-1;
+ param->is_yaffs2 = 1;
+ param->use_nand_ecc=1;
+
+ param->n_reserved_blocks = 5;
+ param->wide_tnodes_disabled=0;
+ param->refresh_period = 1000;
+ param->n_caches = 10; // Use caches
+
+ param->enable_xattr = 1;
+
+ /* dev->driver_context is not used by this simulator */
+
+ yaffs_add_device(dev);
+
+ return dev;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+#ifndef __FILEEM2K_H__
+#define __FILEEM2K_H__
+
+
+struct yaffs_dev;
+
+struct yaffs_dev *yflash2_install_drv(const char *name);
+
+
+#endif
+
/* First set up for M18 with 1k chunks and 16-byte spares.
*
- * NB We're using the oddball M18 modes of operation here
+ * NB We're using the oddball M18 modes of operation here
* The chip is 64MB based at 0x0000, but YAFFS only going to use the top half
* ie. YAFFS will be from 32MB to 64MB.
*
- * The M18 has two ways of writing data. Every Programming Region (1kbytes)
+ * The M18 has two ways of writing data. Every Programming Region (1kbytes)
* can be programmed in two modes:
* * Object Mode 1024 bytes of write once data.
- * * Control Mode: 512bytes of bit-writeable data.
+ * * Control Mode: 512bytes of bit-writeable data.
* This is arranged as 32 * (16 bytes of bit-writable followed by 16 bytes of "dont touch")
- *
+ *
* The block size is 256kB, making 128 blocks in the 32MB YAFFS area.
* Each block comprises:
* Offset 0k: 248 x 1k data pages
* Offset 248k: 248 x 32-byte spare areas implemented as 16 bytes of spare followed by 16 bytes untouched)
* Offset 248k + (248 * 32): Format marker
- *
+ *
*/
-const char *yaffs_norif1_c_version = "$Id: yaffs_norif1.c,v 1.6 2010-02-18 01:18:04 charles Exp $";
-
-#include "yaffs_norif1.h"
+#include "yaffs_m18_drv.h"
#include "yportenv.h"
#include "yaffs_trace.h"
#define CHUNKS_PER_BLOCK 248
#define SPARE_AREA_OFFSET (CHUNKS_PER_BLOCK * PROG_REGION_SIZE)
-#define FORMAT_OFFSET (SPARE_AREA_OFFSET + CHUNKS_PER_BLOCK * (SPARE_BYTES_PER_CHUNK + M18_SKIP))
+#define FORMAT_OFFSET (SPARE_AREA_OFFSET + CHUNKS_PER_BLOCK * \
+ (SPARE_BYTES_PER_CHUNK + M18_SKIP))
#define FORMAT_VALUE 0x1234
/* Compile this for a simulation */
#include "ynorsim.h"
-#define ynorif1_FlashInit() ynorsim_initialise()
-#define ynorif1_FlashDeinit() ynorsim_shutdown()
-#define ynorif1_FlashWrite32(addr,buf,nwords) ynorsim_wr32(addr,buf,nwords)
-#define ynorif1_FlashRead32(addr,buf,nwords) ynorsim_rd32(addr,buf,nwords)
-#define ynorif1_FlashEraseBlock(addr) ynorsim_erase(addr)
-#define DEVICE_BASE ynorsim_get_base()
+
+static struct nor_sim *nor_sim;
+
+#define m18_drv_FlashInit() do {nor_sim = ynorsim_initialise("emfile-m18", BLOCKS_IN_DEVICE, BLOCK_SIZE_IN_BYTES); } while(0)
+#define m18_drv_FlashDeinit() ynorsim_shutdown(nor_sim)
+#define m18_drv_FlashWrite32(addr,buf,nwords) ynorsim_wr32(nor_sim,addr,buf,nwords)
+#define m18_drv_FlashRead32(addr,buf,nwords) ynorsim_rd32(nor_sim,addr,buf,nwords)
+#define m18_drv_FlashEraseBlock(addr) ynorsim_erase(nor_sim,addr)
+#define DEVICE_BASE ynorsim_get_base(nor_sim)
+
#else
-/* Compile this for running on blob, hacked for yaffs access */
+/* Compile this to hook up to read hardware */
#include "../blob/yflashrw.h"
-#define ynorif1_FlashInit() do{} while(0)
-#define ynorif1_FlashDeinit() do {} while(0)
-#define ynorif1_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords)
-#define ynorif1_FlashRead32(addr,buf,nwords) Y_FlashRead(addr,buf,nwords)
-#define ynorif1_FlashEraseBlock(addr) Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES)
+#define m18_drv_FlashInit() do{} while(0)
+#define m18_drv_FlashDeinit() do {} while(0)
+#define m18_drv_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords)
+#define m18_drv_FlashRead32(addr,buf,nwords) Y_FlashRead(addr,buf,nwords)
+#define m18_drv_FlashEraseBlock(addr) Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES)
#define DEVICE_BASE (32 * 1024 * 1024)
#endif
-u32 *Block2Addr(struct yaffs_dev *dev, int blockNumber)
+
+static u32 *Block2Addr(struct yaffs_dev *dev, int blockNumber)
{
- u32 addr;
+ u8 *addr;
dev=dev;
-
- addr = (u32) DEVICE_BASE;
+
+ addr = (u8*) DEVICE_BASE;
addr += blockNumber * BLOCK_SIZE_IN_BYTES;
-
+
return (u32 *) addr;
}
-u32 *Block2FormatAddr(struct yaffs_dev *dev,int blockNumber)
+static u32 *Block2FormatAddr(struct yaffs_dev *dev,int blockNumber)
{
- u32 addr;
+ u8 *addr;
- addr = (u32) Block2Addr(dev,blockNumber);
+ addr = (u8*) Block2Addr(dev,blockNumber);
addr += FORMAT_OFFSET;
-
+
return (u32 *)addr;
}
-u32 *Chunk2DataAddr(struct yaffs_dev *dev,int chunk_id)
+
+static u32 *Chunk2DataAddr(struct yaffs_dev *dev,int chunk_id)
{
unsigned block;
unsigned chunkInBlock;
- u32 addr;
-
+ u8 *addr;
+
block = chunk_id/dev->param.chunks_per_block;
chunkInBlock = chunk_id % dev->param.chunks_per_block;
-
- addr = (u32) Block2Addr(dev,block);
+
+ addr = (u8*) Block2Addr(dev,block);
addr += chunkInBlock * DATA_BYTES_PER_CHUNK;
-
+
return (u32 *)addr;
}
-u32 *Chunk2SpareAddr(struct yaffs_dev *dev,int chunk_id)
+static u32 *Chunk2SpareAddr(struct yaffs_dev *dev,int chunk_id)
{
unsigned block;
unsigned chunkInBlock;
- u32 addr;
-
+ u8 *addr;
+
block = chunk_id/dev->param.chunks_per_block;
chunkInBlock = chunk_id % dev->param.chunks_per_block;
-
- addr = (u32) Block2Addr(dev,block);
+
+ addr = (u8*) Block2Addr(dev,block);
addr += SPARE_AREA_OFFSET;
addr += chunkInBlock * (SPARE_BYTES_PER_CHUNK + M18_SKIP);
return (u32 *)addr;
}
-void ynorif1_AndBytes(u8*target, const u8 *src, int nbytes)
+static void m18_drv_AndBytes(u8*target, const u8 *src, int nbytes)
{
while(nbytes > 0){
*target &= *src;
}
}
-int ynorif1_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_spare *spare)
+static int m18_drv_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len)
{
u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk);
u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk);
-
+
+ struct yaffs_spare *spare = (struct yaffs_spare *)oob;
struct yaffs_spare tmpSpare;
-
+
+ (void) oob_len;
+
/* We should only be getting called for one of 3 reasons:
* Writing a chunk: data and spare will not be NULL
* Writing a deletion marker: data will be NULL, spare not NULL
* Writing a bad block marker: data will be NULL, spare not NULL
*/
-
+
if(sizeof(struct yaffs_spare) != 16)
BUG();
-
- if(data && spare)
+
+ if(data && oob)
{
if(spare->page_status != 0xff)
BUG();
/* Write a pre-marker */
memset(&tmpSpare,0xff,sizeof(tmpSpare));
tmpSpare.page_status = YNOR_PREMARKER;
- ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4);
+ m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4);
+
+ /* Write the data */
+ m18_drv_FlashWrite32(dataAddr,(u32 *)data, data_len/ 4);
+
- /* Write the data */
- ynorif1_FlashWrite32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / 4);
-
-
memcpy(&tmpSpare,spare,sizeof(struct yaffs_spare));
-
+
/* Write the real tags, but override the premarker*/
tmpSpare.page_status = YNOR_PREMARKER;
- ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4);
-
+ m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/4);
+
/* Write a post-marker */
tmpSpare.page_status = YNOR_POSTMARKER;
- ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(tmpSpare)/4);
+ m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(tmpSpare)/4);
} else if(spare){
/* This has to be a read-modify-write operation to handle NOR-ness */
- ynorif1_FlashRead32(spareAddr,(u32 *)&tmpSpare,16/ 4);
-
- ynorif1_AndBytes((u8 *)&tmpSpare,(u8 *)spare,sizeof(struct yaffs_spare));
-
- ynorif1_FlashWrite32(spareAddr,(u32 *)&tmpSpare,16/ 4);
+ m18_drv_FlashRead32(spareAddr,(u32 *)&tmpSpare,16/ 4);
+
+ m18_drv_AndBytes((u8 *)&tmpSpare,(u8 *)spare,sizeof(struct yaffs_spare));
+
+ m18_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,16/ 4);
}
else {
BUG();
}
-
- return YAFFS_OK;
+
+ return YAFFS_OK;
}
-int ynorif1_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_spare *spare)
+static int m18_drv_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result)
{
+ struct yaffs_spare *spare = (struct yaffs_spare *)oob;
u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk);
u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk);
-
+
if(data)
{
- ynorif1_FlashRead32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / 4);
+ m18_drv_FlashRead32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / 4);
}
-
- if(spare)
+
+ if(oob)
{
- ynorif1_FlashRead32(spareAddr,(u32 *)spare,16/ 4);
-
+ m18_drv_FlashRead32(spareAddr,(u32 *)spare, oob_len/ 4);
+
/* If the page status is YNOR_POSTMARKER then it was written properly
* so change that to 0xFF so that the rest of yaffs is happy.
*/
(spare->page_status | YNOR_PREMARKER) != 0xff)
spare->page_status = YNOR_PREMARKER;
}
-
- return YAFFS_OK;
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+ return YAFFS_OK;
}
-static int ynorif1_FormatBlock(struct yaffs_dev *dev, int blockNumber)
+
+static int m18_drv_FormatBlock(struct yaffs_dev *dev, int blockNumber)
{
u32 *blockAddr = Block2Addr(dev,blockNumber);
u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
u32 formatValue = FORMAT_VALUE;
-
- ynorif1_FlashEraseBlock(blockAddr);
- ynorif1_FlashWrite32(formatAddr,&formatValue,1);
-
+
+ m18_drv_FlashEraseBlock(blockAddr);
+ m18_drv_FlashWrite32(formatAddr,&formatValue,1);
+
return YAFFS_OK;
}
-static int ynorif1_UnformatBlock(struct yaffs_dev *dev, int blockNumber)
+static int m18_drv_UnformatBlock(struct yaffs_dev *dev, int blockNumber)
{
u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
u32 formatValue = 0;
-
- ynorif1_FlashWrite32(formatAddr,&formatValue,1);
-
+
+ m18_drv_FlashWrite32(formatAddr,&formatValue,1);
+
return YAFFS_OK;
}
-static int ynorif1_IsBlockFormatted(struct yaffs_dev *dev, int blockNumber)
+static int m18_drv_IsBlockFormatted(struct yaffs_dev *dev, int blockNumber)
{
u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
u32 formatValue;
-
-
- ynorif1_FlashRead32(formatAddr,&formatValue,1);
-
+
+
+ m18_drv_FlashRead32(formatAddr,&formatValue,1);
+
return (formatValue == FORMAT_VALUE);
}
-int ynorif1_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
+static int m18_drv_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
{
if(blockNumber < 0 || blockNumber >= BLOCKS_IN_DEVICE)
}
else
{
- ynorif1_UnformatBlock(dev,blockNumber);
- ynorif1_FormatBlock(dev,blockNumber);
+ m18_drv_UnformatBlock(dev,blockNumber);
+ m18_drv_FormatBlock(dev,blockNumber);
return YAFFS_OK;
}
-
+
}
-int ynorif1_InitialiseNAND(struct yaffs_dev *dev)
+static int m18_drv_InitialiseNAND(struct yaffs_dev *dev)
{
int i;
-
- ynorif1_FlashInit();
+
+ m18_drv_FlashInit();
/* Go through the blocks formatting them if they are not formatted */
for(i = dev->param.start_block; i <= dev->param.end_block; i++){
- if(!ynorif1_IsBlockFormatted(dev,i)){
- ynorif1_FormatBlock(dev,i);
+ if(!m18_drv_IsBlockFormatted(dev,i)){
+ m18_drv_FormatBlock(dev,i);
}
}
return YAFFS_OK;
}
-int ynorif1_Deinitialise_flash_fn(struct yaffs_dev *dev)
+static int m18_drv_Deinitialise_flash_fn(struct yaffs_dev *dev)
{
- dev=dev;
- ynorif1_FlashDeinit();
+ dev=dev;
+
+ m18_drv_FlashDeinit();
return YAFFS_OK;
}
+struct yaffs_dev *yaffs_m18_install_drv(const char *name)
+{
+
+ struct yaffs_dev *dev = malloc(sizeof(struct yaffs_dev));
+ char *name_copy = strdup(name);
+ struct yaffs_param *param;
+ struct yaffs_driver *drv;
+
+
+ if(!dev || !name_copy) {
+ free(name_copy);
+ free(dev);
+ return NULL;
+ }
+
+ param = &dev->param;
+ drv = &dev->drv;
+
+ memset(dev, 0, sizeof(*dev));
+
+ param->name = name_copy;
+
+ param->total_bytes_per_chunk = 1024;
+ param->chunks_per_block =248;
+ param->n_reserved_blocks = 2;
+ param->start_block = 0; // Can use block 0
+ param->end_block = 31; // Last block
+ param->use_nand_ecc = 0; // use YAFFS's ECC
+
+ drv->drv_write_chunk_fn = m18_drv_WriteChunkToNAND;
+ drv->drv_read_chunk_fn = m18_drv_ReadChunkFromNAND;
+ drv->drv_erase_fn = m18_drv_EraseBlockInNAND;
+ drv->drv_initialise_fn = m18_drv_InitialiseNAND;
+ drv->drv_deinitialise_fn = m18_drv_Deinitialise_flash_fn;
+
+ param->n_caches = 10;
+ param->disable_soft_del = 1;
+
+ dev->driver_context = (void *) 1; // Used to identify the device in fstat.
+
+ yaffs_add_device(dev);
+
+ return NULL;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#ifndef __YAFFS_M18_DRV_H__
+#define __YAFFS_M18_DRV_H__
+
+struct yaffs_dev;
+struct yaffs_dev *yaffs_m18_install_drv(const char *name);
+
+#endif
+
+
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+/*
+ * This is an interface module for handling NOR in yaffs1 mode.
+ */
+
+/* This code is intended to be used with "regular" NOR that is bit-modifyable.
+ *
+ * Each "chunk" is a contguous area of 512 + 16 bytes.
+ * This makes 248 such chunks with some space left over where a format markerr
+ * is stored.
+ */
+
+#include "yaffs_nor_drv.h"
+
+#include "yportenv.h"
+#include "yaffs_trace.h"
+
+#include "yaffs_flashif.h"
+#include "yaffs_guts.h"
+
+/* Tunable data */
+#define DATA_BYTES_PER_CHUNK 512
+#define SPARE_BYTES_PER_CHUNK 16
+#define BLOCK_SIZE_IN_BYTES (128*1024)
+#define BYTES_IN_DEVICE (4*1024*1024)
+
+#define BYTES_PER_CHUNK (DATA_BYTES_PER_CHUNK + SPARE_BYTES_PER_CHUNK)
+#define SPARE_AREA_OFFSET DATA_BYTES_PER_CHUNK
+#define CHUNKS_PER_BLOCK (BLOCK_SIZE_IN_BYTES/BYTES_PER_CHUNK)
+
+#define BLOCKS_IN_DEVICE (BYTES_IN_DEVICE/BLOCK_SIZE_IN_BYTES)
+
+#define YNOR_PREMARKER (0xF6)
+#define YNOR_POSTMARKER (0xF0)
+
+#define FORMAT_OFFSET (CHUNKS_PER_BLOCK * BYTES_PER_CHUNK)
+#define FORMAT_VALUE 0x1234
+
+#if 1
+
+/* Compile this for a simulation */
+#include "ynorsim.h"
+
+static struct nor_sim *nor_sim;
+
+#define nor_drv_FlashInit() do {nor_sim = ynorsim_initialise("emfile-nor", BLOCKS_IN_DEVICE, BLOCK_SIZE_IN_BYTES); } while(0)
+#define nor_drv_FlashDeinit() ynorsim_shutdown(nor_sim)
+#define nor_drv_FlashWrite32(addr,buf,nwords) ynorsim_wr32(nor_sim,addr,buf,nwords)
+#define nor_drv_FlashRead32(addr,buf,nwords) ynorsim_rd32(nor_sim,addr,buf,nwords)
+#define nor_drv_FlashEraseBlock(addr) ynorsim_erase(nor_sim,addr)
+#define DEVICE_BASE ynorsim_get_base(nor_sim)
+
+#else
+
+/* Compile this to hook up to read hardware */
+#include "../blob/yflashrw.h"
+#define nor_drv_FlashInit() do{} while(0)
+#define nor_drv_FlashDeinit() do {} while(0)
+#define nor_drv_FlashWrite32(addr,buf,nwords) Y_FlashWrite(addr,buf,nwords)
+#define nor_drv_FlashRead32(addr,buf,nwords) Y_FlashRead(addr,buf,nwords)
+#define nor_drv_FlashEraseBlock(addr) Y_FlashErase(addr,BLOCK_SIZE_IN_BYTES)
+#define DEVICE_BASE (32 * 1024 * 1024)
+#endif
+
+
+static u32 *Block2Addr(struct yaffs_dev *dev, int blockNumber)
+{
+ u8 *addr;
+
+ dev=dev;
+
+ addr = (u8*)DEVICE_BASE;
+ addr += blockNumber * BLOCK_SIZE_IN_BYTES;
+
+ return (u32 *) addr;
+}
+
+static u32 *Block2FormatAddr(struct yaffs_dev *dev, int blockNumber)
+{
+ u8 *addr;
+
+ addr = (u8*) Block2Addr(dev,blockNumber);
+ addr += FORMAT_OFFSET;
+
+ return (u32 *)addr;
+}
+
+static u32 *Chunk2DataAddr(struct yaffs_dev *dev, int chunk_id)
+{
+ unsigned block;
+ unsigned chunkInBlock;
+ u8 *addr;
+
+ block = chunk_id/dev->param.chunks_per_block;
+ chunkInBlock = chunk_id % dev->param.chunks_per_block;
+
+ addr = (u8*) Block2Addr(dev,block);
+ addr += chunkInBlock * BYTES_PER_CHUNK;
+
+ return (u32 *)addr;
+}
+
+static u32 *Chunk2SpareAddr(struct yaffs_dev *dev, int chunk_id)
+{
+ u8 *addr;
+
+ addr = (u8*) Chunk2DataAddr(dev, chunk_id);
+ addr += SPARE_AREA_OFFSET;
+ return (u32 *)addr;
+}
+
+
+static void nor_drv_AndBytes(u8*target, const u8 *src, int nbytes)
+{
+ while(nbytes > 0){
+ *target &= *src;
+ target++;
+ src++;
+ nbytes--;
+ }
+}
+
+static int nor_drv_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len)
+{
+ u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk);
+ u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk);
+
+ struct yaffs_spare *spare = (struct yaffs_spare *)oob;
+ struct yaffs_spare tmpSpare;
+
+ (void) oob_len;
+
+ /* We should only be getting called for one of 3 reasons:
+ * Writing a chunk: data and spare will not be NULL
+ * Writing a deletion marker: data will be NULL, spare not NULL
+ * Writing a bad block marker: data will be NULL, spare not NULL
+ */
+
+ if(sizeof(struct yaffs_spare) != SPARE_BYTES_PER_CHUNK)
+ BUG();
+
+ if(data && oob) {
+ if(spare->page_status != 0xff)
+ BUG();
+ /* Write a pre-marker */
+ memset(&tmpSpare,0xff,sizeof(tmpSpare));
+ tmpSpare.page_status = YNOR_PREMARKER;
+ nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+
+ /* Write the data */
+ nor_drv_FlashWrite32(dataAddr,(u32 *)data, data_len/ sizeof(u32));
+
+ memcpy(&tmpSpare,spare,sizeof(struct yaffs_spare));
+
+ /* Write the real tags, but override the premarker*/
+ tmpSpare.page_status = YNOR_PREMARKER;
+ nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+
+ /* Write a post-marker */
+ tmpSpare.page_status = YNOR_POSTMARKER;
+ nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(tmpSpare)/sizeof(u32));
+
+ } else if(spare){
+ /* This has to be a read-modify-write operation to handle NOR-ness */
+
+ nor_drv_FlashRead32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+
+ nor_drv_AndBytes((u8 *)&tmpSpare,(u8 *)spare,sizeof(struct yaffs_spare));
+
+ nor_drv_FlashWrite32(spareAddr,(u32 *)&tmpSpare,sizeof(struct yaffs_spare)/sizeof(u32));
+ } else {
+ BUG();
+ }
+
+ return YAFFS_OK;
+}
+
+static int nor_drv_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result)
+{
+ struct yaffs_spare *spare = (struct yaffs_spare *)oob;
+
+ u32 *dataAddr = Chunk2DataAddr(dev,nand_chunk);
+ u32 *spareAddr = Chunk2SpareAddr(dev,nand_chunk);
+
+ if (data) {
+ nor_drv_FlashRead32(dataAddr,(u32 *)data,dev->param.total_bytes_per_chunk / sizeof(u32));
+ }
+
+ if (oob) {
+ nor_drv_FlashRead32(spareAddr,(u32 *)spare, oob_len/ sizeof(u32));
+
+ /* If the page status is YNOR_POSTMARKER then it was written properly
+ * so change that to 0xFF so that the rest of yaffs is happy.
+ */
+ if(spare->page_status == YNOR_POSTMARKER)
+ spare->page_status = 0xff;
+ else if(spare->page_status != 0xff &&
+ (spare->page_status | YNOR_PREMARKER) != 0xff)
+ spare->page_status = YNOR_PREMARKER;
+ }
+
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
+ return YAFFS_OK;
+
+}
+
+
+static int nor_drv_FormatBlock(struct yaffs_dev *dev, int blockNumber)
+{
+ u32 *blockAddr = Block2Addr(dev,blockNumber);
+ u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+ u32 formatValue = FORMAT_VALUE;
+
+ nor_drv_FlashEraseBlock(blockAddr);
+ nor_drv_FlashWrite32(formatAddr,&formatValue,1);
+
+ return YAFFS_OK;
+}
+
+static int nor_drv_UnformatBlock(struct yaffs_dev *dev, int blockNumber)
+{
+ u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+ u32 formatValue = 0;
+
+ nor_drv_FlashWrite32(formatAddr,&formatValue,1);
+
+ return YAFFS_OK;
+}
+
+static int nor_drv_IsBlockFormatted(struct yaffs_dev *dev, int blockNumber)
+{
+ u32 *formatAddr = Block2FormatAddr(dev,blockNumber);
+ u32 formatValue;
+
+
+ nor_drv_FlashRead32(formatAddr,&formatValue,1);
+
+ return (formatValue == FORMAT_VALUE);
+}
+
+static int nor_drv_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber)
+{
+
+ if(blockNumber < 0 || blockNumber >= BLOCKS_IN_DEVICE)
+ {
+ yaffs_trace(YAFFS_TRACE_ALWAYS,
+ "Attempt to erase non-existant block %d\n",
+ blockNumber);
+ return YAFFS_FAIL;
+ }
+ else
+ {
+ nor_drv_UnformatBlock(dev,blockNumber);
+ nor_drv_FormatBlock(dev,blockNumber);
+ return YAFFS_OK;
+ }
+
+}
+
+static int nor_drv_InitialiseNAND(struct yaffs_dev *dev)
+{
+ int i;
+
+ nor_drv_FlashInit();
+ /* Go through the blocks formatting them if they are not formatted */
+ for(i = dev->param.start_block; i <= dev->param.end_block; i++){
+ if(!nor_drv_IsBlockFormatted(dev,i)){
+ nor_drv_FormatBlock(dev,i);
+ }
+ }
+ return YAFFS_OK;
+}
+
+static int nor_drv_Deinitialise_flash_fn(struct yaffs_dev *dev)
+{
+ dev=dev;
+
+ nor_drv_FlashDeinit();
+
+ return YAFFS_OK;
+}
+
+
+struct yaffs_dev *yaffs_nor_install_drv(const char *name)
+{
+
+ struct yaffs_dev *dev = malloc(sizeof(struct yaffs_dev));
+ char *name_copy = strdup(name);
+ struct yaffs_param *param;
+ struct yaffs_driver *drv;
+
+
+ if(!dev || !name_copy) {
+ free(name_copy);
+ free(dev);
+ return NULL;
+ }
+
+ param = &dev->param;
+ drv = &dev->drv;
+
+ memset(dev, 0, sizeof(*dev));
+
+ param->name = name_copy;
+
+ param->total_bytes_per_chunk = DATA_BYTES_PER_CHUNK;
+ param->chunks_per_block = CHUNKS_PER_BLOCK;
+ param->n_reserved_blocks = 2;
+ param->start_block = 0; // Can use block 0
+ param->end_block = BLOCKS_IN_DEVICE - 1; // Last block
+ param->use_nand_ecc = 0; // use YAFFS's ECC
+
+ drv->drv_write_chunk_fn = nor_drv_WriteChunkToNAND;
+ drv->drv_read_chunk_fn = nor_drv_ReadChunkFromNAND;
+ drv->drv_erase_fn = nor_drv_EraseBlockInNAND;
+ drv->drv_initialise_fn = nor_drv_InitialiseNAND;
+ drv->drv_deinitialise_fn = nor_drv_Deinitialise_flash_fn;
+
+ param->n_caches = 10;
+ param->disable_soft_del = 1;
+
+ dev->driver_context = (void *) nor_sim;
+
+ yaffs_add_device(dev);
+
+ return NULL;
+}
--- /dev/null
+/*
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License version 2.1 as
+ * published by the Free Software Foundation.
+ *
+ * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
+ */
+
+
+#ifndef __YAFFS_NOR_DRV_H__
+#define __YAFFS_NOR_DRV_H__
+
+struct yaffs_dev;
+struct yaffs_dev *yaffs_nor_install_drv(const char *name);
+
+#endif
+
+
#include "yaffscfg.h"
#include "yaffs_guts.h"
#include "yaffsfs.h"
-#include "yaffs_fileem2k.h"
-#include "yaffs_nandemul2k.h"
-#include "yaffs_norif1.h"
#include "yaffs_trace.h"
#include <assert.h>
return yaffsfs_lastError;
}
+int yaffsfs_CheckMemRegion(const void *addr, size_t size, int writeable)
+{
+ if(!addr)
+ return -1;
+ return 0;
+}
+
#ifdef CONFIG_YAFFS_USE_PTHREADS
#include <pthread.h>
* Use this with dev->use_nand_ecc enabled, then ECC overheads are not required.
*/
-const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.6 2010-01-11 04:06:47 charles Exp $";
-
-
#include "yportenv.h"
#include "yaffs_trace.h"
*/
-const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.8 2010-02-18 01:18:04 charles Exp $";
-
#ifndef __KERNEL__
#define CONFIG_YAFFS_RAM_ENABLED
#else
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+/*
+ * yaffscfg2k.c The configuration for the "direct" use of yaffs.
+ *
+ * This file is intended to be modified to your requirements.
+ * There is no need to redistribute this file.
+ */
+
+#include "yaffscfg.h"
+#include "yaffs_guts.h"
+#include "yaffsfs.h"
+#include "yaffs_fileem2k.h"
+#include "yaffs_nandemul2k.h"
+#include "yaffs_trace.h"
+#include "yaffs_osglue.h"
+
+
+#include <errno.h>
+
+unsigned yaffs_trace_mask =
+
+ YAFFS_TRACE_SCAN |
+ YAFFS_TRACE_GC |
+ YAFFS_TRACE_ERASE |
+ YAFFS_TRACE_ERROR |
+ YAFFS_TRACE_TRACING |
+ YAFFS_TRACE_ALLOCATE |
+ YAFFS_TRACE_BAD_BLOCKS |
+ YAFFS_TRACE_VERIFY |
+
+ 0;
+
+
+
+// Configuration
+
+#include "yaffs_flashif2.h"
+#include "yaffs_m18_drv.h"
+#include "yaffs_nor_drv.h"
+
+int yaffs_start_up(void)
+{
+ static int start_up_called = 0;
+
+ if(start_up_called)
+ return 0;
+ start_up_called = 1;
+
+ // Stuff to configure YAFFS
+ // Stuff to initialise anything special (eg lock semaphore).
+ yaffsfs_OSInitialisation();
+
+
+ yaffs_m18_install_drv("M18-1");
+ yaffs_nor_install_drv("nor");
+
+ // /yaffs2 yaffs2 file emulation
+ yflash2_install_drv("yaffs2");
+
+ return 0;
+}
+
+
+
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+#include "ynorsim.h"
+
+#include <stdio.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <unistd.h>
+#include <time.h>
+
+#define YNORSIM_FNAME "emfile-nor"
+
+/* Set YNORSIM_BIT_CHANGES to a a value from 1..30 to
+ *simulate bit flipping as the programming happens.
+ * A low value results in faster simulation with less chance of encountering a partially programmed
+ * word.
+ */
+
+//#define YNORSIM_BIT_CHANGES 15
+#define YNORSIM_BIT_CHANGES 2
+
+#if 0
+/* Simulate 32MB of flash in 256k byte blocks.
+ * This stuff is x32.
+ */
+
+#define YNORSIM_BLOCK_SIZE_U32 (256*1024/4)
+#define YNORSIM_DEV_SIZE_U32 (32*1024 * 1024/4)
+#else
+/* Simulate 8MB of flash in 256k byte blocks.
+ * This stuff is x32.
+ */
+
+#define YNORSIM_BLOCK_SIZE_U32 (256*1024/4)
+#define YNORSIM_DEV_SIZE_U32 (8*1024 * 1024/4)
+#endif
+
+struct nor_sim {
+ int n_blocks;
+ int block_size_bytes;
+ int file_size;
+ u32 *word;
+ int initialised;
+ char *fname;
+ int remaining_ops;
+ int nops_so_far;
+};
+
+int ops_multiplier = 500;
+extern int random_seed;
+extern int simulate_power_failure;
+
+static void NorError(struct nor_sim *sim)
+{
+ printf("Nor error on device %s\n", sim->fname);
+ while (1) {
+ }
+}
+
+static void ynorsim_save_image(struct nor_sim *sim)
+{
+ int h;
+
+ h = open(sim->fname, O_RDWR | O_CREAT | O_TRUNC, S_IREAD | S_IWRITE);
+ write(h, sim->word, sim->file_size);
+ close(h);
+}
+
+static void ynorsim_restore_image(struct nor_sim *sim)
+{
+ int h;
+
+ h = open(sim->fname, O_RDONLY, S_IREAD | S_IWRITE);
+ memset(sim->word, 0xFF, sim->file_size);
+ read(h, sim->word, sim->file_size);
+ close(h);
+}
+
+static void ynorsim_power_fail(struct nor_sim *sim)
+{
+ ynorsim_save_image(sim);
+ exit(1);
+}
+
+static void ynorsim_maybe_power_fail(struct nor_sim *sim)
+{
+ sim->nops_so_far++;
+ sim->remaining_ops--;
+ if (simulate_power_failure && sim->remaining_ops < 1) {
+ printf("Simulated power failure after %d operations\n",
+ sim->nops_so_far);
+ ynorsim_power_fail(sim);
+ }
+}
+
+static void ynorsim_ready(struct nor_sim *sim)
+{
+ if (sim->initialised)
+ return;
+ srand(random_seed);
+ sim->remaining_ops = 1000000000;
+ sim->remaining_ops =
+ (rand() % 10000) * ops_multiplier * YNORSIM_BIT_CHANGES;
+ ynorsim_restore_image(sim);
+ sim->initialised = 1;
+}
+
+/* Public functions. */
+
+void ynorsim_rd32(struct nor_sim *sim, u32 * addr, u32 * buf, int nwords)
+{
+ sim = sim;
+ while (nwords > 0) {
+ *buf = *addr;
+ buf++;
+ addr++;
+ nwords--;
+ }
+}
+
+void ynorsim_wr_one_word32(struct nor_sim *sim, u32 * addr, u32 val)
+{
+ u32 tmp;
+ u32 m;
+ int i;
+
+ tmp = *addr;
+ if (val & ~tmp) {
+ /* Fail due to trying to change a zero into a 1 */
+ printf("attempt to set a zero to one (%x)->(%x)\n", tmp, val);
+ NorError(sim);
+ }
+
+ for (i = 0; i < YNORSIM_BIT_CHANGES; i++) {
+ m = 1 << (rand() & 31);
+ if (!(m & val)) {
+ tmp &= ~m;
+ *addr = tmp;
+ ynorsim_maybe_power_fail(sim);
+ }
+
+ }
+
+ *addr = tmp & val;
+ ynorsim_maybe_power_fail(sim);
+}
+
+void ynorsim_wr32(struct nor_sim *sim, u32 * addr, u32 * buf, int nwords)
+{
+ while (nwords > 0) {
+ ynorsim_wr_one_word32(sim, addr, *buf);
+ addr++;
+ buf++;
+ nwords--;
+ }
+}
+
+void ynorsim_erase(struct nor_sim *sim, u32 * addr)
+{
+ /* Todo... bit flipping */
+ memset(addr, 0xFF, sim->block_size_bytes);
+}
+
+struct nor_sim *ynorsim_initialise(char *name, int n_blocks,
+ int block_size_bytes)
+{
+ struct nor_sim *sim;
+
+ sim = malloc(sizeof(*sim));
+ if (!sim)
+ return NULL;
+
+ memset(sim, 0, sizeof(*sim));
+ sim->n_blocks = n_blocks;
+ sim->block_size_bytes = block_size_bytes;
+ sim->file_size = n_blocks * block_size_bytes;
+ sim->word = malloc(sim->file_size);
+ sim->fname = strdup(name);
+
+ if(!sim->word)
+ return NULL;
+
+ ynorsim_ready(sim);
+ return sim;
+}
+
+void ynorsim_shutdown(struct nor_sim *sim)
+{
+ ynorsim_save_image(sim);
+ sim->initialised = 0;
+}
+
+u32 *ynorsim_get_base(struct nor_sim *sim)
+{
+ return sim->word;
+}
/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
-
-#ifndef __YAFFS_NOR_IF1_H__
-#define __YAFFS_NOR_IF1_H__
+#ifndef __Y_NORSIM_H__
+#define __Y_NORSIM_H__
#include "yaffs_guts.h"
-int ynorif1_WriteChunkToNAND(struct yaffs_dev *dev,int nand_chunk,const u8 *data, const struct yaffs_spare *spare);
-int ynorif1_ReadChunkFromNAND(struct yaffs_dev *dev,int nand_chunk, u8 *data, struct yaffs_spare *spare);
-int ynorif1_EraseBlockInNAND(struct yaffs_dev *dev, int blockNumber);
-int ynorif1_InitialiseNAND(struct yaffs_dev *dev);
-int ynorif1_Deinitialise_flash_fn(struct yaffs_dev *dev);
-
-#endif
+struct nor_sim;
+void ynorsim_rd32(struct nor_sim *sim, u32 *addr, u32 *data, int nwords);
+void ynorsim_wr32(struct nor_sim *sim, u32 *addr, u32 *data, int nwords);
+void ynorsim_erase(struct nor_sim *sim, u32 *addr);
+void ynorsim_shutdown(struct nor_sim *sim);
+struct nor_sim *ynorsim_initialise(char *name, int n_blocks, int block_size_bytes);
+u32 * ynorsim_get_base(struct nor_sim *sim);
+#endif
{test_yaffs_write,test_yaffs_write_clean,"test_yaffs_write"},
{test_yaffs_write_EBADF,test_yaffs_write_EBADF_clean,"test_yaffs_write_EBADF"},
- {test_yaffs_write_big_file,test_yaffs_write_big_file_clean,"test_yaffs_write_big_file"},
+// {test_yaffs_write_big_file,test_yaffs_write_big_file_clean,"test_yaffs_write_big_file"},
{test_yaffs_write_EROFS,test_yaffs_write_EROFS_clean,"test_yaffs_write_EROFS"},
{test_yaffs_read,test_yaffs_read_clean,"test_yaffs_read"},
#include <config.h>
#include <command.h>
+#include "../fs/yaffs2/yaffs_uboot_glue.h"
#ifdef YAFFS2_DEBUG
#define PRINTF(fmt, args...) printf(fmt, ##args)
#define PRINTF(fmt, args...) do { } while (0)
#endif
-extern void cmd_yaffs_dev_ls(void);
-extern void cmd_yaffs_tracemask(unsigned set, unsigned mask);
-extern void cmd_yaffs_devconfig(char *mp, int flash_dev,
- int start_block, int end_block);
-extern void cmd_yaffs_mount(char *mp);
-extern void cmd_yaffs_umount(char *mp);
-extern void cmd_yaffs_read_file(char *fn);
-extern void cmd_yaffs_write_file(char *fn, char bval, int sizeOfFile);
-extern void cmd_yaffs_ls(const char *mountpt, int longlist);
-extern void cmd_yaffs_mwrite_file(char *fn, char *addr, int size);
-extern void cmd_yaffs_mread_file(char *fn, char *addr);
-extern void cmd_yaffs_mkdir(const char *dir);
-extern void cmd_yaffs_rmdir(const char *dir);
-extern void cmd_yaffs_rm(const char *path);
-extern void cmd_yaffs_mv(const char *oldPath, const char *newPath);
-
-extern int yaffs_dump_dev(const char *path);
/* ytrace - show/set yaffs trace mask */
int do_ytrace(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
if (argc > 1)
- cmd_yaffs_tracemask(1, simple_strtol(argv[1], NULL, 16));
+ return cmd_yaffs_tracemask(1, simple_strtol(argv[1], NULL, 16));
else
- cmd_yaffs_tracemask(0, 0);
-
- return 0;
+ return cmd_yaffs_tracemask(0, 0);
}
/* ydevls - lists yaffs mount points. */
int do_ydevls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
{
- cmd_yaffs_dev_ls();
-
- return 0;
+ return cmd_yaffs_dev_ls();
}
/* ydevconfig mount_pt mtd_dev_num start_block end_block */
start_block = simple_strtol(argv[3], NULL, 16);
end_block = simple_strtol(argv[4], NULL, 16);
- cmd_yaffs_devconfig(mtpoint, mtd_dev, start_block, end_block);
-
- return 0;
+ return cmd_yaffs_devconfig(mtpoint, mtd_dev, start_block, end_block);
}
int do_ymount(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
mtpoint = argv[1];
printf("Mounting yaffs2 mount point %s\n", mtpoint);
- cmd_yaffs_mount(mtpoint);
-
- return 0;
+ return cmd_yaffs_mount(mtpoint);
}
int do_yumount(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
mtpoint = argv[1];
printf("Unmounting yaffs2 mount point %s\n", mtpoint);
- cmd_yaffs_umount(mtpoint);
-
- return 0;
+ return cmd_yaffs_umount(mtpoint);
}
int do_yls(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
dirname = argv[argc - 1];
- cmd_yaffs_ls(dirname, (argc > 2) ? 1 : 0);
+ return cmd_yaffs_ls(dirname, (argc > 2) ? 1 : 0);
+}
- return 0;
+static int ycheck_option_valid(const char *str)
+{
+ return strcmp(str,"DIR") == 0 || strcmp(str,"REG") == 0;
+}
+
+int do_ycheck(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
+{
+ const char *dirname;
+ const char *str = "ANY";
+
+ if (argc < 2 || argc > 3 ||
+ (argc == 3 && ! ycheck_option_valid(argv[2]))) {
+ printf("Bad arguments: ycheck name [DIR|REG]");
+ return -1;
+ }
+
+ dirname = argv[1];
+ if(argc>2)
+ str = argv[2];
+
+ return cmd_yaffs_check(dirname, str);
}
int do_yrd(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
printf("Reading file %s ", filename);
- cmd_yaffs_read_file(filename);
-
- printf("done\n");
- return 0;
+ return cmd_yaffs_read_file(filename);
}
int do_ywr(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
printf("Writing value (%lx) %lx times to %s... ", value, numValues,
filename);
- cmd_yaffs_write_file(filename, value, numValues);
-
- printf("done\n");
- return 0;
+ return cmd_yaffs_write_file(filename, value, numValues);
}
int do_yrdm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
filename = argv[1];
addr = simple_strtoul(argv[2], NULL, 16);
- cmd_yaffs_mread_file(filename, (char *)addr);
-
- return 0;
+ return cmd_yaffs_mread_file(filename, (char *)addr);
}
int do_ywrm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
addr = simple_strtoul(argv[2], NULL, 16);
size = simple_strtoul(argv[3], NULL, 16);
- cmd_yaffs_mwrite_file(filename, (char *)addr, size);
-
- return 0;
+ return cmd_yaffs_mwrite_file(filename, (char *)addr, size);
}
int do_ymkdir(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
}
dirname = argv[1];
- cmd_yaffs_mkdir(dirname);
-
- return 0;
+ return cmd_yaffs_mkdir(dirname);
}
int do_yrmdir(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
}
dirname = argv[1];
- cmd_yaffs_rmdir(dirname);
-
- return 0;
+ return cmd_yaffs_rmdir(dirname);
}
int do_yrm(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
name = argv[1];
- cmd_yaffs_rm(name);
-
- return 0;
+ return cmd_yaffs_rm(name);
}
int do_ymv(cmd_tbl_t *cmdtp, int flag, int argc, char *const argv[])
oldPath = argv[1];
newPath = argv[2];
- cmd_yaffs_mv(newPath, oldPath);
-
- return 0;
+ return cmd_yaffs_mv(newPath, oldPath);
}
U_BOOT_CMD(ytrace, 2, 0, do_ytrace,
U_BOOT_CMD(yls, 3, 0, do_yls, "yaffs ls", "yls [-l] dirname");
+U_BOOT_CMD(ycheck, 3, 0, do_ycheck,
+ "ycheck name [DIR|REG]", "checks if the named object exists");
+
U_BOOT_CMD(yrd, 2, 0, do_yrd,
"read file from yaffs", "yrd path read file from yaffs");
struct mtd_oob_ops ops;
size_t dummy;
int retval = 0;
- loff_t addr = ((loff_t) chunkInNAND) * dev->data_bytes_per_chunk;
+ loff_t addr = ((loff_t) chunkInNAND) * dev->param.total_bytes_per_chunk;
u8 spareAsBytes[8]; /* OOB */
if (data && !spare)
size_t dummy;
int retval = 0;
- loff_t addr = ((loff_t) chunkInNAND) * dev->data_bytes_per_chunk;
+ loff_t addr = ((loff_t) chunkInNAND) * dev->param.total_bytes_per_chunk;
u8 spareAsBytes[8]; /* OOB */
if (data && !spare)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->driver_context);
__u32 addr =
- ((loff_t) blockNumber) * dev->data_bytes_per_chunk
+ ((loff_t) blockNumber) * dev->param.total_bytes_per_chunk
* dev->param.chunks_per_block;
struct erase_info ei;
int retval = 0;
#include "yaffs_packedtags2.h"
#include "yaffs_mtdif.h"
#include "yaffs_mtdif2.h"
+#include "yaffs_uboot_glue.h"
+
#if 0
#include <errno.h>
#else
extern nand_info_t nand_info[];
-void cmd_yaffs_tracemask(unsigned set, unsigned mask)
+int cmd_yaffs_tracemask(unsigned set, unsigned mask)
{
if (set)
yaffs_trace_mask = mask;
printf("yaffs trace mask: %08x\n", yaffs_trace_mask);
+ return 0;
}
static int yaffs_regions_overlap(int a, int b, int x, int y)
(x <= b && b <= y);
}
-void cmd_yaffs_devconfig(char *_mp, int flash_dev,
+int cmd_yaffs_devconfig(char *_mp, int flash_dev,
int start_block, int end_block)
{
struct mtd_info *mtd = NULL;
printf("Configures yaffs mount %s: dev %d start block %d, end block %d %s\n",
mp, flash_dev, start_block, end_block,
dev->param.inband_tags ? "using inband tags" : "");
- return;
+ return 0;
err:
free(dev);
free(mp);
+ return -1;
}
-void cmd_yaffs_dev_ls(void)
+int cmd_yaffs_dev_ls(void)
{
struct yaffs_dev *dev;
int flash_dev;
while (1) {
dev = yaffs_next_dev();
if (!dev)
- return;
+ break;
flash_dev =
((unsigned) dev->driver_context - (unsigned) nand_info)/
sizeof(nand_info[0]);
printf("free 0x%x\n", free_space);
}
+
+ return 0;
}
-void make_a_file(char *yaffsName, char bval, int sizeOfFile)
+int make_a_file(char *yaffsName, char bval, int sizeOfFile)
{
int outh;
int i;
+ int written;
unsigned char buffer[100];
outh = yaffs_open(yaffsName,
S_IREAD | S_IWRITE);
if (outh < 0) {
printf("Error opening file: %d. %s\n", outh, yaffs_error_str());
- return;
+ return -1;
}
memset(buffer, bval, 100);
- do {
- i = sizeOfFile;
+ written = 0;
+ while (written < sizeOfFile) {
+ i = sizeOfFile - written;
if (i > 100)
i = 100;
- sizeOfFile -= i;
-
- yaffs_write(outh, buffer, i);
-
- } while (sizeOfFile > 0);
+ if (yaffs_write(outh, buffer, i) != i)
+ break;
+ written += i;
+ }
yaffs_close(outh);
+
+ return (written == sizeOfFile) ? 0 : -1;
}
-void read_a_file(char *fn)
+int read_a_file(char *fn)
{
int h;
int i = 0;
h = yaffs_open(fn, O_RDWR, 0);
if (h < 0) {
printf("File not found\n");
- return;
+ return -1;
}
while (yaffs_read(h, &b, 1) > 0) {
}
printf("\n");
yaffs_close(h);
+
+ return 0;
}
-void cmd_yaffs_mount(char *mp)
+int cmd_yaffs_mount(char *mp)
{
int retval = yaffs_mount(mp);
if (retval < 0)
printf("Error mounting %s, return value: %d, %s\n", mp,
yaffsfs_GetError(), yaffs_error_str());
+ return retval;
}
-void cmd_yaffs_umount(char *mp)
+int cmd_yaffs_umount(char *mp)
{
- if (yaffs_unmount(mp) == -1)
+ int retval = yaffs_unmount(mp);
+
+ if (retval < 0)
printf("Error umounting %s, return value: %d, %s\n", mp,
yaffsfs_GetError(), yaffs_error_str());
+ return retval;
}
-void cmd_yaffs_write_file(char *yaffsName, char bval, int sizeOfFile)
+int cmd_yaffs_write_file(char *yaffsName, char bval, int sizeOfFile)
{
- make_a_file(yaffsName, bval, sizeOfFile);
+ return make_a_file(yaffsName, bval, sizeOfFile);
}
-void cmd_yaffs_read_file(char *fn)
+int cmd_yaffs_read_file(char *fn)
{
- read_a_file(fn);
+ return read_a_file(fn);
}
-void cmd_yaffs_mread_file(char *fn, char *addr)
+int cmd_yaffs_mread_file(char *fn, char *addr)
{
int h;
+ int retval = 0;
struct yaffs_stat s;
+ int read_size;
+ char buf[16];
yaffs_stat(fn, &s);
h = yaffs_open(fn, O_RDWR, 0);
if (h < 0) {
printf("File not found\n");
- return;
+ retval = -1;
+ read_size = 0;
+ } else {
+ read_size = (int) s.st_size;
+ yaffs_read(h, addr, read_size);
+ printf("\t[DONE]\n");
+
+ yaffs_close(h);
}
+ sprintf(buf,"%x", read_size);
+ setenv("filesize", buf);
- yaffs_read(h, addr, (int)s.st_size);
- printf("\t[DONE]\n");
-
- yaffs_close(h);
+ return retval;
}
-void cmd_yaffs_mwrite_file(char *fn, char *addr, int size)
+int cmd_yaffs_mwrite_file(char *fn, char *addr, int size)
{
int outh;
+ int wrote;
outh = yaffs_open(fn, O_CREAT | O_RDWR | O_TRUNC, S_IREAD | S_IWRITE);
- if (outh < 0)
+ if (outh < 0) {
printf("Error opening file: %d, %s\n", outh, yaffs_error_str());
+ return -1;
+ }
- yaffs_write(outh, addr, size);
-
+ wrote = yaffs_write(outh, addr, size);
yaffs_close(outh);
+
+ if(wrote != size) {
+ printf("only wrote %d (0x%x) bytes\n", wrote, wrote);
+ return -1;
+ }
+ return 0;
+
+
}
-void cmd_yaffs_ls(const char *mountpt, int longlist)
+int cmd_yaffs_ls(const char *mountpt, int longlist)
{
int i;
yaffs_DIR *d;
if (!d) {
printf("opendir failed, %s\n", yaffs_error_str());
- return;
+ return -1;
}
for (i = 0; (de = yaffs_readdir(d)) != NULL; i++) {
}
yaffs_closedir(d);
+
+ return 0;
}
+int cmd_yaffs_check(const char *fname, const char *type)
+{
+ int retval = 0;
+ int ret;
+ struct yaffs_stat stat;
+
+ ret = yaffs_stat(fname, &stat);
+ if (ret < 0) {
+ printf("%s not found\n", fname);
+ return -1;
+ }
+
+ printf("%s is a %s\n", fname, yaffs_file_type_str(&stat));
+
+ if (strcmp(type, "REG") == 0 &&
+ (stat.st_mode & S_IFMT) != S_IFREG)
+ retval = -1;
-void cmd_yaffs_mkdir(const char *dir)
+ if (strcmp(type, "DIR") == 0 &&
+ (stat.st_mode & S_IFMT) != S_IFDIR)
+ retval = -1;
+
+ if (retval == 0)
+ printf("check ok\n");
+ else
+ printf("check failed\n");
+
+ return retval;
+}
+
+
+int cmd_yaffs_mkdir(const char *dir)
{
int retval = yaffs_mkdir(dir, 0);
- if (retval < 0)
+ if (retval < 0) {
printf("yaffs_mkdir returning error: %d, %s\n",
retval, yaffs_error_str());
+ return -1;
+ }
+ return 0;
}
-void cmd_yaffs_rmdir(const char *dir)
+int cmd_yaffs_rmdir(const char *dir)
{
int retval = yaffs_rmdir(dir);
- if (retval < 0)
+ if (retval < 0) {
printf("yaffs_rmdir returning error: %d, %s\n",
retval, yaffs_error_str());
+ return -1;
+ }
+ return 0;
}
-void cmd_yaffs_rm(const char *path)
+int cmd_yaffs_rm(const char *path)
{
int retval = yaffs_unlink(path);
- if (retval < 0)
+ if (retval < 0) {
printf("yaffs_unlink returning error: %d, %s\n",
retval, yaffs_error_str());
+ return -1;
+ }
+
+ return 0;
}
-void cmd_yaffs_mv(const char *oldPath, const char *newPath)
+int cmd_yaffs_mv(const char *oldPath, const char *newPath)
{
int retval = yaffs_rename(newPath, oldPath);
- if (retval < 0)
+ if (retval < 0) {
printf("yaffs_unlink returning error: %d, %s\n",
retval, yaffs_error_str());
+ return -1;
+ }
+
+ return 0;
}
--- /dev/null
+
+#ifndef __YAFFS_UBOOT_GLUE_H__
+#define __YAFFS_UBOOT_GLUE_H__
+
+
+int cmd_yaffs_dev_ls(void);
+int cmd_yaffs_tracemask(unsigned set, unsigned mask);
+int cmd_yaffs_devconfig(char *mp, int flash_dev,
+ int start_block, int end_block);
+int cmd_yaffs_mount(char *mp);
+int cmd_yaffs_umount(char *mp);
+int cmd_yaffs_read_file(char *fn);
+int cmd_yaffs_write_file(char *fn, char bval, int sizeOfFile);
+int cmd_yaffs_ls(const char *mountpt, int longlist);
+int cmd_yaffs_check(const char *fn, const char *type);
+int cmd_yaffs_mwrite_file(char *fn, char *addr, int size);
+int cmd_yaffs_mread_file(char *fn, char *addr);
+int cmd_yaffs_mkdir(const char *dir);
+int cmd_yaffs_rmdir(const char *dir);
+int cmd_yaffs_rm(const char *path);
+int cmd_yaffs_mv(const char *oldPath, const char *newPath);
+
+int yaffs_dump_dev(const char *path);
+#endif
void *yaffsfs_malloc(size_t size);
void yaffsfs_free(void *ptr);
+int yaffsfs_CheckMemRegion(const void *addr, size_t size, int writeable);
+
void yaffsfs_OSInitialisation(void);
if (yaffsfs_handlesInitialised)
return;
+ yaffsfs_handlesInitialised = 1;
+
memset(yaffsfs_inode, 0, sizeof(yaffsfs_inode));
memset(yaffsfs_fd, 0, sizeof(yaffsfs_fd));
memset(yaffsfs_handle, 0, sizeof(yaffsfs_handle));
thisMatchLength = 0;
matching = 1;
+ if(!p)
+ continue;
+
while (matching && *p && *leftOver) {
/* Skip over any /s */
while (yaffsfs_IsPathDivider(*p))
int notDir = 0;
int loop = 0;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0)< 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
Y_LOFF_T maxRead;
u8 *buf = (u8 *) vbuf;
- if (!vbuf) {
+ if (yaffsfs_CheckMemRegion(vbuf, nbyte, 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int nToWrite = 0;
const u8 *buf = (const u8 *)vbuf;
- if (!vbuf) {
+ if (yaffsfs_CheckMemRegion(vbuf, nbyte, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
YCHAR *alt_newpath = NULL;
- if (!oldPath || !newPath) {
+ if (yaffsfs_CheckMemRegion(oldPath, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(newPath, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path || !buf) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
- if (!buf) {
+ if (yaffsfs_CheckMemRegion(buf, sizeof(*buf), 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
- if (!path || !name || !data) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(data, size, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
- if (!name || !data) {
+ if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(data, size, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path || !name || !data) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(data, size, 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
- if (!name || !data) {
+ if (yaffsfs_CheckMemRegion(name, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(data, size, 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path || !data) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(data, size, 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
- if (!data) {
+ if (yaffsfs_CheckMemRegion(data, size, 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int loop = 0;
int retVal = -1;
- if (!path || !name) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(name, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
- if (!name) {
+ if (yaffsfs_CheckMemRegion(name, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int loop = 0;
int retval = -1;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int result;
YCHAR *alt_path;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int result = YAFFS_FAIL;
struct yaffs_dev *dev = NULL;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
struct yaffs_dev *dev = NULL;
YCHAR *dummy;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
struct yaffs_dev *dev = NULL;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int retVal = -1;
struct yaffs_dev *dev = NULL;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
struct yaffs_dev *dev = NULL;
YCHAR *dummy;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
struct yaffs_dev *dev = NULL;
YCHAR *dummy;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
struct yaffs_dev *dev = NULL;
YCHAR *dummy;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!dirname) {
+ if (yaffsfs_CheckMemRegion(dirname, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return NULL;
}
dsc = (struct yaffsfs_DirSearchContxt *) dirp;
+ if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0)
+ return;
+
yaffsfs_Lock();
yaffsfs_SetDirRewound(dsc);
dsc = (struct yaffsfs_DirSearchContxt *) dirp;
- if (!dsc) {
+ if (yaffsfs_CheckMemRegion(dirp, sizeof(*dsc), 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!oldpath || !newpath) {
+ if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(newpath, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int notDir = 0;
int loop = 0;
- if (!path || !buf) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(buf, bufsiz, 1) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
int lnkLoop = 0;
YCHAR *newname;
- if (!oldpath || !linkpath) {
+ if (yaffsfs_CheckMemRegion(oldpath, 0, 0) < 0 ||
+ yaffsfs_CheckMemRegion(linkpath, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
{
struct yaffs_obj *obj;
- if (!path) {
+ if (yaffsfs_CheckMemRegion(path, 0, 0) < 0) {
yaffsfs_SetError(-EFAULT);
return -1;
}
if [ $MULTIORSINGLE = m ]; then
VFS_CODE="yaffs_vfs_multi.c"
- MTD1_CODE="yaffs_mtdif1_multi.c"
- MTD2_CODE="yaffs_mtdif2_multi.c"
+ MTD_CODE="yaffs_mtdif_multi.c"
YPORTENV="yportenv_multi.h"
KCONFIG_SRC="Kconfig_multi"
elif [ $MULTIORSINGLE = s ]; then
VFS_CODE="yaffs_vfs_single.c"
- MTD1_CODE="yaffs_mtdif1_single.c"
- MTD2_CODE="yaffs_mtdif2_single.c"
+ MTD_CODE="yaffs_mtdif_single.c"
YPORTENV="yportenv_single.h"
KCONFIG_SRC="Kconfig_single"
$CPY $PWD/Makefile.kernel $LINUXDIR/fs/yaffs2/Makefile
$CPY $PWD/$KCONFIG_SRC $LINUXDIR/fs/yaffs2/Kconfig
$CPY $PWD/*.c $PWD/*.h $LINUXDIR/fs/yaffs2
- rm $LINUXDIR/fs/yaffs2/yaffs_vfs*.c $LINUXDIR/fs/yaffs2/yaffs_mtdif[12]*.c
+ rm $LINUXDIR/fs/yaffs2/yaffs_vfs*.c $LINUXDIR/fs/yaffs2/yaffs_mtdif*.c
rm $LINUXDIR/fs/yaffs2/yportenv*.h
rm $LINUXDIR/fs/yaffs2/moduleconfig.h
$CPY $PWD/$VFS_CODE $LINUXDIR/fs/yaffs2/yaffs_vfs.c
- $CPY $PWD/$MTD1_CODE $LINUXDIR/fs/yaffs2/yaffs_mtdif1.c
- $CPY $PWD/$MTD2_CODE $LINUXDIR/fs/yaffs2/yaffs_mtdif2.c
+ $CPY $PWD/$MTD_CODE $LINUXDIR/fs/yaffs2/yaffs_mtdif.c
$CPY $PWD/$YPORTENV $LINUXDIR/fs/yaffs2/yportenv.h
fi
{
int i;
- if (!dev->param.erase_fn)
+ if (!dev->drv.drv_erase_fn)
return 0;
yaffs_trace(YAFFS_TRACE_CHECKPOINT,
"checking blocks %d to %d",
dev->n_erasures++;
- result = dev->param.erase_fn(dev, offset_i);
+ result = dev->drv.drv_erase_fn(dev, offset_i);
if(result) {
bi->block_state = YAFFS_BLOCK_STATE_EMPTY;
dev->n_erased_blocks++;
dev->n_free_chunks +=
dev->param.chunks_per_block;
} else {
- dev->param.bad_block_fn(dev, offset_i);
+ dev->drv.drv_mark_bad_fn(dev, offset_i);
bi->block_state = YAFFS_BLOCK_STATE_DEAD;
}
}
enum yaffs_block_state state;
u32 seq;
- dev->param.read_chunk_tags_fn(dev,
+ dev->tagger.read_chunk_tags_fn(dev,
apply_chunk_offset(dev, chunk),
NULL, &tags);
yaffs_trace(YAFFS_TRACE_CHECKPOINT,
if (tags.seq_number != YAFFS_SEQUENCE_CHECKPOINT_DATA)
continue;
- dev->param.query_block_fn(dev,
+ dev->tagger.query_block_fn(dev,
apply_block_offset(dev, i),
&state, &seq);
if (state == YAFFS_BLOCK_STATE_DEAD)
dev->checkpt_open_write = writing;
/* Got the functions we need? */
- if (!dev->param.write_chunk_tags_fn ||
- !dev->param.read_chunk_tags_fn ||
- !dev->param.erase_fn || !dev->param.bad_block_fn)
+ if (!dev->tagger.write_chunk_tags_fn ||
+ !dev->tagger.read_chunk_tags_fn ||
+ !dev->drv.drv_erase_fn ||
+ !dev->drv.drv_mark_bad_fn)
return 0;
if (writing && !yaffs2_checkpt_space_ok(dev))
dev->n_page_writes++;
- dev->param.write_chunk_tags_fn(dev, offset_chunk,
+ dev->tagger.write_chunk_tags_fn(dev, offset_chunk,
dev->checkpt_buffer, &tags);
dev->checkpt_page_seq++;
dev->checkpt_cur_chunk++;
dev->n_page_reads++;
/* read in the next chunk */
- dev->param.read_chunk_tags_fn(dev,
+ dev->tagger.read_chunk_tags_fn(dev,
offset_chunk,
dev->checkpt_buffer,
&tags);
#include "yaffs_guts.h"
#include "yaffs_getblockinfo.h"
#include "yaffs_tagscompat.h"
+#include "yaffs_tagsmarshall.h"
#include "yaffs_nand.h"
#include "yaffs_yaffs1.h"
#include "yaffs_yaffs2.h"
memset(buffer, 0xff, dev->data_bytes_per_chunk);
memset(&tags, 0, sizeof(tags));
tags.seq_number = YAFFS_SEQUENCE_BAD_BLOCK;
- if (dev->param.write_chunk_tags_fn(dev, chunk_id -
- dev->chunk_offset,
- buffer,
- &tags) != YAFFS_OK)
+ if (dev->tagger.write_chunk_tags_fn(dev, chunk_id -
+ dev->chunk_offset,
+ buffer,
+ &tags) != YAFFS_OK)
yaffs_trace(YAFFS_TRACE_ALWAYS,
"yaffs: Failed to write bad block marker to block %d",
flash_block);
int erased_chunks;
int checkpt_block_adjust;
- if (dev->param.gc_control && (dev->param.gc_control(dev) & 1) == 0)
+ if (dev->param.gc_control_fn &&
+ (dev->param.gc_control_fn(dev) & 1) == 0)
return YAFFS_OK;
if (dev->gc_disable)
}
if (n_copy != dev->data_bytes_per_chunk ||
+ !dev->param.cache_bypass_aligned ||
dev->param.inband_tags) {
/* An incomplete start or end chunk (or maybe both
* start and end chunk), or we're using inband tags,
+ * or we're forcing writes through the cache,
* so we want to use the cache buffers.
*/
if (dev->param.n_caches > 0) {
/*--------------------------- Initialisation code -------------------------- */
-static int yaffs_check_dev_fns(const struct yaffs_dev *dev)
+static int yaffs_check_dev_fns(struct yaffs_dev *dev)
{
+ struct yaffs_driver *drv = &dev->drv;
+ struct yaffs_tags_handler *tagger = &dev->tagger;
+
/* Common functions, gotta have */
- if (!dev->param.erase_fn || !dev->param.initialise_flash_fn)
+ if (!drv->drv_read_chunk_fn ||
+ !drv->drv_write_chunk_fn ||
+ !drv->drv_erase_fn)
return 0;
- /* Can use the "with tags" style interface for yaffs1 or yaffs2 */
- if (dev->param.write_chunk_tags_fn &&
- dev->param.read_chunk_tags_fn &&
- !dev->param.write_chunk_fn &&
- !dev->param.read_chunk_fn &&
- dev->param.bad_block_fn && dev->param.query_block_fn)
- return 1;
+ if (dev->param.is_yaffs2 &&
+ (!drv->drv_mark_bad_fn || !drv->drv_check_bad_fn))
+ return 0;
- /* Can use the "spare" style interface for yaffs1 */
- if (!dev->param.is_yaffs2 &&
- !dev->param.write_chunk_tags_fn &&
- !dev->param.read_chunk_tags_fn &&
- dev->param.write_chunk_fn &&
- dev->param.read_chunk_fn &&
- !dev->param.bad_block_fn && !dev->param.query_block_fn)
- return 1;
+ /* Install the default tags marshalling functions if needed. */
+ yaffs_tags_compat_install(dev);
+ yaffs_tags_marshall_install(dev);
- return 0; /* bad */
+ /* Check we now have the marshalling functions required. */
+ if (!tagger->write_chunk_tags_fn ||
+ !tagger->read_chunk_tags_fn ||
+ !tagger->query_block_fn ||
+ !tagger->mark_bad_fn)
+ return 0;
+
+ return 1;
}
static int yaffs_create_initial_dir(struct yaffs_dev *dev)
dev->is_mounted = 0;
- if (dev->param.deinitialise_flash_fn)
- dev->param.deinitialise_flash_fn(dev);
+ yaffs_deinit_nand(dev);
}
}
/*
* Entry parameters set up way early. Yaffs sets up the rest.
* The structure should be zeroed out before use so that unused
- * and defualt values are zero.
+ * and default values are zero.
*/
int inband_tags; /* Use unband tags */
int n_caches; /* If <= 0, then short op caching is disabled,
* else the number of short op caches.
*/
+ int cache_bypass_aligned; /* If non-zero then bypass the cache for
+ * aligned writes.
+ */
+
int use_nand_ecc; /* Flag to decide whether or not to use
* NAND driver ECC on data (yaffs1) */
int tags_9bytes; /* Use 9 byte tags */
int enable_xattr; /* Enable xattribs */
- /* NAND access functions (Must be set before calling YAFFS) */
-
- int (*write_chunk_fn) (struct yaffs_dev *dev,
- int nand_chunk, const u8 *data,
- const struct yaffs_spare *spare);
- int (*read_chunk_fn) (struct yaffs_dev *dev,
- int nand_chunk, u8 *data,
- struct yaffs_spare *spare);
- int (*erase_fn) (struct yaffs_dev *dev, int flash_block);
- int (*initialise_flash_fn) (struct yaffs_dev *dev);
- int (*deinitialise_flash_fn) (struct yaffs_dev *dev);
-
- /* yaffs2 mode functions */
- int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
- int nand_chunk, const u8 *data,
- const struct yaffs_ext_tags *tags);
- int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
- int nand_chunk, u8 *data,
- struct yaffs_ext_tags *tags);
- int (*bad_block_fn) (struct yaffs_dev *dev, int block_no);
- int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
- enum yaffs_block_state *state,
- u32 *seq_number);
+ int max_objects; /*
+ * Set to limit the number of objects created.
+ * 0 = no limit.
+ */
/* The remove_obj_fn function must be supplied by OS flavours that
* need it.
void (*sb_dirty_fn) (struct yaffs_dev *dev);
/* Callback to control garbage collection. */
- unsigned (*gc_control) (struct yaffs_dev *dev);
+ unsigned (*gc_control_fn) (struct yaffs_dev *dev);
/* Debug control flags. Don't use unless you know what you're doing */
int use_header_file_size; /* Flag to determine if we should use
int disable_summary;
- int max_objects; /*
- * Set to limit the number of objects created.
- * 0 = no limit.
- */
+};
+
+struct yaffs_driver {
+ int (*drv_write_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len);
+ int (*drv_read_chunk_fn) (struct yaffs_dev *dev, int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result);
+ int (*drv_erase_fn) (struct yaffs_dev *dev, int block_no);
+ int (*drv_mark_bad_fn) (struct yaffs_dev *dev, int block_no);
+ int (*drv_check_bad_fn) (struct yaffs_dev *dev, int block_no);
+ int (*drv_initialise_fn) (struct yaffs_dev *dev);
+ int (*drv_deinitialise_fn) (struct yaffs_dev *dev);
+};
+
+struct yaffs_tags_handler {
+ int (*write_chunk_tags_fn) (struct yaffs_dev *dev,
+ int nand_chunk, const u8 *data,
+ const struct yaffs_ext_tags *tags);
+ int (*read_chunk_tags_fn) (struct yaffs_dev *dev,
+ int nand_chunk, u8 *data,
+ struct yaffs_ext_tags *tags);
+
+ int (*query_block_fn) (struct yaffs_dev *dev, int block_no,
+ enum yaffs_block_state *state,
+ u32 *seq_number);
+ int (*mark_bad_fn) (struct yaffs_dev *dev, int block_no);
};
struct yaffs_dev {
struct yaffs_param param;
+ struct yaffs_driver drv;
+ struct yaffs_tags_handler tagger;
/* Context storage. Holds extra OS specific data for this device */
u32 n_page_writes;
u32 n_page_reads;
u32 n_erasures;
+ u32 n_bad_markings;
u32 n_erase_failures;
u32 n_gc_copies;
u32 all_gcs;
* at compile time so we have to allocate it.
*/
struct list_head search_contexts;
- void (*put_super_fn) (struct super_block *sb);
-
struct task_struct *readdir_process;
unsigned mount_id;
};
+++ /dev/null
-/*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-#include "yportenv.h"
-
-#include "yaffs_mtdif.h"
-
-#include "linux/mtd/mtd.h"
-#include "linux/types.h"
-#include "linux/time.h"
-#include "linux/mtd/nand.h"
-
-#include "yaffs_linux.h"
-
-int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- u32 addr =
- ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
- dev->param.chunks_per_block;
- struct erase_info ei;
- int retval = 0;
-
- ei.mtd = mtd;
- ei.addr = addr;
- ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
- ei.time = 1000;
- ei.retries = 2;
- ei.callback = NULL;
- ei.priv = (u_long) dev;
-
- retval = mtd->erase(mtd, &ei);
-
- if (retval == 0)
- return YAFFS_OK;
-
- return YAFFS_FAIL;
-}
-
-int nandmtd_initialise(struct yaffs_dev *dev)
-{
- return YAFFS_OK;
-}
#include "yaffs_guts.h"
-int nandmtd_erase_block(struct yaffs_dev *dev, int block_no);
-int nandmtd_initialise(struct yaffs_dev *dev);
+void yaffs_mtd_drv_install(struct yaffs_dev *dev);
+
#endif
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __YAFFS_MTDIF1_H__
-#define __YAFFS_MTDIF1_H__
-
-int nandmtd1_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- const u8 *data,
- const struct yaffs_ext_tags *tags);
-
-int nandmtd1_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- u8 *data, struct yaffs_ext_tags *tags);
-
-int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no);
-
-int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
- enum yaffs_block_state *state, u32 *seq_number);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-/*
- * This module provides the interface between yaffs_nand.c and the
- * MTD API. This version is used when the MTD interface supports the
- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
- * and we have small-page NAND device.
- *
- * These functions are invoked via function pointers in yaffs_nand.c.
- * This replaces functionality provided by functions in yaffs_mtdif.c
- * and the yaffs_tags compatability functions in yaffs_tagscompat.c that are
- * called in yaffs_mtdif.c when the function pointers are NULL.
- * We assume the MTD layer is performing ECC (use_nand_ecc is true).
- */
-
-#include "yportenv.h"
-#include "yaffs_trace.h"
-#include "yaffs_guts.h"
-#include "yaffs_packedtags1.h"
-#include "yaffs_tagscompat.h" /* for yaffs_calc_tags_ecc */
-#include "yaffs_linux.h"
-
-#include "linux/kernel.h"
-#include "linux/version.h"
-#include "linux/types.h"
-#include "linux/mtd/mtd.h"
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
-#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
-#endif
-
-
-/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
-#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
-
-
-#if 0
-/* Use the following nand_ecclayout with MTD when using
- * 9 byte tags and the older on-NAND tags layout.
- * If you have existing Yaffs images and the byte order differs from this,
- * adjust 'oobfree' to match your existing Yaffs data.
- *
- * This nand_ecclayout scatters/gathers to/from the old-yaffs layout with the
- * page_status byte (at NAND spare offset 4) scattered/gathered from/to
- * the 9th byte.
- *
- * Old-style on-NAND format: T0,T1,T2,T3,P,B,T4,T5,E0,E1,E2,T6,T7,E3,E4,E5
- * We have/need packed_tags1 plus page_status: T0,T1,T2,T3,T4,T5,T6,T7,P
- * where Tn are the tag bytes, En are MTD's ECC bytes, P is the page_status
- * byte and B is the small-page bad-block indicator byte.
- */
-static struct nand_ecclayout nand_oob_16 = {
- .eccbytes = 6,
- .eccpos = {8, 9, 10, 13, 14, 15},
- .oobavail = 9,
- .oobfree = {{0, 4}, {6, 2}, {11, 2}, {4, 1} }
-};
-#endif
-
-/* Write a chunk (page) of data to NAND.
- *
- * Caller always provides ExtendedTags data which are converted to a more
- * compact (packed) form for storage in NAND. A mini-ECC runs over the
- * contents of the tags meta-data; used to valid the tags when read.
- *
- * - Pack ExtendedTags to packed_tags1 form
- * - Compute mini-ECC for packed_tags1
- * - Write data and packed tags to NAND.
- *
- * Note: Due to the use of the packed_tags1 meta-data which does not include
- * a full sequence number (as found in the larger packed_tags2 form) it is
- * necessary for Yaffs to re-write a chunk/page (just once) to mark it as
- * discarded and dirty. This is not ideal: newer NAND parts are supposed
- * to be written just once. When Yaffs performs this operation, this
- * function is called with a NULL data pointer -- calling MTD write_oob
- * without data is valid usage (2.6.17).
- *
- * Any underlying MTD error results in YAFFS_FAIL.
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-int nandmtd1_write_chunk_tags(struct yaffs_dev *dev,
- int nand_chunk, const u8 *data,
- const struct yaffs_ext_tags *etags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int chunk_bytes = dev->data_bytes_per_chunk;
- loff_t addr = ((loff_t) nand_chunk) * chunk_bytes;
- struct mtd_oob_ops ops;
- struct yaffs_packed_tags1 pt1;
- int retval;
-
- /* we assume that packed_tags1 and struct yaffs_tags are compatible */
- compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
- compile_time_assertion(sizeof(struct yaffs_tags) == 8);
-
- yaffs_pack_tags1(&pt1, etags);
- yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
-
- /* When deleting a chunk, the upper layer provides only skeletal
- * etags, one with is_deleted set. However, we need to update the
- * tags, not erase them completely. So we use the NAND write property
- * that only zeroed-bits stick and set tag bytes to all-ones and
- * zero just the (not) deleted bit.
- */
- if(dev->param.tags_9bytes) {
- ((u8 *) &pt1)[8] = 0xff;
- if (etags->is_deleted) {
- memset(&pt1, 0xff, 8);
- /* zero page_status byte to indicate deleted */
- ((u8 *) &pt1)[8] = 0;
- }
- } else {
- if (etags->is_deleted) {
- memset(&pt1, 0xff, 8);
- /* clear delete status bit to indicate deleted */
- pt1.deleted = 0;
- }
- }
-
- memset(&ops, 0, sizeof(ops));
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.len = (data) ? chunk_bytes : 0;
- ops.ooblen = dev->param.tags_9bytes ? 9 : 8;
- ops.datbuf = (u8 *) data;
- ops.oobbuf = (u8 *) &pt1;
-
- retval = mtd->write_oob(mtd, addr, &ops);
- if (retval) {
- yaffs_trace(YAFFS_TRACE_MTD,
- "write_oob failed, chunk %d, mtd error %d",
- nand_chunk, retval);
- }
- return retval ? YAFFS_FAIL : YAFFS_OK;
-}
-
-/* Return with empty ExtendedTags but add ecc_result.
- */
-static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval)
-{
- if (etags) {
- memset(etags, 0, sizeof(*etags));
- etags->ecc_result = ecc_result;
- }
- return retval;
-}
-
-/* Read a chunk (page) from NAND.
- *
- * Caller expects ExtendedTags data to be usable even on error; that is,
- * all members except ecc_result and block_bad are zeroed.
- *
- * - Check ECC results for data (if applicable)
- * - Check for blank/erased block (return empty ExtendedTags if blank)
- * - Check the packed_tags1 mini-ECC (correct if necessary/possible)
- * - Convert packed_tags1 to ExtendedTags
- * - Update ecc_result and block_bad members to refect state.
- *
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
- int nand_chunk, u8 *data,
- struct yaffs_ext_tags *etags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int chunk_bytes = dev->data_bytes_per_chunk;
- loff_t addr = ((loff_t) nand_chunk) * chunk_bytes;
- int eccres = YAFFS_ECC_RESULT_NO_ERROR;
- struct mtd_oob_ops ops;
- struct yaffs_packed_tags1 pt1;
- int retval;
- int deleted;
-
- memset(&ops, 0, sizeof(ops));
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.len = (data) ? chunk_bytes : 0;
- ops.ooblen = dev->param.tags_9bytes ? 9 : 8;
- ops.datbuf = data;
- ops.oobbuf = (u8 *) &pt1;
-
-#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
- /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
- * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
- */
- ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
-#endif
- /* Read page and oob using MTD.
- * Check status and determine ECC result.
- */
- retval = mtd->read_oob(mtd, addr, &ops);
- if (retval)
- yaffs_trace(YAFFS_TRACE_MTD,
- "read_oob failed, chunk %d, mtd error %d",
- nand_chunk, retval);
-
- switch (retval) {
- case 0:
- /* no error */
- break;
-
- case -EUCLEAN:
- /* MTD's ECC fixed the data */
- eccres = YAFFS_ECC_RESULT_FIXED;
- dev->n_ecc_fixed++;
- break;
-
- case -EBADMSG:
- /* MTD's ECC could not fix the data */
- dev->n_ecc_unfixed++;
- /* fall into... */
- default:
- rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
- etags->block_bad = (mtd->block_isbad) (mtd, addr);
- return YAFFS_FAIL;
- }
-
- /* Check for a blank/erased chunk.
- */
- if (yaffs_check_ff((u8 *) &pt1, 8)) {
- /* when blank, upper layers want ecc_result to be <= NO_ERROR */
- return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK);
- }
-
- if(dev->param.tags_9bytes) {
- deleted = (hweight8(((u8 *) &pt1)[8]) < 7);
- } else {
- /* Read deleted status (bit) then return it to it's non-deleted
- * state before performing tags mini-ECC check. pt1.deleted is
- * inverted.
- */
- deleted = !pt1.deleted;
- pt1.deleted = 1;
- }
-
- /* Check the packed tags mini-ECC and correct if necessary/possible.
- */
- retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
- switch (retval) {
- case 0:
- /* no tags error, use MTD result */
- break;
- case 1:
- /* recovered tags-ECC error */
- dev->n_tags_ecc_fixed++;
- if (eccres == YAFFS_ECC_RESULT_NO_ERROR)
- eccres = YAFFS_ECC_RESULT_FIXED;
- break;
- default:
- /* unrecovered tags-ECC error */
- dev->n_tags_ecc_unfixed++;
- return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL);
- }
-
- /* Unpack the tags to extended form and set ECC result.
- * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
- */
- pt1.should_be_ff = 0xffffffff;
- yaffs_unpack_tags1(etags, &pt1);
- etags->ecc_result = eccres;
-
- /* Set deleted state */
- etags->is_deleted = deleted;
- return YAFFS_OK;
-}
-
-/* Mark a block bad.
- *
- * This is a persistant state.
- * Use of this function should be rare.
- *
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
- int retval;
-
- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
-
- retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no);
- return (retval) ? YAFFS_FAIL : YAFFS_OK;
-}
-
-/* Check any MTD prerequists.
- *
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-static int nandmtd1_test_prerequists(struct yaffs_dev *dev, struct mtd_info *mtd)
-{
- /* 2.6.18 has mtd->ecclayout->oobavail */
- /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
- int oobavail = mtd->ecclayout->oobavail;
-
- if (oobavail < (dev->param.tags_9bytes ? 9 : 8)) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "mtd device has only %d bytes for tags, need %d",
- oobavail, dev->param.tags_9bytes ? 9 : 8);
- return YAFFS_FAIL;
- }
- return YAFFS_OK;
-}
-
-/* Query for the current state of a specific block.
- *
- * Examine the tags of the first chunk of the block and return the state:
- * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
- * - YAFFS_BLOCK_STATE_NEEDS_SCAN, the block is in use
- * - YAFFS_BLOCK_STATE_EMPTY, the block is clean
- *
- * Always returns YAFFS_OK.
- */
-int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
- enum yaffs_block_state *state_ptr, u32 * seq_ptr)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int chunk_num = block_no * dev->param.chunks_per_block;
- loff_t addr = (loff_t) chunk_num * dev->data_bytes_per_chunk;
- struct yaffs_ext_tags etags;
- int state = YAFFS_BLOCK_STATE_DEAD;
- int seqnum = 0;
- int retval;
-
- /* We don't yet have a good place to test for MTD config prerequists.
- * Do it here as we are called during the initial scan.
- */
- if (nandmtd1_test_prerequists(dev, mtd) != YAFFS_OK)
- return YAFFS_FAIL;
-
- retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags);
- etags.block_bad = (mtd->block_isbad) (mtd, addr);
- if (etags.block_bad) {
- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
- "block %d is marked bad",
- block_no);
- state = YAFFS_BLOCK_STATE_DEAD;
- } else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
- /* bad tags, need to look more closely */
- state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
- } else if (etags.chunk_used) {
- state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
- seqnum = etags.seq_number;
- } else {
- state = YAFFS_BLOCK_STATE_EMPTY;
- }
-
- *state_ptr = state;
- *seq_ptr = seqnum;
-
- /* query always succeeds */
- return YAFFS_OK;
-}
-
-#endif /*MTD_VERSION */
+++ /dev/null
-/*
- * YAFFS: Yet another FFS. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-/*
- * This module provides the interface between yaffs_nand.c and the
- * MTD API. This version is used when the MTD interface supports the
- * 'mtd_oob_ops' style calls to read_oob and write_oob, circa 2.6.17,
- * and we have small-page NAND device.
- *
- * These functions are invoked via function pointers in yaffs_nand.c.
- * This replaces functionality provided by functions in yaffs_mtdif.c
- * and the yaffs_tags compatability functions in yaffs_tagscompat.c that are
- * called in yaffs_mtdif.c when the function pointers are NULL.
- * We assume the MTD layer is performing ECC (use_nand_ecc is true).
- */
-
-#include "yportenv.h"
-#include "yaffs_trace.h"
-#include "yaffs_guts.h"
-#include "yaffs_packedtags1.h"
-#include "yaffs_tagscompat.h" /* for yaffs_calc_tags_ecc */
-#include "yaffs_linux.h"
-#include "linux/kernel.h"
-#include "linux/version.h"
-#include "linux/types.h"
-#include "linux/mtd/mtd.h"
-
-/* Write a chunk (page) of data to NAND.
- *
- * Caller always provides ExtendedTags data which are converted to a more
- * compact (packed) form for storage in NAND. A mini-ECC runs over the
- * contents of the tags meta-data; used to valid the tags when read.
- *
- * - Pack ExtendedTags to packed_tags1 form
- * - Compute mini-ECC for packed_tags1
- * - Write data and packed tags to NAND.
- *
- * Note: Due to the use of the packed_tags1 meta-data which does not include
- * a full sequence number (as found in the larger packed_tags2 form) it is
- * necessary for Yaffs to re-write a chunk/page (just once) to mark it as
- * discarded and dirty. This is not ideal: newer NAND parts are supposed
- * to be written just once. When Yaffs performs this operation, this
- * function is called with a NULL data pointer -- calling MTD write_oob
- * without data is valid usage (2.6.17).
- *
- * Any underlying MTD error results in YAFFS_FAIL.
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-int nandmtd1_write_chunk_tags(struct yaffs_dev *dev,
- int nand_chunk, const u8 *data,
- const struct yaffs_ext_tags *etags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int chunk_bytes = dev->data_bytes_per_chunk;
- loff_t addr = ((loff_t) nand_chunk) * chunk_bytes;
- struct mtd_oob_ops ops;
- struct yaffs_packed_tags1 pt1;
- int retval;
-
- /* we assume that packed_tags1 and struct yaffs_tags are compatible */
- compile_time_assertion(sizeof(struct yaffs_packed_tags1) == 12);
- compile_time_assertion(sizeof(struct yaffs_tags) == 8);
-
- yaffs_pack_tags1(&pt1, etags);
- yaffs_calc_tags_ecc((struct yaffs_tags *)&pt1);
-
- /* When deleting a chunk, the upper layer provides only skeletal
- * etags, one with is_deleted set. However, we need to update the
- * tags, not erase them completely. So we use the NAND write property
- * that only zeroed-bits stick and set tag bytes to all-ones and
- * zero just the (not) deleted bit.
- */
-
- if (dev->param.tags_9bytes) {
- ((u8 *) &pt1)[8] = 0xff;
- if (etags->is_deleted) {
- memset(&pt1, 0xff, 8);
- /* zero page_status byte to indicate deleted */
- ((u8 *) &pt1)[8] = 0;
- }
- } else {
- if (etags->is_deleted) {
- memset(&pt1, 0xff, 8);
- /* clear delete status bit to indicate deleted */
- pt1.deleted = 0;
- }
- }
-
- memset(&ops, 0, sizeof(ops));
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.len = (data) ? chunk_bytes : 0;
- ops.ooblen = dev->param.tags_9bytes ? 9 : 8;
- ops.datbuf = (u8 *) data;
- ops.oobbuf = (u8 *) &pt1;
-
- retval = mtd->write_oob(mtd, addr, &ops);
- if (retval) {
- yaffs_trace(YAFFS_TRACE_MTD,
- "write_oob failed, chunk %d, mtd error %d",
- nand_chunk, retval);
- }
- return retval ? YAFFS_FAIL : YAFFS_OK;
-}
-
-/* Return with empty ExtendedTags but add ecc_result.
- */
-static int rettags(struct yaffs_ext_tags *etags, int ecc_result, int retval)
-{
- if (etags) {
- memset(etags, 0, sizeof(*etags));
- etags->ecc_result = ecc_result;
- }
- return retval;
-}
-
-/* Read a chunk (page) from NAND.
- *
- * Caller expects ExtendedTags data to be usable even on error; that is,
- * all members except ecc_result and block_bad are zeroed.
- *
- * - Check ECC results for data (if applicable)
- * - Check for blank/erased block (return empty ExtendedTags if blank)
- * - Check the packed_tags1 mini-ECC (correct if necessary/possible)
- * - Convert packed_tags1 to ExtendedTags
- * - Update ecc_result and block_bad members to refect state.
- *
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-int nandmtd1_read_chunk_tags(struct yaffs_dev *dev,
- int nand_chunk, u8 *data,
- struct yaffs_ext_tags *etags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int chunk_bytes = dev->data_bytes_per_chunk;
- loff_t addr = ((loff_t) nand_chunk) * chunk_bytes;
- int eccres = YAFFS_ECC_RESULT_NO_ERROR;
- struct mtd_oob_ops ops;
- struct yaffs_packed_tags1 pt1;
- int retval;
- int deleted;
-
- memset(&ops, 0, sizeof(ops));
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.len = (data) ? chunk_bytes : 0;
- ops.ooblen = dev->param.tags_9bytes ? 9 : 8;
- ops.datbuf = data;
- ops.oobbuf = (u8 *) &pt1;
-
- /* Read page and oob using MTD.
- * Check status and determine ECC result.
- */
- retval = mtd->read_oob(mtd, addr, &ops);
- if (retval) {
- yaffs_trace(YAFFS_TRACE_MTD,
- "read_oob failed, chunk %d, mtd error %d",
- nand_chunk, retval);
- }
-
- switch (retval) {
- case 0:
- /* no error */
- break;
-
- case -EUCLEAN:
- /* MTD's ECC fixed the data */
- eccres = YAFFS_ECC_RESULT_FIXED;
- dev->n_ecc_fixed++;
- break;
-
- case -EBADMSG:
- /* MTD's ECC could not fix the data */
- dev->n_ecc_unfixed++;
- /* fall into... */
- default:
- rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
- etags->block_bad = (mtd->block_isbad) (mtd, addr);
- return YAFFS_FAIL;
- }
-
- /* Check for a blank/erased chunk.
- */
- if (yaffs_check_ff((u8 *) &pt1, 8)) {
- /* when blank, upper layers want ecc_result to be <= NO_ERROR */
- return rettags(etags, YAFFS_ECC_RESULT_NO_ERROR, YAFFS_OK);
- }
-#ifndef CONFIG_YAFFS_9BYTE_TAGS
- /* Read deleted status (bit) then return it to it's non-deleted
- * state before performing tags mini-ECC check. pt1.deleted is
- * inverted.
- */
- deleted = !pt1.deleted;
- pt1.deleted = 1;
-#else
- deleted = (hweight8(((u8 *) &pt1)[8]) < 7);
-#endif
-
- /* Check the packed tags mini-ECC and correct if necessary/possible.
- */
- retval = yaffs_check_tags_ecc((struct yaffs_tags *)&pt1);
- switch (retval) {
- case 0:
- /* no tags error, use MTD result */
- break;
- case 1:
- /* recovered tags-ECC error */
- dev->n_tags_ecc_fixed++;
- if (eccres == YAFFS_ECC_RESULT_NO_ERROR)
- eccres = YAFFS_ECC_RESULT_FIXED;
- break;
- default:
- /* unrecovered tags-ECC error */
- dev->n_tags_ecc_unfixed++;
- return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL);
- }
-
- /* Unpack the tags to extended form and set ECC result.
- * [set should_be_ff just to keep yaffs_unpack_tags1 happy]
- */
- pt1.should_be_ff = 0xffffffff;
- yaffs_unpack_tags1(etags, &pt1);
- etags->ecc_result = eccres;
-
- /* Set deleted state */
- etags->is_deleted = deleted;
- return YAFFS_OK;
-}
-
-/* Mark a block bad.
- *
- * This is a persistant state.
- * Use of this function should be rare.
- *
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-int nandmtd1_mark_block_bad(struct yaffs_dev *dev, int block_no)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
- int retval;
-
- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
- "marking block %d bad", block_no);
-
- retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no);
- return (retval) ? YAFFS_FAIL : YAFFS_OK;
-}
-
-/* Check any MTD prerequists.
- *
- * Returns YAFFS_OK or YAFFS_FAIL.
- */
-static int nandmtd1_test_prerequists(struct yaffs_dev *dev,
- struct mtd_info *mtd)
-{
- /* 2.6.18 has mtd->ecclayout->oobavail */
- /* 2.6.21 has mtd->ecclayout->oobavail and mtd->oobavail */
- int oobavail = mtd->ecclayout->oobavail;
-
- if (oobavail < (dev->param.tags_9bytes ? 9 : 8)) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "mtd device has only %d bytes for tags, need %d",
- oobavail, (dev->param.tags_9bytes ? 9 : 8));
- return YAFFS_FAIL;
- }
- return YAFFS_OK;
-}
-
-/* Query for the current state of a specific block.
- *
- * Examine the tags of the first chunk of the block and return the state:
- * - YAFFS_BLOCK_STATE_DEAD, the block is marked bad
- * - YAFFS_BLOCK_STATE_NEEDS_SCAN, the block is in use
- * - YAFFS_BLOCK_STATE_EMPTY, the block is clean
- *
- * Always returns YAFFS_OK.
- */
-int nandmtd1_query_block(struct yaffs_dev *dev, int block_no,
- enum yaffs_block_state *state_ptr, u32 * seq_ptr)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int chunk_num = block_no * dev->param.chunks_per_block;
- loff_t addr = (loff_t) chunk_num * dev->data_bytes_per_chunk;
- struct yaffs_ext_tags etags;
- int state = YAFFS_BLOCK_STATE_DEAD;
- int seqnum = 0;
- int retval;
-
- /* We don't yet have a good place to test for MTD config prerequists.
- * Do it here as we are called during the initial scan.
- */
- if (nandmtd1_test_prerequists(dev, mtd) != YAFFS_OK)
- return YAFFS_FAIL;
-
- retval = nandmtd1_read_chunk_tags(dev, chunk_num, NULL, &etags);
- etags.block_bad = (mtd->block_isbad) (mtd, addr);
- if (etags.block_bad) {
- yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
- "block %d is marked bad", block_no);
- state = YAFFS_BLOCK_STATE_DEAD;
- } else if (etags.ecc_result != YAFFS_ECC_RESULT_NO_ERROR) {
- /* bad tags, need to look more closely */
- state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
- } else if (etags.chunk_used) {
- state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
- seqnum = etags.seq_number;
- } else {
- state = YAFFS_BLOCK_STATE_EMPTY;
- }
-
- *state_ptr = state;
- *seq_ptr = seqnum;
-
- /* query always succeeds */
- return YAFFS_OK;
-}
+++ /dev/null
-/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License version 2.1 as
- * published by the Free Software Foundation.
- *
- * Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
- */
-
-#ifndef __YAFFS_MTDIF2_H__
-#define __YAFFS_MTDIF2_H__
-
-#include "yaffs_guts.h"
-int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- const u8 *data,
- const struct yaffs_ext_tags *tags);
-int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- u8 *data, struct yaffs_ext_tags *tags);
-int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no);
-int nandmtd2_query_block(struct yaffs_dev *dev, int block_no,
- enum yaffs_block_state *state, u32 *seq_number);
-
-#endif
+++ /dev/null
-/*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-/* mtd interface for YAFFS2 */
-
-#include "yportenv.h"
-#include "yaffs_trace.h"
-
-#include "yaffs_mtdif2.h"
-
-#include "linux/mtd/mtd.h"
-#include "linux/types.h"
-#include "linux/time.h"
-
-#include "yaffs_packedtags2.h"
-
-#include "yaffs_linux.h"
-
-#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
-#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
-#endif
-
-
-
-/* NB For use with inband tags....
- * We assume that the data buffer is of size total_bytes_per_chunk so
- * that we can also use it to load the tags.
- */
-int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- const u8 *data,
- const struct yaffs_ext_tags *tags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
-#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
- struct mtd_oob_ops ops;
-#else
- size_t dummy;
-#endif
- int retval = 0;
-
- loff_t addr;
-
- struct yaffs_packed_tags2 pt;
-
- int packed_tags_size =
- dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
- void *packed_tags_ptr =
- dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
-
- yaffs_trace(YAFFS_TRACE_MTD,
- "nandmtd2_write_chunk_tags chunk %d data %p tags %p",
- nand_chunk, data, tags);
-
- addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
-
- /* For yaffs2 writing there must be both data and tags.
- * If we're using inband tags, then the tags are stuffed into
- * the end of the data buffer.
- */
- if (!data || !tags)
- BUG();
- else if (dev->param.inband_tags) {
- struct yaffs_packed_tags2_tags_only *pt2tp;
- pt2tp =
- (struct yaffs_packed_tags2_tags_only *)(data +
- dev->
- data_bytes_per_chunk);
- yaffs_pack_tags2_tags_only(pt2tp, tags);
- } else {
- yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
- }
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size;
- ops.len = dev->param.total_bytes_per_chunk;
- ops.ooboffs = 0;
- ops.datbuf = (u8 *) data;
- ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr;
- retval = mtd->write_oob(mtd, addr, &ops);
-
-#else
- if (!dev->param.inband_tags) {
- retval =
- mtd->write_ecc(mtd, addr, dev->data_bytes_per_chunk,
- &dummy, data, (u8 *) packed_tags_ptr, NULL);
- } else {
- retval =
- mtd->write(mtd, addr, dev->param.total_bytes_per_chunk,
- &dummy, data);
- }
-#endif
-
- if (retval == 0)
- return YAFFS_OK;
- else
- return YAFFS_FAIL;
-}
-
-int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- u8 *data, struct yaffs_ext_tags *tags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
-#if (MTD_VERSION_CODE > MTD_VERSION(2, 6, 17))
- struct mtd_oob_ops ops;
-#endif
- size_t dummy;
- int retval = 0;
- int local_data = 0;
-
- loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
-
- struct yaffs_packed_tags2 pt;
-
- int packed_tags_size =
- dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
- void *packed_tags_ptr =
- dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
-
- yaffs_trace(YAFFS_TRACE_MTD,
- "nandmtd2_read_chunk_tags chunk %d data %p tags %p",
- nand_chunk, data, tags);
-
- if (dev->param.inband_tags) {
-
- if (!data) {
- local_data = 1;
- data = yaffs_get_temp_buffer(dev);
- }
-
- }
-
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
- if (dev->param.inband_tags || (data && !tags))
- retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk,
- &dummy, data);
- else if (tags) {
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.ooblen = packed_tags_size;
- ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
- ops.ooboffs = 0;
- ops.datbuf = data;
- ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer;
- retval = mtd->read_oob(mtd, addr, &ops);
- }
-#else
- if (!dev->param.inband_tags && data && tags) {
-
- retval = mtd->read_ecc(mtd, addr, dev->data_bytes_per_chunk,
- &dummy, data, dev->spare_buffer, NULL);
- } else {
- if (data)
- retval =
- mtd->read(mtd, addr, dev->data_bytes_per_chunk,
- &dummy, data);
- if (!dev->param.inband_tags && tags)
- retval =
- mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
- dev->spare_buffer);
- }
-#endif
-
- if (dev->param.inband_tags) {
- if (tags) {
- struct yaffs_packed_tags2_tags_only *pt2tp;
- pt2tp =
- (struct yaffs_packed_tags2_tags_only *)
- &data[dev->data_bytes_per_chunk];
- yaffs_unpack_tags2_tags_only(tags, pt2tp);
- }
- } else {
- if (tags) {
- memcpy(packed_tags_ptr,
- yaffs_dev_to_lc(dev)->spare_buffer,
- packed_tags_size);
- yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
- }
- }
-
- if (local_data)
- yaffs_release_temp_buffer(dev, data);
-
- if (tags && retval == -EBADMSG
- && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
- tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
- dev->n_ecc_unfixed++;
- }
- if (tags && retval == -EUCLEAN
- && tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
- tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
- dev->n_ecc_fixed++;
- }
- if (retval == 0)
- return YAFFS_OK;
- else
- return YAFFS_FAIL;
-}
-
-int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int retval;
- yaffs_trace(YAFFS_TRACE_MTD,
- "nandmtd2_mark_block_bad %d",
- block_no);
-
- retval =
- mtd->block_markbad(mtd,
- block_no * dev->param.chunks_per_block *
- dev->param.total_bytes_per_chunk);
-
- if (retval == 0)
- return YAFFS_OK;
- else
- return YAFFS_FAIL;
-
-}
-
-int nandmtd2_query_block(struct yaffs_dev *dev, int block_no,
- enum yaffs_block_state *state, u32 *seq_number)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int retval;
-
- yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_query_block %d", block_no);
- retval =
- mtd->block_isbad(mtd,
- block_no * dev->param.chunks_per_block *
- dev->param.total_bytes_per_chunk);
-
- if (retval) {
- yaffs_trace(YAFFS_TRACE_MTD, "block is bad");
-
- *state = YAFFS_BLOCK_STATE_DEAD;
- *seq_number = 0;
- } else {
- struct yaffs_ext_tags t;
- nandmtd2_read_chunk_tags(dev, block_no *
- dev->param.chunks_per_block, NULL, &t);
-
- if (t.chunk_used) {
- *seq_number = t.seq_number;
- *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
- } else {
- *seq_number = 0;
- *state = YAFFS_BLOCK_STATE_EMPTY;
- }
- }
- yaffs_trace(YAFFS_TRACE_MTD,
- "block is bad seq %d state %d",
- *seq_number, *state);
-
- if (retval == 0)
- return YAFFS_OK;
- else
- return YAFFS_FAIL;
-}
-
+++ /dev/null
-/*
- * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
- *
- * Copyright (C) 2002-2011 Aleph One Ltd.
- * for Toby Churchill Ltd and Brightstar Engineering
- *
- * Created by Charles Manning <charles@aleph1.co.uk>
- *
- * 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.
- */
-
-/* mtd interface for YAFFS2 */
-
-#include "yportenv.h"
-#include "yaffs_trace.h"
-#include "yaffs_mtdif2.h"
-#include "yaffs_packedtags2.h"
-#include "yaffs_linux.h"
-#include "linux/mtd/mtd.h"
-#include "linux/types.h"
-#include "linux/time.h"
-#include "mtd/mtd-abi.h"
-
-
-/* NB For use with inband tags....
- * We assume that the data buffer is of size total_bytes_per_chunk so that
- * we can also use it to load the tags.
- */
-int nandmtd2_write_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- const u8 *data,
- const struct yaffs_ext_tags *tags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- struct mtd_oob_ops ops;
- int retval = 0;
- loff_t addr;
- struct yaffs_packed_tags2 pt;
- int packed_tags_size =
- dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
- void *packed_tags_ptr =
- dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
-
- yaffs_trace(YAFFS_TRACE_MTD,
- "nandmtd2_write_chunk_tags chunk %d data %p tags %p",
- nand_chunk, data, tags);
-
- addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
-
- /* For yaffs2 writing there must be both data and tags.
- * If we're using inband tags, then the tags are stuffed into
- * the end of the data buffer.
- */
- if (!data || !tags)
- BUG();
- else if (dev->param.inband_tags) {
- struct yaffs_packed_tags2_tags_only *pt2tp;
-
- pt2tp =
- (struct yaffs_packed_tags2_tags_only *)
- (data + dev->data_bytes_per_chunk);
- yaffs_pack_tags2_tags_only(pt2tp, tags);
- } else {
- yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
- }
-
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.ooblen = (dev->param.inband_tags) ? 0 : packed_tags_size;
- ops.len = dev->param.total_bytes_per_chunk;
- ops.ooboffs = 0;
- ops.datbuf = (u8 *) data;
- ops.oobbuf = (dev->param.inband_tags) ? NULL : packed_tags_ptr;
- retval = mtd->write_oob(mtd, addr, &ops);
-
- if (retval == 0)
- return YAFFS_OK;
-
- return YAFFS_FAIL;
-}
-
-int nandmtd2_read_chunk_tags(struct yaffs_dev *dev, int nand_chunk,
- u8 *data, struct yaffs_ext_tags *tags)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- struct mtd_oob_ops ops;
- size_t dummy;
- int retval = 0;
- int local_data = 0;
- loff_t addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
- struct yaffs_packed_tags2 pt;
- int packed_tags_size =
- dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
- void *packed_tags_ptr =
- dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
-
- yaffs_trace(YAFFS_TRACE_MTD,
- "nandmtd2_read_chunk_tags chunk %d data %p tags %p",
- nand_chunk, data, tags);
-
- if (dev->param.inband_tags && !data) {
- local_data = 1;
- data = yaffs_get_temp_buffer(dev);
- }
-
- if (dev->param.inband_tags || (data && !tags)) {
- retval = mtd->read(mtd, addr, dev->param.total_bytes_per_chunk,
- &dummy, data);
- } else if (tags) {
- ops.mode = MTD_OPS_AUTO_OOB;
- ops.ooblen = packed_tags_size;
- ops.len = data ? dev->data_bytes_per_chunk : packed_tags_size;
- ops.ooboffs = 0;
- ops.datbuf = data;
- ops.oobbuf = yaffs_dev_to_lc(dev)->spare_buffer;
- retval = mtd->read_oob(mtd, addr, &ops);
- }
-
- if (dev->param.inband_tags && tags) {
- struct yaffs_packed_tags2_tags_only *pt2tp;
-
- pt2tp =
- (struct yaffs_packed_tags2_tags_only *)
- &data[dev->data_bytes_per_chunk];
- yaffs_unpack_tags2_tags_only(tags, pt2tp);
- } else if (tags) {
- memcpy(packed_tags_ptr,
- yaffs_dev_to_lc(dev)->spare_buffer,
- packed_tags_size);
- yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
- }
-
- if (local_data)
- yaffs_release_temp_buffer(dev, data);
-
- if (tags && retval == -EBADMSG &&
- tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
- tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
- dev->n_ecc_unfixed++;
- }
- if (tags && retval == -EUCLEAN &&
- tags->ecc_result == YAFFS_ECC_RESULT_NO_ERROR) {
- tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
- dev->n_ecc_fixed++;
- }
-
- if (retval == 0)
- return YAFFS_OK;
-
- return YAFFS_FAIL;
-}
-
-int nandmtd2_mark_block_bad(struct yaffs_dev *dev, int block_no)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int retval;
-
- yaffs_trace(YAFFS_TRACE_MTD,
- "nandmtd2_mark_block_bad %d", block_no);
-
- retval =
- mtd->block_markbad(mtd,
- block_no * dev->param.chunks_per_block *
- dev->param.total_bytes_per_chunk);
-
- if (retval == 0)
- return YAFFS_OK;
-
- return YAFFS_FAIL;
-}
-
-int nandmtd2_query_block(struct yaffs_dev *dev, int block_no,
- enum yaffs_block_state *state, u32 * seq_number)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- int retval;
-
- yaffs_trace(YAFFS_TRACE_MTD, "nandmtd2_query_block %d", block_no);
- retval =
- mtd->block_isbad(mtd,
- block_no * dev->param.chunks_per_block *
- dev->param.total_bytes_per_chunk);
-
- if (retval) {
- yaffs_trace(YAFFS_TRACE_MTD, "block is bad");
-
- *state = YAFFS_BLOCK_STATE_DEAD;
- *seq_number = 0;
- } else {
- struct yaffs_ext_tags t;
-
- nandmtd2_read_chunk_tags(dev, block_no *
- dev->param.chunks_per_block, NULL, &t);
-
- if (t.chunk_used) {
- *seq_number = t.seq_number;
- *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
- } else {
- *seq_number = 0;
- *state = YAFFS_BLOCK_STATE_EMPTY;
- }
- }
- yaffs_trace(YAFFS_TRACE_MTD,
- "block is bad seq %d state %d", *seq_number, *state);
-
- if (retval == 0)
- return YAFFS_OK;
-
- return YAFFS_FAIL;
-}
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+#include "yportenv.h"
+
+#include "yaffs_mtdif.h"
+
+#include "linux/mtd/mtd.h"
+#include "linux/types.h"
+#include "linux/time.h"
+#include "linux/mtd/nand.h"
+#include "linux/kernel.h"
+#include "linux/version.h"
+#include "linux/types.h"
+
+#include "yaffs_trace.h"
+#include "yaffs_guts.h"
+#include "yaffs_linux.h"
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
+#endif
+
+
+int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ u32 addr =
+ ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
+ dev->param.chunks_per_block;
+ struct erase_info ei;
+ int retval = 0;
+
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
+ ei.time = 1000;
+ ei.retries = 2;
+ ei.callback = NULL;
+ ei.priv = (u_long) dev;
+
+ retval = mtd->erase(mtd, &ei);
+
+ if (retval == 0)
+ return YAFFS_OK;
+
+ return YAFFS_FAIL;
+}
+
+
+static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ loff_t addr;
+ struct mtd_oob_ops ops;
+ int retval;
+
+ addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+ memset(&ops, 0, sizeof(ops));
+ ops.mode = MTD_OPS_AUTO_OOB;
+ ops.len = (data) ? data_len : 0;
+ ops.ooblen = oob_len;
+ ops.datbuf = (u8 *)data;
+ ops.oobbuf = (u8 *)oob;
+
+ retval = mtd->write_oob(mtd, addr, &ops);
+ if (retval) {
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "write_oob failed, chunk %d, mtd error %d",
+ nand_chunk, retval);
+ }
+ return retval ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ loff_t addr;
+ struct mtd_oob_ops ops;
+ int retval;
+
+ addr = ((loff_t) nand_chunk) * dev->data_bytes_per_chunk;
+ memset(&ops, 0, sizeof(ops));
+ ops.mode = MTD_OPS_AUTO_OOB;
+ ops.len = (data) ? data_len : 0;
+ ops.ooblen = oob_len;
+ ops.datbuf = data;
+ ops.oobbuf = oob;
+
+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
+ /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+ * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+ */
+ ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
+#endif
+ /* Read page and oob using MTD.
+ * Check status and determine ECC result.
+ */
+ retval = mtd->read_oob(mtd, addr, &ops);
+ if (retval)
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "read_oob failed, chunk %d, mtd error %d",
+ nand_chunk, retval);
+
+ switch (retval) {
+ case 0:
+ /* no error */
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+ break;
+
+ case -EUCLEAN:
+ /* MTD's ECC fixed the data */
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_FIXED;
+ dev->n_ecc_fixed++;
+ break;
+
+ case -EBADMSG:
+ default:
+ /* MTD's ECC could not fix the data */
+ dev->n_ecc_unfixed++;
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ return YAFFS_FAIL;
+ }
+
+ return YAFFS_OK;
+}
+
+static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+
+ loff_t addr;
+ struct erase_info ei;
+ int retval = 0;
+ u32 block_size;
+
+ block_size = dev->param.total_bytes_per_chunk *
+ dev->param.chunks_per_block;
+ addr = ((loff_t) block_no) * block_size;
+
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = block_size;
+ ei.time = 1000;
+ ei.retries = 2;
+ ei.callback = NULL;
+ ei.priv = (u_long) dev;
+
+ retval = mtd->erase(mtd, &ei);
+
+ if (retval == 0)
+ return YAFFS_OK;
+
+ return YAFFS_FAIL;
+}
+
+static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
+
+ retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no);
+ return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "checking block %d bad", block_no);
+
+ retval = mtd->block_isbad(mtd, (loff_t) blocksize * block_no);
+ return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_initialise(struct yaffs_dev *dev)
+{
+ return YAFFS_OK;
+}
+
+static int yaffs_mtd_deinitialise(struct yaffs_dev *dev)
+{
+ return YAFFS_OK;
+}
+
+
+
+void yaffs_mtd_drv_install(struct yaffs_dev *dev)
+{
+ struct yaffs_driver *drv = &dev->drv;
+
+ drv->drv_write_chunk_fn = yaffs_mtd_write;
+ drv->drv_read_chunk_fn = yaffs_mtd_read;
+ drv->drv_erase_fn = yaffs_mtd_erase;
+ drv->drv_mark_bad_fn = yaffs_mtd_mark_bad;
+ drv->drv_check_bad_fn = yaffs_mtd_check_bad;
+ drv->drv_initialise_fn = yaffs_mtd_initialise;
+ drv->drv_deinitialise_fn = yaffs_mtd_deinitialise;
+}
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+#include "yportenv.h"
+
+#include "yaffs_mtdif.h"
+
+#include "linux/mtd/mtd.h"
+#include "linux/types.h"
+#include "linux/time.h"
+#include "linux/mtd/nand.h"
+#include "linux/kernel.h"
+#include "linux/version.h"
+#include "linux/types.h"
+
+#include "yaffs_trace.h"
+#include "yaffs_guts.h"
+#include "yaffs_linux.h"
+
+
+#if (LINUX_VERSION_CODE < KERNEL_VERSION(3, 2, 0))
+#define MTD_OPS_AUTO_OOB MTD_OOB_AUTO
+#endif
+
+
+int nandmtd_erase_block(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ u32 addr =
+ ((loff_t) block_no) * dev->param.total_bytes_per_chunk *
+ dev->param.chunks_per_block;
+ struct erase_info ei;
+ int retval = 0;
+
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = dev->param.total_bytes_per_chunk * dev->param.chunks_per_block;
+ ei.time = 1000;
+ ei.retries = 2;
+ ei.callback = NULL;
+ ei.priv = (u_long) dev;
+
+ retval = mtd->erase(mtd, &ei);
+
+ if (retval == 0)
+ return YAFFS_OK;
+
+ return YAFFS_FAIL;
+}
+
+
+static int yaffs_mtd_write(struct yaffs_dev *dev, int nand_chunk,
+ const u8 *data, int data_len,
+ const u8 *oob, int oob_len)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ loff_t addr;
+ struct mtd_oob_ops ops;
+ int retval;
+
+ addr = ((loff_t) nand_chunk) * dev->param.total_bytes_per_chunk;
+ memset(&ops, 0, sizeof(ops));
+ ops.mode = MTD_OPS_AUTO_OOB;
+ ops.len = (data) ? data_len : 0;
+ ops.ooblen = oob_len;
+ ops.datbuf = (u8 *)data;
+ ops.oobbuf = (u8 *)oob;
+
+ retval = mtd->write_oob(mtd, addr, &ops);
+ if (retval) {
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "write_oob failed, chunk %d, mtd error %d",
+ nand_chunk, retval);
+ }
+ return retval ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_read(struct yaffs_dev *dev, int nand_chunk,
+ u8 *data, int data_len,
+ u8 *oob, int oob_len,
+ enum yaffs_ecc_result *ecc_result)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ loff_t addr;
+ struct mtd_oob_ops ops;
+ int retval;
+
+ addr = ((loff_t) nand_chunk) * dev->data_bytes_per_chunk;
+ memset(&ops, 0, sizeof(ops));
+ ops.mode = MTD_OPS_AUTO_OOB;
+ ops.len = (data) ? data_len : 0;
+ ops.ooblen = oob_len;
+ ops.datbuf = data;
+ ops.oobbuf = oob;
+
+#if (MTD_VERSION_CODE < MTD_VERSION(2, 6, 20))
+ /* In MTD 2.6.18 to 2.6.19 nand_base.c:nand_do_read_oob() has a bug;
+ * help it out with ops.len = ops.ooblen when ops.datbuf == NULL.
+ */
+ ops.len = (ops.datbuf) ? ops.len : ops.ooblen;
+#endif
+ /* Read page and oob using MTD.
+ * Check status and determine ECC result.
+ */
+ retval = mtd->read_oob(mtd, addr, &ops);
+ if (retval)
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "read_oob failed, chunk %d, mtd error %d",
+ nand_chunk, retval);
+
+ switch (retval) {
+ case 0:
+ /* no error */
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+ break;
+
+ case -EUCLEAN:
+ /* MTD's ECC fixed the data */
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_FIXED;
+ dev->n_ecc_fixed++;
+ break;
+
+ case -EBADMSG:
+ default:
+ /* MTD's ECC could not fix the data */
+ dev->n_ecc_unfixed++;
+ if(ecc_result)
+ *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ return YAFFS_FAIL;
+ }
+
+ return YAFFS_OK;
+}
+
+static int yaffs_mtd_erase(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+
+ loff_t addr;
+ struct erase_info ei;
+ int retval = 0;
+ u32 block_size;
+
+ block_size = dev->param.total_bytes_per_chunk *
+ dev->param.chunks_per_block;
+ addr = ((loff_t) block_no) * block_size;
+
+ ei.mtd = mtd;
+ ei.addr = addr;
+ ei.len = block_size;
+ ei.time = 1000;
+ ei.retries = 2;
+ ei.callback = NULL;
+ ei.priv = (u_long) dev;
+
+ retval = mtd->erase(mtd, &ei);
+
+ if (retval == 0)
+ return YAFFS_OK;
+
+ return YAFFS_FAIL;
+}
+
+static int yaffs_mtd_mark_bad(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad", block_no);
+
+ retval = mtd->block_markbad(mtd, (loff_t) blocksize * block_no);
+ return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_check_bad(struct yaffs_dev *dev, int block_no)
+{
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
+ int blocksize = dev->param.chunks_per_block * dev->data_bytes_per_chunk;
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "checking block %d bad", block_no);
+
+ retval = mtd->block_isbad(mtd, (loff_t) blocksize * block_no);
+ return (retval) ? YAFFS_FAIL : YAFFS_OK;
+}
+
+static int yaffs_mtd_initialise(struct yaffs_dev *dev)
+{
+ return YAFFS_OK;
+}
+
+static int yaffs_mtd_deinitialise(struct yaffs_dev *dev)
+{
+ return YAFFS_OK;
+}
+
+
+
+void yaffs_mtd_drv_install(struct yaffs_dev *dev)
+{
+ struct yaffs_driver *drv = &dev->drv;
+
+ drv->drv_write_chunk_fn = yaffs_mtd_write;
+ drv->drv_read_chunk_fn = yaffs_mtd_read;
+ drv->drv_erase_fn = yaffs_mtd_erase;
+ drv->drv_mark_bad_fn = yaffs_mtd_mark_bad;
+ drv->drv_check_bad_fn = yaffs_mtd_check_bad;
+ drv->drv_initialise_fn = yaffs_mtd_initialise;
+ drv->drv_deinitialise_fn = yaffs_mtd_deinitialise;
+}
#include "yaffs_getblockinfo.h"
#include "yaffs_summary.h"
+static int apply_chunk_offset(struct yaffs_dev *dev, int chunk)
+{
+ return chunk - dev->chunk_offset;
+}
+
int yaffs_rd_chunk_tags_nand(struct yaffs_dev *dev, int nand_chunk,
u8 *buffer, struct yaffs_ext_tags *tags)
{
int result;
struct yaffs_ext_tags local_tags;
- int flash_chunk = nand_chunk - dev->chunk_offset;
+ int flash_chunk = apply_chunk_offset(dev, nand_chunk);
dev->n_page_reads++;
if (!tags)
tags = &local_tags;
- if (dev->param.read_chunk_tags_fn)
- result =
- dev->param.read_chunk_tags_fn(dev, flash_chunk, buffer,
- tags);
- else
- result = yaffs_tags_compat_rd(dev,
- flash_chunk, buffer, tags);
+ result = dev->tagger.read_chunk_tags_fn(dev, flash_chunk, buffer, tags);
if (tags && tags->ecc_result > YAFFS_ECC_RESULT_NO_ERROR) {
struct yaffs_block_info *bi;
const u8 *buffer, struct yaffs_ext_tags *tags)
{
int result;
- int flash_chunk = nand_chunk - dev->chunk_offset;
+ int flash_chunk = apply_chunk_offset(dev, nand_chunk);
dev->n_page_writes++;
- if (tags) {
- tags->seq_number = dev->seq_number;
- tags->chunk_used = 1;
- yaffs_trace(YAFFS_TRACE_WRITE,
- "Writing chunk %d tags %d %d",
- nand_chunk, tags->obj_id, tags->chunk_id);
- } else {
+ if (!tags) {
yaffs_trace(YAFFS_TRACE_ERROR, "Writing with no tags");
BUG();
return YAFFS_FAIL;
}
- if (dev->param.write_chunk_tags_fn)
- result = dev->param.write_chunk_tags_fn(dev, flash_chunk,
+ tags->seq_number = dev->seq_number;
+ tags->chunk_used = 1;
+ yaffs_trace(YAFFS_TRACE_WRITE,
+ "Writing chunk %d tags %d %d",
+ nand_chunk, tags->obj_id, tags->chunk_id);
+
+ result = dev->tagger.write_chunk_tags_fn(dev, flash_chunk,
buffer, tags);
- else
- result = yaffs_tags_compat_wr(dev, flash_chunk, buffer, tags);
yaffs_summary_add(dev, tags, nand_chunk);
int yaffs_mark_bad(struct yaffs_dev *dev, int block_no)
{
block_no -= dev->block_offset;
- if (dev->param.bad_block_fn)
- return dev->param.bad_block_fn(dev, block_no);
-
- return yaffs_tags_compat_mark_bad(dev, block_no);
+ dev->n_bad_markings++;
+ return dev->tagger.mark_bad_fn(dev, block_no);
}
+
int yaffs_query_init_block_state(struct yaffs_dev *dev,
int block_no,
enum yaffs_block_state *state,
u32 *seq_number)
{
block_no -= dev->block_offset;
- if (dev->param.query_block_fn)
- return dev->param.query_block_fn(dev, block_no, state,
- seq_number);
-
- return yaffs_tags_compat_query_block(dev, block_no, state, seq_number);
+ return dev->tagger.query_block_fn(dev, block_no, state, seq_number);
}
-int yaffs_erase_block(struct yaffs_dev *dev, int flash_block)
+int yaffs_erase_block(struct yaffs_dev *dev, int block_no)
{
int result;
- flash_block -= dev->block_offset;
+ block_no -= dev->block_offset;
dev->n_erasures++;
- result = dev->param.erase_fn(dev, flash_block);
+ result = dev->drv.drv_erase_fn(dev, block_no);
return result;
}
int yaffs_init_nand(struct yaffs_dev *dev)
{
- if (dev->param.initialise_flash_fn)
- return dev->param.initialise_flash_fn(dev);
+ if (dev->drv.drv_initialise_fn)
+ return dev->drv.drv_initialise_fn(dev);
+ return YAFFS_OK;
+}
+
+int yaffs_deinit_nand(struct yaffs_dev *dev)
+{
+ if (dev->drv.drv_deinitialise_fn)
+ return dev->drv.drv_deinitialise_fn(dev);
return YAFFS_OK;
}
int yaffs_erase_block(struct yaffs_dev *dev, int flash_block);
int yaffs_init_nand(struct yaffs_dev *dev);
+int yaffs_deinit_nand(struct yaffs_dev *dev);
#endif
/********** Tags ECC calculations *********/
-static void yaffs_calc_ecc(const u8 *data, struct yaffs_spare *spare)
-{
- yaffs_ecc_calc(data, spare->ecc1);
- yaffs_ecc_calc(&data[256], spare->ecc2);
-}
void yaffs_calc_tags_ecc(struct yaffs_tags *tags)
{
int nand_chunk, const u8 *data,
struct yaffs_spare *spare)
{
- if (nand_chunk < dev->param.start_block * dev->param.chunks_per_block) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>> yaffs chunk %d is not valid",
- nand_chunk);
- return YAFFS_FAIL;
- }
+ int data_size = dev->data_bytes_per_chunk;
- return dev->param.write_chunk_fn(dev, nand_chunk, data, spare);
+ return dev->drv.drv_write_chunk_fn(dev, nand_chunk,
+ data, data_size,
+ (u8 *) spare, sizeof(*spare));
}
static int yaffs_rd_chunk_nand(struct yaffs_dev *dev,
{
int ret_val;
struct yaffs_spare local_spare;
+ int data_size;
+ int spare_size;
+ int ecc_result1, ecc_result2;
+ u8 calc_ecc[3];
if (!spare) {
/* If we don't have a real spare, then we use a local one. */
/* Need this for the calculation of the ecc */
spare = &local_spare;
}
+ data_size = dev->data_bytes_per_chunk;
+ spare_size = sizeof(struct yaffs_spare);
- if (!dev->param.use_nand_ecc) {
- ret_val =
- dev->param.read_chunk_fn(dev, nand_chunk, data, spare);
- if (data && correct_errors) {
- /* Do ECC correction */
- /* Todo handle any errors */
- int ecc_result1, ecc_result2;
- u8 calc_ecc[3];
-
- yaffs_ecc_calc(data, calc_ecc);
- ecc_result1 =
- yaffs_ecc_correct(data, spare->ecc1, calc_ecc);
- yaffs_ecc_calc(&data[256], calc_ecc);
- ecc_result2 =
- yaffs_ecc_correct(&data[256], spare->ecc2,
- calc_ecc);
-
- if (ecc_result1 > 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>yaffs ecc error fix performed on chunk %d:0",
- nand_chunk);
- dev->n_ecc_fixed++;
- } else if (ecc_result1 < 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>yaffs ecc error unfixed on chunk %d:0",
- nand_chunk);
- dev->n_ecc_unfixed++;
- }
-
- if (ecc_result2 > 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>yaffs ecc error fix performed on chunk %d:1",
- nand_chunk);
- dev->n_ecc_fixed++;
- } else if (ecc_result2 < 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>yaffs ecc error unfixed on chunk %d:1",
- nand_chunk);
- dev->n_ecc_unfixed++;
- }
-
- if (ecc_result1 || ecc_result2) {
- /* We had a data problem on this page */
- yaffs_handle_rd_data_error(dev, nand_chunk);
- }
-
- if (ecc_result1 < 0 || ecc_result2 < 0)
- *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
- else if (ecc_result1 > 0 || ecc_result2 > 0)
- *ecc_result = YAFFS_ECC_RESULT_FIXED;
- else
- *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
- }
- } else {
- /* Must allocate enough memory for spare+2*sizeof(int) */
- /* for ecc results from device. */
- struct yaffs_nand_spare nspare;
-
- memset(&nspare, 0, sizeof(nspare));
-
- ret_val = dev->param.read_chunk_fn(dev, nand_chunk, data,
- (struct yaffs_spare *)
- &nspare);
- memcpy(spare, &nspare, sizeof(struct yaffs_spare));
- if (data && correct_errors) {
- if (nspare.eccres1 > 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>mtd ecc error fix performed on chunk %d:0",
- nand_chunk);
- } else if (nspare.eccres1 < 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>mtd ecc error unfixed on chunk %d:0",
- nand_chunk);
- }
-
- if (nspare.eccres2 > 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>mtd ecc error fix performed on chunk %d:1",
- nand_chunk);
- } else if (nspare.eccres2 < 0) {
- yaffs_trace(YAFFS_TRACE_ERROR,
- "**>>mtd ecc error unfixed on chunk %d:1",
- nand_chunk);
- }
-
- if (nspare.eccres1 || nspare.eccres2) {
- /* We had a data problem on this page */
- yaffs_handle_rd_data_error(dev, nand_chunk);
- }
-
- if (nspare.eccres1 < 0 || nspare.eccres2 < 0)
- *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
- else if (nspare.eccres1 > 0 || nspare.eccres2 > 0)
- *ecc_result = YAFFS_ECC_RESULT_FIXED;
- else
- *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+ if (dev->param.use_nand_ecc)
+ return dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, data_size,
+ (u8 *) spare, spare_size,
+ ecc_result);
- }
+
+ /* Handle the ECC at this level. */
+
+ ret_val = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, data_size,
+ (u8 *)spare, spare_size,
+ NULL);
+ if (!data || !correct_errors)
+ return ret_val;
+
+ /* Do ECC correction if needed. */
+ yaffs_ecc_calc(data, calc_ecc);
+ ecc_result1 = yaffs_ecc_correct(data, spare->ecc1, calc_ecc);
+ yaffs_ecc_calc(&data[256], calc_ecc);
+ ecc_result2 = yaffs_ecc_correct(&data[256], spare->ecc2, calc_ecc);
+
+ if (ecc_result1 > 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error fix performed on chunk %d:0",
+ nand_chunk);
+ dev->n_ecc_fixed++;
+ } else if (ecc_result1 < 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error unfixed on chunk %d:0",
+ nand_chunk);
+ dev->n_ecc_unfixed++;
}
+
+ if (ecc_result2 > 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error fix performed on chunk %d:1",
+ nand_chunk);
+ dev->n_ecc_fixed++;
+ } else if (ecc_result2 < 0) {
+ yaffs_trace(YAFFS_TRACE_ERROR,
+ "**>>yaffs ecc error unfixed on chunk %d:1",
+ nand_chunk);
+ dev->n_ecc_unfixed++;
+ }
+
+ if (ecc_result1 || ecc_result2) {
+ /* We had a data problem on this page */
+ yaffs_handle_rd_data_error(dev, nand_chunk);
+ }
+
+ if (ecc_result1 < 0 || ecc_result2 < 0)
+ *ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ else if (ecc_result1 > 0 || ecc_result2 > 0)
+ *ecc_result = YAFFS_ECC_RESULT_FIXED;
+ else
+ *ecc_result = YAFFS_ECC_RESULT_NO_ERROR;
+
return ret_val;
}
*/
}
-int yaffs_tags_compat_wr(struct yaffs_dev *dev,
+static int yaffs_tags_compat_wr(struct yaffs_dev *dev,
int nand_chunk,
const u8 *data, const struct yaffs_ext_tags *ext_tags)
{
tags.serial_number = ext_tags->serial_number;
- if (!dev->param.use_nand_ecc && data)
- yaffs_calc_ecc(data, &spare);
+ if (!dev->param.use_nand_ecc && data) {
+ yaffs_ecc_calc(data, spare.ecc1);
+ yaffs_ecc_calc(&data[256], spare.ecc2);
+ }
yaffs_load_tags_to_spare(&spare, &tags);
}
return yaffs_wr_nand(dev, nand_chunk, data, &spare);
}
-int yaffs_tags_compat_rd(struct yaffs_dev *dev,
+static int yaffs_tags_compat_rd(struct yaffs_dev *dev,
int nand_chunk,
u8 *data, struct yaffs_ext_tags *ext_tags)
{
return YAFFS_OK;
}
-int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block)
+static int yaffs_tags_compat_mark_bad(struct yaffs_dev *dev, int flash_block)
{
struct yaffs_spare spare;
return YAFFS_OK;
}
-int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
+static int yaffs_tags_compat_query_block(struct yaffs_dev *dev,
int block_no,
enum yaffs_block_state *state,
u32 *seq_number)
*seq_number = 0;
- yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block, NULL,
- &spare0, &dummy, 1);
+ /* Look for bad block markers in the first two chunks */
+ yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block,
+ NULL, &spare0, &dummy, 0);
yaffs_rd_chunk_nand(dev, block_no * dev->param.chunks_per_block + 1,
- NULL, &spare1, &dummy, 1);
+ NULL, &spare1, &dummy, 0);
if (hweight8(spare0.block_status & spare1.block_status) < 7)
*state = YAFFS_BLOCK_STATE_DEAD;
return YAFFS_OK;
}
+
+void yaffs_tags_compat_install(struct yaffs_dev *dev)
+{
+ if(dev->param.is_yaffs2)
+ return;
+ if(!dev->tagger.write_chunk_tags_fn)
+ dev->tagger.write_chunk_tags_fn = yaffs_tags_compat_wr;
+ if(!dev->tagger.read_chunk_tags_fn)
+ dev->tagger.read_chunk_tags_fn = yaffs_tags_compat_rd;
+ if(!dev->tagger.query_block_fn)
+ dev->tagger.query_block_fn = yaffs_tags_compat_query_block;
+ if(!dev->tagger.mark_bad_fn)
+ dev->tagger.mark_bad_fn = yaffs_tags_compat_mark_bad;
+}
#ifndef __YAFFS_TAGSCOMPAT_H__
#define __YAFFS_TAGSCOMPAT_H__
+
#include "yaffs_guts.h"
+
+#if 0
+
+
int yaffs_tags_compat_wr(struct yaffs_dev *dev,
int nand_chunk,
const u8 *data, const struct yaffs_ext_tags *tags);
enum yaffs_block_state *state,
u32 *seq_number);
+#endif
+
+
+void yaffs_tags_compat_install(struct yaffs_dev *dev);
void yaffs_calc_tags_ecc(struct yaffs_tags *tags);
int yaffs_check_tags_ecc(struct yaffs_tags *tags);
-int yaffs_count_bits(u8 byte);
#endif
--- /dev/null
+/*
+ * YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
+ *
+ * Copyright (C) 2002-2011 Aleph One Ltd.
+ * for Toby Churchill Ltd and Brightstar Engineering
+ *
+ * Created by Charles Manning <charles@aleph1.co.uk>
+ *
+ * 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.
+ */
+
+#include "yaffs_guts.h"
+#include "yaffs_trace.h"
+#include "yaffs_packedtags2.h"
+
+static int yaffs_tags_marshall_write(struct yaffs_dev *dev,
+ int nand_chunk, const u8 *data,
+ const struct yaffs_ext_tags *tags)
+{
+ struct yaffs_packed_tags2 pt;
+ int retval;
+
+ int packed_tags_size =
+ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+ void *packed_tags_ptr =
+ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
+
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "yaffs_tags_marshall_write chunk %d data %p tags %p",
+ nand_chunk, data, tags);
+
+ /* For yaffs2 writing there must be both data and tags.
+ * If we're using inband tags, then the tags are stuffed into
+ * the end of the data buffer.
+ */
+ if (!data || !tags)
+ BUG();
+ else if (dev->param.inband_tags) {
+ struct yaffs_packed_tags2_tags_only *pt2tp;
+ pt2tp =
+ (struct yaffs_packed_tags2_tags_only *)(data +
+ dev->
+ data_bytes_per_chunk);
+ yaffs_pack_tags2_tags_only(pt2tp, tags);
+ } else {
+ yaffs_pack_tags2(&pt, tags, !dev->param.no_tags_ecc);
+ }
+
+ retval = dev->drv.drv_write_chunk_fn(dev, nand_chunk,
+ data, dev->param.total_bytes_per_chunk,
+ (dev->param.inband_tags) ? NULL : packed_tags_ptr,
+ (dev->param.inband_tags) ? 0 : packed_tags_size);
+
+ return retval;
+}
+
+static int yaffs_tags_marshall_read(struct yaffs_dev *dev,
+ int nand_chunk, u8 *data,
+ struct yaffs_ext_tags *tags)
+{
+ int retval = 0;
+ int local_data = 0;
+ u8 spare_buffer[100];
+ enum yaffs_ecc_result ecc_result;
+
+ struct yaffs_packed_tags2 pt;
+
+ int packed_tags_size =
+ dev->param.no_tags_ecc ? sizeof(pt.t) : sizeof(pt);
+ void *packed_tags_ptr =
+ dev->param.no_tags_ecc ? (void *)&pt.t : (void *)&pt;
+
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "yaffs_tags_marshall_read chunk %d data %p tags %p",
+ nand_chunk, data, tags);
+
+ if (dev->param.inband_tags) {
+ if (!data) {
+ local_data = 1;
+ data = yaffs_get_temp_buffer(dev);
+ }
+ }
+
+ if (dev->param.inband_tags || (data && !tags))
+ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, dev->param.total_bytes_per_chunk,
+ NULL, 0,
+ &ecc_result);
+ else if (tags)
+ retval = dev->drv.drv_read_chunk_fn(dev, nand_chunk,
+ data, dev->param.total_bytes_per_chunk,
+ spare_buffer, packed_tags_size,
+ &ecc_result);
+ else
+ BUG();
+
+
+ if (dev->param.inband_tags) {
+ if (tags) {
+ struct yaffs_packed_tags2_tags_only *pt2tp;
+ pt2tp =
+ (struct yaffs_packed_tags2_tags_only *)
+ &data[dev->data_bytes_per_chunk];
+ yaffs_unpack_tags2_tags_only(tags, pt2tp);
+ }
+ } else if (tags) {
+ memcpy(packed_tags_ptr, spare_buffer, packed_tags_size);
+ yaffs_unpack_tags2(tags, &pt, !dev->param.no_tags_ecc);
+ }
+
+ if (local_data)
+ yaffs_release_temp_buffer(dev, data);
+
+ if (tags && ecc_result == YAFFS_ECC_RESULT_UNFIXED) {
+ tags->ecc_result = YAFFS_ECC_RESULT_UNFIXED;
+ dev->n_ecc_unfixed++;
+ }
+
+ if (tags && ecc_result == -YAFFS_ECC_RESULT_FIXED) {
+ if (tags->ecc_result <= YAFFS_ECC_RESULT_NO_ERROR)
+ tags->ecc_result = YAFFS_ECC_RESULT_FIXED;
+ dev->n_ecc_fixed++;
+ }
+
+ if (ecc_result < YAFFS_ECC_RESULT_UNFIXED)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+static int yaffs_tags_marshall_query_block(struct yaffs_dev *dev, int block_no,
+ enum yaffs_block_state *state,
+ u32 *seq_number)
+{
+ int retval;
+
+ yaffs_trace(YAFFS_TRACE_MTD, "yaffs_tags_marshall_query_block %d",
+ block_no);
+
+ retval = dev->drv.drv_check_bad_fn(dev, block_no);
+
+ if (retval== YAFFS_FAIL) {
+ yaffs_trace(YAFFS_TRACE_MTD, "block is bad");
+
+ *state = YAFFS_BLOCK_STATE_DEAD;
+ *seq_number = 0;
+ } else {
+ struct yaffs_ext_tags t;
+
+ yaffs_tags_marshall_read(dev,
+ block_no * dev->param.chunks_per_block,
+ NULL, &t);
+
+ if (t.chunk_used) {
+ *seq_number = t.seq_number;
+ *state = YAFFS_BLOCK_STATE_NEEDS_SCAN;
+ } else {
+ *seq_number = 0;
+ *state = YAFFS_BLOCK_STATE_EMPTY;
+ }
+ }
+
+ yaffs_trace(YAFFS_TRACE_MTD,
+ "block query returns seq %d state %d",
+ *seq_number, *state);
+
+ if (retval == 0)
+ return YAFFS_OK;
+ else
+ return YAFFS_FAIL;
+}
+
+static int yaffs_tags_marshall_mark_bad(struct yaffs_dev *dev, int block_no)
+{
+ return dev->drv.drv_mark_bad_fn(dev, block_no);
+
+}
+
+
+void yaffs_tags_marshall_install(struct yaffs_dev *dev)
+{
+ if (!dev->param.is_yaffs2)
+ return;
+
+ if (!dev->tagger.write_chunk_tags_fn)
+ dev->tagger.write_chunk_tags_fn = yaffs_tags_marshall_write;
+
+ if (!dev->tagger.read_chunk_tags_fn)
+ dev->tagger.read_chunk_tags_fn = yaffs_tags_marshall_read;
+
+ if (!dev->tagger.query_block_fn)
+ dev->tagger.query_block_fn = yaffs_tags_marshall_query_block;
+
+ if (!dev->tagger.mark_bad_fn)
+ dev->tagger.mark_bad_fn = yaffs_tags_marshall_mark_bad;
+
+}
/*
- * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
+ * YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2011 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
* Note: Only YAFFS headers are LGPL, YAFFS C code is covered by GPL.
*/
-#ifndef __Y_NORSIM_H__
-#define __Y_NORSIM_H__
+#ifndef __YAFFS_TAGSMARSHALL_H__
+#define __YAFFS_TAGSMARSHALL_H__
#include "yaffs_guts.h"
-
-void ynorsim_rd32(u32 *addr, u32 *data, int nwords);
-void ynorsim_wr32(u32 *addr, u32 *data, int nwords);
-void ynorsim_erase(u32 *addr);
-void ynorsim_shutdown(void);
-void ynorsim_initialise(void);
-u32 * ynorsim_get_base(void);
+void yaffs_tags_marshall_install(struct yaffs_dev *dev);
#endif
#include "yaffs_linux.h"
#include "yaffs_mtdif.h"
-#include "yaffs_mtdif1.h"
-#include "yaffs_mtdif2.h"
unsigned int yaffs_trace_mask = YAFFS_TRACE_BAD_BLOCKS | YAFFS_TRACE_ALWAYS;
unsigned int yaffs_wr_attempts = YAFFS_WR_ATTEMPTS;
static void yaffs_put_super(struct super_block *sb)
{
struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
- yaffs_trace(YAFFS_TRACE_OS, "yaffs_put_super");
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
+ "yaffs_put_super");
yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_BACKGROUND,
"Shutting down yaffs background thread");
yaffs_flush_super(sb, 1);
- if (yaffs_dev_to_lc(dev)->put_super_fn)
- yaffs_dev_to_lc(dev)->put_super_fn(sb);
-
yaffs_deinitialise(dev);
yaffs_gross_unlock(dev);
}
kfree(dev);
-}
-
-static void yaffs_mtd_put_super(struct super_block *sb)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(yaffs_super_to_dev(sb));
- if (mtd->sync)
+ if (mtd && mtd->sync)
mtd->sync(mtd);
- put_mtd_device(mtd);
+ if(mtd)
+ put_mtd_device(mtd);
+
+ yaffs_trace(YAFFS_TRACE_OS | YAFFS_TRACE_ALWAYS,
+ "yaffs_put_super done");
}
+
static void yaffs_touch_super(struct yaffs_dev *dev)
{
struct super_block *sb = yaffs_dev_to_lc(dev)->super;
/* Set up the memory size parameters.... */
- n_blocks =
- YCALCBLOCKS(mtd->size,
- (YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK));
- param->start_block = 0;
- param->end_block = n_blocks - 1;
- param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
- param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
param->n_reserved_blocks = 5;
param->n_caches = (options.no_cache) ? 0 : 10;
param->inband_tags = options.inband_tags;
/* ... and the functions. */
if (yaffs_version == 2) {
- param->write_chunk_tags_fn = nandmtd2_write_chunk_tags;
- param->read_chunk_tags_fn = nandmtd2_read_chunk_tags;
- param->bad_block_fn = nandmtd2_mark_block_bad;
- param->query_block_fn = nandmtd2_query_block;
- yaffs_dev_to_lc(dev)->spare_buffer =
- kmalloc(mtd->oobsize, GFP_NOFS);
param->is_yaffs2 = 1;
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
param->total_bytes_per_chunk = mtd->writesize;
param->start_block = 0;
param->end_block = n_blocks - 1;
} else {
-#if (LINUX_VERSION_CODE > KERNEL_VERSION(2, 6, 17))
- /* use the MTD interface in yaffs_mtdif1.c */
- param->write_chunk_tags_fn = nandmtd1_write_chunk_tags;
- param->read_chunk_tags_fn = nandmtd1_read_chunk_tags;
- param->bad_block_fn = nandmtd1_mark_block_bad;
- param->query_block_fn = nandmtd1_query_block;
-#else
- param->write_chunk_fn = nandmtd_write_chunk;
- param->read_chunk_fn = nandmtd_read_chunk;
-#endif
param->is_yaffs2 = 0;
+ n_blocks = YCALCBLOCKS(mtd->size,
+ YAFFS_CHUNKS_PER_BLOCK * YAFFS_BYTES_PER_CHUNK);
+
+ param->chunks_per_block = YAFFS_CHUNKS_PER_BLOCK;
+ param->total_bytes_per_chunk = YAFFS_BYTES_PER_CHUNK;
}
- /* ... and common functions */
- param->erase_fn = nandmtd_erase_block;
- param->initialise_flash_fn = nandmtd_initialise;
- yaffs_dev_to_lc(dev)->put_super_fn = yaffs_mtd_put_super;
+ param->start_block = 0;
+ param->end_block = n_blocks - 1;
+
+ yaffs_mtd_drv_install(dev);
param->sb_dirty_fn = yaffs_touch_super;
- param->gc_control = yaffs_gc_control_callback;
+ param->gc_control_fn = yaffs_gc_control_callback;
yaffs_dev_to_lc(dev)->super = sb;
static void yaffs_put_super(struct super_block *sb)
{
struct yaffs_dev *dev = yaffs_super_to_dev(sb);
+ struct mtd_info *mtd = yaffs_dev_to_mtd(dev);
yaffs_trace(YAFFS_TRACE_OS, "yaffs_put_super");
}
kfree(dev);
-}
-static void yaffs_mtd_put_super(struct super_block *sb)
-{
- struct mtd_info *mtd = yaffs_dev_to_mtd(yaffs_super_to_dev(sb));
- if (mtd->sync)
+
+ if (mtd && mtd->sync)
mtd->sync(mtd);
- put_mtd_device(mtd);
+ if (mtd)
+ put_mtd_device(mtd);
}
static const struct super_operations yaffs_super_ops = {
yaffs_dev_to_lc(dev)->put_super_fn = yaffs_mtd_put_super;
param->sb_dirty_fn = yaffs_touch_super;
- param->gc_control = yaffs_gc_control_callback;
+ param->gc_control_fn = yaffs_gc_control_callback;
yaffs_dev_to_lc(dev)->super = sb;