Clean out unneeded files

Signed-off-by: William Juul <william.juul@tandberg.com>
master
William Juul 16 years ago committed by Scott Wood
parent ec29a32b5a
commit 98824ce3f9
  1. 176
      fs/yaffs2/Kconfig
  2. 40
      fs/yaffs2/Makefile
  3. 10
      fs/yaffs2/Makefile.kernel
  4. 20
      fs/yaffs2/README-linux-patch
  5. 2282
      fs/yaffs2/direct/dtest.c
  6. 75
      fs/yaffs2/direct/fsx_test/Makefile
  7. 7
      fs/yaffs2/direct/fsx_test/README
  8. 1007
      fs/yaffs2/direct/fsx_test/yaffs_fsx.c
  9. 219
      fs/yaffs2/direct/yaffs_fileem.c
  10. 443
      fs/yaffs2/direct/yaffs_fileem2k.c
  11. 50
      fs/yaffs2/direct/yaffs_fileem2k.h
  12. 230
      fs/yaffs2/direct/yaffs_flashif.c
  13. 235
      fs/yaffs2/direct/yaffs_ramdisk.c
  14. 364
      fs/yaffs2/direct/yaffs_ramem2k.c
  15. 231
      fs/yaffs2/direct/yaffscfg2k.c
  16. 65
      fs/yaffs2/moduleconfig.h
  17. 33
      fs/yaffs2/mtdemul/Makefile
  18. 714
      fs/yaffs2/mtdemul/nandemul2k.c
  19. 121
      fs/yaffs2/patch-ker.sh
  20. 6
      fs/yaffs2/patches/README.txt
  21. 258
      fs/yaffs2/patches/yaffs_mtdif2.c
  22. 54
      fs/yaffs2/utils/Makefile
  23. 520
      fs/yaffs2/utils/mkyaffs2image.c
  24. 590
      fs/yaffs2/utils/mkyaffsimage.c
  25. 2299
      fs/yaffs2/yaffs_fs.c
  26. 369
      fs/yaffs2/yaffs_mtdif1.c
  27. 28
      fs/yaffs2/yaffs_mtdif1.h

@ -1,176 +0,0 @@
#
# YAFFS file system configurations
#
config YAFFS_FS
tristate "YAFFS2 file system support"
default n
depends on MTD
select YAFFS_YAFFS1
select YAFFS_YAFFS2
help
YAFFS2, or Yet Another Flash Filing System, is a filing system
optimised for NAND Flash chips.
To compile the YAFFS2 file system support as a module, choose M
here: the module will be called yaffs2.
If unsure, say N.
Further information on YAFFS2 is available at
<http://www.aleph1.co.uk/yaffs/>.
config YAFFS_YAFFS1
bool "512 byte / page devices"
depends on YAFFS_FS
default y
help
Enable YAFFS1 support -- yaffs for 512 byte / page devices
Not needed for 2K-page devices.
If unsure, say Y.
config YAFFS_9BYTE_TAGS
bool "Use older-style on-NAND data format with pageStatus byte"
depends on YAFFS_YAFFS1
default n
help
Older-style on-NAND data format has a "pageStatus" byte to record
chunk/page state. This byte is zero when the page is discarded.
Choose this option if you have existing on-NAND data using this
format that you need to continue to support. New data written
also uses the older-style format. Note: Use of this option
generally requires that MTD's oob layout be adjusted to use the
older-style format. See notes on tags formats and MTD versions
in yaffs_mtdif1.c.
If unsure, say N.
config YAFFS_DOES_ECC
bool "Lets Yaffs do its own ECC"
depends on YAFFS_FS && YAFFS_YAFFS1 && !YAFFS_9BYTE_TAGS
default n
help
This enables Yaffs to use its own ECC functions instead of using
the ones from the generic MTD-NAND driver.
If unsure, say N.
config YAFFS_ECC_WRONG_ORDER
bool "Use the same ecc byte order as Steven Hill's nand_ecc.c"
depends on YAFFS_FS && YAFFS_DOES_ECC && !YAFFS_9BYTE_TAGS
default n
help
This makes yaffs_ecc.c use the same ecc byte order as Steven
Hill's nand_ecc.c. If not set, then you get the same ecc byte
order as SmartMedia.
If unsure, say N.
config YAFFS_YAFFS2
bool "2048 byte (or larger) / page devices"
depends on YAFFS_FS
default y
help
Enable YAFFS2 support -- yaffs for >= 2K bytes per page devices
If unsure, say Y.
config YAFFS_AUTO_YAFFS2
bool "Autoselect yaffs2 format"
depends on YAFFS_YAFFS2
default y
help
Without this, you need to explicitely use yaffs2 as the file
system type. With this, you can say "yaffs" and yaffs or yaffs2
will be used depending on the device page size (yaffs on
512-byte page devices, yaffs2 on 2K page devices).
If unsure, say Y.
config YAFFS_DISABLE_LAZY_LOAD
bool "Disable lazy loading"
depends on YAFFS_YAFFS2
default n
help
"Lazy loading" defers loading file details until they are
required. This saves mount time, but makes the first look-up
a bit longer.
Lazy loading will only happen if enabled by this option being 'n'
and if the appropriate tags are available, else yaffs2 will
automatically fall back to immediate loading and do the right
thing.
Lazy laoding will be required by checkpointing.
Setting this to 'y' will disable lazy loading.
If unsure, say N.
config YAFFS_CHECKPOINT_RESERVED_BLOCKS
int "Reserved blocks for checkpointing"
depends on YAFFS_YAFFS2
default 10
help
Give the number of Blocks to reserve for checkpointing.
Checkpointing saves the state at unmount so that mounting is
much faster as a scan of all the flash to regenerate this state
is not needed. These Blocks are reserved per partition, so if
you have very small partitions the default (10) may be a mess
for you. You can set this value to 0, but that does not mean
checkpointing is disabled at all. There only won't be any
specially reserved blocks for checkpointing, so if there is
enough free space on the filesystem, it will be used for
checkpointing.
If unsure, leave at default (10), but don't wonder if there are
always 2MB used on your large page device partition (10 x 2k
pagesize). When using small partitions or when being very small
on space, you probably want to set this to zero.
config YAFFS_DISABLE_WIDE_TNODES
bool "Turn off wide tnodes"
depends on YAFFS_FS
default n
help
Wide tnodes are only used for NAND arrays >=32MB for 512-byte
page devices and >=128MB for 2k page devices. They use slightly
more RAM but are faster since they eliminate chunk group
searching.
Setting this to 'y' will force tnode width to 16 bits and save
memory but make large arrays slower.
If unsure, say N.
config YAFFS_ALWAYS_CHECK_CHUNK_ERASED
bool "Force chunk erase check"
depends on YAFFS_FS
default n
help
Normally YAFFS only checks chunks before writing until an erased
chunk is found. This helps to detect any partially written
chunks that might have happened due to power loss.
Enabling this forces on the test that chunks are erased in flash
before writing to them. This takes more time but is potentially
a bit more secure.
Suggest setting Y during development and ironing out driver
issues etc. Suggest setting to N if you want faster writing.
If unsure, say Y.
config YAFFS_SHORT_NAMES_IN_RAM
bool "Cache short names in RAM"
depends on YAFFS_FS
default y
help
If this config is set, then short names are stored with the
yaffs_Object. This costs an extra 16 bytes of RAM per object,
but makes look-ups faster.
If unsure, say Y.

@ -1,40 +0,0 @@
# Main Makefile for YAFFS
#
#
# YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
#
# Copyright (C) 2002-2007 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.
ifneq ($(KERNELRELEASE),)
EXTRA_CFLAGS += -DYAFFS_OUT_OF_TREE
obj-m := yaffs2.o
yaffs2-objs := yaffs_mtdif.o yaffs_mtdif2.o
yaffs2-objs += yaffs_mtdif1.o yaffs_packedtags1.o
yaffs2-objs += yaffs_ecc.o yaffs_fs.o yaffs_guts.o
yaffs2-objs += yaffs_packedtags2.o yaffs_qsort.o
yaffs2-objs += yaffs_tagscompat.o yaffs_tagsvalidity.o
yaffs2-objs += yaffs_checkptrw.o yaffs_nand.o
else
KERNELDIR ?= /lib/modules/$(shell uname -r)/build
PWD := $(shell pwd)
modules default:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules
mi modules_install:
$(MAKE) -C $(KERNELDIR) M=$(PWD) modules_install
clean:
$(MAKE) -C $(KERNELDIR) M=$(PWD) clean
endif

@ -1,10 +0,0 @@
#
# Makefile for the linux YAFFS filesystem routines.
#
obj-$(CONFIG_YAFFS_FS) += yaffs.o
yaffs-y := yaffs_ecc.o yaffs_fs.o yaffs_guts.o yaffs_checkptrw.o
yaffs-y += yaffs_packedtags1.o yaffs_packedtags2.o yaffs_nand.o yaffs_qsort.o
yaffs-y += yaffs_tagscompat.o yaffs_tagsvalidity.o
yaffs-y += yaffs_mtdif.o yaffs_mtdif1.o yaffs_mtdif2.o

@ -1,20 +0,0 @@
To build YAFFS in the Linux kernel tree you need to run the patch-ker.sh
script from the yaffs source directory, giving your choice as to whether
you wish to copy (c) or link (l) the code and the path to your kernel
sources, e.g:
./patch-ker.sh c /usr/src/linux
This will copy the yaffs files into fs/yaffs2 and modify the Kconfig
and Makefiles in the fs directory.
./patch-ker.sh l /usr/src/linux
This does the same as the above but makes symbolic links instead.
After you've run the script, go back to your normal kernel making procedure
and configure the yaffs settings you want.
Prolems? Contact the yaffs mailing list:
http://www.aleph1.co.uk/mailman/listinfo/yaffs

File diff suppressed because it is too large Load Diff

@ -1,75 +0,0 @@
# Makefile for YAFFS direct test
#
#
# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
#
# Copyright (C) 2003 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.1 2007/10/16 00:46:33 charles Exp $
#EXTRA_COMPILE_FLAGS = -DYAFFS_IGNORE_TAGS_ECC
CFLAGS = -Wall -DCONFIG_YAFFS_DIRECT -DCONFIG_YAFFS_SHORT_NAMES_IN_RAM -DCONFIG_YAFFS_YAFFS2 -g $(EXTRA_COMPILE_FLAGS) -DNO_Y_INLINE
CFLAGS+= -fstack-check -O0
#CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
#CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
FSXTESTOBJS = yaffs_fsx.o yaffscfg2k.o yaffs_ecc.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_tagsvalidity.o yaffs_nand.o \
yaffs_checkptrw.o yaffs_qsort.o \
# yaffs_checkptrwtest.o\
BOOTTESTOBJS = bootldtst.o yboot.o yaffs_fileem.o nand_ecc.o
#ALLOBJS = dtest.o nand_ecc.o yaffscfg.o yaffs_fileem.o yaffsfs.o yaffs_ramdisk.o bootldtst.o yboot.o yaffs_ramem2k.o
ALLOBJS = $(FSXTESTOBJS) $(BOOTTESTOBJS)
YAFFSSYMLINKS = devextras.h yaffs_ecc.c yaffs_ecc.h yaffs_guts.c yaffs_guts.h yaffsinterface.h yportenv.h yaffs_tagscompat.c yaffs_tagscompat.h \
yaffs_packedtags1.c yaffs_packedtags1.h yaffs_packedtags2.c yaffs_packedtags2.h yaffs_nandemul2k.h \
yaffs_nand.c yaffs_nand.h \
yaffs_tagsvalidity.c yaffs_tagsvalidity.h yaffs_checkptrw.h yaffs_checkptrw.c \
yaffs_qsort.c yaffs_qsort.h
YAFFSDIRECTSYMLINKS = yaffscfg2k.c yaffs_fileem2k.c yaffsfs.c yaffs_flashif.h \
yaffs_fileem2k.h yaffsfs.h yaffs_malloc.h yaffs_ramdisk.h ydirectenv.h \
yaffscfg.h yaffs_fileem.c yaffs_flashif.c yaffs_ramdisk.c yaffs_ramem2k.c
#all: fsxtest boottest
all: fsxtest
$(ALLOBJS): %.o: %.c
gcc -c $(CFLAGS) $< -o $@
$(YAFFSSYMLINKS):
ln -s ../../$@ $@
$(YAFFSDIRECTSYMLINKS):
ln -s ../$@ $@
fsxtest: $(YAFFSSYMLINKS) $(YAFFSDIRECTSYMLINKS) $(FSXTESTOBJS)
gcc -o $@ $(FSXTESTOBJS)
boottest: $(SYMLINKS) $(BOOTTESTOBJS)
gcc -o $@ $(BOOTTESTOBJS)
clean:
rm -f $(ALLOBJS) core

@ -1,7 +0,0 @@
NB THis directory uses a hacked version of fsx.c which is released under
Apple Public Source License.
From what I have been able to determine, it is legally OK to release a hacked
version for the purposes of testing.
If anyone knows otherwise, please contact me: manningc2@actrix.gen.nz

File diff suppressed because it is too large Load Diff

@ -1,219 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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.
* This is only intended as test code to test persistence etc.
*/
/* XXX U-BOOT XXX */
#include <common.h>
const char *yaffs_flashif_c_version = "$Id: yaffs_fileem.c,v 1.3 2007/02/14 01:09:06 wookey Exp $";
#include "yportenv.h"
#include "yaffs_flashif.h"
#include "yaffs_guts.h"
#include "devextras.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#define SIZE_IN_MB 16
#define BLOCK_SIZE (32 * 528)
#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512))
typedef struct
{
__u8 data[528]; // Data + spare
} yflash_Page;
typedef struct
{
yflash_Page page[32]; // The pages in the block
} yflash_Block;
typedef struct
{
int handle;
int nBlocks;
} yflash_Device;
static yflash_Device filedisk;
static int CheckInit(yaffs_Device *dev)
{
static int initialised = 0;
int i;
int fSize;
int written;
yflash_Page p;
if(initialised)
{
return YAFFS_OK;
}
initialised = 1;
filedisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024);
filedisk.handle = open("yaffsemfile", O_RDWR | O_CREAT, S_IREAD | S_IWRITE);
if(filedisk.handle < 0)
{
perror("Failed to open yaffs emulation file");
return YAFFS_FAIL;
}
fSize = lseek(filedisk.handle,0,SEEK_END);
if(fSize < SIZE_IN_MB * 1024 * 1024)
{
printf("Creating yaffs emulation file\n");
lseek(filedisk.handle,0,SEEK_SET);
memset(&p,0xff,sizeof(yflash_Page));
for(i = 0; i < SIZE_IN_MB * 1024 * 1024; i+= 512)
{
written = write(filedisk.handle,&p,sizeof(yflash_Page));
if(written != sizeof(yflash_Page))
{
printf("Write failed\n");
return YAFFS_FAIL;
}
}
}
return 1;
}
int yflash_WriteChunkToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_Spare *spare)
{
int written;
CheckInit(dev);
if(data)
{
lseek(filedisk.handle,chunkInNAND * 528,SEEK_SET);
written = write(filedisk.handle,data,512);
if(written != 512) return YAFFS_FAIL;
}
if(spare)
{
lseek(filedisk.handle,chunkInNAND * 528 + 512,SEEK_SET);
written = write(filedisk.handle,spare,16);
if(written != 16) return YAFFS_FAIL;
}
return YAFFS_OK;
}
int yflash_ReadChunkFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Spare *spare)
{
int nread;
CheckInit(dev);
if(data)
{
lseek(filedisk.handle,chunkInNAND * 528,SEEK_SET);
nread = read(filedisk.handle,data,512);
if(nread != 512) return YAFFS_FAIL;
}
if(spare)
{
lseek(filedisk.handle,chunkInNAND * 528 + 512,SEEK_SET);
nread= read(filedisk.handle,spare,16);
if(nread != 16) return YAFFS_FAIL;
}
return YAFFS_OK;
}
int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
{
int i;
CheckInit(dev);
if(blockNumber < 0 || blockNumber >= filedisk.nBlocks)
{
T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
return YAFFS_FAIL;
}
else
{
yflash_Page pg;
memset(&pg,0xff,sizeof(yflash_Page));
lseek(filedisk.handle, blockNumber * 32 * 528, SEEK_SET);
for(i = 0; i < 32; i++)
{
write(filedisk.handle,&pg,528);
}
return YAFFS_OK;
}
}
int yflash_InitialiseNAND(yaffs_Device *dev)
{
dev->useNANDECC = 1; // force on useNANDECC which gets faked.
// This saves us doing ECC checks.
return YAFFS_OK;
}

@ -1,443 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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.
*/
/* XXX U-BOOT XXX */
#include <common.h>
const char *yaffs_flashif_c_version = "$Id: yaffs_fileem2k.c,v 1.12 2007/02/14 01:09:06 wookey Exp $";
#include "yportenv.h"
#include "yaffs_flashif.h"
#include "yaffs_guts.h"
#include "devextras.h"
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <unistd.h>
#include "yaffs_fileem2k.h"
#include "yaffs_packedtags2.h"
//#define SIMULATE_FAILURES
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 8000
typedef struct
{
int handle[MAX_HANDLES];
int nBlocks;
} yflash_Device;
static yflash_Device filedisk;
int yaffs_testPartialWrite = 0;
static __u8 localBuffer[PAGE_SIZE];
static char *NToName(char *buf,int n)
{
sprintf(buf,"emfile%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 h;
int i;
off_t fSize;
off_t requiredSize;
int written;
int blk;
yflash_Page p;
if(initialised)
{
return YAFFS_OK;
}
initialised = 1;
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 yflash_GetNumberOfBlocks(void)
{
CheckInit();
return filedisk.nBlocks;
}
int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
{
int written;
int pos;
int h;
int i;
int nRead;
int error;
T(YAFFS_TRACE_MTD,(TSTR("write chunk %d data %x tags %x" TENDSTR),chunkInNAND,(unsigned)data, (unsigned)tags));
CheckInit();
if(data)
{
pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
lseek(h,pos,SEEK_SET);
nRead = read(h, localBuffer,dev->nDataBytesPerChunk);
for(i = error = 0; i < dev->nDataBytesPerChunk && !error; i++){
if(localBuffer[i] != 0xFF){
printf("nand simulation: chunk %d data byte %d was %0x2\n",
chunkInNAND,i,localBuffer[i]);
error = 1;
}
}
for(i = 0; i < dev->nDataBytesPerChunk; i++)
localBuffer[i] &= data[i];
if(memcmp(localBuffer,data,dev->nDataBytesPerChunk))
printf("nand simulator: data does not match\n");
lseek(h,pos,SEEK_SET);
written = write(h,localBuffer,dev->nDataBytesPerChunk);
if(yaffs_testPartialWrite){
close(h);
exit(1);
}
#ifdef SIMULATE_FAILURES
if((chunkInNAND >> 6) == 100)
written = 0;
if((chunkInNAND >> 6) == 110)
written = 0;
#endif
if(written != dev->nDataBytesPerChunk) return YAFFS_FAIL;
}
if(tags)
{
pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE ;
h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
lseek(h,pos,SEEK_SET);
if( 0 && dev->isYaffs2)
{
written = write(h,tags,sizeof(yaffs_ExtendedTags));
if(written != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
}
else
{
yaffs_PackedTags2 pt;
yaffs_PackTags2(&pt,tags);
__u8 * ptab = (__u8 *)&pt;
nRead = read(h,localBuffer,sizeof(pt));
for(i = error = 0; i < sizeof(pt) && !error; i++){
if(localBuffer[i] != 0xFF){
printf("nand simulation: chunk %d oob byte %d was %0x2\n",
chunkInNAND,i,localBuffer[i]);
error = 1;
}
}
for(i = 0; i < sizeof(pt); i++)
localBuffer[i] &= ptab[i];
if(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;
}
}
return YAFFS_OK;
}
int yaffs_CheckAllFF(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 yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
{
int nread;
int pos;
int h;
T(YAFFS_TRACE_MTD,(TSTR("read chunk %d data %x tags %x" TENDSTR),chunkInNAND,(unsigned)data, (unsigned)tags));
CheckInit();
if(data)
{
pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE;
h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
lseek(h,pos,SEEK_SET);
nread = read(h,data,dev->nDataBytesPerChunk);
if(nread != dev->nDataBytesPerChunk) return YAFFS_FAIL;
}
if(tags)
{
pos = (chunkInNAND % (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE)) * PAGE_SIZE + PAGE_DATA_SIZE;
h = filedisk.handle[(chunkInNAND / (PAGES_PER_BLOCK * BLOCKS_PER_HANDLE))];
lseek(h,pos,SEEK_SET);
if(0 && dev->isYaffs2)
{
nread= read(h,tags,sizeof(yaffs_ExtendedTags));
if(nread != sizeof(yaffs_ExtendedTags)) return YAFFS_FAIL;
if(yaffs_CheckAllFF((__u8 *)tags,sizeof(yaffs_ExtendedTags)))
{
yaffs_InitialiseTags(tags);
}
else
{
tags->chunkUsed = 1;
}
}
else
{
yaffs_PackedTags2 pt;
nread= read(h,&pt,sizeof(pt));
yaffs_UnpackTags2(tags,&pt);
#ifdef SIMULATE_FAILURES
if((chunkInNAND >> 6) == 100) {
if(fail300 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
tags->eccResult = YAFFS_ECC_RESULT_FIXED;
fail300 = 0;
}
}
if((chunkInNAND >> 6) == 110) {
if(fail320 && tags->eccResult == YAFFS_ECC_RESULT_NO_ERROR){
tags->eccResult = YAFFS_ECC_RESULT_FIXED;
fail320 = 0;
}
}
#endif
if(failRead10>0 && chunkInNAND == 10){
failRead10--;
nread = 0;
}
if(nread != sizeof(pt)) return YAFFS_FAIL;
}
}
return YAFFS_OK;
}
int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
int written;
int h;
yaffs_PackedTags2 pt;
CheckInit();
memset(&pt,0,sizeof(pt));
h = filedisk.handle[(blockNo / ( BLOCKS_PER_HANDLE))];
lseek(h,((blockNo % BLOCKS_PER_HANDLE) * dev->nChunksPerBlock) * PAGE_SIZE + PAGE_DATA_SIZE,SEEK_SET);
written = write(h,&pt,sizeof(pt));
if(written != sizeof(pt)) return YAFFS_FAIL;
return YAFFS_OK;
}
int yflash_EraseBlockInNAND(yaffs_Device *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)
{
T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",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->nChunksPerBlock) * PAGE_SIZE,SEEK_SET);
for(i = 0; i < dev->nChunksPerBlock; i++)
{
write(h,pg,PAGE_SIZE);
}
pos = lseek(h, 0,SEEK_CUR);
return YAFFS_OK;
}
}
int yflash_InitialiseNAND(yaffs_Device *dev)
{
CheckInit();
return YAFFS_OK;
}
int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
{
yaffs_ExtendedTags tags;
int chunkNo;
*sequenceNumber = 0;
chunkNo = blockNo * dev->nChunksPerBlock;
yflash_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
if(tags.blockBad)
{
*state = YAFFS_BLOCK_STATE_DEAD;
}
else if(!tags.chunkUsed)
{
*state = YAFFS_BLOCK_STATE_EMPTY;
}
else if(tags.chunkUsed)
{
*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
*sequenceNumber = tags.sequenceNumber;
}
return YAFFS_OK;
}

@ -1,50 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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 128
//#define SIZE_IN_MB 8000
#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 yflash_GetNumberOfBlocks(void);
#endif

@ -1,230 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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.
*/
/* XXX U-BOOT XXX */
#include <common.h>
const char *yaffs_flashif_c_version = "$Id: yaffs_flashif.c,v 1.3 2007/02/14 01:09:06 wookey Exp $";
#include "yportenv.h"
#include "yaffs_flashif.h"
#include "yaffs_guts.h"
#include "devextras.h"
#define SIZE_IN_MB 16
#define BLOCK_SIZE (32 * 528)
#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512))
typedef struct
{
__u8 data[528]; // Data + spare
} yflash_Page;
typedef struct
{
yflash_Page page[32]; // The pages in the block
} yflash_Block;
typedef struct
{
yflash_Block **block;
int nBlocks;
} yflash_Device;
static yflash_Device ramdisk;
static int CheckInit(yaffs_Device *dev)
{
static int initialised = 0;
int i;
int fail = 0;
int nAllocated = 0;
if(initialised)
{
return YAFFS_OK;
}
initialised = 1;
ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024);
ramdisk.block = YMALLOC(sizeof(yflash_Block *) * ramdisk.nBlocks);
if(!ramdisk.block) return 0;
for(i=0; i <ramdisk.nBlocks; i++)
{
ramdisk.block[i] = NULL;
}
for(i=0; i <ramdisk.nBlocks && !fail; i++)
{
if((ramdisk.block[i] = YMALLOC(sizeof(yflash_Block))) == 0)
{
fail = 1;
}
else
{
yflash_EraseBlockInNAND(dev,i);
nAllocated++;
}
}
if(fail)
{
for(i = 0; i < nAllocated; i++)
{
YFREE(ramdisk.block[i]);
}
YFREE(ramdisk.block);
T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n",
nAllocated/64,ramdisk.nBlocks * YAFFS_BYTES_PER_BLOCK));
return 0;
}
return 1;
}
int yflash_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
{
int blk;
int pg;
CheckInit(dev);
blk = chunkInNAND/32;
pg = chunkInNAND%32;
if(data)
{
memcpy(ramdisk.block[blk]->page[pg].data,data,512);
}
if(tags)
{
yaffs_PackedTags pt;
yaffs_PackTags(&pt,tags);
memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt));
}
return YAFFS_OK;
}
int yflash_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_Tags *tags)
{
int blk;
int pg;
CheckInit(dev);
blk = chunkInNAND/32;
pg = chunkInNAND%32;
if(data)
{
memcpy(data,ramdisk.block[blk]->page[pg].data,512);
}
if(tags)
{
yaffs_PackedTags pt;
memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(yaffs_PackedTags));
yaffs_UnpackTags(tags,&pt);
}
return YAFFS_OK;
}
int yflash_CheckChunkErased(yaffs_Device *dev,int chunkInNAND)
{
int blk;
int pg;
int i;
CheckInit(dev);
blk = chunkInNAND/32;
pg = chunkInNAND%32;
for(i = 0; i < 528; i++)
{
if(ramdisk.block[blk]->page[pg].data[i] != 0xFF)
{
return YAFFS_FAIL;
}
}
return YAFFS_OK;
}
int yflash_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
{
CheckInit(dev);
if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks)
{
T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
return YAFFS_FAIL;
}
else
{
memset(ramdisk.block[blockNumber],0xFF,sizeof(yflash_Block));
return YAFFS_OK;
}
}
int yflash_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
return YAFFS_OK;
}
int yflash_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
{
*state = YAFFS_BLOCK_STATE_EMPTY;
*sequenceNumber = 0;
}
int yflash_InitialiseNAND(yaffs_Device *dev)
{
return YAFFS_OK;
}

@ -1,235 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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.
*/
/*
* yaffs_ramdisk.c: yaffs ram disk component
* This provides a ram disk under yaffs.
* NB this is not intended for NAND emulation.
* Use this with dev->useNANDECC enabled, then ECC overheads are not required.
*/
/* XXX U-BOOT XXX */
#include <common.h>
const char *yaffs_ramdisk_c_version = "$Id: yaffs_ramdisk.c,v 1.4 2007/02/14 01:09:06 wookey Exp $";
#include "yportenv.h"
#include "yaffs_ramdisk.h"
#include "yaffs_guts.h"
#include "devextras.h"
#include "yaffs_packedtags1.h"
#define SIZE_IN_MB 2
#define BLOCK_SIZE (32 * 528)
#define BLOCKS_PER_MEG ((1024*1024)/(32 * 512))
typedef struct
{
__u8 data[528]; // Data + spare
} yramdisk_Page;
typedef struct
{
yramdisk_Page page[32]; // The pages in the block
} yramdisk_Block;
typedef struct
{
yramdisk_Block **block;
int nBlocks;
} yramdisk_Device;
static yramdisk_Device ramdisk;
static int CheckInit(yaffs_Device *dev)
{
static int initialised = 0;
int i;
int fail = 0;
//int nBlocks;
int nAllocated = 0;
if(initialised)
{
return YAFFS_OK;
}
initialised = 1;
ramdisk.nBlocks = (SIZE_IN_MB * 1024 * 1024)/(16 * 1024);
ramdisk.block = YMALLOC(sizeof(yramdisk_Block *) * ramdisk.nBlocks);
if(!ramdisk.block) return 0;
for(i=0; i <ramdisk.nBlocks; i++)
{
ramdisk.block[i] = NULL;
}
for(i=0; i <ramdisk.nBlocks && !fail; i++)
{
if((ramdisk.block[i] = YMALLOC(sizeof(yramdisk_Block))) == 0)
{
fail = 1;
}
else
{
yramdisk_EraseBlockInNAND(dev,i);
nAllocated++;
}
}
if(fail)
{
for(i = 0; i < nAllocated; i++)
{
YFREE(ramdisk.block[i]);
}
YFREE(ramdisk.block);
T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n",
nAllocated/64,ramdisk.nBlocks * 528));
return 0;
}
return 1;
}
int yramdisk_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
{
int blk;
int pg;
CheckInit(dev);
blk = chunkInNAND/32;
pg = chunkInNAND%32;
if(data)
{
memcpy(ramdisk.block[blk]->page[pg].data,data,512);
}
if(tags)
{
yaffs_PackedTags1 pt;
yaffs_PackTags1(&pt,tags);
memcpy(&ramdisk.block[blk]->page[pg].data[512],&pt,sizeof(pt));
}
return YAFFS_OK;
}
int yramdisk_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
{
int blk;
int pg;
CheckInit(dev);
blk = chunkInNAND/32;
pg = chunkInNAND%32;
if(data)
{
memcpy(data,ramdisk.block[blk]->page[pg].data,512);
}
if(tags)
{
yaffs_PackedTags1 pt;
memcpy(&pt,&ramdisk.block[blk]->page[pg].data[512],sizeof(pt));
yaffs_UnpackTags1(tags,&pt);
}
return YAFFS_OK;
}
int yramdisk_CheckChunkErased(yaffs_Device *dev,int chunkInNAND)
{
int blk;
int pg;
int i;
CheckInit(dev);
blk = chunkInNAND/32;
pg = chunkInNAND%32;
for(i = 0; i < 528; i++)
{
if(ramdisk.block[blk]->page[pg].data[i] != 0xFF)
{
return YAFFS_FAIL;
}
}
return YAFFS_OK;
}
int yramdisk_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
{
CheckInit(dev);
if(blockNumber < 0 || blockNumber >= ramdisk.nBlocks)
{
T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
return YAFFS_FAIL;
}
else
{
memset(ramdisk.block[blockNumber],0xFF,sizeof(yramdisk_Block));
return YAFFS_OK;
}
}
int yramdisk_InitialiseNAND(yaffs_Device *dev)
{
//dev->useNANDECC = 1; // force on useNANDECC which gets faked.
// This saves us doing ECC checks.
return YAFFS_OK;
}

@ -1,364 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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.
*/
/*
* yaffs_ramem2k.c: RAM emulation in-kernel for 2K pages (YAFFS2)
*/
/* XXX U-BOOT XXX */
#include <common.h>
const char *yaffs_ramem2k_c_version = "$Id: yaffs_ramem2k.c,v 1.3 2007/02/14 01:09:06 wookey Exp $";
#ifndef __KERNEL__
#define CONFIG_YAFFS_RAM_ENABLED
#else
#include <linux/config.h>
#endif
#ifdef CONFIG_YAFFS_RAM_ENABLED
#include "yportenv.h"
#include "yaffs_nandemul2k.h"
#include "yaffs_guts.h"
#include "yaffsinterface.h"
#include "devextras.h"
#include "yaffs_packedtags2.h"
#define EM_SIZE_IN_MEG (32)
#define PAGE_DATA_SIZE (2048)
#define PAGE_SPARE_SIZE (64)
#define PAGES_PER_BLOCK (64)
#define EM_SIZE_IN_BYTES (EM_SIZE_IN_MEG * (1<<20))
#define PAGE_TOTAL_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE)
#define BLOCK_TOTAL_SIZE (PAGES_PER_BLOCK * PAGE_TOTAL_SIZE)
#define BLOCKS_PER_MEG ((1<<20)/(PAGES_PER_BLOCK * PAGE_DATA_SIZE))
typedef struct
{
__u8 data[PAGE_TOTAL_SIZE]; // Data + spare
int empty; // is this empty?
} nandemul_Page;
typedef struct
{
nandemul_Page *page[PAGES_PER_BLOCK];
int damaged;
} nandemul_Block;
typedef struct
{
nandemul_Block**block;
int nBlocks;
} nandemul_Device;
static nandemul_Device ned;
static int sizeInMB = EM_SIZE_IN_MEG;
static void nandemul_yield(int n)
{
#ifdef __KERNEL__
if(n > 0) schedule_timeout(n);
#endif
}
static void nandemul_ReallyEraseBlock(int blockNumber)
{
int i;
nandemul_Block *blk;
if(blockNumber < 0 || blockNumber >= ned.nBlocks)
{
return;
}
blk = ned.block[blockNumber];
for(i = 0; i < PAGES_PER_BLOCK; i++)
{
memset(blk->page[i],0xff,sizeof(nandemul_Page));
blk->page[i]->empty = 1;
}
nandemul_yield(2);
}
static int nandemul2k_CalcNBlocks(void)
{
return EM_SIZE_IN_MEG * BLOCKS_PER_MEG;
}
static int CheckInit(void)
{
static int initialised = 0;
int i,j;
int fail = 0;
int nBlocks;
int nAllocated = 0;
if(initialised)
{
return YAFFS_OK;
}
ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks();
ned.block = YMALLOC(sizeof(nandemul_Block*) * nBlocks );
if(!ned.block) return YAFFS_FAIL;
for(i=fail=0; i <nBlocks; i++)
{
nandemul_Block *blk;
if(!(blk = ned.block[i] = YMALLOC(sizeof(nandemul_Block))))
{
fail = 1;
}
else
{
for(j = 0; j < PAGES_PER_BLOCK; j++)
{
if((blk->page[j] = YMALLOC(sizeof(nandemul_Page))) == 0)
{
fail = 1;
}
}
nandemul_ReallyEraseBlock(i);
ned.block[i]->damaged = 0;
nAllocated++;
}
}
if(fail)
{
//Todo thump pages
for(i = 0; i < nAllocated; i++)
{
YFREE(ned.block[i]);
}
YFREE(ned.block);
T(YAFFS_TRACE_ALWAYS,("Allocation failed, could only allocate %dMB of %dMB requested.\n",
nAllocated/64,sizeInMB));
return 0;
}
ned.nBlocks = nBlocks;
initialised = 1;
return 1;
}
int nandemul2k_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, yaffs_ExtendedTags *tags)
{
int blk;
int pg;
int i;
__u8 *x;
blk = chunkInNAND/PAGES_PER_BLOCK;
pg = chunkInNAND%PAGES_PER_BLOCK;
if(data)
{
x = ned.block[blk]->page[pg]->data;
for(i = 0; i < PAGE_DATA_SIZE; i++)
{
x[i] &=data[i];
}
ned.block[blk]->page[pg]->empty = 0;
}
if(tags)
{
x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
yaffs_PackTags2((yaffs_PackedTags2 *)x,tags);
}
if(tags || data)
{
nandemul_yield(1);
}
return YAFFS_OK;
}
int nandemul2k_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
{
int blk;
int pg;
__u8 *x;
blk = chunkInNAND/PAGES_PER_BLOCK;
pg = chunkInNAND%PAGES_PER_BLOCK;
if(data)
{
memcpy(data,ned.block[blk]->page[pg]->data,PAGE_DATA_SIZE);
}
if(tags)
{
x = &ned.block[blk]->page[pg]->data[PAGE_DATA_SIZE];
yaffs_UnpackTags2(tags,(yaffs_PackedTags2 *)x);
}
return YAFFS_OK;
}
static int nandemul2k_CheckChunkErased(yaffs_Device *dev,int chunkInNAND)
{
int blk;
int pg;
int i;
blk = chunkInNAND/PAGES_PER_BLOCK;
pg = chunkInNAND%PAGES_PER_BLOCK;
for(i = 0; i < PAGE_TOTAL_SIZE; i++)
{
if(ned.block[blk]->page[pg]->data[i] != 0xFF)
{
return YAFFS_FAIL;
}
}
return YAFFS_OK;
}
int nandemul2k_EraseBlockInNAND(yaffs_Device *dev, int blockNumber)
{
if(blockNumber < 0 || blockNumber >= ned.nBlocks)
{
T(YAFFS_TRACE_ALWAYS,("Attempt to erase non-existant block %d\n",blockNumber));
}
else if(ned.block[blockNumber]->damaged)
{
T(YAFFS_TRACE_ALWAYS,("Attempt to erase damaged block %d\n",blockNumber));
}
else
{
nandemul_ReallyEraseBlock(blockNumber);
}
return YAFFS_OK;
}
int nandemul2k_InitialiseNAND(yaffs_Device *dev)
{
CheckInit();
return YAFFS_OK;
}
int nandemul2k_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
__u8 *x;
x = &ned.block[blockNo]->page[0]->data[PAGE_DATA_SIZE];
memset(x,0,sizeof(yaffs_PackedTags2));
return YAFFS_OK;
}
int nandemul2k_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo, yaffs_BlockState *state, int *sequenceNumber)
{
yaffs_ExtendedTags tags;
int chunkNo;
*sequenceNumber = 0;
chunkNo = blockNo * dev->nChunksPerBlock;
nandemul2k_ReadChunkWithTagsFromNAND(dev,chunkNo,NULL,&tags);
if(tags.blockBad)
{
*state = YAFFS_BLOCK_STATE_DEAD;
}
else if(!tags.chunkUsed)
{
*state = YAFFS_BLOCK_STATE_EMPTY;
}
else if(tags.chunkUsed)
{
*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
*sequenceNumber = tags.sequenceNumber;
}
return YAFFS_OK;
}
int nandemul2k_GetBytesPerChunk(void) { return PAGE_DATA_SIZE;}
int nandemul2k_GetChunksPerBlock(void) { return PAGES_PER_BLOCK; }
int nandemul2k_GetNumberOfBlocks(void) {return nandemul2k_CalcNBlocks();}
#endif //YAFFS_RAM_ENABLED

@ -1,231 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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.
*/
/* XXX U-BOOT XXX */
#include <common.h>
#include "yaffscfg.h"
#include "yaffsfs.h"
#include "yaffs_fileem2k.h"
#include "yaffs_nandemul2k.h"
#include <errno.h>
unsigned yaffs_traceMask =
YAFFS_TRACE_SCAN |
YAFFS_TRACE_GC | YAFFS_TRACE_GC_DETAIL |
YAFFS_TRACE_ERASE |
YAFFS_TRACE_TRACING |
YAFFS_TRACE_ALLOCATE |
YAFFS_TRACE_CHECKPOINT |
YAFFS_TRACE_BAD_BLOCKS |
YAFFS_TRACE_VERIFY |
YAFFS_TRACE_VERIFY_NAND |
YAFFS_TRACE_VERIFY_FULL |
// (~0) |
0;
void yaffsfs_SetError(int err)
{
//Do whatever to set error
errno = err;
}
void yaffsfs_Lock(void)
{
}
void yaffsfs_Unlock(void)
{
}
__u32 yaffsfs_CurrentTime(void)
{
return 0;
}
static int yaffs_kill_alloc = 0;
static size_t total_malloced = 0;
static size_t malloc_limit = 0 & 6000000;
void *yaffs_malloc(size_t size)
{
size_t this;
if(yaffs_kill_alloc)
return NULL;
if(malloc_limit && malloc_limit <(total_malloced + size) )
return NULL;
this = malloc(size);
if(this)
total_malloced += size;
return this;
}
void yaffs_free(void *ptr)
{
free(ptr);
}
void yaffsfs_LocalInitialisation(void)
{
// Define locking semaphore.
}
// Configuration for:
// /ram 2MB ramdisk
// /boot 2MB boot disk (flash)
// /flash 14MB flash disk (flash)
// NB Though /boot and /flash occupy the same physical device they
// are still disticnt "yaffs_Devices. You may think of these as "partitions"
// using non-overlapping areas in the same device.
//
#include "yaffs_ramdisk.h"
#include "yaffs_flashif.h"
#include "yaffs_nandemul2k.h"
static yaffs_Device ramDev;
static yaffs_Device bootDev;
static yaffs_Device flashDev;
static yaffs_Device ram2kDev;
static yaffsfs_DeviceConfiguration yaffsfs_config[] = {
#if 0
{ "/ram", &ramDev},
{ "/boot", &bootDev},
{ "/flash/", &flashDev},
{ "/ram2k", &ram2kDev},
{(void *)0,(void *)0}
#else
{ "/", &ramDev},
{ "/flash/boot", &bootDev},
{ "/flash/flash", &flashDev},
{ "/ram2k", &ram2kDev},
{(void *)0,(void *)0} /* Null entry to terminate list */
#endif
};
int yaffs_StartUp(void)
{
// Stuff to configure YAFFS
// Stuff to initialise anything special (eg lock semaphore).
yaffsfs_LocalInitialisation();
// Set up devices
// /ram
memset(&ramDev,0,sizeof(ramDev));
ramDev.nDataBytesPerChunk = 512;
ramDev.nChunksPerBlock = 32;
ramDev.nReservedBlocks = 2; // Set this smaller for RAM
ramDev.startBlock = 0; // Can use block 0
ramDev.endBlock = 127; // Last block in 2MB.
//ramDev.useNANDECC = 1;
ramDev.nShortOpCaches = 0; // Disable caching on this device.
ramDev.genericDevice = (void *) 0; // Used to identify the device in fstat.
ramDev.writeChunkWithTagsToNAND = yramdisk_WriteChunkWithTagsToNAND;
ramDev.readChunkWithTagsFromNAND = yramdisk_ReadChunkWithTagsFromNAND;
ramDev.eraseBlockInNAND = yramdisk_EraseBlockInNAND;
ramDev.initialiseNAND = yramdisk_InitialiseNAND;
// /boot
memset(&bootDev,0,sizeof(bootDev));
bootDev.nDataBytesPerChunk = 512;
bootDev.nChunksPerBlock = 32;
bootDev.nReservedBlocks = 5;
bootDev.startBlock = 0; // Can use block 0
bootDev.endBlock = 63; // Last block
//bootDev.useNANDECC = 0; // use YAFFS's ECC
bootDev.nShortOpCaches = 10; // Use caches
bootDev.genericDevice = (void *) 1; // Used to identify the device in fstat.
bootDev.writeChunkWithTagsToNAND = yflash_WriteChunkWithTagsToNAND;
bootDev.readChunkWithTagsFromNAND = yflash_ReadChunkWithTagsFromNAND;
bootDev.eraseBlockInNAND = yflash_EraseBlockInNAND;
bootDev.initialiseNAND = yflash_InitialiseNAND;
bootDev.markNANDBlockBad = yflash_MarkNANDBlockBad;
bootDev.queryNANDBlock = yflash_QueryNANDBlock;
// /flash
// Set this puppy up to use
// the file emulation space as
// 2kpage/64chunk per block/128MB device
memset(&flashDev,0,sizeof(flashDev));
flashDev.nDataBytesPerChunk = 2048;
flashDev.nChunksPerBlock = 64;
flashDev.nReservedBlocks = 5;
flashDev.nCheckpointReservedBlocks = 5;
//flashDev.checkpointStartBlock = 1;
//flashDev.checkpointEndBlock = 20;
flashDev.startBlock = 0;
flashDev.endBlock = 200; // Make it smaller
//flashDev.endBlock = yflash_GetNumberOfBlocks()-1;
flashDev.isYaffs2 = 1;
flashDev.wideTnodesDisabled=0;
flashDev.nShortOpCaches = 10; // Use caches
flashDev.genericDevice = (void *) 2; // Used to identify the device in fstat.
flashDev.writeChunkWithTagsToNAND = yflash_WriteChunkWithTagsToNAND;
flashDev.readChunkWithTagsFromNAND = yflash_ReadChunkWithTagsFromNAND;
flashDev.eraseBlockInNAND = yflash_EraseBlockInNAND;
flashDev.initialiseNAND = yflash_InitialiseNAND;
flashDev.markNANDBlockBad = yflash_MarkNANDBlockBad;
flashDev.queryNANDBlock = yflash_QueryNANDBlock;
// /ram2k
// Set this puppy up to use
// the file emulation space as
// 2kpage/64chunk per block/128MB device
memset(&ram2kDev,0,sizeof(ram2kDev));
ram2kDev.nDataBytesPerChunk = nandemul2k_GetBytesPerChunk();
ram2kDev.nChunksPerBlock = nandemul2k_GetChunksPerBlock();
ram2kDev.nReservedBlocks = 5;
ram2kDev.startBlock = 0; // First block after /boot
//ram2kDev.endBlock = 127; // Last block in 16MB
ram2kDev.endBlock = nandemul2k_GetNumberOfBlocks() - 1; // Last block in 512MB
ram2kDev.isYaffs2 = 1;
ram2kDev.nShortOpCaches = 10; // Use caches
ram2kDev.genericDevice = (void *) 3; // Used to identify the device in fstat.
ram2kDev.writeChunkWithTagsToNAND = nandemul2k_WriteChunkWithTagsToNAND;
ram2kDev.readChunkWithTagsFromNAND = nandemul2k_ReadChunkWithTagsFromNAND;
ram2kDev.eraseBlockInNAND = nandemul2k_EraseBlockInNAND;
ram2kDev.initialiseNAND = nandemul2k_InitialiseNAND;
ram2kDev.markNANDBlockBad = nandemul2k_MarkNANDBlockBad;
ram2kDev.queryNANDBlock = nandemul2k_QueryNANDBlock;
yaffs_initialise(yaffsfs_config);
return 0;
}
void SetCheckpointReservedBlocks(int n)
{
flashDev.nCheckpointReservedBlocks = n;
}

@ -1,65 +0,0 @@
/*
* YAFFS: Yet another Flash File System . A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Martin Fouts <Martin.Fouts@palmsource.com>
*
* 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_CONFIG_H__
#define __YAFFS_CONFIG_H__
#ifdef YAFFS_OUT_OF_TREE
/* DO NOT UNSET THESE THREE. YAFFS2 will not compile if you do. */
#define CONFIG_YAFFS_FS
#define CONFIG_YAFFS_YAFFS1
#define CONFIG_YAFFS_YAFFS2
/* These options are independent of each other. Select those that matter. */
/* Default: Not selected */
/* Meaning: Yaffs does its own ECC, rather than using MTD ECC */
//#define CONFIG_YAFFS_DOES_ECC
/* Default: Not selected */
/* Meaning: ECC byte order is 'wrong'. Only meaningful if */
/* CONFIG_YAFFS_DOES_ECC is set */
//#define CONFIG_YAFFS_ECC_WRONG_ORDER
/* Default: Selected */
/* Meaning: Disables testing whether chunks are erased before writing to them*/
#define CONFIG_YAFFS_DISABLE_CHUNK_ERASED_CHECK
/* Default: Selected */
/* Meaning: Cache short names, taking more RAM, but faster look-ups */
#define CONFIG_YAFFS_SHORT_NAMES_IN_RAM
/* Default: 10 */
/* Meaning: set the count of blocks to reserve for checkpointing */
#define CONFIG_YAFFS_CHECKPOINT_RESERVED_BLOCKS 10
/*
Older-style on-NAND data format has a "pageStatus" byte to record
chunk/page state. This byte is zeroed when the page is discarded.
Choose this option if you have existing on-NAND data in this format
that you need to continue to support. New data written also uses the
older-style format.
Note: Use of this option generally requires that MTD's oob layout be
adjusted to use the older-style format. See notes on tags formats and
MTD versions in yaffs_mtdif1.c.
*/
/* Default: Not selected */
/* Meaning: Use older-style on-NAND data format with pageStatus byte */
//#define CONFIG_YAFFS_9BYTE_TAGS
#endif /* YAFFS_OUT_OF_TREE */
#endif /* __YAFFS_CONFIG_H__ */

@ -1,33 +0,0 @@
#Makefile for NANDemul MTD
#
# NB this is not yet suitable for putting into the kernel tree.
# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
#
# Copyright (C) 2002 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.
## Change or override KERNELDIR to your kernel
## comment out USE_xxxx if you don't want these features.
KERNELDIR = /usr/src/kernel-headers-2.4.27
CFLAGS = -D__KERNEL__ -DMODULE -I$(KERNELDIR)/include -O2 -Wall -g
TARGET = nandemul2k.o
default: $(TARGET)
clean:
rm -f $(TARGET)
$(TARGET): %.o: %.c
gcc -c $(CFLAGS) $< -o $@

@ -1,714 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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 version hacked for emulating 2kpage NAND for YAFFS2 testing.
*/
#include <linux/config.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/version.h>
#include <linux/slab.h>
#include <linux/init.h>
#include <linux/list.h>
#include <linux/fs.h>
#include <linux/proc_fs.h>
#include <linux/pagemap.h>
#include <linux/mtd/mtd.h>
#include <linux/interrupt.h>
#include <linux/string.h>
#if (LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0))
#include <linux/locks.h>
#endif
#include <asm/uaccess.h>
#include <linux/mtd/mtd.h>
#include <linux/mtd/partitions.h>
#include <linux/mtd/nand.h>
#include "../yaffs_nandemul2k.h"
#define ALLOCATE(x) kmalloc(x,GFP_KERNEL)
#define FREE(x) kfree(x)
#define NAND_SHIFT (11) // Shifter for 2k
#define PAGE_DATA_SIZE (1 << NAND_SHIFT)
#define PAGE_SPARE_SIZE (64)
#define BLK_SHIFT 6
#define PAGES_PER_BLOCK (1 << BLK_SHIFT) // = 64
#define EM_SIZE_IN_MEG 4
#define EM_SIZE_IN_BYTES (EM_SIZE_IN_MEG * (1<<20))
#define PAGE_TOTAL_SIZE (PAGE_DATA_SIZE+PAGE_SPARE_SIZE)
#define BLOCK_TOTAL_SIZE (PAGES_PER_BLOCK * PAGE_TOTAL_SIZE)
#define BLOCKS_PER_MEG ((1<<20)/(PAGES_PER_BLOCK * PAGE_DATA_SIZE))
static struct mtd_info nandemul2k_mtd;
typedef struct
{
__u8 data[PAGE_TOTAL_SIZE]; // Data + spare
int empty; // is this empty?
} nandemul_Page;
typedef struct
{
nandemul_Page *page[PAGES_PER_BLOCK];
int damaged;
} nandemul_Block;
typedef struct
{
nandemul_Block**block;
int nBlocks;
} nandemul_Device;
static nandemul_Device ned;
static int sizeInMB = EM_SIZE_IN_MEG;
static void nandemul_yield(int n)
{
#ifdef __KERNEL__
if(n > 0) schedule_timeout(n);
#endif
}
static void nandemul2k_Read(void *buffer, int page, int start, int nBytes)
{
int pg = page%PAGES_PER_BLOCK;
int blk = page/PAGES_PER_BLOCK;
if(buffer && nBytes > 0)
{
memcpy(buffer,&ned.block[blk]->page[pg]->data[start],nBytes);
}
}
static void nandemul2k_Program(const void *buffer, int page, int start, int nBytes)
{
int pg = page%PAGES_PER_BLOCK;
int blk = page/PAGES_PER_BLOCK;
__u8 *p;
__u8 *b = (__u8 *)buffer;
p = &ned.block[blk]->page[pg]->data[start];
while(buffer && nBytes>0)
{
*p = *p & *b;
p++;
b++;
nBytes--;
}
}
static void nandemul2k_DoErase(int blockNumber)
{
int i;
nandemul_Block *blk;
if(blockNumber < 0 || blockNumber >= ned.nBlocks)
{
return;
}
blk = ned.block[blockNumber];
for(i = 0; i < PAGES_PER_BLOCK; i++)
{
memset(blk->page[i],0xff,sizeof(nandemul_Page));
blk->page[i]->empty = 1;
}
nandemul_yield(2);
}
static int nandemul2k_CalcNBlocks(void)
{
return EM_SIZE_IN_MEG * BLOCKS_PER_MEG;
}
static int CheckInit(void)
{
static int initialised = 0;
int i,j;
int fail = 0;
int nBlocks;
int nAllocated = 0;
if(initialised)
{
return 0;
}
ned.nBlocks = nBlocks = nandemul2k_CalcNBlocks();
ned.block = ALLOCATE(sizeof(nandemul_Block*) * nBlocks );
if(!ned.block) return ENOMEM;
for(i=fail=0; i <nBlocks; i++)
{
nandemul_Block *blk;
if(!(blk = ned.block[i] = ALLOCATE(sizeof(nandemul_Block))))
{
fail = 1;
}
else
{
for(j = 0; j < PAGES_PER_BLOCK; j++)
{
if((blk->page[j] = ALLOCATE(sizeof(nandemul_Page))) == 0)
{
fail = 1;
}
}
nandemul2k_DoErase(i);
ned.block[i]->damaged = 0;
nAllocated++;
}
}
if(fail)
{
//Todo thump pages
for(i = 0; i < nAllocated; i++)
{
FREE(ned.block[i]);
}
FREE(ned.block);
return ENOMEM;
}
ned.nBlocks = nBlocks;
initialised = 1;
return 1;
}
static void nandemul2k_CleanUp(void)
{
int i,j;
for(i = 0; i < ned.nBlocks; i++)
{
for(j = 0; j < PAGES_PER_BLOCK; j++)
{
FREE(ned.block[i]->page[j]);
}
FREE(ned.block[i]);
}
FREE(ned.block);
ned.block = 0;
}
int nandemul2k_GetBytesPerChunk(void) { return PAGE_DATA_SIZE;}
int nandemul2k_GetChunksPerBlock(void) { return PAGES_PER_BLOCK; }
int nandemul2k_GetNumberOfBlocks(void) {return nandemul2k_CalcNBlocks();}
static int nandemul2k_ReadId(__u8 *vendorId, __u8 *deviceId)
{
*vendorId = 'Y';
*deviceId = '2';
return 1;
}
static int nandemul2k_ReadStatus(__u8 *status)
{
*status = 0;
return 1;
}
#ifdef CONFIG_MTD_NAND_ECC
#include <linux/mtd/nand_ecc.h>
#endif
/*
* NAND low-level MTD interface functions
*/
static int nand_read (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf, u_char *oob_buf, struct nand_oobinfo *dummy);
static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf);
static int nand_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf);
static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf,
u_char *oob_buf, struct nand_oobinfo *dummy);
static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf);
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7))
static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen);
#else
static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs,
unsigned long count, loff_t to, size_t *retlen);
#endif
static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
static void nand_sync (struct mtd_info *mtd);
/*
* NAND read
*/
static int nand_read (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
return nand_read_ecc (mtd, from, len, retlen, buf, NULL,NULL);
}
/*
* NAND read with ECC
*/
static int nand_read_ecc (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf, u_char *oob_buf,struct nand_oobinfo *oobsel)
{
int start, page;
int n = len;
int nToCopy;
/* Do not allow reads past end of device */
if ((from + len) > mtd->size) {
*retlen = 0;
return -EINVAL;
}
/* Initialize return value */
*retlen = 0;
while(n > 0)
{
/* First we calculate the starting page */
page = from >> NAND_SHIFT;
/* Get raw starting column */
start = from & (mtd->oobblock-1);
// OK now check for the curveball where the start and end are in
// the same page
if((start + n) < mtd->oobblock)
{
nToCopy = n;
}
else
{
nToCopy = mtd->oobblock - start;
}
nandemul2k_Read(buf, page, start, nToCopy);
nandemul2k_Read(oob_buf,page,PAGE_DATA_SIZE,PAGE_SPARE_SIZE);
n -= nToCopy;
from += nToCopy;
buf += nToCopy;
if(oob_buf) oob_buf += PAGE_SPARE_SIZE;
*retlen += nToCopy;
}
return 0;
}
/*
* NAND read out-of-band
*/
static int nand_read_oob (struct mtd_info *mtd, loff_t from, size_t len,
size_t *retlen, u_char *buf)
{
int col, page;
T(0,("nand_read_oob: from = 0x%08x, buf = 0x%08x, len = %i\n", (unsigned int) from, (unsigned int) buf,
(int) len));
/* Shift to get page */
page = ((int) from) >> NAND_SHIFT;
/* Mask to get column */
col = from & 0x0f;
/* Initialize return length value */
*retlen = 0;
/* Do not allow reads past end of device */
if ((from + len) > mtd->size) {
T(0,
("nand_read_oob: Attempt read beyond end of device\n"));
*retlen = 0;
return -EINVAL;
}
nandemul2k_Read(buf,page,PAGE_DATA_SIZE + col,len);
/* Return happy */
*retlen = len;
return 0;
}
/*
* NAND write
*/
static int nand_write (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
return nand_write_ecc (mtd, to, len, retlen, buf, NULL,NULL);
}
/*
* NAND write with ECC
*/
static int nand_write_ecc (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf,
u_char *oob_buf, struct nand_oobinfo *dummy)
{
int start, page;
int n = len;
int nToCopy;
/* Do not allow reads past end of device */
if ((to + len) > mtd->size) {
*retlen = 0;
return -EINVAL;
}
/* Initialize return value */
*retlen = 0;
while(n > 0)
{
/* First we calculate the starting page */
page = to >> NAND_SHIFT;
/* Get raw starting column */
start = to & (mtd->oobblock - 1);
// OK now check for the curveball where the start and end are in
// the same page
if((start + n) < mtd->oobblock)
{
nToCopy = n;
}
else
{
nToCopy = mtd->oobblock - start;
}
nandemul2k_Program(buf, page, start, nToCopy);
nandemul2k_Program(oob_buf, page, PAGE_DATA_SIZE, PAGE_SPARE_SIZE);
n -= nToCopy;
to += nToCopy;
buf += nToCopy;
if(oob_buf) oob_buf += PAGE_SPARE_SIZE;
*retlen += nToCopy;
}
return 0;
}
/*
* NAND write out-of-band
*/
static int nand_write_oob (struct mtd_info *mtd, loff_t to, size_t len,
size_t *retlen, const u_char *buf)
{
int col, page;
T(0,(
"nand_read_oob: to = 0x%08x, len = %i\n", (unsigned int) to,
(int) len));
/* Shift to get page */
page = ((int) to) >> NAND_SHIFT;
/* Mask to get column */
col = to & 0x0f;
/* Initialize return length value */
*retlen = 0;
/* Do not allow reads past end of device */
if ((to + len) > mtd->size) {
T(0,(
"nand_read_oob: Attempt read beyond end of device\n"));
*retlen = 0;
return -EINVAL;
}
nandemul2k_Program(buf,page,512 + col,len);
/* Return happy */
*retlen = len;
return 0;
}
/*
* NAND write with iovec
*/
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,7))
static int nand_writev (struct mtd_info *mtd, const struct kvec *vecs,
unsigned long count, loff_t to, size_t *retlen)
#else
static int nand_writev (struct mtd_info *mtd, const struct iovec *vecs,
unsigned long count, loff_t to, size_t *retlen)
#endif
{
return -EINVAL;
}
/*
* NAND erase a block
*/
static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
{
int i, nBlocks,block;
T(0,(
"nand_erase: start = 0x%08x, len = %i\n",
(unsigned int) instr->addr, (unsigned int) instr->len));
/* Start address must align on block boundary */
if (instr->addr & (mtd->erasesize - 1)) {
T(0,(
"nand_erase: Unaligned address\n"));
return -EINVAL;
}
/* Length must align on block boundary */
if (instr->len & (mtd->erasesize - 1)) {
T(0,(
"nand_erase: Length not block aligned\n"));
return -EINVAL;
}
/* Do not allow erase past end of device */
if ((instr->len + instr->addr) > mtd->size) {
T(0,(
"nand_erase: Erase past end of device\n"));
return -EINVAL;
}
nBlocks = instr->len >> (NAND_SHIFT + BLK_SHIFT);
block = instr->addr >> (NAND_SHIFT + BLK_SHIFT);
for(i = 0; i < nBlocks; i++)
{
nandemul2k_DoErase(block);
block++;
}
instr->state = MTD_ERASE_DONE;  * change state to ERASE_DONE */
instr->callback(instr);  * wake up */
return 0;
}
static int nand_block_isbad(struct mtd_info *mtd, loff_t ofs)
{
return 0;
}
static int nand_block_markbad(struct mtd_info *mtd, loff_t ofs)
{
return 0;
}
/*
* NAND sync
*/
static void nand_sync (struct mtd_info *mtd)
{
T(0,("nand_sync: called\n"));
}
/*
* Scan for the NAND device
*/
static int nandemul2k_scan (struct mtd_info *mtd,int nchips)
{
mtd->oobblock = PAGE_DATA_SIZE;
mtd->oobsize = PAGE_SPARE_SIZE;
mtd->erasesize = PAGE_DATA_SIZE * PAGES_PER_BLOCK;
mtd->size = sizeInMB * 1024*1024;
/* Fill in remaining MTD driver data */
mtd->type = MTD_NANDFLASH;
mtd->flags = MTD_CAP_NANDFLASH;
mtd->owner = THIS_MODULE;
mtd->ecctype = MTD_ECC_NONE;
mtd->erase = nand_erase;
mtd->point = NULL;
mtd->unpoint = NULL;
mtd->read = nand_read;
mtd->write = nand_write;
mtd->read_ecc = nand_read_ecc;
mtd->write_ecc = nand_write_ecc;
mtd->read_oob = nand_read_oob;
mtd->write_oob = nand_write_oob;
mtd->block_isbad = nand_block_isbad;
mtd->block_markbad = nand_block_markbad;
mtd->readv = NULL;
mtd->writev = nand_writev;
mtd->sync = nand_sync;
mtd->lock = NULL;
mtd->unlock = NULL;
mtd->suspend = NULL;
mtd->resume = NULL;
mtd->name = "NANDemul2k";
/* Return happy */
return 0;
}
#if 0
#ifdef MODULE
MODULE_PARM(sizeInMB, "i");
__setup("sizeInMB=",sizeInMB);
#endif
#endif
/*
* Define partitions for flash devices
*/
static struct mtd_partition nandemul2k_partition[] =
{
{ .name = "NANDemul partition 1",
.offset = 0,
.size = 0 },
};
static int nPartitions = sizeof(nandemul2k_partition)/sizeof(nandemul2k_partition[0]);
/*
* Main initialization routine
*/
int __init nandemul2k_init (void)
{
// Do the nand init
CheckInit();
nandemul2k_scan(&nandemul2k_mtd,1);
// Build the partition table
nandemul2k_partition[0].size = sizeInMB * 1024 * 1024;
// Register the partition
add_mtd_partitions(&nandemul2k_mtd,nandemul2k_partition,nPartitions);
return 0;
}
module_init(nandemul2k_init);
/*
* Clean up routine
*/
#ifdef MODULE
static void __exit nandemul2k_cleanup (void)
{
nandemul2k_CleanUp();
/* Unregister partitions */
del_mtd_partitions(&nandemul2k_mtd);
/* Unregister the device */
del_mtd_device (&nandemul2k_mtd);
}
module_exit(nandemul2k_cleanup);
#endif
MODULE_LICENSE("GPL");
MODULE_AUTHOR("Charles Manning <manningc@aleph1.co.uk>");
MODULE_DESCRIPTION("2k Page/128k Block NAND emulated in RAM");

@ -1,121 +0,0 @@
#!/bin/sh
#
# YAFFS: Yet another FFS. A NAND-flash specific file system.
#
# Copyright (C) 2002-2006 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.
#
# Patch YAFFS into the kernel
#
# args: kpath : Full path to kernel sources to be patched
#
# Somewhat "inspired by" the mtd patchin script
#
# $Id: patch-ker.sh,v 1.3 2007/07/25 01:04:38 charles Exp $
VERSION=0
PATCHLEVEL=0
SUBLEVEL=0
COPYORLINK=$1
LINUXDIR=$2
# To be a Linux directory, it must have a Makefile
# Display usage of this script
usage () {
echo "usage: $0 c/l kernelpath"
echo " if c/l is c, then copy. If l then link"
exit 1
}
if [ -z $LINUXDIR ]
then
usage;
fi
if [ $COPYORLINK = l ]; then
CPY="ln -s"
elif [ $COPYORLINK = c ]; then
CPY="cp"
else
echo "unknown copy or link type"
usage;
fi
# Check if kerneldir contains a Makefile
if [ ! -f $LINUXDIR/Makefile ]
then
echo "Directory $LINUXDIR does not exist or is not a kernel source directory";
exit 1;
fi
# Get kernel version
VERSION=`grep -s VERSION <$LINUXDIR/Makefile | head -n 1 | sed s/'VERSION = '//`
PATCHLEVEL=`grep -s PATCHLEVEL <$LINUXDIR/Makefile | head -n 1 | sed s/'PATCHLEVEL = '//`
SUBLEVEL=`grep -s SUBLEVEL <$LINUXDIR/Makefile | head -n 1 | sed s/'SUBLEVEL = '//`
# Can we handle this version?
if [ $VERSION -ne 2 -o $PATCHLEVEL -lt 6 ]
then
echo "Cannot patch kernel version $VERSION.$PATCHLEVEL.$SUBLEVEL, must be 2.6.x or higher"
exit 1;
fi
KCONFIG=$LINUXDIR/fs/Kconfig
KCONFIGOLD=$LINUXDIR/fs/Kconfig.pre.yaffs
YAFFS_PATCHED_STRING=`grep -s yaffs <$KCONFIG | head -n 1`
MAKEFILE=$LINUXDIR/fs/Makefile
MAKEFILEOLD=$LINUXDIR/fs/Makefile.pre.yaffs
if [ ! -z "$YAFFS_PATCHED_STRING" ]
then
YAFFS_PATCHED=0
echo "$KCONFIG already mentions YAFFS, so we will not change it"
else
# Change the fs/Kconfig file
# Save the old Kconfig
# Copy all stuff up to JFFS
# Insert some YAFFS stuff
# Copy all the rest of the stuff
YAFFS_PATCHED=1
echo "Updating $KCONFIG"
mv -f $KCONFIG $KCONFIGOLD
sed -n -e "/JFFS/,99999 ! p" $KCONFIGOLD >$KCONFIG
echo "">>$KCONFIG
echo "# Patched by YAFFS" >>$KCONFIG
echo "source \"fs/yaffs2/Kconfig\"">>$KCONFIG
echo "">>$KCONFIG
sed -n -e "/JFFS/,99999 p" $KCONFIGOLD >>$KCONFIG
# now do fs/Makefile -- simply add the target at the end
echo "Updating $MAKEFILE"
cp -f $MAKEFILE $MAKEFILEOLD
echo "">>$MAKEFILE
echo "# Patched by YAFFS" >>$MAKEFILE
echo "obj-\$(CONFIG_YAFFS_FS) += yaffs2/" >>$MAKEFILE
fi
YAFFSDIR=$LINUXDIR/fs/yaffs2
if [ -e $YAFFSDIR ]
then
echo "$YAFFSDIR exists, not patching"
else
mkdir $LINUXDIR/fs/yaffs2
$CPY $PWD/Makefile.kernel $LINUXDIR/fs/yaffs2/Makefile
$CPY $PWD/Kconfig $LINUXDIR/fs/yaffs2
$CPY $PWD/*.c $PWD/*.h $LINUXDIR/fs/yaffs2
fi

@ -1,6 +0,0 @@
This directory holds patches that are useful for Linux integration.
Right now there is only one patched file, yaffs_mtdif2.c. This has been
patched with a tweaked version of "Sergey's patch" and typically makes a
stock mtd work properly.

@ -1,258 +0,0 @@
/*
* YAFFS: Yet another FFS. A NAND-flash specific file system.
*
* Copyright (C) 2002 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 */
const char *yaffs_mtdif2_c_version =
"$Id: yaffs_mtdif2.c,v 1.2 2007/03/07 08:05:58 colin Exp $";
#include "yportenv.h"
#include "yaffs_mtdif2.h"
#include "linux/mtd/mtd.h"
#include "linux/types.h"
#include "linux/time.h"
#include "yaffs_packedtags2.h"
void nandmtd2_pt2buf(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
__u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
int i, j = 0, k, n;
/* Pack buffer with 0xff */
for (i = 0; i < mtd->oobsize; i++)
dev->spareBuffer[i] = 0xff;
if(!is_raw){
memcpy(dev->spareBuffer,pt,sizeof(yaffs_PackedTags2));
} else {
j = 0;
k = mtd->oobinfo.oobfree[j][0];
n = mtd->oobinfo.oobfree[j][1];
if (n == 0) {
T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
YBUG();
}
for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
if (n == 0) {
j++;
k = mtd->oobinfo.oobfree[j][0];
n = mtd->oobinfo.oobfree[j][1];
if (n == 0) {
T(YAFFS_TRACE_ERROR, (TSTR("No OOB space for tags" TENDSTR)));
YBUG();
}
}
dev->spareBuffer[k] = ptab[i];
k++;
n--;
}
}
}
void nandmtd2_buf2pt(yaffs_Device *dev, yaffs_PackedTags2 *pt, int is_raw)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
int i, j = 0, k, n;
__u8 *ptab = (__u8 *)pt; /* packed tags as bytes */
if (!is_raw) {
memcpy(pt,dev->spareBuffer,sizeof(yaffs_PackedTags2));
} else {
j = 0;
k = mtd->oobinfo.oobfree[j][0];
n = mtd->oobinfo.oobfree[j][1];
if (n == 0) {
T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
YBUG();
}
for (i = 0; i < sizeof(yaffs_PackedTags2); i++) {
if (n == 0) {
j++;
k = mtd->oobinfo.oobfree[j][0];
n = mtd->oobinfo.oobfree[j][1];
if (n == 0) {
T(YAFFS_TRACE_ERROR, (TSTR("No space in OOB for tags" TENDSTR)));
YBUG();
}
}
ptab[i] = dev->spareBuffer[k];
k++;
n--;
}
}
}
int nandmtd2_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
const __u8 * data,
const yaffs_ExtendedTags * tags)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
size_t dummy;
int retval = 0;
loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
yaffs_PackedTags2 pt;
T(YAFFS_TRACE_MTD,
(TSTR
("nandmtd2_WriteChunkWithTagsToNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
if (tags) {
yaffs_PackTags2(&pt, tags);
}
if (data && tags) {
nandmtd2_pt2buf(dev, &pt, 0);
retval =
mtd->write_ecc(mtd, addr, dev->nBytesPerChunk,
&dummy, data, dev->spareBuffer,
NULL);
} else {
T(YAFFS_TRACE_ALWAYS,
(TSTR
("Write chunk with null tags or data!" TENDSTR)));
YBUG();
}
if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;
}
int nandmtd2_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
__u8 * data, yaffs_ExtendedTags * tags)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
size_t dummy;
int retval = 0;
loff_t addr = ((loff_t) chunkInNAND) * dev->nBytesPerChunk;
yaffs_PackedTags2 pt;
T(YAFFS_TRACE_MTD,
(TSTR
("nandmtd2_ReadChunkWithTagsToNAND chunk %d data %p tags %p"
TENDSTR), chunkInNAND, data, tags));
if (0 && data && tags) {
retval =
mtd->read_ecc(mtd, addr, dev->nBytesPerChunk,
&dummy, data, dev->spareBuffer,
NULL);
nandmtd2_buf2pt(dev, &pt, 0);
} else {
if (data)
retval =
mtd->read(mtd, addr, dev->nBytesPerChunk, &dummy,
data);
if (tags) {
retval =
mtd->read_oob(mtd, addr, mtd->oobsize, &dummy,
dev->spareBuffer);
nandmtd2_buf2pt(dev, &pt, 1);
}
}
if (tags)
yaffs_UnpackTags2(tags, &pt);
if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;
}
int nandmtd2_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
int retval;
T(YAFFS_TRACE_MTD,
(TSTR("nandmtd2_MarkNANDBlockBad %d" TENDSTR), blockNo));
retval =
mtd->block_markbad(mtd,
blockNo * dev->nChunksPerBlock *
dev->nBytesPerChunk);
if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;
}
int nandmtd2_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState * state, int *sequenceNumber)
{
struct mtd_info *mtd = (struct mtd_info *)(dev->genericDevice);
int retval;
T(YAFFS_TRACE_MTD,
(TSTR("nandmtd2_QueryNANDBlock %d" TENDSTR), blockNo));
retval =
mtd->block_isbad(mtd,
blockNo * dev->nChunksPerBlock *
dev->nBytesPerChunk);
if (retval) {
T(YAFFS_TRACE_MTD, (TSTR("block is bad" TENDSTR)));
*state = YAFFS_BLOCK_STATE_DEAD;
*sequenceNumber = 0;
} else {
yaffs_ExtendedTags t;
nandmtd2_ReadChunkWithTagsFromNAND(dev,
blockNo *
dev->nChunksPerBlock, NULL,
&t);
if (t.chunkUsed) {
*sequenceNumber = t.sequenceNumber;
*state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
} else {
*sequenceNumber = 0;
*state = YAFFS_BLOCK_STATE_EMPTY;
}
T(YAFFS_TRACE_MTD,
(TSTR("block is OK seq %d state %d" TENDSTR), *sequenceNumber,
*state));
}
if (retval == 0)
return YAFFS_OK;
else
return YAFFS_FAIL;
}

@ -1,54 +0,0 @@
#Makefile for mkyaffs
#
# NB this is not yet suitable for putting into the kernel tree.
# YAFFS: Yet another Flash File System. A NAND-flash specific file system.
#
# Copyright (C) 2002 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.
## Change or override KERNELDIR to your kernel
#KERNELDIR = /usr/src/kernel-headers-2.4.18
CFLAGS = -I/usr/include -I.. -O2 -Wall -DCONFIG_YAFFS_UTIL
CFLAGS+= -Wshadow -Wpointer-arith -Wwrite-strings -Wstrict-prototypes -Wmissing-declarations
CFLAGS+= -Wmissing-prototypes -Wredundant-decls -Wnested-externs -Winline
## Change if you are using a cross-compiler
MAKETOOLS =
CC=$(MAKETOOLS)gcc
COMMONLINKS = yaffs_ecc.c
COMMONOBJS = $(COMMONLINKS:.c=.o)
MKYAFFSSOURCES = mkyaffsimage.c
MKYAFFSIMAGEOBJS = $(MKYAFFSSOURCES:.c=.o)
MKYAFFS2SOURCES = mkyaffs2image.c
MKYAFFS2LINKS = yaffs_packedtags2.c yaffs_tagsvalidity.c
MKYAFFS2IMAGEOBJS = $(MKYAFFS2SOURCES:.c=.o) $(MKYAFFS2LINKS:.c=.o)
all: mkyaffsimage mkyaffs2image
$(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS):
ln -s ../$@ $@
$(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) : %.o: %.c
$(CC) -c $(CFLAGS) $< -o $@
mkyaffsimage: $(COMMONOBJS) $(MKYAFFSIMAGEOBJS)
$(CC) -o $@ $(COMMONOBJS) $(MKYAFFSIMAGEOBJS)
mkyaffs2image: $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS)
$(CC) -o $@ $(COMMONOBJS) $(MKYAFFS2IMAGEOBJS)
clean:
rm -f $(COMMONOBJS) $(MKYAFFSIMAGEOBJS) $(MKYAFFS2IMAGEOBJS) $(COMMONLINKS) $(MKYAFFSLINKS) $(MKYAFFS2LINKS) mkyaffsimage mkyaffs2image core

@ -1,520 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
* Nick Bane modifications flagged NCB
* Endian handling patches by James Ng.
* mkyaffs2image hacks by NCB
*
* 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.
*/
/*
* makeyaffs2image.c
*
* Makes a YAFFS2 file system image that can be used to load up a file system.
* Uses default Linux MTD layout - change if you need something different.
*/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include "yaffs_ecc.h"
#include "yaffs_guts.h"
#include "yaffs_tagsvalidity.h"
#include "yaffs_packedtags2.h"
unsigned yaffs_traceMask=0;
#define MAX_OBJECTS 10000
#define chunkSize 2048
#define spareSize 64
const char * mkyaffsimage_c_version = "$Id: mkyaffs2image.c,v 1.4 2007/02/14 01:09:06 wookey Exp $";
typedef struct
{
dev_t dev;
ino_t ino;
int obj;
} objItem;
static objItem obj_list[MAX_OBJECTS];
static int n_obj = 0;
static int obj_id = YAFFS_NOBJECT_BUCKETS + 1;
static int nObjects, nDirectories, nPages;
static int outFile;
static int error;
static int convert_endian = 0;
static int obj_compare(const void *a, const void * b)
{
objItem *oa, *ob;
oa = (objItem *)a;
ob = (objItem *)b;
if(oa->dev < ob->dev) return -1;
if(oa->dev > ob->dev) return 1;
if(oa->ino < ob->ino) return -1;
if(oa->ino > ob->ino) return 1;
return 0;
}
static void add_obj_to_list(dev_t dev, ino_t ino, int obj)
{
if(n_obj < MAX_OBJECTS)
{
obj_list[n_obj].dev = dev;
obj_list[n_obj].ino = ino;
obj_list[n_obj].obj = obj;
n_obj++;
qsort(obj_list,n_obj,sizeof(objItem),obj_compare);
}
else
{
// oops! not enough space in the object array
fprintf(stderr,"Not enough space in object array\n");
exit(2);
}
}
static int find_obj_in_list(dev_t dev, ino_t ino)
{
objItem *i = NULL;
objItem test;
test.dev = dev;
test.ino = ino;
if(n_obj > 0)
{
i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare);
}
if(i)
{
return i->obj;
}
return -1;
}
/* This little function converts a little endian tag to a big endian tag.
* NOTE: The tag is not usable after this other than calculating the CRC
* with.
*/
static void little_to_big_endian(yaffs_Tags *tagsPtr)
{
#if 0 // FIXME NCB
yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes.
yaffs_TagsUnion temp;
memset(&temp, 0, sizeof(temp));
// Ick, I hate magic numbers.
temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4);
temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4);
temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6);
temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6);
temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2);
temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2);
temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F);
temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6);
// Now copy it back.
tags->asBytes[0] = temp.asBytes[0];
tags->asBytes[1] = temp.asBytes[1];
tags->asBytes[2] = temp.asBytes[2];
tags->asBytes[3] = temp.asBytes[3];
tags->asBytes[4] = temp.asBytes[4];
tags->asBytes[5] = temp.asBytes[5];
tags->asBytes[6] = temp.asBytes[6];
tags->asBytes[7] = temp.asBytes[7];
#endif
}
static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
{
yaffs_ExtendedTags t;
yaffs_PackedTags2 pt;
error = write(outFile,data,chunkSize);
if(error < 0) return error;
yaffs_InitialiseTags(&t);
t.chunkId = chunkId;
// t.serialNumber = 0;
t.serialNumber = 1; // **CHECK**
t.byteCount = nBytes;
t.objectId = objId;
t.sequenceNumber = YAFFS_LOWEST_SEQUENCE_NUMBER;
// added NCB **CHECK**
t.chunkUsed = 1;
if (convert_endian)
{
little_to_big_endian(&t);
}
nPages++;
yaffs_PackTags2(&pt,&t);
// return write(outFile,&pt,sizeof(yaffs_PackedTags2));
return write(outFile,&pt,spareSize);
}
#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \
(((x) & 0x0000FF00) << 8 ) | \
(((x) & 0x00FF0000) >> 8 ) | \
(((x) & 0xFF000000) >> 24))
#define SWAP16(x) ((((x) & 0x00FF) << 8) | \
(((x) & 0xFF00) >> 8))
// This one is easier, since the types are more standard. No funky shifts here.
static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh)
{
oh->type = SWAP32(oh->type); // GCC makes enums 32 bits.
oh->parentObjectId = SWAP32(oh->parentObjectId); // int
oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness.
// name = skip. Char array. Not swapped.
oh->yst_mode = SWAP32(oh->yst_mode);
#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case.
// In fact, WinCE would be *THE* place where this would be an issue!
oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]);
oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]);
oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]);
oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]);
oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]);
#else
// Regular POSIX.
oh->yst_uid = SWAP32(oh->yst_uid);
oh->yst_gid = SWAP32(oh->yst_gid);
oh->yst_atime = SWAP32(oh->yst_atime);
oh->yst_mtime = SWAP32(oh->yst_mtime);
oh->yst_ctime = SWAP32(oh->yst_ctime);
#endif
oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that!
oh->equivalentObjectId = SWAP32(oh->equivalentObjectId);
// alias - char array.
oh->yst_rdev = SWAP32(oh->yst_rdev);
#ifdef CONFIG_YAFFS_WINCE
oh->win_ctime[0] = SWAP32(oh->win_ctime[0]);
oh->win_ctime[1] = SWAP32(oh->win_ctime[1]);
oh->win_atime[0] = SWAP32(oh->win_atime[0]);
oh->win_atime[1] = SWAP32(oh->win_atime[1]);
oh->win_mtime[0] = SWAP32(oh->win_mtime[0]);
oh->win_mtime[1] = SWAP32(oh->win_mtime[1]);
oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]);
oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]);
oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]);
oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]);
oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]);
oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]);
#else
oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]);
oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]);
oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]);
oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]);
oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]);
oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]);
oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]);
oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]);
oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]);
oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]);
oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]);
oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]);
#endif
}
static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias)
{
__u8 bytes[chunkSize];
yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes;
memset(bytes,0xff,sizeof(bytes));
oh->type = t;
oh->parentObjectId = parent;
strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH);
if(t != YAFFS_OBJECT_TYPE_HARDLINK)
{
oh->yst_mode = s->st_mode;
oh->yst_uid = s->st_uid;
// NCB 12/9/02 oh->yst_gid = s->yst_uid;
oh->yst_gid = s->st_gid;
oh->yst_atime = s->st_atime;
oh->yst_mtime = s->st_mtime;
oh->yst_ctime = s->st_ctime;
oh->yst_rdev = s->st_rdev;
}
if(t == YAFFS_OBJECT_TYPE_FILE)
{
oh->fileSize = s->st_size;
}
if(t == YAFFS_OBJECT_TYPE_HARDLINK)
{
oh->equivalentObjectId = equivalentObj;
}
if(t == YAFFS_OBJECT_TYPE_SYMLINK)
{
strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH);
}
if (convert_endian)
{
object_header_little_to_big_endian(oh);
}
return write_chunk(bytes,objId,0,0xffff);
}
static int process_directory(int parent, const char *path)
{
DIR *dir;
struct dirent *entry;
nDirectories++;
dir = opendir(path);
if(dir)
{
while((entry = readdir(dir)) != NULL)
{
/* Ignore . and .. */
if(strcmp(entry->d_name,".") &&
strcmp(entry->d_name,".."))
{
char full_name[500];
struct stat stats;
int equivalentObj;
int newObj;
sprintf(full_name,"%s/%s",path,entry->d_name);
lstat(full_name,&stats);
if(S_ISLNK(stats.st_mode) ||
S_ISREG(stats.st_mode) ||
S_ISDIR(stats.st_mode) ||
S_ISFIFO(stats.st_mode) ||
S_ISBLK(stats.st_mode) ||
S_ISCHR(stats.st_mode) ||
S_ISSOCK(stats.st_mode))
{
newObj = obj_id++;
nObjects++;
printf("Object %d, %s is a ",newObj,full_name);
/* We're going to create an object for it */
if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0)
{
/* we need to make a hard link */
printf("hard link to object %d\n",equivalentObj);
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL);
}
else
{
add_obj_to_list(stats.st_dev,stats.st_ino,newObj);
if(S_ISLNK(stats.st_mode))
{
char symname[500];
memset(symname,0, sizeof(symname));
readlink(full_name,symname,sizeof(symname) -1);
printf("symlink to \"%s\"\n",symname);
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname);
}
else if(S_ISREG(stats.st_mode))
{
printf("file, ");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL);
if(error >= 0)
{
int h;
__u8 bytes[chunkSize];
int nBytes;
int chunk = 0;
h = open(full_name,O_RDONLY);
if(h >= 0)
{
memset(bytes,0xff,sizeof(bytes));
while((nBytes = read(h,bytes,sizeof(bytes))) > 0)
{
chunk++;
write_chunk(bytes,newObj,chunk,nBytes);
memset(bytes,0xff,sizeof(bytes));
}
if(nBytes < 0)
error = nBytes;
printf("%d data chunks written\n",chunk);
}
else
{
perror("Error opening file");
}
close(h);
}
}
else if(S_ISSOCK(stats.st_mode))
{
printf("socket\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISFIFO(stats.st_mode))
{
printf("fifo\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISCHR(stats.st_mode))
{
printf("character device\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISBLK(stats.st_mode))
{
printf("block device\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISDIR(stats.st_mode))
{
printf("directory\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL);
// NCB modified 10/9/2001 process_directory(1,full_name);
process_directory(newObj,full_name);
}
}
}
else
{
printf(" we don't handle this type\n");
}
}
}
}
return 0;
}
int main(int argc, char *argv[])
{
struct stat stats;
printf("mkyaffs2image: image building tool for YAFFS2 built "__DATE__"\n");
if(argc < 3)
{
printf("usage: mkyaffs2image dir image_file [convert]\n");
printf(" dir the directory tree to be converted\n");
printf(" image_file the output file to hold the image\n");
printf(" 'convert' produce a big-endian image from a little-endian machine\n");
exit(1);
}
if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert"))))
{
convert_endian = 1;
}
if(stat(argv[1],&stats) < 0)
{
printf("Could not stat %s\n",argv[1]);
exit(1);
}
if(!S_ISDIR(stats.st_mode))
{
printf(" %s is not a directory\n",argv[1]);
exit(1);
}
outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE);
if(outFile < 0)
{
printf("Could not open output file %s\n",argv[2]);
exit(1);
}
printf("Processing directory %s into image file %s\n",argv[1],argv[2]);
error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL);
if(error)
error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]);
close(outFile);
if(error < 0)
{
perror("operation incomplete");
exit(1);
}
else
{
printf("Operation complete.\n"
"%d objects in %d directories\n"
"%d NAND pages\n",nObjects, nDirectories, nPages);
}
close(outFile);
exit(0);
}

@ -1,590 +0,0 @@
/*
* YAFFS: Yet Another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 Aleph One Ltd.
* for Toby Churchill Ltd and Brightstar Engineering
*
* Created by Charles Manning <charles@aleph1.co.uk>
* Nick Bane modifications flagged NCB
* Endian handling patches by James Ng
*
* 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.
*/
/*
* makeyaffsimage.c
*
* Makes a YAFFS file system image that can be used to load up a file system.
*/
#include <stdlib.h>
#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <dirent.h>
#include <string.h>
#include <unistd.h>
#include "yaffs_ecc.h"
#include "yaffs_guts.h"
#define MAX_OBJECTS 10000
const char * mkyaffsimage_c_version = "$Id: mkyaffsimage.c,v 1.7 2003/07/16 03:00:48 charles Exp $";
typedef struct
{
dev_t dev;
ino_t ino;
int obj;
} objItem;
static objItem obj_list[MAX_OBJECTS];
static int n_obj = 0;
static int obj_id = YAFFS_NOBJECT_BUCKETS + 1;
static int nObjects, nDirectories, nPages;
static int outFile;
static int error;
static int convert_endian = 0;
static int obj_compare(const void *a, const void * b)
{
objItem *oa, *ob;
oa = (objItem *)a;
ob = (objItem *)b;
if(oa->dev < ob->dev) return -1;
if(oa->dev > ob->dev) return 1;
if(oa->ino < ob->ino) return -1;
if(oa->ino > ob->ino) return 1;
return 0;
}
static void add_obj_to_list(dev_t dev, ino_t ino, int obj)
{
if(n_obj < MAX_OBJECTS)
{
obj_list[n_obj].dev = dev;
obj_list[n_obj].ino = ino;
obj_list[n_obj].obj = obj;
n_obj++;
qsort(obj_list,n_obj,sizeof(objItem),obj_compare);
}
else
{
// oops! not enough space in the object array
fprintf(stderr,"Not enough space in object array\n");
exit(2);
}
}
static int find_obj_in_list(dev_t dev, ino_t ino)
{
objItem *i = NULL;
objItem test;
test.dev = dev;
test.ino = ino;
if(n_obj > 0)
{
i = bsearch(&test,obj_list,n_obj,sizeof(objItem),obj_compare);
}
if(i)
{
return i->obj;
}
return -1;
}
// NCB added 10/9/2002
static __u16 yaffs_CalcNameSum(const char *name)
{
__u16 sum = 0;
__u16 i = 1;
__u8 *bname = (__u8 *)name;
while (*bname)
{
sum += (*bname) * i;
i++;
bname++;
}
return sum;
}
static void yaffs_CalcECC(const __u8 *data, yaffs_Spare *spare)
{
yaffs_ECCCalculate(data , spare->ecc1);
yaffs_ECCCalculate(&data[256] , spare->ecc2);
}
static void yaffs_CalcTagsECC(yaffs_Tags *tags)
{
// Todo don't do anything yet. Need to calculate ecc
unsigned char *b = ((yaffs_TagsUnion *)tags)->asBytes;
unsigned i,j;
unsigned ecc = 0;
unsigned bit = 0;
// Clear ECC fields
if (!convert_endian)
{
tags->ecc = 0;
}
else
{
// Because we're in "munged tag" mode, we have to clear it manually
b[6] &= 0xC0;
b[7] &= 0x03;
}
for(i = 0; i < 8; i++)
{
// NCB modified 20-9-02 for(j = 1; j &0x7f; j<<=1)
for(j = 1; j &0xff; j<<=1)
{
bit++;
if(b[i] & j)
{
ecc ^= bit;
}
}
}
// Write out ECC
if (!convert_endian)
{
tags->ecc = ecc;
}
else
{
// We have to munge the ECC again.
b[6] |= ((ecc >> 6) & 0x3F);
b[7] |= ((ecc & 0x3F) << 2);
}
}
static void yaffs_LoadTagsIntoSpare(yaffs_Spare *sparePtr, yaffs_Tags *tagsPtr)
{
yaffs_TagsUnion *tu = (yaffs_TagsUnion *)tagsPtr;
//yaffs_CalcTagsECC(tagsPtr);
sparePtr->tagByte0 = tu->asBytes[0];
sparePtr->tagByte1 = tu->asBytes[1];
sparePtr->tagByte2 = tu->asBytes[2];
sparePtr->tagByte3 = tu->asBytes[3];
sparePtr->tagByte4 = tu->asBytes[4];
sparePtr->tagByte5 = tu->asBytes[5];
sparePtr->tagByte6 = tu->asBytes[6];
sparePtr->tagByte7 = tu->asBytes[7];
}
/* This little function converts a little endian tag to a big endian tag.
* NOTE: The tag is not usable after this other than calculating the CRC
* with.
*/
static void little_to_big_endian(yaffs_Tags *tagsPtr)
{
yaffs_TagsUnion * tags = (yaffs_TagsUnion* )tagsPtr; // Work in bytes.
yaffs_TagsUnion temp;
memset(&temp, 0, sizeof(temp));
// Ick, I hate magic numbers.
temp.asBytes[0] = ((tags->asBytes[2] & 0x0F) << 4) | ((tags->asBytes[1] & 0xF0) >> 4);
temp.asBytes[1] = ((tags->asBytes[1] & 0x0F) << 4) | ((tags->asBytes[0] & 0xF0) >> 4);
temp.asBytes[2] = ((tags->asBytes[0] & 0x0F) << 4) | ((tags->asBytes[2] & 0x30) >> 2) | ((tags->asBytes[3] & 0xC0) >> 6);
temp.asBytes[3] = ((tags->asBytes[3] & 0x3F) << 2) | ((tags->asBytes[2] & 0xC0) >> 6);
temp.asBytes[4] = ((tags->asBytes[6] & 0x03) << 6) | ((tags->asBytes[5] & 0xFC) >> 2);
temp.asBytes[5] = ((tags->asBytes[5] & 0x03) << 6) | ((tags->asBytes[4] & 0xFC) >> 2);
temp.asBytes[6] = ((tags->asBytes[4] & 0x03) << 6) | (tags->asBytes[7] & 0x3F);
temp.asBytes[7] = (tags->asBytes[6] & 0xFC) | ((tags->asBytes[7] & 0xC0) >> 6);
// Now copy it back.
tags->asBytes[0] = temp.asBytes[0];
tags->asBytes[1] = temp.asBytes[1];
tags->asBytes[2] = temp.asBytes[2];
tags->asBytes[3] = temp.asBytes[3];
tags->asBytes[4] = temp.asBytes[4];
tags->asBytes[5] = temp.asBytes[5];
tags->asBytes[6] = temp.asBytes[6];
tags->asBytes[7] = temp.asBytes[7];
}
static int write_chunk(__u8 *data, __u32 objId, __u32 chunkId, __u32 nBytes)
{
yaffs_Tags t;
yaffs_Spare s;
error = write(outFile,data,512);
if(error < 0) return error;
memset(&t,0xff,sizeof (yaffs_Tags));
memset(&s,0xff,sizeof (yaffs_Spare));
t.chunkId = chunkId;
t.serialNumber = 0;
t.byteCount = nBytes;
t.objectId = objId;
if (convert_endian)
{
little_to_big_endian(&t);
}
yaffs_CalcTagsECC(&t);
yaffs_LoadTagsIntoSpare(&s,&t);
yaffs_CalcECC(data,&s);
nPages++;
return write(outFile,&s,sizeof(yaffs_Spare));
}
#define SWAP32(x) ((((x) & 0x000000FF) << 24) | \
(((x) & 0x0000FF00) << 8 ) | \
(((x) & 0x00FF0000) >> 8 ) | \
(((x) & 0xFF000000) >> 24))
#define SWAP16(x) ((((x) & 0x00FF) << 8) | \
(((x) & 0xFF00) >> 8))
// This one is easier, since the types are more standard. No funky shifts here.
static void object_header_little_to_big_endian(yaffs_ObjectHeader* oh)
{
oh->type = SWAP32(oh->type); // GCC makes enums 32 bits.
oh->parentObjectId = SWAP32(oh->parentObjectId); // int
oh->sum__NoLongerUsed = SWAP16(oh->sum__NoLongerUsed); // __u16 - Not used, but done for completeness.
// name = skip. Char array. Not swapped.
oh->yst_mode = SWAP32(oh->yst_mode);
#ifdef CONFIG_YAFFS_WINCE // WinCE doesn't implement this, but we need to just in case.
// In fact, WinCE would be *THE* place where this would be an issue!
oh->notForWinCE[0] = SWAP32(oh->notForWinCE[0]);
oh->notForWinCE[1] = SWAP32(oh->notForWinCE[1]);
oh->notForWinCE[2] = SWAP32(oh->notForWinCE[2]);
oh->notForWinCE[3] = SWAP32(oh->notForWinCE[3]);
oh->notForWinCE[4] = SWAP32(oh->notForWinCE[4]);
#else
// Regular POSIX.
oh->yst_uid = SWAP32(oh->yst_uid);
oh->yst_gid = SWAP32(oh->yst_gid);
oh->yst_atime = SWAP32(oh->yst_atime);
oh->yst_mtime = SWAP32(oh->yst_mtime);
oh->yst_ctime = SWAP32(oh->yst_ctime);
#endif
oh->fileSize = SWAP32(oh->fileSize); // Aiee. An int... signed, at that!
oh->equivalentObjectId = SWAP32(oh->equivalentObjectId);
// alias - char array.
oh->yst_rdev = SWAP32(oh->yst_rdev);
#ifdef CONFIG_YAFFS_WINCE
oh->win_ctime[0] = SWAP32(oh->win_ctime[0]);
oh->win_ctime[1] = SWAP32(oh->win_ctime[1]);
oh->win_atime[0] = SWAP32(oh->win_atime[0]);
oh->win_atime[1] = SWAP32(oh->win_atime[1]);
oh->win_mtime[0] = SWAP32(oh->win_mtime[0]);
oh->win_mtime[1] = SWAP32(oh->win_mtime[1]);
oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]);
oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]);
oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]);
oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]);
oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]);
oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]);
#else
oh->roomToGrow[0] = SWAP32(oh->roomToGrow[0]);
oh->roomToGrow[1] = SWAP32(oh->roomToGrow[1]);
oh->roomToGrow[2] = SWAP32(oh->roomToGrow[2]);
oh->roomToGrow[3] = SWAP32(oh->roomToGrow[3]);
oh->roomToGrow[4] = SWAP32(oh->roomToGrow[4]);
oh->roomToGrow[5] = SWAP32(oh->roomToGrow[5]);
oh->roomToGrow[6] = SWAP32(oh->roomToGrow[6]);
oh->roomToGrow[7] = SWAP32(oh->roomToGrow[7]);
oh->roomToGrow[8] = SWAP32(oh->roomToGrow[8]);
oh->roomToGrow[9] = SWAP32(oh->roomToGrow[9]);
oh->roomToGrow[10] = SWAP32(oh->roomToGrow[10]);
oh->roomToGrow[11] = SWAP32(oh->roomToGrow[11]);
#endif
}
static int write_object_header(int objId, yaffs_ObjectType t, struct stat *s, int parent, const char *name, int equivalentObj, const char * alias)
{
__u8 bytes[512];
yaffs_ObjectHeader *oh = (yaffs_ObjectHeader *)bytes;
memset(bytes,0xff,512);
oh->type = t;
oh->parentObjectId = parent;
strncpy(oh->name,name,YAFFS_MAX_NAME_LENGTH);
if(t != YAFFS_OBJECT_TYPE_HARDLINK)
{
oh->yst_mode = s->st_mode;
oh->yst_uid = s->st_uid;
// NCB 12/9/02 oh->yst_gid = s->yst_uid;
oh->yst_gid = s->st_gid;
oh->yst_atime = s->st_atime;
oh->yst_mtime = s->st_mtime;
oh->yst_ctime = s->st_ctime;
oh->yst_rdev = s->st_rdev;
}
if(t == YAFFS_OBJECT_TYPE_FILE)
{
oh->fileSize = s->st_size;
}
if(t == YAFFS_OBJECT_TYPE_HARDLINK)
{
oh->equivalentObjectId = equivalentObj;
}
if(t == YAFFS_OBJECT_TYPE_SYMLINK)
{
strncpy(oh->alias,alias,YAFFS_MAX_ALIAS_LENGTH);
}
if (convert_endian)
{
object_header_little_to_big_endian(oh);
}
return write_chunk(bytes,objId,0,0xffff);
}
static int process_directory(int parent, const char *path)
{
DIR *dir;
struct dirent *entry;
nDirectories++;
dir = opendir(path);
if(dir)
{
while((entry = readdir(dir)) != NULL)
{
/* Ignore . and .. */
if(strcmp(entry->d_name,".") &&
strcmp(entry->d_name,".."))
{
char full_name[500];
struct stat stats;
int equivalentObj;
int newObj;
sprintf(full_name,"%s/%s",path,entry->d_name);
lstat(full_name,&stats);
if(S_ISLNK(stats.st_mode) ||
S_ISREG(stats.st_mode) ||
S_ISDIR(stats.st_mode) ||
S_ISFIFO(stats.st_mode) ||
S_ISBLK(stats.st_mode) ||
S_ISCHR(stats.st_mode) ||
S_ISSOCK(stats.st_mode))
{
newObj = obj_id++;
nObjects++;
printf("Object %d, %s is a ",newObj,full_name);
/* We're going to create an object for it */
if((equivalentObj = find_obj_in_list(stats.st_dev, stats.st_ino)) > 0)
{
/* we need to make a hard link */
printf("hard link to object %d\n",equivalentObj);
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_HARDLINK, &stats, parent, entry->d_name, equivalentObj, NULL);
}
else
{
add_obj_to_list(stats.st_dev,stats.st_ino,newObj);
if(S_ISLNK(stats.st_mode))
{
char symname[500];
memset(symname,0, sizeof(symname));
readlink(full_name,symname,sizeof(symname) -1);
printf("symlink to \"%s\"\n",symname);
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SYMLINK, &stats, parent, entry->d_name, -1, symname);
}
else if(S_ISREG(stats.st_mode))
{
printf("file, ");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_FILE, &stats, parent, entry->d_name, -1, NULL);
if(error >= 0)
{
int h;
__u8 bytes[512];
int nBytes;
int chunk = 0;
h = open(full_name,O_RDONLY);
if(h >= 0)
{
memset(bytes,0xff,512);
while((nBytes = read(h,bytes,512)) > 0)
{
chunk++;
write_chunk(bytes,newObj,chunk,nBytes);
memset(bytes,0xff,512);
}
if(nBytes < 0)
error = nBytes;
printf("%d data chunks written\n",chunk);
}
else
{
perror("Error opening file");
}
close(h);
}
}
else if(S_ISSOCK(stats.st_mode))
{
printf("socket\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISFIFO(stats.st_mode))
{
printf("fifo\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISCHR(stats.st_mode))
{
printf("character device\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISBLK(stats.st_mode))
{
printf("block device\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_SPECIAL, &stats, parent, entry->d_name, -1, NULL);
}
else if(S_ISDIR(stats.st_mode))
{
printf("directory\n");
error = write_object_header(newObj, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, parent, entry->d_name, -1, NULL);
// NCB modified 10/9/2001 process_directory(1,full_name);
process_directory(newObj,full_name);
}
}
}
else
{
printf(" we don't handle this type\n");
}
}
}
}
return 0;
}
int main(int argc, char *argv[])
{
struct stat stats;
printf("mkyaffsimage: image building tool for YAFFS built "__DATE__"\n");
if(argc < 3)
{
printf("usage: mkyaffsimage dir image_file [convert]\n");
printf(" dir the directory tree to be converted\n");
printf(" image_file the output file to hold the image\n");
printf(" 'convert' produce a big-endian image from a little-endian machine\n");
exit(1);
}
if ((argc == 4) && (!strncmp(argv[3], "convert", strlen("convert"))))
{
convert_endian = 1;
}
if(stat(argv[1],&stats) < 0)
{
printf("Could not stat %s\n",argv[1]);
exit(1);
}
if(!S_ISDIR(stats.st_mode))
{
printf(" %s is not a directory\n",argv[1]);
exit(1);
}
outFile = open(argv[2],O_CREAT | O_TRUNC | O_WRONLY, S_IREAD | S_IWRITE);
if(outFile < 0)
{
printf("Could not open output file %s\n",argv[2]);
exit(1);
}
printf("Processing directory %s into image file %s\n",argv[1],argv[2]);
error = write_object_header(1, YAFFS_OBJECT_TYPE_DIRECTORY, &stats, 1,"", -1, NULL);
if(error)
error = process_directory(YAFFS_OBJECTID_ROOT,argv[1]);
close(outFile);
if(error < 0)
{
perror("operation incomplete");
exit(1);
}
else
{
printf("Operation complete.\n"
"%d objects in %d directories\n"
"%d NAND pages\n",nObjects, nDirectories, nPages);
}
close(outFile);
exit(0);
}

File diff suppressed because it is too large Load Diff

@ -1,369 +0,0 @@
/*
* YAFFS: Yet another FFS. A NAND-flash specific file system.
* yaffs_mtdif1.c NAND mtd interface functions for small-page NAND.
*
* Copyright (C) 2002 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 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_TagsCompatability 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 (useNANDECC is true).
*/
#include "yportenv.h"
#include "yaffs_guts.h"
#include "yaffs_packedtags1.h"
#include "yaffs_tagscompat.h" // for yaffs_CalcTagsECC
#include "linux/kernel.h"
#include "linux/version.h"
#include "linux/types.h"
#include "linux/mtd/mtd.h"
/* Don't compile this module if we don't have MTD's mtd_oob_ops interface */
#if (LINUX_VERSION_CODE > KERNEL_VERSION(2,6,17))
const char *yaffs_mtdif1_c_version = "$Id: yaffs_mtdif1.c,v 1.5 2007/10/29 14:59:57 imcd Exp $";
#ifndef CONFIG_YAFFS_9BYTE_TAGS
# define YTAG1_SIZE 8
#else
# define YTAG1_SIZE 9
#endif
#if 0
/* Use the following nand_ecclayout with MTD when using
* CONFIG_YAFFS_9BYTE_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
* pageStatus 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 PackedTags1 plus pageStatus: T0,T1,T2,T3,T4,T5,T6,T7,P
* where Tn are the tag bytes, En are MTD's ECC bytes, P is the pageStatus
* 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 PackedTags1 form
* - Compute mini-ECC for PackedTags1
* - Write data and packed tags to NAND.
*
* Note: Due to the use of the PackedTags1 meta-data which does not include
* a full sequence number (as found in the larger PackedTags2 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_WriteChunkWithTagsToNAND(yaffs_Device *dev,
int chunkInNAND, const __u8 * data, const yaffs_ExtendedTags * etags)
{
struct mtd_info * mtd = dev->genericDevice;
int chunkBytes = dev->nDataBytesPerChunk;
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
struct mtd_oob_ops ops;
yaffs_PackedTags1 pt1;
int retval;
/* we assume that PackedTags1 and yaffs_Tags are compatible */
compile_time_assertion(sizeof(yaffs_PackedTags1) == 12);
compile_time_assertion(sizeof(yaffs_Tags) == 8);
dev->nPageWrites++;
yaffs_PackTags1(&pt1, etags);
yaffs_CalcTagsECC((yaffs_Tags *)&pt1);
/* When deleting a chunk, the upper layer provides only skeletal
* etags, one with chunkDeleted 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.
*/
#ifndef CONFIG_YAFFS_9BYTE_TAGS
if (etags->chunkDeleted) {
memset(&pt1, 0xff, 8);
/* clear delete status bit to indicate deleted */
pt1.deleted = 0;
}
#else
((__u8 *)&pt1)[8] = 0xff;
if (etags->chunkDeleted) {
memset(&pt1, 0xff, 8);
/* zero pageStatus byte to indicate deleted */
((__u8 *)&pt1)[8] = 0;
}
#endif
memset(&ops, 0, sizeof(ops));
ops.mode = MTD_OOB_AUTO;
ops.len = (data) ? chunkBytes : 0;
ops.ooblen = YTAG1_SIZE;
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\n",
chunkInNAND, retval);
}
return retval ? YAFFS_FAIL : YAFFS_OK;
}
/* Return with empty ExtendedTags but add eccResult.
*/
static int rettags(yaffs_ExtendedTags * etags, int eccResult, int retval)
{
if (etags) {
memset(etags, 0, sizeof(*etags));
etags->eccResult = eccResult;
}
return retval;
}
/* Read a chunk (page) from NAND.
*
* Caller expects ExtendedTags data to be usable even on error; that is,
* all members except eccResult and blockBad are zeroed.
*
* - Check ECC results for data (if applicable)
* - Check for blank/erased block (return empty ExtendedTags if blank)
* - Check the PackedTags1 mini-ECC (correct if necessary/possible)
* - Convert PackedTags1 to ExtendedTags
* - Update eccResult and blockBad members to refect state.
*
* Returns YAFFS_OK or YAFFS_FAIL.
*/
int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device *dev,
int chunkInNAND, __u8 * data, yaffs_ExtendedTags * etags)
{
struct mtd_info * mtd = dev->genericDevice;
int chunkBytes = dev->nDataBytesPerChunk;
loff_t addr = ((loff_t)chunkInNAND) * chunkBytes;
int eccres = YAFFS_ECC_RESULT_NO_ERROR;
struct mtd_oob_ops ops;
yaffs_PackedTags1 pt1;
int retval;
int deleted;
dev->nPageReads++;
memset(&ops, 0, sizeof(ops));
ops.mode = MTD_OOB_AUTO;
ops.len = (data) ? chunkBytes : 0;
ops.ooblen = YTAG1_SIZE;
ops.datbuf = data;
ops.oobbuf = (__u8 *)&pt1;
#if (LINUX_VERSION_CODE < KERNEL_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\n",
chunkInNAND, retval);
}
switch (retval) {
case 0:
/* no error */
break;
case -EUCLEAN:
/* MTD's ECC fixed the data */
eccres = YAFFS_ECC_RESULT_FIXED;
dev->eccFixed++;
break;
case -EBADMSG:
/* MTD's ECC could not fix the data */
dev->eccUnfixed++;
/* fall into... */
default:
rettags(etags, YAFFS_ECC_RESULT_UNFIXED, 0);
etags->blockBad = (mtd->block_isbad)(mtd, addr);
return YAFFS_FAIL;
}
/* Check for a blank/erased chunk.
*/
if (yaffs_CheckFF((__u8 *)&pt1, 8)) {
/* when blank, upper layers want eccResult 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 = (yaffs_CountBits(((__u8 *)&pt1)[8]) < 7);
#endif
/* Check the packed tags mini-ECC and correct if necessary/possible.
*/
retval = yaffs_CheckECCOnTags((yaffs_Tags *)&pt1);
switch (retval) {
case 0:
/* no tags error, use MTD result */
break;
case 1:
/* recovered tags-ECC error */
dev->tagsEccFixed++;
if (eccres == YAFFS_ECC_RESULT_NO_ERROR)
eccres = YAFFS_ECC_RESULT_FIXED;
break;
default:
/* unrecovered tags-ECC error */
dev->tagsEccUnfixed++;
return rettags(etags, YAFFS_ECC_RESULT_UNFIXED, YAFFS_FAIL);
}
/* Unpack the tags to extended form and set ECC result.
* [set shouldBeFF just to keep yaffs_UnpackTags1 happy]
*/
pt1.shouldBeFF = 0xFFFFFFFF;
yaffs_UnpackTags1(etags, &pt1);
etags->eccResult = eccres;
/* Set deleted state */
etags->chunkDeleted = 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_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo)
{
struct mtd_info * mtd = dev->genericDevice;
int blocksize = dev->nChunksPerBlock * dev->nDataBytesPerChunk;
int retval;
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS, "marking block %d bad\n", blockNo);
retval = mtd->block_markbad(mtd, (loff_t)blocksize * blockNo);
return (retval) ? YAFFS_FAIL : YAFFS_OK;
}
/* Check any MTD prerequists.
*
* Returns YAFFS_OK or YAFFS_FAIL.
*/
static int nandmtd1_TestPrerequists(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 < YTAG1_SIZE) {
yaffs_trace(YAFFS_TRACE_ERROR,
"mtd device has only %d bytes for tags, need %d\n",
oobavail, YTAG1_SIZE);
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_SCANNING, the block is in use
* - YAFFS_BLOCK_STATE_EMPTY, the block is clean
*
* Always returns YAFFS_OK.
*/
int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState * pState, int *pSequenceNumber)
{
struct mtd_info * mtd = dev->genericDevice;
int chunkNo = blockNo * dev->nChunksPerBlock;
loff_t addr = (loff_t)chunkNo * dev->nDataBytesPerChunk;
yaffs_ExtendedTags 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_TestPrerequists(mtd) != YAFFS_OK) {
return YAFFS_FAIL;
}
retval = nandmtd1_ReadChunkWithTagsFromNAND(dev, chunkNo, NULL, &etags);
etags.blockBad = (mtd->block_isbad)(mtd, addr);
if (etags.blockBad) {
yaffs_trace(YAFFS_TRACE_BAD_BLOCKS,
"block %d is marked bad\n", blockNo);
state = YAFFS_BLOCK_STATE_DEAD;
}
else if (etags.eccResult != YAFFS_ECC_RESULT_NO_ERROR) {
/* bad tags, need to look more closely */
state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
}
else if (etags.chunkUsed) {
state = YAFFS_BLOCK_STATE_NEEDS_SCANNING;
seqnum = etags.sequenceNumber;
}
else {
state = YAFFS_BLOCK_STATE_EMPTY;
}
*pState = state;
*pSequenceNumber = seqnum;
/* query always succeeds */
return YAFFS_OK;
}
#endif /*KERNEL_VERSION*/

@ -1,28 +0,0 @@
/*
* YAFFS: Yet another Flash File System. A NAND-flash specific file system.
*
* Copyright (C) 2002-2007 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_WriteChunkWithTagsToNAND(yaffs_Device * dev, int chunkInNAND,
const __u8 * data, const yaffs_ExtendedTags * tags);
int nandmtd1_ReadChunkWithTagsFromNAND(yaffs_Device * dev, int chunkInNAND,
__u8 * data, yaffs_ExtendedTags * tags);
int nandmtd1_MarkNANDBlockBad(struct yaffs_DeviceStruct *dev, int blockNo);
int nandmtd1_QueryNANDBlock(struct yaffs_DeviceStruct *dev, int blockNo,
yaffs_BlockState * state, int *sequenceNumber);
#endif
Loading…
Cancel
Save