mirror of
https://gitlab.rtems.org/rtems/rtos/rtems.git
synced 2026-08-28 05:03:37 +08:00
JFFS2: Add RTEMS support
This commit is contained in:
@@ -120,6 +120,9 @@ include_rtems_rfs_HEADERS += libfs/src/rfs/rtems-rfs-link.h
|
||||
include_rtems_rfs_HEADERS += libfs/src/rfs/rtems-rfs-mutex.h
|
||||
include_rtems_rfs_HEADERS += libfs/src/rfs/rtems-rfs-trace.h
|
||||
|
||||
# JFFS2
|
||||
include_rtems_HEADERS += libfs/src/jffs2/include/rtems/jffs2.h
|
||||
|
||||
## libblock
|
||||
include_rtems_HEADERS += libblock/include/rtems/bdbuf.h
|
||||
include_rtems_HEADERS += libblock/include/rtems/blkdev.h
|
||||
|
||||
@@ -1437,6 +1437,7 @@ extern int rtems_mkdir(const char *path, mode_t mode);
|
||||
#define RTEMS_FILESYSTEM_TYPE_NFS "nfs"
|
||||
#define RTEMS_FILESYSTEM_TYPE_DOSFS "dosfs"
|
||||
#define RTEMS_FILESYSTEM_TYPE_RFS "rfs"
|
||||
#define RTEMS_FILESYSTEM_TYPE_JFFS2 "jffs2"
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
@@ -102,6 +102,35 @@ librfs_a_SOURCES = \
|
||||
src/rfs/rtems-rfs-rtems-dir.c src/rfs/rtems-rfs-rtems-file.c \
|
||||
src/rfs/rtems-rfs-trace.c
|
||||
|
||||
# JFFS2
|
||||
noinst_LIBRARIES += libjffs2.a
|
||||
libjffs2_a_SOURCES =
|
||||
libjffs2_a_SOURCES += src/jffs2/src/build.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/compat-crc32.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/compat-rbtree.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/compr.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/compr_rtime.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/compr_zlib.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/debug.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/dir-rtems.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/erase.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/flashio.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/fs-rtems.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/gc.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/malloc-rtems.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/nodelist.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/nodemgmt.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/read.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/readinode.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/scan.c
|
||||
libjffs2_a_SOURCES += src/jffs2/src/write.c
|
||||
libjffs2_a_CFLAGS =
|
||||
libjffs2_a_CFLAGS += -Wno-pointer-sign
|
||||
libjffs2_a_CPPFLAGS =
|
||||
libjffs2_a_CPPFLAGS += $(AM_CPPFLAGS) -I$(srcdir)/src/jffs2/include
|
||||
libjffs2_a_CPPFLAGS += -D__ECOS
|
||||
libjffs2_a_CPPFLAGS += '-DKBUILD_MODNAME="JFFS2"'
|
||||
|
||||
# ---
|
||||
include $(srcdir)/preinstall.am
|
||||
include $(top_srcdir)/automake/subdirs.am
|
||||
|
||||
@@ -55,130 +55,11 @@
|
||||
//
|
||||
|
||||
#include <stddef.h> // Definition of NULL from the compiler
|
||||
#include <stdint.h>
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Some useful macros. These are defined here by default.
|
||||
typedef uint16_t cyg_uint16;
|
||||
|
||||
// __externC is used in mixed C/C++ headers to force C linkage on an external
|
||||
// definition. It avoids having to put all sorts of ifdefs in.
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define __externC extern "C"
|
||||
#else
|
||||
# define __externC extern
|
||||
#endif
|
||||
// Also define externC for now - but it is deprecated
|
||||
#define externC __externC
|
||||
|
||||
// Compiler version.
|
||||
#ifdef __GNUC__
|
||||
# if defined(__GNU_PATCHLEVEL__)
|
||||
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100 \
|
||||
+ __GNUC_PATCHLEVEL__)
|
||||
# else
|
||||
# define __GNUC_VERSION__ (__GNUC__ * 10000 \
|
||||
+ __GNUC_MINOR__ * 100)
|
||||
# endif
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// The header <basetype.h> defines the base types used here. It is
|
||||
// supplied either by the target architecture HAL, or by the host
|
||||
// porting kit. They are all defined as macros, and only those that
|
||||
// make choices other than the defaults given below need be defined.
|
||||
|
||||
#define CYG_LSBFIRST 1234
|
||||
#define CYG_MSBFIRST 4321
|
||||
|
||||
#include <cyg/hal/basetype.h>
|
||||
|
||||
#if (CYG_BYTEORDER != CYG_LSBFIRST) && (CYG_BYTEORDER != CYG_MSBFIRST)
|
||||
# error You must define CYG_BYTEORDER to equal CYG_LSBFIRST or CYG_MSBFIRST
|
||||
#endif
|
||||
|
||||
#ifndef CYG_DOUBLE_BYTEORDER
|
||||
#define CYG_DOUBLE_BYTEORDER CYG_BYTEORDER
|
||||
#endif
|
||||
|
||||
#ifndef cyg_halint8
|
||||
# define cyg_halint8 char
|
||||
#endif
|
||||
#ifndef cyg_halint16
|
||||
# define cyg_halint16 short
|
||||
#endif
|
||||
#ifndef cyg_halint32
|
||||
# define cyg_halint32 int
|
||||
#endif
|
||||
#ifndef cyg_halint64
|
||||
# define cyg_halint64 long long
|
||||
#endif
|
||||
|
||||
#ifndef cyg_halcount8
|
||||
# define cyg_halcount8 int
|
||||
#endif
|
||||
#ifndef cyg_halcount16
|
||||
# define cyg_halcount16 int
|
||||
#endif
|
||||
#ifndef cyg_halcount32
|
||||
# define cyg_halcount32 int
|
||||
#endif
|
||||
#ifndef cyg_halcount64
|
||||
# define cyg_halcount64 long long
|
||||
#endif
|
||||
|
||||
#ifndef cyg_haladdress
|
||||
# define cyg_haladdress cyg_uint32
|
||||
#endif
|
||||
#ifndef cyg_haladdrword
|
||||
# define cyg_haladdrword cyg_uint32
|
||||
#endif
|
||||
|
||||
#ifndef cyg_halbool
|
||||
# define cyg_halbool int
|
||||
#endif
|
||||
|
||||
#ifndef cyg_halatomic
|
||||
# define cyg_halatomic cyg_halint8
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Provide a default architecture alignment
|
||||
// This may be overridden in basetype.h if necessary.
|
||||
// These should be straightforward numbers to allow use in assembly.
|
||||
|
||||
#ifndef CYGARC_ALIGNMENT
|
||||
# define CYGARC_ALIGNMENT 8
|
||||
#endif
|
||||
// And corresponding power of two alignment
|
||||
#ifndef CYGARC_P2ALIGNMENT
|
||||
# define CYGARC_P2ALIGNMENT 3
|
||||
#endif
|
||||
#if (CYGARC_ALIGNMENT) != (1 << CYGARC_P2ALIGNMENT)
|
||||
# error "Inconsistent CYGARC_ALIGNMENT and CYGARC_P2ALIGNMENT values"
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// The obvious few that compilers may define for you.
|
||||
// But in case they don't:
|
||||
|
||||
#ifndef NULL
|
||||
# define NULL 0
|
||||
#endif
|
||||
|
||||
#ifndef __cplusplus
|
||||
|
||||
typedef cyg_halbool bool;
|
||||
|
||||
# ifndef false
|
||||
# define false 0
|
||||
# endif
|
||||
|
||||
# ifndef true
|
||||
# define true (!false)
|
||||
# endif
|
||||
|
||||
#endif
|
||||
typedef uint32_t cyg_uint32;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Allow creation of procedure-like macros that are a single statement,
|
||||
@@ -195,365 +76,6 @@ typedef cyg_halbool bool;
|
||||
__tmp1 = __tmp2; \
|
||||
CYG_MACRO_END
|
||||
|
||||
|
||||
//----------------------------------------------------------------------------
|
||||
// The unused attribute stops the compiler warning about the variable
|
||||
// not being used.
|
||||
// The used attribute prevents the compiler from optimizing it away.
|
||||
|
||||
#define CYG_REFERENCE_OBJECT(__object__) \
|
||||
CYG_MACRO_START \
|
||||
static const void* __cygvar_discard_me__ \
|
||||
__attribute__ ((unused, used)) = (const void*)&(__object__); \
|
||||
CYG_MACRO_END
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define basic types for using integers in memory and structures;
|
||||
// depends on compiler defaults and CPU type.
|
||||
|
||||
typedef unsigned cyg_halint8 cyg_uint8 ;
|
||||
typedef signed cyg_halint8 cyg_int8 ;
|
||||
|
||||
typedef unsigned cyg_halint16 cyg_uint16 ;
|
||||
typedef signed cyg_halint16 cyg_int16 ;
|
||||
|
||||
typedef unsigned cyg_halint32 cyg_uint32 ;
|
||||
typedef signed cyg_halint32 cyg_int32 ;
|
||||
|
||||
typedef unsigned cyg_halint64 cyg_uint64 ;
|
||||
typedef signed cyg_halint64 cyg_int64 ;
|
||||
|
||||
typedef cyg_halbool cyg_bool ;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define types for using integers in registers for looping and the like;
|
||||
// depends on CPU type, choose what it is most comfortable with, with at
|
||||
// least the range required.
|
||||
|
||||
typedef unsigned cyg_halcount8 cyg_ucount8 ;
|
||||
typedef signed cyg_halcount8 cyg_count8 ;
|
||||
|
||||
typedef unsigned cyg_halcount16 cyg_ucount16 ;
|
||||
typedef signed cyg_halcount16 cyg_count16 ;
|
||||
|
||||
typedef unsigned cyg_halcount32 cyg_ucount32 ;
|
||||
typedef signed cyg_halcount32 cyg_count32 ;
|
||||
|
||||
typedef unsigned cyg_halcount64 cyg_ucount64 ;
|
||||
typedef signed cyg_halcount64 cyg_count64 ;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define a type to be used for atomic accesses. This type is guaranteed
|
||||
// to be read or written in a single uninterruptible operation. This type
|
||||
// is at least a single byte.
|
||||
|
||||
typedef volatile unsigned cyg_halatomic cyg_atomic;
|
||||
typedef volatile unsigned cyg_halatomic CYG_ATOMIC;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Define types for access plain, on-the-metal memory or devices.
|
||||
|
||||
typedef cyg_uint32 CYG_WORD;
|
||||
typedef cyg_uint8 CYG_BYTE;
|
||||
typedef cyg_uint16 CYG_WORD16;
|
||||
typedef cyg_uint32 CYG_WORD32;
|
||||
typedef cyg_uint64 CYG_WORD64;
|
||||
|
||||
typedef cyg_haladdress CYG_ADDRESS;
|
||||
typedef cyg_haladdrword CYG_ADDRWORD;
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Number of elements in a (statically allocated) array.
|
||||
|
||||
#define CYG_NELEM(a) (sizeof(a) / sizeof((a)[0]))
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Constructor ordering macros. These are added as annotations to all
|
||||
// static objects to order the constuctors appropriately.
|
||||
|
||||
#if defined(__cplusplus) && defined(__GNUC__) && \
|
||||
!defined(CYGBLD_ATTRIB_INIT_PRI)
|
||||
# define CYGBLD_ATTRIB_INIT_PRI( _pri_ ) __attribute__((init_priority(_pri_)))
|
||||
#elif !defined(CYGBLD_ATTRIB_INIT_PRI)
|
||||
// FIXME: should maybe just bomb out if this is attempted anywhere else?
|
||||
// Not sure
|
||||
# define CYGBLD_ATTRIB_INIT_PRI( _pri_ )
|
||||
#endif
|
||||
|
||||
// The following will be removed eventually as it doesn't allow the use of
|
||||
// e.g. pri+5 format
|
||||
#define CYG_INIT_PRIORITY( _pri_ ) CYGBLD_ATTRIB_INIT_PRI( CYG_INIT_##_pri_ )
|
||||
|
||||
#define CYGBLD_ATTRIB_INIT_BEFORE( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_-100)
|
||||
#define CYGBLD_ATTRIB_INIT_AFTER( _pri_ ) CYGBLD_ATTRIB_INIT_PRI(_pri_+100)
|
||||
|
||||
#if defined(__GNUC__) && !defined(__cplusplus) && (__GNUC_VERSION__ >= 40300)
|
||||
// Equivalents of the above for C functions, available from gcc 4.3 onwards.
|
||||
# define CYGBLD_ATTRIB_C_INIT_PRI( _pri_) __attribute__((constructor (_pri_)))
|
||||
# define CYGBLD_ATTRIB_C_INIT_BEFORE( _pri_ ) __attribute__((constructor (_pri_-100)))
|
||||
# define CYGBLD_ATTRIB_C_INIT_AFTER( _pri_ ) __attribute__((constructor (_pri_+100)))
|
||||
#endif
|
||||
|
||||
// Start with initializing everything inside the cpu and the main memory.
|
||||
#define CYG_INIT_HAL 10000
|
||||
#define CYG_INIT_SCHEDULER 11000
|
||||
#define CYG_INIT_IDLE_THREAD 11100
|
||||
#define CYG_INIT_INTERRUPTS 12000
|
||||
#define CYG_INIT_CLOCK 14000
|
||||
#define CYG_INIT_THREADS 16000
|
||||
#define CYG_INIT_KERNEL 19000
|
||||
#define CYG_INIT_MEMALLOC 20000
|
||||
// Now move on to I/O subsystems and device drivers. These can make use of
|
||||
// kernel and HAL functionality, and can dynamically allocate memory if
|
||||
// absolutely needed. For now they can also assume that diag_printf()
|
||||
// functionality is available, but that may change in future.
|
||||
//
|
||||
// Primary buses are ones very closely tied to the processor, e.g. PCI.
|
||||
#define CYG_INIT_BUS_PRIMARY 30000
|
||||
// Not yet: on some targets cyg_pci_init() has to be called very early
|
||||
// on for HAL diagnostics to work.
|
||||
// #define CYG_INIT_BUS_PCI CYG_INIT_BUS_PRIMARY
|
||||
//
|
||||
// Secondary buses may hang off primary buses, e.g. USB host.
|
||||
#define CYG_INIT_BUS_SECONDARY 31000
|
||||
// Tertiary buses are everything else.
|
||||
#define CYG_INIT_BUS_TERTIARY 32000
|
||||
#define CYG_INIT_BUS_I2C CYG_INIT_BUS_TERTIARY
|
||||
#define CYG_INIT_BUS_SPI CYG_INIT_BUS_TERTIARY
|
||||
//
|
||||
// In future HAL diag initialization may happen at this point.
|
||||
//
|
||||
// Watchdogs and wallclocks often hang off a tertiary bus but
|
||||
// have no dependencies
|
||||
#define CYG_INIT_DEV_WATCHDOG 35000
|
||||
#define CYG_INIT_DEV_WALLCLOCK 36000
|
||||
// A primary block configuration can be initialized with no need
|
||||
// for per-unit configuration information.
|
||||
#define CYG_INIT_DEV_BLOCK_PRIMARY 37000
|
||||
#define CYG_INIT_DEV_FLASH CYG_INIT_DEV_BLOCK_PRIMARY
|
||||
// Per-unit configuration data extracted from primary storage.
|
||||
// NOTE: for future use, not implemented yet.
|
||||
#define CYG_INIT_CONFIG 38000
|
||||
// Secondary block devices may use per-unit configuration data
|
||||
// for e.g. interpreting partition layout. Few devices are expected
|
||||
// to fall into this category. Note that these devices, as well as
|
||||
// some char devices, may not actually be usable until interrupts
|
||||
// are enabled.
|
||||
#define CYG_INIT_DEV_BLOCK_SECONDARY 40000
|
||||
// Char devices are everything else: serial, ethernet, CAN, ...
|
||||
#define CYG_INIT_DEV_CHAR 41000
|
||||
// For backwards compatibility. Subject to change in future so
|
||||
// a CYG_INIT_DEV_ priority should be used instead.
|
||||
#define CYG_INIT_DRIVERS 48000
|
||||
// CYG_INIT_IO and CYG_INIT_IO_FS are poorly defined at present,
|
||||
// and may get reorganized in future.
|
||||
#define CYG_INIT_IO 49000
|
||||
#define CYG_INIT_IO_FS 50000
|
||||
// The I/O subsystems and device drivers have been initialized.
|
||||
#define CYG_INIT_LIBC 56000
|
||||
#define CYG_INIT_COMPAT 58000
|
||||
#define CYG_INIT_APPLICATION 60000
|
||||
#define CYG_INIT_PREDEFAULT 65534
|
||||
#define CYG_INIT_DEFAULT 65535
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Label name macros. Some toolsets generate labels with initial
|
||||
// underscores and others don't. CYG_LABEL_NAME should be used on
|
||||
// labels in C/C++ code that are defined in assembly code or linker
|
||||
// scripts. CYG_LABEL_DEFN is for use in assembly code and linker
|
||||
// scripts where we need to manufacture labels that can be used from
|
||||
// C/C++.
|
||||
// These are default implementations that should work for most targets.
|
||||
// They may be overridden in basetype.h if necessary.
|
||||
|
||||
#ifndef CYG_LABEL_NAME
|
||||
|
||||
#define CYG_LABEL_NAME(_name_) _name_
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef CYG_LABEL_DEFN
|
||||
|
||||
#define CYG_LABEL_DEFN(_label) _label
|
||||
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// COMPILER-SPECIFIC STUFF
|
||||
|
||||
#ifdef __GNUC__
|
||||
// Force a 'C' routine to be called like a 'C++' contructor
|
||||
# if !defined(CYGBLD_ATTRIB_CONSTRUCTOR)
|
||||
# define CYGBLD_ATTRIB_CONSTRUCTOR __attribute__((constructor))
|
||||
# endif
|
||||
|
||||
// Define a compiler-specific rune for saying a function doesn't return
|
||||
# if !defined(CYGBLD_ATTRIB_NORET)
|
||||
# define CYGBLD_ATTRIB_NORET __attribute__((noreturn))
|
||||
# endif
|
||||
|
||||
// How to define weak symbols - this is only relevant for ELF and a.out,
|
||||
// but that won't be a problem for eCos
|
||||
# if !defined(CYGBLD_ATTRIB_WEAK)
|
||||
# define CYGBLD_ATTRIB_WEAK __attribute__ ((weak))
|
||||
# endif
|
||||
|
||||
// How to define alias to symbols. Just pass in the symbol itself, not
|
||||
// the string name of the symbol
|
||||
# if !defined(CYGBLD_ATTRIB_ALIAS)
|
||||
# define CYGBLD_ATTRIB_ALIAS(__symbol__) \
|
||||
__attribute__ ((alias (#__symbol__)))
|
||||
# endif
|
||||
|
||||
// This effectively does the reverse of the previous macro. It defines
|
||||
// a name that the attributed variable or function will actually have
|
||||
// in assembler.
|
||||
# if !defined(CYGBLD_ATTRIB_ASM_ALIAS)
|
||||
# define __Str(x) #x
|
||||
# define __Xstr(x) __Str(x)
|
||||
# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) \
|
||||
__asm__ ( __Xstr( CYG_LABEL_DEFN( __symbol__ ) ) )
|
||||
# endif
|
||||
|
||||
// Shows that a function returns the same value when given the same args, but
|
||||
// note this can't be used if there are pointer args
|
||||
# if !defined(CYGBLD_ATTRIB_CONST)
|
||||
# define CYGBLD_ATTRIB_CONST __attribute__((const))
|
||||
#endif
|
||||
|
||||
// Assign a defined variable to a specific section
|
||||
# if !defined(CYGBLD_ATTRIB_SECTION)
|
||||
# define CYGBLD_ATTRIB_SECTION(__sect__) __attribute__((section (__sect__)))
|
||||
# endif
|
||||
|
||||
// Give a type or object explicit minimum alignment
|
||||
# if !defined(CYGBLD_ATTRIB_ALIGN)
|
||||
# define CYGBLD_ATTRIB_ALIGN(__align__) __attribute__((aligned(__align__)))
|
||||
# endif
|
||||
|
||||
# if !defined(CYGBLD_ATTRIB_ALIGN_MAX)
|
||||
# define CYGBLD_ATTRIB_ALIGN_MAX __attribute__((aligned))
|
||||
# endif
|
||||
|
||||
# if !defined(CYGBLD_ATTRIB_ALIGNOFTYPE)
|
||||
# define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) \
|
||||
__attribute__((aligned(__alignof__( _type_ ))))
|
||||
# endif
|
||||
|
||||
// Teach compiler how to check format of printf-like functions
|
||||
# define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__) \
|
||||
__attribute__((format (printf, __format__, __args__)))
|
||||
|
||||
// Teach compiler how to check format of scanf-like functions
|
||||
# define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__) \
|
||||
__attribute__((format (scanf, __format__, __args__)))
|
||||
|
||||
// Teach compiler how to check format of strftime-like functions
|
||||
# define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__) \
|
||||
__attribute__((format (strftime, __format__, __args__)))
|
||||
|
||||
// Tell compiler not to warn us about an unused variable -- generally
|
||||
// because it will be used when sources are build under certain
|
||||
// circumstances (e.g. with debugging or asserts enabled.
|
||||
# define CYGBLD_ATTRIB_UNUSED __attribute__((unused))
|
||||
|
||||
// Tell the compiler not to throw away a variable or function. Only known
|
||||
// available on 3.3.2 or above. Old version's didn't throw them away,
|
||||
// but using the unused attribute should stop warnings.
|
||||
# if !defined(CYGBLD_ATTRIB_USED)
|
||||
# if __GNUC_VERSION__ >= 30302
|
||||
# define CYGBLD_ATTRIB_USED __attribute__((used))
|
||||
# else
|
||||
# define CYGBLD_ATTRIB_USED __attribute__((unused))
|
||||
# endif
|
||||
# endif
|
||||
|
||||
// Enforce inlining of a C function. GCC does not inline any C
|
||||
// function when not optimizing, unless you specify "always_inline" attribute.
|
||||
// Other attributes suppress generation of standalone function.
|
||||
# if !defined(CYGBLD_FORCE_INLINE)
|
||||
# define CYGBLD_FORCE_INLINE __externC inline __attribute((gnu_inline)) __attribute((always_inline))
|
||||
# endif
|
||||
|
||||
// Suppress function inlining
|
||||
#define CYGBLD_ATTRIB_NO_INLINE __attribute__((noinline))
|
||||
|
||||
#else // non-GNU
|
||||
|
||||
# define CYGBLD_ATTRIB_UNUSED /* nothing */
|
||||
|
||||
# define CYGBLD_ATTRIB_CONSTRUCTOR
|
||||
|
||||
# define CYGBLD_ATTRIB_NORET
|
||||
// This intentionally gives an error only if we actually try to
|
||||
// use it. #error would give an error if we simply can't.
|
||||
// FIXME: Had to disarm the bomb - the CYGBLD_ATTRIB_WEAK macro is now
|
||||
// (indirectly) used in host tools.
|
||||
# define CYGBLD_ATTRIB_WEAK /* !!!-- Attribute weak not defined --!!! */
|
||||
|
||||
# define CYGBLD_ATTRIB_ALIAS(__x__) !!!-- Attribute alias not defined --!!!
|
||||
|
||||
# define CYGBLD_ATTRIB_ASM_ALIAS(__symbol__) !!!-- Asm alias not defined --!!!
|
||||
|
||||
# define CYGBLD_ATTRIB_CONST
|
||||
|
||||
# define CYGBLD_ATTRIB_ALIGN(__align__) !!!-- Alignment alias not defined --!!!
|
||||
|
||||
# define CYGBLD_ATTRIB_ALIGN_MAX !!!-- Alignment alias not defined --!!!
|
||||
|
||||
# define CYGBLD_ATTRIB_ALIGNOFTYPE( _type_ ) !!!-- Alignment alias not defined --!!!
|
||||
|
||||
# define CYGBLD_ATTRIB_PRINTF_FORMAT(__format__, __args__)
|
||||
|
||||
# define CYGBLD_ATTRIB_SCANF_FORMAT(__format__, __args__)
|
||||
|
||||
# define CYGBLD_ATTRIB_STRFTIME_FORMAT(__format__, __args__)
|
||||
|
||||
#define CYGBLD_FORCE_INLINE
|
||||
|
||||
#define CYGBLD_ATTRIB_NO_INLINE
|
||||
|
||||
#endif
|
||||
|
||||
// How to define weak aliases. Currently this is simply a mixture of the
|
||||
// above
|
||||
|
||||
# define CYGBLD_ATTRIB_WEAK_ALIAS(__symbol__) \
|
||||
CYGBLD_ATTRIB_WEAK CYGBLD_ATTRIB_ALIAS(__symbol__)
|
||||
|
||||
#ifdef __cplusplus
|
||||
# define __THROW throw()
|
||||
#else
|
||||
# define __THROW
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Variable annotations
|
||||
// These annotations may be added to various static variables in the
|
||||
// HAL and kernel to indicate which component they belong to. These
|
||||
// are used by some targets to optimize memory placement of these
|
||||
// variables.
|
||||
|
||||
#ifndef CYGBLD_ANNOTATE_VARIABLE_HAL
|
||||
#define CYGBLD_ANNOTATE_VARIABLE_HAL
|
||||
#endif
|
||||
#ifndef CYGBLD_ANNOTATE_VARIABLE_SCHED
|
||||
#define CYGBLD_ANNOTATE_VARIABLE_SCHED
|
||||
#endif
|
||||
#ifndef CYGBLD_ANNOTATE_VARIABLE_CLOCK
|
||||
#define CYGBLD_ANNOTATE_VARIABLE_CLOCK
|
||||
#endif
|
||||
#ifndef CYGBLD_ANNOTATE_VARIABLE_INTR
|
||||
#define CYGBLD_ANNOTATE_VARIABLE_INTR
|
||||
#endif
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
// Various "flavours" of memory regions that can be described by the
|
||||
// Memory Layout Tool (MLT).
|
||||
|
||||
#define CYGMEM_REGION_ATTR_R 0x01 // Region can be read
|
||||
#define CYGMEM_REGION_ATTR_W 0x02 // Region can be written
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
#endif // CYGONCE_INFRA_CYG_TYPE_H multiple inclusion protection
|
||||
// EOF cyg_type.h
|
||||
|
||||
@@ -0,0 +1,455 @@
|
||||
/*
|
||||
* Copyright (c) 2013 embedded brains GmbH. All rights reserved.
|
||||
*
|
||||
* embedded brains GmbH
|
||||
* Dornierstr. 4
|
||||
* 82178 Puchheim
|
||||
* Germany
|
||||
* <rtems@embedded-brains.de>
|
||||
*
|
||||
* The license and distribution terms for this file may be
|
||||
* found in the file LICENSE in this distribution or at
|
||||
* http://www.rtems.com/license/LICENSE.
|
||||
*/
|
||||
|
||||
#ifndef RTEMS_JFFS2_H
|
||||
#define RTEMS_JFFS2_H
|
||||
|
||||
#include <rtems/fs.h>
|
||||
#include <sys/param.h>
|
||||
#include <zlib.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif /* __cplusplus */
|
||||
|
||||
typedef struct rtems_jffs2_flash_control rtems_jffs2_flash_control;
|
||||
|
||||
/**
|
||||
* @defgroup JFFS2 Journalling Flash File System Version 2 (JFFS2) Support
|
||||
*
|
||||
* @ingroup FileSystemTypesAndMount
|
||||
*
|
||||
* @brief Mount options for the Journalling Flash File System, Version 2
|
||||
* (JFFS2).
|
||||
*
|
||||
* The application must provide flash device geometry information and flash
|
||||
* device operations in the flash control structure
|
||||
* @ref rtems_jffs2_flash_control.
|
||||
*
|
||||
* The application can optionally provide a compressor control structure to
|
||||
* enable data compression using the selected compression algorithm.
|
||||
*
|
||||
* The application must enable JFFS2 support with rtems_filesystem_register()
|
||||
* or CONFIGURE_FILESYSTEM_JFFS2 via <rtems/confdefs.h>.
|
||||
*
|
||||
* An example mount with a simple memory based flash device simulation follows.
|
||||
* The zlib is used for as the compressor.
|
||||
*
|
||||
* @code
|
||||
* #include <string.h>
|
||||
*
|
||||
* #include <rtems/jffs2.h>
|
||||
* #include <rtems/libio.h>
|
||||
*
|
||||
* #define BLOCK_SIZE (32UL * 1024UL)
|
||||
*
|
||||
* #define FLASH_SIZE (32UL * BLOCK_SIZE)
|
||||
*
|
||||
* typedef struct {
|
||||
* rtems_jffs2_flash_control super;
|
||||
* unsigned char area[FLASH_SIZE];
|
||||
* } flash_control;
|
||||
*
|
||||
* static flash_control *get_flash_control(rtems_jffs2_flash_control *super)
|
||||
* {
|
||||
* return (flash_control *) super;
|
||||
* }
|
||||
*
|
||||
* static int flash_read(
|
||||
* rtems_jffs2_flash_control *super,
|
||||
* uint32_t offset,
|
||||
* unsigned char *buffer,
|
||||
* size_t size_of_buffer
|
||||
* )
|
||||
* {
|
||||
* flash_control *self = get_flash_control(super);
|
||||
* unsigned char *chunk = &self->area[offset];
|
||||
*
|
||||
* memcpy(buffer, chunk, size_of_buffer);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* static int flash_write(
|
||||
* rtems_jffs2_flash_control *super,
|
||||
* uint32_t offset,
|
||||
* const unsigned char *buffer,
|
||||
* size_t size_of_buffer
|
||||
* )
|
||||
* {
|
||||
* flash_control *self = get_flash_control(super);
|
||||
* unsigned char *chunk = &self->area[offset];
|
||||
* size_t i;
|
||||
*
|
||||
* for (i = 0; i < size_of_buffer; ++i) {
|
||||
* chunk[i] &= buffer[i];
|
||||
* }
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* static int flash_erase(
|
||||
* rtems_jffs2_flash_control *super,
|
||||
* uint32_t offset
|
||||
* )
|
||||
* {
|
||||
* flash_control *self = get_flash_control(super);
|
||||
* unsigned char *chunk = &self->area[offset];
|
||||
*
|
||||
* memset(chunk, 0xff, BLOCK_SIZE);
|
||||
*
|
||||
* return 0;
|
||||
* }
|
||||
*
|
||||
* static flash_control flash_instance = {
|
||||
* .super = {
|
||||
* .block_size = BLOCK_SIZE,
|
||||
* .flash_size = FLASH_SIZE,
|
||||
* .read = flash_read,
|
||||
* .write = flash_write,
|
||||
* .erase = flash_erase
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* static rtems_jffs2_compressor_zlib_control compressor_instance = {
|
||||
* .super = {
|
||||
* .compress = rtems_jffs2_compressor_zlib_compress,
|
||||
* .decompress = rtems_jffs2_compressor_zlib_decompress
|
||||
* }
|
||||
* };
|
||||
*
|
||||
* static const rtems_jffs2_mount_data mount_data = {
|
||||
* .flash_control = &flash_instance.super,
|
||||
* .compressor_control = &compressor_instance.super
|
||||
* };
|
||||
*
|
||||
* static void erase_all(void)
|
||||
* {
|
||||
* memset(&flash_instance.area[0], 0xff, FLASH_SIZE);
|
||||
* }
|
||||
*
|
||||
* void example_jffs2_mount(const char *mount_dir)
|
||||
* {
|
||||
* int rv;
|
||||
*
|
||||
* erase_all();
|
||||
*
|
||||
* rv = mount_and_make_target_path(
|
||||
* NULL,
|
||||
* mount_dir,
|
||||
* RTEMS_FILESYSTEM_TYPE_JFFS2,
|
||||
* RTEMS_FILESYSTEM_READ_WRITE,
|
||||
* &mount_data
|
||||
* );
|
||||
* assert(rv == 0);
|
||||
* }
|
||||
* @endcode
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
/**
|
||||
* @brief Read from flash operation.
|
||||
*
|
||||
* @param[in, out] self The flash control.
|
||||
* @param[in] offset The offset to read from the flash begin in bytes.
|
||||
* @param[out] buffer The buffer receiving the data.
|
||||
* @param[in] size_of_buffer The size of the buffer in bytes.
|
||||
*
|
||||
* @retval 0 Successful operation.
|
||||
* @retval -EIO An error occurred. Please note that the value is negative.
|
||||
* @retval other All other values are reserved and must not be used.
|
||||
*/
|
||||
typedef int (*rtems_jffs2_flash_read)(
|
||||
rtems_jffs2_flash_control *self,
|
||||
uint32_t offset,
|
||||
unsigned char *buffer,
|
||||
size_t size_of_buffer
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Write to flash operation.
|
||||
*
|
||||
* @param[in, out] self The flash control.
|
||||
* @param[in] offset The offset to write from the flash begin in bytes.
|
||||
* @param[in] buffer The buffer containing the data to write.
|
||||
* @param[in] size_of_buffer The size of the buffer in bytes.
|
||||
*
|
||||
* @retval 0 Successful operation.
|
||||
* @retval -EIO An error occurred. Please note that the value is negative.
|
||||
* @retval other All other values are reserved and must not be used.
|
||||
*/
|
||||
typedef int (*rtems_jffs2_flash_write)(
|
||||
rtems_jffs2_flash_control *self,
|
||||
uint32_t offset,
|
||||
const unsigned char *buffer,
|
||||
size_t size_of_buffer
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Flash erase operation.
|
||||
*
|
||||
* This operation must erase one block specified by the offset.
|
||||
*
|
||||
* @param[in, out] self The flash control.
|
||||
* @param[in] offset The offset to erase from the flash begin in bytes.
|
||||
*
|
||||
* @retval 0 Successful operation.
|
||||
* @retval -EIO An error occurred. Please note that the value is negative.
|
||||
* @retval other All other values are reserved and must not be used.
|
||||
*/
|
||||
typedef int (*rtems_jffs2_flash_erase)(
|
||||
rtems_jffs2_flash_control *self,
|
||||
uint32_t offset
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Flash destroy operation.
|
||||
*
|
||||
* The flash destroy operation is called during unmount of the file system
|
||||
* instance. It can be used to free the resources associated with the now
|
||||
* unused flash control
|
||||
*
|
||||
* @param[in, out] self The flash control.
|
||||
*/
|
||||
typedef void (*rtems_jffs2_flash_destroy)(
|
||||
rtems_jffs2_flash_control *self
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief JFFS2 flash device control.
|
||||
*/
|
||||
struct rtems_jffs2_flash_control {
|
||||
/**
|
||||
* @brief The size in bytes of the erasable unit of the flash device.
|
||||
*/
|
||||
uint32_t block_size;
|
||||
|
||||
/**
|
||||
* @brief The size in bytes of the flash device.
|
||||
*
|
||||
* It must be an integral multiple of the block size. The flash device must
|
||||
* have at least five blocks.
|
||||
*/
|
||||
uint32_t flash_size;
|
||||
|
||||
/**
|
||||
* @brief Read from flash operation.
|
||||
*/
|
||||
rtems_jffs2_flash_read read;
|
||||
|
||||
/**
|
||||
* @brief Write to flash operation.
|
||||
*/
|
||||
rtems_jffs2_flash_write write;
|
||||
|
||||
/**
|
||||
* @brief Flash erase operation.
|
||||
*/
|
||||
rtems_jffs2_flash_erase erase;
|
||||
|
||||
/**
|
||||
* @brief Flash destroy operation.
|
||||
*
|
||||
* This operation is optional and the pointer may be @c NULL.
|
||||
*/
|
||||
rtems_jffs2_flash_destroy destroy;
|
||||
};
|
||||
|
||||
typedef struct rtems_jffs2_compressor_control rtems_jffs2_compressor_control;
|
||||
|
||||
/**
|
||||
* @brief Compress operation.
|
||||
*
|
||||
* @param[in, out] self The compressor control.
|
||||
* @param[in] data_in The uncompressed data.
|
||||
* @param[out] cdata_out Pointer to buffer with the compressed data.
|
||||
* @param[in, out] datalen On entry, the size in bytes of the uncompressed
|
||||
* data. On exit, the size in bytes of uncompressed data which was actually
|
||||
* compressed.
|
||||
* @param[in, out] cdatalen On entry, the size in bytes available for
|
||||
* compressed data. On exit, the size in bytes of the actually compressed
|
||||
* data.
|
||||
*
|
||||
* @return The compressor type.
|
||||
*/
|
||||
typedef uint16_t (*rtems_jffs2_compressor_compress)(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
unsigned char *data_in,
|
||||
unsigned char *cdata_out,
|
||||
uint32_t *datalen,
|
||||
uint32_t *cdatalen
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Decompress operation.
|
||||
*
|
||||
* @param[in, out] self The compressor control.
|
||||
* @param[in] comprtype The compressor type.
|
||||
* @param[in] cdata_in The compressed data.
|
||||
* @param[out] data_out The uncompressed data.
|
||||
* @param[in] cdatalen The size in bytes of the compressed data.
|
||||
* @param[in] datalen The size in bytes of the uncompressed data.
|
||||
*
|
||||
* @retval 0 Successful operation.
|
||||
* @retval -EIO An error occurred. Please note that the value is negative.
|
||||
* @retval other All other values are reserved and must not be used.
|
||||
*/
|
||||
typedef int (*rtems_jffs2_compressor_decompress)(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
uint16_t comprtype,
|
||||
unsigned char *cdata_in,
|
||||
unsigned char *data_out,
|
||||
uint32_t cdatalen,
|
||||
uint32_t datalen
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Compressor destroy operation.
|
||||
*
|
||||
* The compressor destroy operation is called during unmount of the file system
|
||||
* instance. It can be used to free the resources associated with the now
|
||||
* unused compressor operations.
|
||||
*
|
||||
* @param[in, out] self The compressor control.
|
||||
*/
|
||||
typedef void (*rtems_jffs2_compressor_destroy)(
|
||||
rtems_jffs2_compressor_control *self
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief JFFS2 compressor control.
|
||||
*/
|
||||
struct rtems_jffs2_compressor_control {
|
||||
/**
|
||||
* @brief Compress operation.
|
||||
*/
|
||||
rtems_jffs2_compressor_compress compress;
|
||||
|
||||
/**
|
||||
* @brief Decompress operation.
|
||||
*/
|
||||
rtems_jffs2_compressor_decompress decompress;
|
||||
|
||||
/**
|
||||
* @brief Compressor destroy operation.
|
||||
*
|
||||
* This operation is optional and the pointer may be @c NULL.
|
||||
*/
|
||||
rtems_jffs2_compressor_destroy destroy;
|
||||
|
||||
/**
|
||||
* @brief Compression buffer.
|
||||
*/
|
||||
unsigned char buffer[PAGE_SIZE];
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief RTIME compressor compress operation.
|
||||
*/
|
||||
uint16_t rtems_jffs2_compressor_rtime_compress(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
unsigned char *data_in,
|
||||
unsigned char *cdata_out,
|
||||
uint32_t *datalen,
|
||||
uint32_t *cdatalen
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief RTIME compressor decompress operation.
|
||||
*/
|
||||
int rtems_jffs2_compressor_rtime_decompress(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
uint16_t comprtype,
|
||||
unsigned char *cdata_in,
|
||||
unsigned char *data_out,
|
||||
uint32_t cdatalen,
|
||||
uint32_t datalen
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief ZLIB compressor control structure.
|
||||
*/
|
||||
typedef struct {
|
||||
rtems_jffs2_compressor_control super;
|
||||
z_stream stream;
|
||||
} rtems_jffs2_compressor_zlib_control;
|
||||
|
||||
/**
|
||||
* @brief ZLIB compressor compress operation.
|
||||
*/
|
||||
uint16_t rtems_jffs2_compressor_zlib_compress(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
unsigned char *data_in,
|
||||
unsigned char *cdata_out,
|
||||
uint32_t *datalen,
|
||||
uint32_t *cdatalen
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief ZLIB compressor decompress operation.
|
||||
*/
|
||||
int rtems_jffs2_compressor_zlib_decompress(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
uint16_t comprtype,
|
||||
unsigned char *cdata_in,
|
||||
unsigned char *data_out,
|
||||
uint32_t cdatalen,
|
||||
uint32_t datalen
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief JFFS2 mount options.
|
||||
*
|
||||
* For JFFS2 the mount options are mandatory.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* @brief Flash control.
|
||||
*/
|
||||
rtems_jffs2_flash_control *flash_control;
|
||||
|
||||
/**
|
||||
* @brief Compressor control.
|
||||
*
|
||||
* The compressor is optional and this pointer may be @c NULL.
|
||||
*/
|
||||
rtems_jffs2_compressor_control *compressor_control;
|
||||
} rtems_jffs2_mount_data;
|
||||
|
||||
/**
|
||||
* @brief Initialization handler of the JFFS2 file system.
|
||||
*
|
||||
* @param[in, out] mt_entry The mount table entry.
|
||||
* @param[in] data The mount options are mandatory for JFFS2 and data must
|
||||
* point to a valid @ref rtems_jffs2_mount_data structure used for this file
|
||||
* system instance.
|
||||
*
|
||||
* @retval 0 Successful operation.
|
||||
* @retval -1 An error occurred. The @c errno indicates the error.
|
||||
*
|
||||
* @see mount().
|
||||
*/
|
||||
int rtems_jffs2_initialize(
|
||||
rtems_filesystem_mount_table_entry_t *mt_entry,
|
||||
const void *data
|
||||
);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif /* __cplusplus */
|
||||
|
||||
#endif /* RTEMS_JFFS2_H */
|
||||
@@ -5,6 +5,7 @@
|
||||
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
* Copyright © 2004 Ferenc Havasi <havasi@inf.u-szeged.hu>,
|
||||
* University of Szeged, Hungary
|
||||
* Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
|
||||
*
|
||||
* Created by Arjan van de Ven <arjan@infradead.org>
|
||||
*
|
||||
@@ -16,117 +17,6 @@
|
||||
|
||||
#include "compr.h"
|
||||
|
||||
static DEFINE_SPINLOCK(jffs2_compressor_list_lock);
|
||||
|
||||
/* Available compressors are on this list */
|
||||
static LIST_HEAD(jffs2_compressor_list);
|
||||
|
||||
/* Actual compression mode */
|
||||
static int jffs2_compression_mode = JFFS2_COMPR_MODE_PRIORITY;
|
||||
|
||||
/* Statistics for blocks stored without compression */
|
||||
static uint32_t none_stat_compr_blocks=0,none_stat_decompr_blocks=0,none_stat_compr_size=0;
|
||||
|
||||
|
||||
/*
|
||||
* Return 1 to use this compression
|
||||
*/
|
||||
static int jffs2_is_best_compression(struct jffs2_compressor *this,
|
||||
struct jffs2_compressor *best, uint32_t size, uint32_t bestsize)
|
||||
{
|
||||
switch (jffs2_compression_mode) {
|
||||
case JFFS2_COMPR_MODE_SIZE:
|
||||
if (bestsize > size)
|
||||
return 1;
|
||||
return 0;
|
||||
case JFFS2_COMPR_MODE_FAVOURLZO:
|
||||
if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > size))
|
||||
return 1;
|
||||
if ((best->compr != JFFS2_COMPR_LZO) && (bestsize > size))
|
||||
return 1;
|
||||
if ((this->compr == JFFS2_COMPR_LZO) && (bestsize > (size * FAVOUR_LZO_PERCENT / 100)))
|
||||
return 1;
|
||||
if ((bestsize * FAVOUR_LZO_PERCENT / 100) > size)
|
||||
return 1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
/* Shouldn't happen */
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* jffs2_selected_compress:
|
||||
* @compr: Explicit compression type to use (ie, JFFS2_COMPR_ZLIB).
|
||||
* If 0, just take the first available compression mode.
|
||||
* @data_in: Pointer to uncompressed data
|
||||
* @cpage_out: Pointer to returned pointer to buffer for compressed data
|
||||
* @datalen: On entry, holds the amount of data available for compression.
|
||||
* On exit, expected to hold the amount of data actually compressed.
|
||||
* @cdatalen: On entry, holds the amount of space available for compressed
|
||||
* data. On exit, expected to hold the actual size of the compressed
|
||||
* data.
|
||||
*
|
||||
* Returns: the compression type used. Zero is used to show that the data
|
||||
* could not be compressed; probably because we couldn't find the requested
|
||||
* compression mode.
|
||||
*/
|
||||
static int jffs2_selected_compress(u8 compr, unsigned char *data_in,
|
||||
unsigned char **cpage_out, u32 *datalen, u32 *cdatalen)
|
||||
{
|
||||
struct jffs2_compressor *this;
|
||||
int err, ret = JFFS2_COMPR_NONE;
|
||||
uint32_t orig_slen, orig_dlen;
|
||||
char *output_buf;
|
||||
|
||||
output_buf = kmalloc(*cdatalen, GFP_KERNEL);
|
||||
if (!output_buf) {
|
||||
pr_warn("No memory for compressor allocation. Compression failed.\n");
|
||||
return ret;
|
||||
}
|
||||
orig_slen = *datalen;
|
||||
orig_dlen = *cdatalen;
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
list_for_each_entry(this, &jffs2_compressor_list, list) {
|
||||
/* Skip decompress-only and disabled modules */
|
||||
if (!this->compress || this->disabled)
|
||||
continue;
|
||||
|
||||
/* Skip if not the desired compression type */
|
||||
if (compr && (compr != this->compr))
|
||||
continue;
|
||||
|
||||
/*
|
||||
* Either compression type was unspecified, or we found our
|
||||
* compressor; either way, we're good to go.
|
||||
*/
|
||||
this->usecount++;
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
|
||||
*datalen = orig_slen;
|
||||
*cdatalen = orig_dlen;
|
||||
err = this->compress(data_in, output_buf, datalen, cdatalen);
|
||||
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
this->usecount--;
|
||||
if (!err) {
|
||||
/* Success */
|
||||
ret = this->compr;
|
||||
this->stat_compr_blocks++;
|
||||
this->stat_compr_orig_size += *datalen;
|
||||
this->stat_compr_new_size += *cdatalen;
|
||||
break;
|
||||
}
|
||||
}
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
if (ret == JFFS2_COMPR_NONE)
|
||||
kfree(output_buf);
|
||||
else
|
||||
*cpage_out = output_buf;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* jffs2_compress:
|
||||
* @data_in: Pointer to uncompressed data
|
||||
* @cpage_out: Pointer to returned pointer to buffer for compressed data
|
||||
@@ -149,103 +39,20 @@ uint16_t jffs2_compress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
||||
unsigned char *data_in, unsigned char **cpage_out,
|
||||
uint32_t *datalen, uint32_t *cdatalen)
|
||||
{
|
||||
int ret = JFFS2_COMPR_NONE;
|
||||
int mode, compr_ret;
|
||||
struct jffs2_compressor *this, *best=NULL;
|
||||
unsigned char *output_buf = NULL, *tmp_buf;
|
||||
uint32_t orig_slen, orig_dlen;
|
||||
uint32_t best_slen=0, best_dlen=0;
|
||||
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
|
||||
int ret;
|
||||
|
||||
if (c->mount_opts.override_compr)
|
||||
mode = c->mount_opts.compr;
|
||||
else
|
||||
mode = jffs2_compression_mode;
|
||||
|
||||
switch (mode) {
|
||||
case JFFS2_COMPR_MODE_NONE:
|
||||
break;
|
||||
case JFFS2_COMPR_MODE_PRIORITY:
|
||||
ret = jffs2_selected_compress(0, data_in, cpage_out, datalen,
|
||||
cdatalen);
|
||||
break;
|
||||
case JFFS2_COMPR_MODE_SIZE:
|
||||
case JFFS2_COMPR_MODE_FAVOURLZO:
|
||||
orig_slen = *datalen;
|
||||
orig_dlen = *cdatalen;
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
list_for_each_entry(this, &jffs2_compressor_list, list) {
|
||||
/* Skip decompress-only backwards-compatibility and disabled modules */
|
||||
if ((!this->compress)||(this->disabled))
|
||||
continue;
|
||||
/* Allocating memory for output buffer if necessary */
|
||||
if ((this->compr_buf_size < orig_slen) && (this->compr_buf)) {
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
kfree(this->compr_buf);
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
this->compr_buf_size=0;
|
||||
this->compr_buf=NULL;
|
||||
}
|
||||
if (!this->compr_buf) {
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
tmp_buf = kmalloc(orig_slen, GFP_KERNEL);
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
if (!tmp_buf) {
|
||||
pr_warn("No memory for compressor allocation. (%d bytes)\n",
|
||||
orig_slen);
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
this->compr_buf = tmp_buf;
|
||||
this->compr_buf_size = orig_slen;
|
||||
}
|
||||
}
|
||||
this->usecount++;
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
*datalen = orig_slen;
|
||||
*cdatalen = orig_dlen;
|
||||
compr_ret = this->compress(data_in, this->compr_buf, datalen, cdatalen);
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
this->usecount--;
|
||||
if (!compr_ret) {
|
||||
if (((!best_dlen) || jffs2_is_best_compression(this, best, *cdatalen, best_dlen))
|
||||
&& (*cdatalen < *datalen)) {
|
||||
best_dlen = *cdatalen;
|
||||
best_slen = *datalen;
|
||||
best = this;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (best_dlen) {
|
||||
*cdatalen = best_dlen;
|
||||
*datalen = best_slen;
|
||||
output_buf = best->compr_buf;
|
||||
best->compr_buf = NULL;
|
||||
best->compr_buf_size = 0;
|
||||
best->stat_compr_blocks++;
|
||||
best->stat_compr_orig_size += best_slen;
|
||||
best->stat_compr_new_size += best_dlen;
|
||||
ret = best->compr;
|
||||
*cpage_out = output_buf;
|
||||
}
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
break;
|
||||
case JFFS2_COMPR_MODE_FORCELZO:
|
||||
ret = jffs2_selected_compress(JFFS2_COMPR_LZO, data_in,
|
||||
cpage_out, datalen, cdatalen);
|
||||
break;
|
||||
case JFFS2_COMPR_MODE_FORCEZLIB:
|
||||
ret = jffs2_selected_compress(JFFS2_COMPR_ZLIB, data_in,
|
||||
cpage_out, datalen, cdatalen);
|
||||
break;
|
||||
default:
|
||||
pr_err("unknown compression mode\n");
|
||||
if (cc != NULL) {
|
||||
*cpage_out = &cc->buffer[0];
|
||||
ret = (*cc->compress)(cc, data_in, *cpage_out, datalen, cdatalen);
|
||||
} else {
|
||||
ret = JFFS2_COMPR_NONE;
|
||||
}
|
||||
|
||||
if (ret == JFFS2_COMPR_NONE) {
|
||||
*cpage_out = data_in;
|
||||
*datalen = *cdatalen;
|
||||
none_stat_compr_blocks++;
|
||||
none_stat_compr_size += *datalen;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
@@ -254,8 +61,8 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
||||
uint16_t comprtype, unsigned char *cdata_in,
|
||||
unsigned char *data_out, uint32_t cdatalen, uint32_t datalen)
|
||||
{
|
||||
struct jffs2_compressor *this;
|
||||
int ret;
|
||||
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
rtems_jffs2_compressor_control *cc = sb->s_compressor_control;
|
||||
|
||||
/* Older code had a bug where it would write non-zero 'usercompr'
|
||||
fields. Deal with it. */
|
||||
@@ -266,153 +73,16 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
||||
case JFFS2_COMPR_NONE:
|
||||
/* This should be special-cased elsewhere, but we might as well deal with it */
|
||||
memcpy(data_out, cdata_in, datalen);
|
||||
none_stat_decompr_blocks++;
|
||||
break;
|
||||
case JFFS2_COMPR_ZERO:
|
||||
memset(data_out, 0, datalen);
|
||||
break;
|
||||
default:
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
list_for_each_entry(this, &jffs2_compressor_list, list) {
|
||||
if (comprtype == this->compr) {
|
||||
this->usecount++;
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
ret = this->decompress(cdata_in, data_out, cdatalen, datalen);
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
if (ret) {
|
||||
pr_warn("Decompressor \"%s\" returned %d\n",
|
||||
this->name, ret);
|
||||
}
|
||||
else {
|
||||
this->stat_decompr_blocks++;
|
||||
}
|
||||
this->usecount--;
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
pr_warn("compression type 0x%02x not available\n", comprtype);
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
return -EIO;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jffs2_register_compressor(struct jffs2_compressor *comp)
|
||||
{
|
||||
struct jffs2_compressor *this;
|
||||
|
||||
if (!comp->name) {
|
||||
pr_warn("NULL compressor name at registering JFFS2 compressor. Failed.\n");
|
||||
return -1;
|
||||
}
|
||||
comp->compr_buf_size=0;
|
||||
comp->compr_buf=NULL;
|
||||
comp->usecount=0;
|
||||
comp->stat_compr_orig_size=0;
|
||||
comp->stat_compr_new_size=0;
|
||||
comp->stat_compr_blocks=0;
|
||||
comp->stat_decompr_blocks=0;
|
||||
jffs2_dbg(1, "Registering JFFS2 compressor \"%s\"\n", comp->name);
|
||||
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
|
||||
list_for_each_entry(this, &jffs2_compressor_list, list) {
|
||||
if (this->priority < comp->priority) {
|
||||
list_add(&comp->list, this->list.prev);
|
||||
goto out;
|
||||
if (cc != NULL) {
|
||||
return (*cc->decompress)(cc, comprtype, cdata_in, data_out, cdatalen, datalen);
|
||||
} else {
|
||||
return -EIO;
|
||||
}
|
||||
}
|
||||
list_add_tail(&comp->list, &jffs2_compressor_list);
|
||||
out:
|
||||
D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
|
||||
printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
|
||||
})
|
||||
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jffs2_unregister_compressor(struct jffs2_compressor *comp)
|
||||
{
|
||||
D2(struct jffs2_compressor *this);
|
||||
|
||||
jffs2_dbg(1, "Unregistering JFFS2 compressor \"%s\"\n", comp->name);
|
||||
|
||||
spin_lock(&jffs2_compressor_list_lock);
|
||||
|
||||
if (comp->usecount) {
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
pr_warn("Compressor module is in use. Unregister failed.\n");
|
||||
return -1;
|
||||
}
|
||||
list_del(&comp->list);
|
||||
|
||||
D2(list_for_each_entry(this, &jffs2_compressor_list, list) {
|
||||
printk(KERN_DEBUG "Compressor \"%s\", prio %d\n", this->name, this->priority);
|
||||
})
|
||||
spin_unlock(&jffs2_compressor_list_lock);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig)
|
||||
{
|
||||
if (orig != comprbuf)
|
||||
kfree(comprbuf);
|
||||
}
|
||||
|
||||
int __init jffs2_compressors_init(void)
|
||||
{
|
||||
/* Registering compressors */
|
||||
#ifdef CONFIG_JFFS2_ZLIB
|
||||
jffs2_zlib_init();
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_RTIME
|
||||
jffs2_rtime_init();
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_RUBIN
|
||||
jffs2_rubinmips_init();
|
||||
jffs2_dynrubin_init();
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_LZO
|
||||
jffs2_lzo_init();
|
||||
#endif
|
||||
/* Setting default compression mode */
|
||||
#ifdef CONFIG_JFFS2_CMODE_NONE
|
||||
jffs2_compression_mode = JFFS2_COMPR_MODE_NONE;
|
||||
jffs2_dbg(1, "default compression mode: none\n");
|
||||
#else
|
||||
#ifdef CONFIG_JFFS2_CMODE_SIZE
|
||||
jffs2_compression_mode = JFFS2_COMPR_MODE_SIZE;
|
||||
jffs2_dbg(1, "default compression mode: size\n");
|
||||
#else
|
||||
#ifdef CONFIG_JFFS2_CMODE_FAVOURLZO
|
||||
jffs2_compression_mode = JFFS2_COMPR_MODE_FAVOURLZO;
|
||||
jffs2_dbg(1, "default compression mode: favourlzo\n");
|
||||
#else
|
||||
jffs2_dbg(1, "default compression mode: priority\n");
|
||||
#endif
|
||||
#endif
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
int jffs2_compressors_exit(void)
|
||||
{
|
||||
/* Unregistering compressors */
|
||||
#ifdef CONFIG_JFFS2_LZO
|
||||
jffs2_lzo_exit();
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_RUBIN
|
||||
jffs2_dynrubin_exit();
|
||||
jffs2_rubinmips_exit();
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_RTIME
|
||||
jffs2_rtime_exit();
|
||||
#endif
|
||||
#ifdef CONFIG_JFFS2_ZLIB
|
||||
jffs2_zlib_exit();
|
||||
#endif
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ int jffs2_decompress(struct jffs2_sb_info *c, struct jffs2_inode_info *f,
|
||||
uint16_t comprtype, unsigned char *cdata_in,
|
||||
unsigned char *data_out, uint32_t cdatalen, uint32_t datalen);
|
||||
|
||||
void jffs2_free_comprbuf(unsigned char *comprbuf, unsigned char *orig);
|
||||
#define jffs2_free_comprbuf(x, y) do { } while (0)
|
||||
|
||||
/* Compressor modules */
|
||||
/* These functions will be called by jffs2_compressors_init/exit */
|
||||
|
||||
@@ -28,15 +28,20 @@
|
||||
#include <linux/jffs2.h>
|
||||
#include "compr.h"
|
||||
|
||||
/* _compress returns the compressed size, -1 if bigger */
|
||||
static int jffs2_rtime_compress(unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t *sourcelen, uint32_t *dstlen)
|
||||
uint16_t rtems_jffs2_compressor_rtime_compress(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t *sourcelen,
|
||||
uint32_t *dstlen
|
||||
)
|
||||
{
|
||||
short positions[256];
|
||||
int outpos = 0;
|
||||
int pos=0;
|
||||
|
||||
(void) self;
|
||||
|
||||
memset(positions,0,sizeof(positions));
|
||||
|
||||
while (pos < (*sourcelen) && outpos <= (*dstlen)-2) {
|
||||
@@ -60,24 +65,35 @@ static int jffs2_rtime_compress(unsigned char *data_in,
|
||||
|
||||
if (outpos >= pos) {
|
||||
/* We failed */
|
||||
return -1;
|
||||
return JFFS2_COMPR_NONE;
|
||||
}
|
||||
|
||||
/* Tell the caller how much we managed to compress, and how much space it took */
|
||||
*sourcelen = pos;
|
||||
*dstlen = outpos;
|
||||
return 0;
|
||||
return JFFS2_COMPR_RTIME;
|
||||
}
|
||||
|
||||
|
||||
static int jffs2_rtime_decompress(unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t srclen, uint32_t destlen)
|
||||
int rtems_jffs2_compressor_rtime_decompress(
|
||||
rtems_jffs2_compressor_control *self,
|
||||
uint16_t comprtype,
|
||||
unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t srclen,
|
||||
uint32_t destlen
|
||||
)
|
||||
{
|
||||
short positions[256];
|
||||
int outpos = 0;
|
||||
int pos=0;
|
||||
|
||||
(void) self;
|
||||
|
||||
if (comprtype != JFFS2_COMPR_RTIME) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
memset(positions,0,sizeof(positions));
|
||||
|
||||
while (outpos<destlen) {
|
||||
@@ -105,26 +121,3 @@ static int jffs2_rtime_decompress(unsigned char *data_in,
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct jffs2_compressor jffs2_rtime_comp = {
|
||||
.priority = JFFS2_RTIME_PRIORITY,
|
||||
.name = "rtime",
|
||||
.compr = JFFS2_COMPR_RTIME,
|
||||
.compress = &jffs2_rtime_compress,
|
||||
.decompress = &jffs2_rtime_decompress,
|
||||
#ifdef JFFS2_RTIME_DISABLED
|
||||
.disabled = 1,
|
||||
#else
|
||||
.disabled = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
int jffs2_rtime_init(void)
|
||||
{
|
||||
return jffs2_register_compressor(&jffs2_rtime_comp);
|
||||
}
|
||||
|
||||
void jffs2_rtime_exit(void)
|
||||
{
|
||||
jffs2_unregister_compressor(&jffs2_rtime_comp);
|
||||
}
|
||||
|
||||
@@ -33,126 +33,115 @@
|
||||
|
||||
static DEFINE_MUTEX(deflate_mutex);
|
||||
static DEFINE_MUTEX(inflate_mutex);
|
||||
static z_stream inf_strm, def_strm;
|
||||
|
||||
#ifdef __KERNEL__ /* Linux-only */
|
||||
#include <linux/vmalloc.h>
|
||||
#include <linux/init.h>
|
||||
#include <linux/mutex.h>
|
||||
|
||||
static int __init alloc_workspaces(void)
|
||||
static rtems_jffs2_compressor_zlib_control *get_zlib_control(
|
||||
rtems_jffs2_compressor_control *super
|
||||
)
|
||||
{
|
||||
def_strm.workspace = vmalloc(zlib_deflate_workspacesize(MAX_WBITS,
|
||||
MAX_MEM_LEVEL));
|
||||
if (!def_strm.workspace)
|
||||
return -ENOMEM;
|
||||
|
||||
jffs2_dbg(1, "Allocated %d bytes for deflate workspace\n",
|
||||
zlib_deflate_workspacesize(MAX_WBITS, MAX_MEM_LEVEL));
|
||||
inf_strm.workspace = vmalloc(zlib_inflate_workspacesize());
|
||||
if (!inf_strm.workspace) {
|
||||
vfree(def_strm.workspace);
|
||||
return -ENOMEM;
|
||||
}
|
||||
jffs2_dbg(1, "Allocated %d bytes for inflate workspace\n",
|
||||
zlib_inflate_workspacesize());
|
||||
return 0;
|
||||
return (rtems_jffs2_compressor_zlib_control *) super;
|
||||
}
|
||||
|
||||
static void free_workspaces(void)
|
||||
{
|
||||
vfree(def_strm.workspace);
|
||||
vfree(inf_strm.workspace);
|
||||
}
|
||||
#else
|
||||
#define alloc_workspaces() (0)
|
||||
#define free_workspaces() do { } while(0)
|
||||
#endif /* __KERNEL__ */
|
||||
|
||||
static int jffs2_zlib_compress(unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t *sourcelen, uint32_t *dstlen)
|
||||
uint16_t rtems_jffs2_compressor_zlib_compress(
|
||||
rtems_jffs2_compressor_control *super,
|
||||
unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t *sourcelen,
|
||||
uint32_t *dstlen
|
||||
)
|
||||
{
|
||||
rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
|
||||
z_stream *def_strm = &self->stream;
|
||||
int ret;
|
||||
|
||||
if (*dstlen <= STREAM_END_SPACE)
|
||||
return -1;
|
||||
return JFFS2_COMPR_NONE;
|
||||
|
||||
mutex_lock(&deflate_mutex);
|
||||
|
||||
if (Z_OK != zlib_deflateInit(&def_strm, 3)) {
|
||||
if (Z_OK != zlib_deflateInit(def_strm, 3)) {
|
||||
pr_warn("deflateInit failed\n");
|
||||
mutex_unlock(&deflate_mutex);
|
||||
return -1;
|
||||
return JFFS2_COMPR_NONE;
|
||||
}
|
||||
|
||||
def_strm.next_in = data_in;
|
||||
def_strm.total_in = 0;
|
||||
def_strm->next_in = data_in;
|
||||
def_strm->total_in = 0;
|
||||
|
||||
def_strm.next_out = cpage_out;
|
||||
def_strm.total_out = 0;
|
||||
def_strm->next_out = cpage_out;
|
||||
def_strm->total_out = 0;
|
||||
|
||||
while (def_strm.total_out < *dstlen - STREAM_END_SPACE && def_strm.total_in < *sourcelen) {
|
||||
def_strm.avail_out = *dstlen - (def_strm.total_out + STREAM_END_SPACE);
|
||||
def_strm.avail_in = min((unsigned)(*sourcelen-def_strm.total_in), def_strm.avail_out);
|
||||
while (def_strm->total_out < *dstlen - STREAM_END_SPACE && def_strm->total_in < *sourcelen) {
|
||||
def_strm->avail_out = *dstlen - (def_strm->total_out + STREAM_END_SPACE);
|
||||
def_strm->avail_in = min((unsigned)(*sourcelen-def_strm->total_in), def_strm->avail_out);
|
||||
jffs2_dbg(1, "calling deflate with avail_in %d, avail_out %d\n",
|
||||
def_strm.avail_in, def_strm.avail_out);
|
||||
ret = zlib_deflate(&def_strm, Z_PARTIAL_FLUSH);
|
||||
def_strm->avail_in, def_strm->avail_out);
|
||||
ret = zlib_deflate(def_strm, Z_PARTIAL_FLUSH);
|
||||
jffs2_dbg(1, "deflate returned with avail_in %d, avail_out %d, total_in %ld, total_out %ld\n",
|
||||
def_strm.avail_in, def_strm.avail_out,
|
||||
def_strm.total_in, def_strm.total_out);
|
||||
def_strm->avail_in, def_strm->avail_out,
|
||||
def_strm->total_in, def_strm->total_out);
|
||||
if (ret != Z_OK) {
|
||||
jffs2_dbg(1, "deflate in loop returned %d\n", ret);
|
||||
zlib_deflateEnd(&def_strm);
|
||||
zlib_deflateEnd(def_strm);
|
||||
mutex_unlock(&deflate_mutex);
|
||||
return -1;
|
||||
return JFFS2_COMPR_NONE;
|
||||
}
|
||||
}
|
||||
def_strm.avail_out += STREAM_END_SPACE;
|
||||
def_strm.avail_in = 0;
|
||||
ret = zlib_deflate(&def_strm, Z_FINISH);
|
||||
zlib_deflateEnd(&def_strm);
|
||||
def_strm->avail_out += STREAM_END_SPACE;
|
||||
def_strm->avail_in = 0;
|
||||
ret = zlib_deflate(def_strm, Z_FINISH);
|
||||
zlib_deflateEnd(def_strm);
|
||||
|
||||
if (ret != Z_STREAM_END) {
|
||||
jffs2_dbg(1, "final deflate returned %d\n", ret);
|
||||
ret = -1;
|
||||
ret = JFFS2_COMPR_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (def_strm.total_out >= def_strm.total_in) {
|
||||
if (def_strm->total_out >= def_strm->total_in) {
|
||||
jffs2_dbg(1, "zlib compressed %ld bytes into %ld; failing\n",
|
||||
def_strm.total_in, def_strm.total_out);
|
||||
ret = -1;
|
||||
def_strm->total_in, def_strm->total_out);
|
||||
ret = JFFS2_COMPR_NONE;
|
||||
goto out;
|
||||
}
|
||||
|
||||
jffs2_dbg(1, "zlib compressed %ld bytes into %ld\n",
|
||||
def_strm.total_in, def_strm.total_out);
|
||||
def_strm->total_in, def_strm->total_out);
|
||||
|
||||
*dstlen = def_strm.total_out;
|
||||
*sourcelen = def_strm.total_in;
|
||||
ret = 0;
|
||||
*dstlen = def_strm->total_out;
|
||||
*sourcelen = def_strm->total_in;
|
||||
ret = JFFS2_COMPR_ZLIB;
|
||||
out:
|
||||
mutex_unlock(&deflate_mutex);
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int jffs2_zlib_decompress(unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t srclen, uint32_t destlen)
|
||||
int rtems_jffs2_compressor_zlib_decompress(
|
||||
rtems_jffs2_compressor_control *super,
|
||||
uint16_t comprtype,
|
||||
unsigned char *data_in,
|
||||
unsigned char *cpage_out,
|
||||
uint32_t srclen,
|
||||
uint32_t destlen
|
||||
)
|
||||
{
|
||||
rtems_jffs2_compressor_zlib_control *self = get_zlib_control(super);
|
||||
z_stream *inf_strm = &self->stream;
|
||||
int ret;
|
||||
int wbits = MAX_WBITS;
|
||||
|
||||
if (comprtype != JFFS2_COMPR_ZLIB) {
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
mutex_lock(&inflate_mutex);
|
||||
|
||||
inf_strm.next_in = data_in;
|
||||
inf_strm.avail_in = srclen;
|
||||
inf_strm.total_in = 0;
|
||||
inf_strm->next_in = data_in;
|
||||
inf_strm->avail_in = srclen;
|
||||
inf_strm->total_in = 0;
|
||||
|
||||
inf_strm.next_out = cpage_out;
|
||||
inf_strm.avail_out = destlen;
|
||||
inf_strm.total_out = 0;
|
||||
inf_strm->next_out = cpage_out;
|
||||
inf_strm->avail_out = destlen;
|
||||
inf_strm->total_out = 0;
|
||||
|
||||
/* If it's deflate, and it's got no preset dictionary, then
|
||||
we can tell zlib to skip the adler32 check. */
|
||||
@@ -162,60 +151,26 @@ static int jffs2_zlib_decompress(unsigned char *data_in,
|
||||
|
||||
jffs2_dbg(2, "inflate skipping adler32\n");
|
||||
wbits = -((data_in[0] >> 4) + 8);
|
||||
inf_strm.next_in += 2;
|
||||
inf_strm.avail_in -= 2;
|
||||
inf_strm->next_in += 2;
|
||||
inf_strm->avail_in -= 2;
|
||||
} else {
|
||||
/* Let this remain D1 for now -- it should never happen */
|
||||
jffs2_dbg(1, "inflate not skipping adler32\n");
|
||||
}
|
||||
|
||||
|
||||
if (Z_OK != zlib_inflateInit2(&inf_strm, wbits)) {
|
||||
if (Z_OK != zlib_inflateInit2(inf_strm, wbits)) {
|
||||
pr_warn("inflateInit failed\n");
|
||||
mutex_unlock(&inflate_mutex);
|
||||
return 1;
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
while((ret = zlib_inflate(&inf_strm, Z_FINISH)) == Z_OK)
|
||||
while((ret = zlib_inflate(inf_strm, Z_FINISH)) == Z_OK)
|
||||
;
|
||||
if (ret != Z_STREAM_END) {
|
||||
pr_notice("inflate returned %d\n", ret);
|
||||
}
|
||||
zlib_inflateEnd(&inf_strm);
|
||||
zlib_inflateEnd(inf_strm);
|
||||
mutex_unlock(&inflate_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct jffs2_compressor jffs2_zlib_comp = {
|
||||
.priority = JFFS2_ZLIB_PRIORITY,
|
||||
.name = "zlib",
|
||||
.compr = JFFS2_COMPR_ZLIB,
|
||||
.compress = &jffs2_zlib_compress,
|
||||
.decompress = &jffs2_zlib_decompress,
|
||||
#ifdef JFFS2_ZLIB_DISABLED
|
||||
.disabled = 1,
|
||||
#else
|
||||
.disabled = 0,
|
||||
#endif
|
||||
};
|
||||
|
||||
int __init jffs2_zlib_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = alloc_workspaces();
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = jffs2_register_compressor(&jffs2_zlib_comp);
|
||||
if (ret)
|
||||
free_workspaces();
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
void jffs2_zlib_exit(void)
|
||||
{
|
||||
jffs2_unregister_compressor(&jffs2_zlib_comp);
|
||||
free_workspaces();
|
||||
}
|
||||
|
||||
@@ -75,6 +75,7 @@ do { \
|
||||
#define JFFS2_DBG_MSG_PREFIX JFFS2_DBG JFFS2_DBG_PREFIX
|
||||
|
||||
/* JFFS2 message macros */
|
||||
#ifndef __rtems__
|
||||
#define JFFS2_ERROR(fmt, ...) \
|
||||
pr_err("error: (%d) %s: " fmt, \
|
||||
task_pid_nr(current), __func__, ##__VA_ARGS__)
|
||||
@@ -90,6 +91,23 @@ do { \
|
||||
#define JFFS2_DEBUG(fmt, ...) \
|
||||
printk(KERN_DEBUG "[JFFS2 DBG] (%d) %s: " fmt, \
|
||||
task_pid_nr(current), __func__, ##__VA_ARGS__)
|
||||
#else /* __rtems__ */
|
||||
#define JFFS2_ERROR(fmt, ...) \
|
||||
pr_err("error: %s: " fmt, \
|
||||
__func__, ##__VA_ARGS__)
|
||||
|
||||
#define JFFS2_WARNING(fmt, ...) \
|
||||
pr_warn("warning: %s: " fmt, \
|
||||
__func__, ##__VA_ARGS__)
|
||||
|
||||
#define JFFS2_NOTICE(fmt, ...) \
|
||||
pr_notice("notice: %s: " fmt, \
|
||||
__func__, ##__VA_ARGS__)
|
||||
|
||||
#define JFFS2_DEBUG(fmt, ...) \
|
||||
printk(KERN_DEBUG "[JFFS2 DBG] %s: " fmt, \
|
||||
__func__, ##__VA_ARGS__)
|
||||
#endif /* __rtems__ */
|
||||
|
||||
/*
|
||||
* We split our debugging messages on several parts, depending on the JFFS2
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
/*
|
||||
* JFFS2 -- Journalling Flash File System, Version 2.
|
||||
*
|
||||
* Copyright (C) 2001-2003 Free Software Foundation, Inc.
|
||||
* Copyright © 2001-2003 Free Software Foundation, Inc.
|
||||
* Copyright © 2001-2007 Red Hat, Inc.
|
||||
* Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
|
||||
* Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
|
||||
*
|
||||
* Created by David Woodhouse <dwmw2@cambridge.redhat.com>
|
||||
*
|
||||
* Port to the RTEMS by embedded brains GmbH.
|
||||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
* $Id: dir-ecos.c,v 1.11 2005/02/08 19:36:27 lunn Exp $
|
||||
@@ -18,39 +23,39 @@
|
||||
/***********************************************************************/
|
||||
|
||||
/* Takes length argument because it can be either NUL-terminated or '/'-terminated */
|
||||
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, int namelen)
|
||||
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, size_t namelen)
|
||||
{
|
||||
struct jffs2_inode_info *dir_f;
|
||||
struct jffs2_sb_info *c;
|
||||
struct jffs2_full_dirent *fd = NULL, *fd_list;
|
||||
uint32_t ino = 0;
|
||||
uint32_t hash = full_name_hash(d_name, namelen);
|
||||
uint32_t hash = full_name_hash(name, namelen);
|
||||
struct _inode *inode = NULL;
|
||||
|
||||
D1(printk("jffs2_lookup()\n"));
|
||||
|
||||
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
c = JFFS2_SB_INFO(dir_i->i_sb);
|
||||
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
/* NB: The 2.2 backport will need to explicitly check for '.' and '..' here */
|
||||
for (fd_list = dir_f->dents; fd_list && fd_list->nhash <= hash; fd_list = fd_list->next) {
|
||||
if (fd_list->nhash == hash &&
|
||||
(!fd || fd_list->version > fd->version) &&
|
||||
strlen((char *)fd_list->name) == namelen &&
|
||||
!strncmp((char *)fd_list->name, (char *)d_name, namelen)) {
|
||||
!strncmp((char *)fd_list->name, (char *)name, namelen)) {
|
||||
fd = fd_list;
|
||||
}
|
||||
}
|
||||
if (fd)
|
||||
ino = fd->ino;
|
||||
up(&dir_f->sem);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
if (ino) {
|
||||
inode = jffs2_iget(dir_i->i_sb, ino);
|
||||
if (IS_ERR(inode)) {
|
||||
printk("jffs2_iget() failed for ino #%u\n", ino);
|
||||
return inode;
|
||||
} else {
|
||||
inode->i_fd = fd;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,14 +66,17 @@ struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *d_name, i
|
||||
|
||||
|
||||
|
||||
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
|
||||
struct _inode **new_i)
|
||||
int jffs2_create(struct _inode *dir_i, const char *d_name, size_t d_namelen, int mode)
|
||||
{
|
||||
struct jffs2_raw_inode *ri;
|
||||
struct jffs2_inode_info *f, *dir_f;
|
||||
struct jffs2_sb_info *c;
|
||||
struct _inode *inode;
|
||||
int ret;
|
||||
struct qstr qstr;
|
||||
|
||||
qstr.name = d_name;
|
||||
qstr.len = d_namelen;
|
||||
|
||||
ri = jffs2_alloc_raw_inode();
|
||||
if (!ri)
|
||||
@@ -89,9 +97,7 @@ int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
|
||||
f = JFFS2_INODE_INFO(inode);
|
||||
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
|
||||
ret = jffs2_do_create(c, dir_f, f, ri,
|
||||
(const char *)d_name,
|
||||
strlen((char *)d_name));
|
||||
ret = jffs2_do_create(c, dir_f, f, ri, &qstr);
|
||||
|
||||
if (ret) {
|
||||
inode->i_nlink = 0;
|
||||
@@ -100,34 +106,36 @@ int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode,
|
||||
return ret;
|
||||
}
|
||||
|
||||
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(ri->ctime));
|
||||
|
||||
jffs2_free_raw_inode(ri);
|
||||
|
||||
D1(printk(KERN_DEBUG "jffs2_create: Created ino #%lu with mode %o, nlink %d(%d)\n",
|
||||
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->nlink));
|
||||
*new_i = inode;
|
||||
inode->i_ino, inode->i_mode, inode->i_nlink, f->inocache->pino_nlink));
|
||||
jffs2_iput(inode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/***********************************************************************/
|
||||
|
||||
|
||||
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
|
||||
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
|
||||
{
|
||||
struct jffs2_sb_info *c = JFFS2_SB_INFO(dir_i->i_sb);
|
||||
struct jffs2_inode_info *dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
struct jffs2_inode_info *dead_f = JFFS2_INODE_INFO(d_inode);
|
||||
int ret;
|
||||
|
||||
ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
|
||||
strlen((char *)d_name), dead_f);
|
||||
ret = jffs2_do_unlink(c, dir_f, (const char *)d_name,
|
||||
d_namelen, dead_f, get_seconds());
|
||||
if (dead_f->inocache)
|
||||
d_inode->i_nlink = dead_f->inocache->nlink;
|
||||
d_inode->i_nlink = dead_f->inocache->pino_nlink;
|
||||
return ret;
|
||||
}
|
||||
/***********************************************************************/
|
||||
|
||||
|
||||
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name)
|
||||
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen)
|
||||
{
|
||||
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_d_inode->i_sb);
|
||||
struct jffs2_inode_info *f = JFFS2_INODE_INFO(old_d_inode);
|
||||
@@ -140,17 +148,26 @@ int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned
|
||||
|
||||
ret = jffs2_do_link(c, dir_f, f->inocache->ino, type,
|
||||
(const char * )d_name,
|
||||
strlen((char *)d_name));
|
||||
d_namelen, get_seconds());
|
||||
|
||||
if (!ret) {
|
||||
down(&f->sem);
|
||||
old_d_inode->i_nlink = ++f->inocache->nlink;
|
||||
up(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
old_d_inode->i_nlink = ++f->inocache->pino_nlink;
|
||||
mutex_unlock(&f->sem);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
|
||||
/***********************************************************************/
|
||||
|
||||
int jffs2_mknod(
|
||||
struct _inode *dir_i,
|
||||
const unsigned char *d_name,
|
||||
size_t d_namelen,
|
||||
int mode,
|
||||
const unsigned char *data,
|
||||
size_t datalen
|
||||
)
|
||||
{
|
||||
struct jffs2_inode_info *f, *dir_f;
|
||||
struct jffs2_sb_info *c;
|
||||
@@ -159,23 +176,26 @@ int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
|
||||
struct jffs2_raw_dirent *rd;
|
||||
struct jffs2_full_dnode *fn;
|
||||
struct jffs2_full_dirent *fd;
|
||||
int namelen;
|
||||
uint32_t alloclen, phys_ofs;
|
||||
uint32_t alloclen;
|
||||
int ret;
|
||||
|
||||
mode |= S_IFDIR;
|
||||
/* FIXME: If you care. We'd need to use frags for the data
|
||||
if it grows much more than this */
|
||||
if (datalen > 254)
|
||||
return -ENAMETOOLONG;
|
||||
|
||||
ri = jffs2_alloc_raw_inode();
|
||||
|
||||
if (!ri)
|
||||
return -ENOMEM;
|
||||
|
||||
|
||||
c = JFFS2_SB_INFO(dir_i->i_sb);
|
||||
|
||||
/* Try to reserve enough space for both node and dirent.
|
||||
* Just the node will do for now, though
|
||||
/* Try to reserve enough space for both node and dirent.
|
||||
* Just the node will do for now, though
|
||||
*/
|
||||
namelen = strlen((char *)d_name);
|
||||
ret = jffs2_reserve_space(c, sizeof(*ri), &phys_ofs, &alloclen, ALLOC_NORMAL);
|
||||
ret = jffs2_reserve_space(c, sizeof(*ri) + datalen, &alloclen,
|
||||
ALLOC_NORMAL, JFFS2_SUMMARY_INODE_SIZE);
|
||||
|
||||
if (ret) {
|
||||
jffs2_free_raw_inode(ri);
|
||||
@@ -192,104 +212,132 @@ int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode)
|
||||
|
||||
f = JFFS2_INODE_INFO(inode);
|
||||
|
||||
ri->data_crc = cpu_to_je32(0);
|
||||
inode->i_size = datalen;
|
||||
ri->isize = ri->dsize = ri->csize = cpu_to_je32(inode->i_size);
|
||||
ri->totlen = cpu_to_je32(sizeof(*ri) + inode->i_size);
|
||||
ri->hdr_crc = cpu_to_je32(crc32(0, ri, sizeof(struct jffs2_unknown_node)-4));
|
||||
|
||||
ri->compr = JFFS2_COMPR_NONE;
|
||||
ri->data_crc = cpu_to_je32(crc32(0, data, datalen));
|
||||
ri->node_crc = cpu_to_je32(crc32(0, ri, sizeof(*ri)-8));
|
||||
|
||||
fn = jffs2_write_dnode(c, f, ri, NULL, 0, phys_ofs, ALLOC_NORMAL);
|
||||
|
||||
fn = jffs2_write_dnode(c, f, ri, data, datalen, ALLOC_NORMAL);
|
||||
|
||||
jffs2_free_raw_inode(ri);
|
||||
|
||||
if (IS_ERR(fn)) {
|
||||
/* Eeek. Wave bye bye */
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
inode->i_nlink = 0;
|
||||
jffs2_iput(inode);
|
||||
return PTR_ERR(fn);
|
||||
ret = PTR_ERR(fn);
|
||||
goto fail;
|
||||
}
|
||||
/* No data here. Only a metadata node, which will be
|
||||
|
||||
if (S_ISLNK(mode)) {
|
||||
/* We use f->target field to store the target path. */
|
||||
f->target = kmemdup(data, datalen + 1, GFP_KERNEL);
|
||||
if (!f->target) {
|
||||
pr_warn("Can't allocate %d bytes of memory\n", datalen + 1);
|
||||
mutex_unlock(&f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
jffs2_dbg(1, "%s(): symlink's target '%s' cached\n",
|
||||
__func__, (char *)f->target);
|
||||
}
|
||||
|
||||
/* No data here. Only a metadata node, which will be
|
||||
obsoleted by the first data write
|
||||
*/
|
||||
f->metadata = fn;
|
||||
up(&f->sem);
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
ret = jffs2_reserve_space(c, sizeof(*rd)+namelen, &phys_ofs, &alloclen, ALLOC_NORMAL);
|
||||
if (ret) {
|
||||
/* Eep. */
|
||||
inode->i_nlink = 0;
|
||||
jffs2_iput(inode);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
ret = jffs2_reserve_space(c, sizeof(*rd)+d_namelen, &alloclen,
|
||||
ALLOC_NORMAL, JFFS2_SUMMARY_DIRENT_SIZE(d_namelen));
|
||||
if (ret)
|
||||
goto fail;
|
||||
|
||||
rd = jffs2_alloc_raw_dirent();
|
||||
if (!rd) {
|
||||
/* Argh. Now we treat it like a normal delete */
|
||||
jffs2_complete_reservation(c);
|
||||
inode->i_nlink = 0;
|
||||
jffs2_iput(inode);
|
||||
return -ENOMEM;
|
||||
ret = -ENOMEM;
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dir_f = JFFS2_INODE_INFO(dir_i);
|
||||
down(&dir_f->sem);
|
||||
mutex_lock(&dir_f->sem);
|
||||
|
||||
rd->magic = cpu_to_je16(JFFS2_MAGIC_BITMASK);
|
||||
rd->nodetype = cpu_to_je16(JFFS2_NODETYPE_DIRENT);
|
||||
rd->totlen = cpu_to_je32(sizeof(*rd) + namelen);
|
||||
rd->totlen = cpu_to_je32(sizeof(*rd) + d_namelen);
|
||||
rd->hdr_crc = cpu_to_je32(crc32(0, rd, sizeof(struct jffs2_unknown_node)-4));
|
||||
|
||||
rd->pino = cpu_to_je32(dir_i->i_ino);
|
||||
rd->version = cpu_to_je32(++dir_f->highest_version);
|
||||
rd->ino = cpu_to_je32(inode->i_ino);
|
||||
rd->mctime = cpu_to_je32(cyg_timestamp());
|
||||
rd->nsize = namelen;
|
||||
rd->type = DT_DIR;
|
||||
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
|
||||
rd->name_crc = cpu_to_je32(crc32(0, d_name, namelen));
|
||||
rd->mctime = cpu_to_je32(get_seconds());
|
||||
rd->nsize = d_namelen;
|
||||
|
||||
/* XXX: This is ugly. */
|
||||
rd->type = (mode & S_IFMT) >> 12;
|
||||
|
||||
rd->node_crc = cpu_to_je32(crc32(0, rd, sizeof(*rd)-8));
|
||||
rd->name_crc = cpu_to_je32(crc32(0, d_name, d_namelen));
|
||||
|
||||
fd = jffs2_write_dirent(c, dir_f, rd, d_name, d_namelen, ALLOC_NORMAL);
|
||||
|
||||
fd = jffs2_write_dirent(c, dir_f, rd, d_name, namelen, phys_ofs, ALLOC_NORMAL);
|
||||
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_free_raw_dirent(rd);
|
||||
|
||||
if (IS_ERR(fd)) {
|
||||
/* dirent failed to write. Delete the inode normally
|
||||
/* dirent failed to write. Delete the inode normally
|
||||
as if it were the final unlink() */
|
||||
up(&dir_f->sem);
|
||||
inode->i_nlink = 0;
|
||||
jffs2_iput(inode);
|
||||
return PTR_ERR(fd);
|
||||
jffs2_complete_reservation(c);
|
||||
jffs2_free_raw_dirent(rd);
|
||||
mutex_unlock(&dir_f->sem);
|
||||
ret = PTR_ERR(fd);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
dir_i->i_mtime = dir_i->i_ctime = ITIME(je32_to_cpu(rd->mctime));
|
||||
|
||||
jffs2_free_raw_dirent(rd);
|
||||
|
||||
/* Link the fd into the inode's list, obsoleting an old
|
||||
one if necessary. */
|
||||
jffs2_add_fd_to_list(c, fd, &dir_f->dents);
|
||||
up(&dir_f->sem);
|
||||
|
||||
mutex_unlock(&dir_f->sem);
|
||||
jffs2_complete_reservation(c);
|
||||
|
||||
fail:
|
||||
jffs2_iput(inode);
|
||||
return 0;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name)
|
||||
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen)
|
||||
{
|
||||
struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
|
||||
struct jffs2_full_dirent *fd;
|
||||
|
||||
for (fd = f->dents ; fd; fd = fd->next) {
|
||||
if (fd->ino)
|
||||
return EPERM; //-ENOTEMPTY;
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
return jffs2_unlink(dir_i, d_inode, d_name);
|
||||
return jffs2_unlink(dir_i, d_inode, d_name, d_namelen);
|
||||
}
|
||||
|
||||
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
|
||||
struct _inode *new_dir_i, const unsigned char *new_d_name)
|
||||
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, size_t old_d_namelen,
|
||||
struct _inode *new_dir_i, const unsigned char *new_d_name, size_t new_d_namelen)
|
||||
{
|
||||
int ret;
|
||||
struct jffs2_sb_info *c = JFFS2_SB_INFO(old_dir_i->i_sb);
|
||||
struct jffs2_inode_info *victim_f = NULL;
|
||||
uint8_t type;
|
||||
uint32_t now;
|
||||
|
||||
#if 0 /* FIXME -- this really doesn't belong in individual file systems.
|
||||
The fileio code ought to do this for us, or at least part of it */
|
||||
@@ -309,14 +357,14 @@ int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsign
|
||||
/* Cannot rename non-directory over directory */
|
||||
return -EINVAL;
|
||||
}
|
||||
down(&victim_f->sem);
|
||||
mutex_lock(&victim_f->sem);
|
||||
for (fd = victim_f->dents; fd; fd = fd->next) {
|
||||
if (fd->ino) {
|
||||
up(&victim_f->sem);
|
||||
mutex_unlock(&victim_f->sem);
|
||||
return -ENOTEMPTY;
|
||||
}
|
||||
}
|
||||
up(&victim_f->sem);
|
||||
mutex_unlock(&victim_f->sem);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -332,10 +380,11 @@ int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsign
|
||||
type = (d_inode->i_mode & S_IFMT) >> 12;
|
||||
if (!type) type = DT_REG;
|
||||
|
||||
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
|
||||
now = get_seconds();
|
||||
ret = jffs2_do_link(c, JFFS2_INODE_INFO(new_dir_i),
|
||||
d_inode->i_ino, type,
|
||||
(const char *)new_d_name,
|
||||
strlen((char *)new_d_name));
|
||||
(const char *)new_d_name,
|
||||
new_d_namelen, now);
|
||||
|
||||
if (ret)
|
||||
return ret;
|
||||
@@ -345,24 +394,24 @@ int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsign
|
||||
/* Don't oops if the victim was a dirent pointing to an
|
||||
inode which didn't exist. */
|
||||
if (victim_f->inocache) {
|
||||
down(&victim_f->sem);
|
||||
victim_f->inocache->nlink--;
|
||||
up(&victim_f->sem);
|
||||
mutex_lock(&victim_f->sem);
|
||||
victim_f->inocache->pino_nlink--;
|
||||
mutex_unlock(&victim_f->sem);
|
||||
}
|
||||
}
|
||||
|
||||
/* Unlink the original */
|
||||
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
|
||||
(const char *)old_d_name,
|
||||
strlen((char *)old_d_name), NULL);
|
||||
ret = jffs2_do_unlink(c, JFFS2_INODE_INFO(old_dir_i),
|
||||
(const char *)old_d_name,
|
||||
old_d_namelen, NULL, now);
|
||||
|
||||
if (ret) {
|
||||
/* Oh shit. We really ought to make a single node which can do both atomically */
|
||||
struct jffs2_inode_info *f = JFFS2_INODE_INFO(d_inode);
|
||||
down(&f->sem);
|
||||
mutex_lock(&f->sem);
|
||||
if (f->inocache)
|
||||
d_inode->i_nlink = f->inocache->nlink++;
|
||||
up(&f->sem);
|
||||
d_inode->i_nlink = f->inocache->pino_nlink++;
|
||||
mutex_unlock(&f->sem);
|
||||
|
||||
printk(KERN_NOTICE "jffs2_rename(): Link succeeded, unlink failed (err %d). You now have a hard link\n", ret);
|
||||
}
|
||||
|
||||
@@ -391,7 +391,7 @@ static int jffs2_block_check_erase(struct jffs2_sb_info *c, struct jffs2_erasebl
|
||||
|
||||
*bad_offset = ofs;
|
||||
|
||||
ret = mtd_read(c->mtd, ofs, readlen, &retlen, ebuf);
|
||||
ret = jffs2_flash_read(c, ofs, readlen, &retlen, ebuf);
|
||||
if (ret) {
|
||||
pr_warn("Read of newly-erased block at 0x%08x failed: %d. Putting on bad_list\n",
|
||||
ofs, ret);
|
||||
|
||||
@@ -15,46 +15,28 @@
|
||||
#include <linux/kernel.h>
|
||||
#include "nodelist.h"
|
||||
|
||||
#include <cyg/io/io.h>
|
||||
#include <cyg/io/config_keys.h>
|
||||
#include <cyg/io/flash.h>
|
||||
|
||||
cyg_bool jffs2_flash_read(struct jffs2_sb_info * c,
|
||||
int jffs2_flash_read(struct jffs2_sb_info * c,
|
||||
cyg_uint32 read_buffer_offset, const size_t size,
|
||||
size_t * return_size, unsigned char *write_buffer)
|
||||
{
|
||||
Cyg_ErrNo err;
|
||||
cyg_uint32 len = size;
|
||||
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
const struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
rtems_jffs2_flash_control *fc = sb->s_flash_control;
|
||||
|
||||
//D2(printf("FLASH READ\n"));
|
||||
//D2(printf("read address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + read_buffer_offset));
|
||||
//D2(printf("write address = %x\n", write_buffer));
|
||||
//D2(printf("size = %x\n", size));
|
||||
err = cyg_io_bread(sb->s_dev, write_buffer, &len, read_buffer_offset);
|
||||
*return_size = size;
|
||||
|
||||
*return_size = (size_t) len;
|
||||
return ((err == ENOERR) ? ENOERR : -EIO);
|
||||
return (*fc->read)(fc, read_buffer_offset, write_buffer, size);
|
||||
}
|
||||
|
||||
cyg_bool jffs2_flash_write(struct jffs2_sb_info * c,
|
||||
int jffs2_flash_write(struct jffs2_sb_info * c,
|
||||
cyg_uint32 write_buffer_offset, const size_t size,
|
||||
size_t * return_size, unsigned char *read_buffer)
|
||||
{
|
||||
const struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
rtems_jffs2_flash_control *fc = sb->s_flash_control;
|
||||
|
||||
Cyg_ErrNo err;
|
||||
cyg_uint32 len = size;
|
||||
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
*return_size = size;
|
||||
|
||||
// D2(printf("FLASH WRITE ENABLED!!!\n"));
|
||||
// D2(printf("write address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + write_buffer_offset));
|
||||
// D2(printf("read address = %x\n", read_buffer));
|
||||
// D2(printf("size = %x\n", size));
|
||||
|
||||
err = cyg_io_bwrite(sb->s_dev, read_buffer, &len, write_buffer_offset);
|
||||
*return_size = (size_t) len;
|
||||
|
||||
return ((err == ENOERR) ? ENOERR : -EIO);
|
||||
return (*fc->write)(fc, write_buffer_offset, read_buffer, size);
|
||||
}
|
||||
|
||||
int
|
||||
@@ -140,26 +122,12 @@ jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
|
||||
return ret;
|
||||
}
|
||||
|
||||
cyg_bool jffs2_flash_erase(struct jffs2_sb_info * c,
|
||||
int jffs2_flash_erase(struct jffs2_sb_info * c,
|
||||
struct jffs2_eraseblock * jeb)
|
||||
{
|
||||
cyg_io_flash_getconfig_erase_t e;
|
||||
cyg_flashaddr_t err_addr;
|
||||
Cyg_ErrNo err;
|
||||
cyg_uint32 len = sizeof (e);
|
||||
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
const struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
rtems_jffs2_flash_control *fc = sb->s_flash_control;
|
||||
|
||||
e.offset = jeb->offset;
|
||||
e.len = c->sector_size;
|
||||
e.err_address = &err_addr;
|
||||
|
||||
// D2(printf("FLASH ERASE ENABLED!!!\n"));
|
||||
// D2(printf("erase address = %x\n", CYGNUM_FS_JFFS2_BASE_ADDRESS + jeb->offset));
|
||||
// D2(printf("size = %x\n", c->sector_size));
|
||||
|
||||
err = cyg_io_get_config(sb->s_dev, CYG_IO_GET_CONFIG_FLASH_ERASE,
|
||||
&e, &len);
|
||||
|
||||
return (err != ENOERR || e.flasherr != 0);
|
||||
return (*fc->erase)(fc, jeb->offset);
|
||||
}
|
||||
|
||||
|
||||
+1094
-1692
File diff suppressed because it is too large
Load Diff
@@ -741,7 +741,9 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
|
||||
struct jffs2_full_dnode *new_fn;
|
||||
struct jffs2_raw_inode ri;
|
||||
struct jffs2_node_frag *last_frag;
|
||||
#ifndef __rtems__
|
||||
union jffs2_device_node dev;
|
||||
#endif /* __rtems__ */
|
||||
char *mdata = NULL;
|
||||
int mdatalen = 0;
|
||||
uint32_t alloclen, ilen;
|
||||
@@ -749,11 +751,15 @@ static int jffs2_garbage_collect_metadata(struct jffs2_sb_info *c, struct jffs2_
|
||||
|
||||
if (S_ISBLK(JFFS2_F_I_MODE(f)) ||
|
||||
S_ISCHR(JFFS2_F_I_MODE(f)) ) {
|
||||
#ifndef __rtems__
|
||||
/* For these, we don't actually need to read the old node */
|
||||
mdatalen = jffs2_encode_dev(&dev, JFFS2_F_I_RDEV(f));
|
||||
mdata = (char *)&dev;
|
||||
jffs2_dbg(1, "%s(): Writing %d bytes of kdev_t\n",
|
||||
__func__, mdatalen);
|
||||
#else /* __rtems__ */
|
||||
return -EIO;
|
||||
#endif /* __rtems__ */
|
||||
} else if (S_ISLNK(JFFS2_F_I_MODE(f))) {
|
||||
mdatalen = fn->size;
|
||||
mdata = kmalloc(fn->size, GFP_KERNEL);
|
||||
|
||||
@@ -50,7 +50,9 @@ struct jffs2_inode_info {
|
||||
|
||||
uint16_t flags;
|
||||
uint8_t usercompr;
|
||||
#if !defined (__ECOS)
|
||||
struct inode vfs_inode;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif /* _JFFS2_FS_I */
|
||||
|
||||
@@ -12,13 +12,8 @@
|
||||
*/
|
||||
|
||||
#include <linux/kernel.h>
|
||||
#include <cyg/hal/drv_api.h>
|
||||
#include "nodelist.h"
|
||||
|
||||
#if !defined(CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE)
|
||||
# define CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE 0
|
||||
#endif
|
||||
|
||||
struct jffs2_full_dirent *jffs2_alloc_full_dirent(int namesize)
|
||||
{
|
||||
return malloc(sizeof(struct jffs2_full_dirent) + namesize);
|
||||
@@ -69,6 +64,60 @@ void jffs2_free_tmp_dnode_info(struct jffs2_tmp_dnode_info *x)
|
||||
free(x);
|
||||
}
|
||||
|
||||
static struct jffs2_raw_node_ref *jffs2_alloc_refblock(void)
|
||||
{
|
||||
struct jffs2_raw_node_ref *ret;
|
||||
|
||||
ret = malloc((REFS_PER_BLOCK + 1) * sizeof(*ret));
|
||||
if (ret) {
|
||||
int i = 0;
|
||||
for (i=0; i < REFS_PER_BLOCK; i++) {
|
||||
ret[i].flash_offset = REF_EMPTY_NODE;
|
||||
ret[i].next_in_ino = NULL;
|
||||
}
|
||||
ret[i].flash_offset = REF_LINK_NODE;
|
||||
ret[i].next_in_ino = NULL;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
int jffs2_prealloc_raw_node_refs(struct jffs2_sb_info *c,
|
||||
struct jffs2_eraseblock *jeb, int nr)
|
||||
{
|
||||
struct jffs2_raw_node_ref **p, *ref;
|
||||
int i = nr;
|
||||
|
||||
p = &jeb->last_node;
|
||||
ref = *p;
|
||||
|
||||
/* If jeb->last_node is really a valid node then skip over it */
|
||||
if (ref && ref->flash_offset != REF_EMPTY_NODE)
|
||||
ref++;
|
||||
|
||||
while (i) {
|
||||
if (!ref) {
|
||||
ref = *p = jffs2_alloc_refblock();
|
||||
if (!ref)
|
||||
return -ENOMEM;
|
||||
}
|
||||
if (ref->flash_offset == REF_LINK_NODE) {
|
||||
p = &ref->next_in_ino;
|
||||
ref = *p;
|
||||
continue;
|
||||
}
|
||||
i--;
|
||||
ref++;
|
||||
}
|
||||
jeb->allocated_refs = nr;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jffs2_free_refblock(struct jffs2_raw_node_ref *x)
|
||||
{
|
||||
free(x);
|
||||
}
|
||||
|
||||
struct jffs2_node_frag *jffs2_alloc_node_frag(void)
|
||||
{
|
||||
return malloc(sizeof(struct jffs2_node_frag));
|
||||
@@ -79,75 +128,6 @@ void jffs2_free_node_frag(struct jffs2_node_frag *x)
|
||||
free(x);
|
||||
}
|
||||
|
||||
#if CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
|
||||
|
||||
int jffs2_create_slab_caches(void)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jffs2_destroy_slab_caches(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
|
||||
{
|
||||
return malloc(sizeof(struct jffs2_raw_node_ref));
|
||||
}
|
||||
|
||||
void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
|
||||
{
|
||||
free(x);
|
||||
}
|
||||
|
||||
#else // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
|
||||
|
||||
static struct jffs2_raw_node_ref
|
||||
rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE] __attribute__ ((aligned (4))),
|
||||
* first = NULL;
|
||||
static cyg_drv_mutex_t mutex;
|
||||
|
||||
int jffs2_create_slab_caches(void)
|
||||
{
|
||||
struct jffs2_raw_node_ref * p;
|
||||
cyg_drv_mutex_init(&mutex);
|
||||
for (
|
||||
p = rnr_pool;
|
||||
p < rnr_pool + CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1;
|
||||
p++
|
||||
)
|
||||
p->next_phys = p + 1;
|
||||
rnr_pool[CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE - 1].next_phys = NULL;
|
||||
first = &rnr_pool[0];
|
||||
return 0;
|
||||
}
|
||||
|
||||
void jffs2_destroy_slab_caches(void)
|
||||
{
|
||||
}
|
||||
|
||||
struct jffs2_raw_node_ref *jffs2_alloc_raw_node_ref(void)
|
||||
{
|
||||
struct jffs2_raw_node_ref * p;
|
||||
|
||||
cyg_drv_mutex_lock(&mutex);
|
||||
p = first;
|
||||
if (p != NULL)
|
||||
first = p->next_phys;
|
||||
cyg_drv_mutex_unlock(&mutex);
|
||||
return p;
|
||||
}
|
||||
|
||||
void jffs2_free_raw_node_ref(struct jffs2_raw_node_ref *x)
|
||||
{
|
||||
cyg_drv_mutex_lock(&mutex);
|
||||
x->next_phys = first;
|
||||
first = x;
|
||||
cyg_drv_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
#endif // CYGNUM_FS_JFFS2_RAW_NODE_REF_CACHE_POOL_SIZE == 0
|
||||
|
||||
struct jffs2_inode_cache *jffs2_alloc_inode_cache(void)
|
||||
{
|
||||
struct jffs2_inode_cache *ret = malloc(sizeof(struct jffs2_inode_cache));
|
||||
|
||||
@@ -21,8 +21,8 @@
|
||||
#include "acl.h"
|
||||
#include "summary.h"
|
||||
|
||||
#ifdef __ECOS
|
||||
#include "os-ecos.h"
|
||||
#ifdef __rtems__
|
||||
#include "os-rtems.h"
|
||||
#else
|
||||
#include "os-linux.h"
|
||||
#endif
|
||||
@@ -309,6 +309,7 @@ static inline int jffs2_blocks_use_vmalloc(struct jffs2_sb_info *c)
|
||||
|
||||
#define PAD(x) (((x)+3)&~3)
|
||||
|
||||
#ifndef __rtems__
|
||||
static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
|
||||
{
|
||||
if (old_valid_dev(rdev)) {
|
||||
@@ -319,6 +320,7 @@ static inline int jffs2_encode_dev(union jffs2_device_node *jdev, dev_t rdev)
|
||||
return sizeof(jdev->new_id);
|
||||
}
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
|
||||
static inline struct jffs2_node_frag *frag_first(struct rb_root *root)
|
||||
{
|
||||
|
||||
@@ -1,55 +1,40 @@
|
||||
/*
|
||||
* JFFS2 -- Journalling Flash File System, Version 2.
|
||||
*
|
||||
* Copyright (C) 2002-2003 Free Software Foundation, Inc.
|
||||
* Copyright © 2002-2003 Free Software Foundation, Inc.
|
||||
* Copyright © 2013 embedded brains GmbH <rtems@embedded-brains.de>
|
||||
*
|
||||
* Created by David Woodhouse <dwmw2@cambridge.redhat.com>
|
||||
*
|
||||
* Port to the RTEMS by embedded brains GmbH.
|
||||
*
|
||||
* For licensing information, see the file 'LICENCE' in this directory.
|
||||
*
|
||||
* $Id: os-ecos.h,v 1.24 2005/02/09 09:23:55 pavlov Exp $
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __JFFS2_OS_ECOS_H__
|
||||
#define __JFFS2_OS_ECOS_H__
|
||||
#ifndef __JFFS2_OS_RTEMS_H__
|
||||
#define __JFFS2_OS_RTEMS_H__
|
||||
|
||||
#include <pkgconf/fs_jffs2.h>
|
||||
#include <cyg/io/io.h>
|
||||
#include <sys/types.h>
|
||||
#include <asm/atomic.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/compiler.h>
|
||||
|
||||
#include <pkgconf/system.h>
|
||||
#include <pkgconf/hal.h>
|
||||
#include <pkgconf/io_fileio.h>
|
||||
|
||||
#include <cyg/infra/cyg_trac.h> // tracing macros
|
||||
#include <cyg/infra/cyg_ass.h> // assertion macros
|
||||
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <errno.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <cyg/fileio/fileio.h>
|
||||
|
||||
#include <cyg/hal/drv_api.h>
|
||||
#include <cyg/infra/diag.h>
|
||||
|
||||
#include <cyg/io/flash.h>
|
||||
|
||||
#include <linux/types.h>
|
||||
#include <linux/list.h>
|
||||
#include <asm/bug.h>
|
||||
#include <linux/compiler.h>
|
||||
#include <linux/list.h>
|
||||
#include <linux/pagemap.h>
|
||||
#include <linux/stat.h>
|
||||
#include <linux/types.h>
|
||||
#include <dirent.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
|
||||
#define printf diag_printf
|
||||
#include <rtems/jffs2.h>
|
||||
|
||||
#define CONFIG_JFFS2_RTIME
|
||||
|
||||
#define CONFIG_JFFS2_ZLIB
|
||||
|
||||
struct _inode;
|
||||
struct super_block;
|
||||
@@ -59,7 +44,7 @@ struct iovec {
|
||||
ssize_t iov_len;
|
||||
};
|
||||
|
||||
static inline unsigned int full_name_hash(const unsigned char * name, unsigned int len) {
|
||||
static inline unsigned int full_name_hash(const unsigned char * name, size_t len) {
|
||||
|
||||
unsigned hash = 0;
|
||||
while (len--) {
|
||||
@@ -69,17 +54,14 @@ static inline unsigned int full_name_hash(const unsigned char * name, unsigned i
|
||||
return hash;
|
||||
}
|
||||
|
||||
#ifdef CYGOPT_FS_JFFS2_WRITE
|
||||
#define jffs2_is_readonly(c) (0)
|
||||
#else
|
||||
#define jffs2_is_readonly(c) (1)
|
||||
#endif
|
||||
|
||||
/* NAND flash not currently supported on eCos */
|
||||
/* NAND flash not currently supported on RTEMS */
|
||||
#define jffs2_can_mark_obsolete(c) (1)
|
||||
|
||||
#define JFFS2_INODE_INFO(i) (&(i)->jffs2_i)
|
||||
#define OFNI_EDONI_2SFFJ(f) ((struct _inode *) ( ((char *)f) - ((char *)(&((struct _inode *)NULL)->jffs2_i)) ) )
|
||||
|
||||
#define ITIME(sec) (sec)
|
||||
#define I_SEC(tv) (tv)
|
||||
|
||||
#define JFFS2_F_I_SIZE(f) (OFNI_EDONI_2SFFJ(f)->i_size)
|
||||
#define JFFS2_F_I_MODE(f) (OFNI_EDONI_2SFFJ(f)->i_mode)
|
||||
@@ -89,11 +71,7 @@ static inline unsigned int full_name_hash(const unsigned char * name, unsigned i
|
||||
#define JFFS2_F_I_MTIME(f) (OFNI_EDONI_2SFFJ(f)->i_mtime)
|
||||
#define JFFS2_F_I_ATIME(f) (OFNI_EDONI_2SFFJ(f)->i_atime)
|
||||
|
||||
/* FIXME: eCos doesn't hav a concept of device major/minor numbers */
|
||||
#define JFFS2_F_I_RDEV_MIN(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)&0xff)
|
||||
#define JFFS2_F_I_RDEV_MAJ(f) ((OFNI_EDONI_2SFFJ(f)->i_rdev)>>8)
|
||||
|
||||
#define get_seconds cyg_timestamp
|
||||
#define get_seconds() time(NULL)
|
||||
|
||||
struct _inode {
|
||||
cyg_uint32 i_ino;
|
||||
@@ -112,6 +90,7 @@ struct _inode {
|
||||
off_t i_size; // For files only
|
||||
// };
|
||||
struct super_block * i_sb;
|
||||
struct jffs2_full_dirent * i_fd;
|
||||
|
||||
struct jffs2_inode_info jffs2_i;
|
||||
|
||||
@@ -125,39 +104,30 @@ struct _inode {
|
||||
struct super_block {
|
||||
struct jffs2_sb_info jffs2_sb;
|
||||
struct _inode * s_root;
|
||||
unsigned long s_mount_count;
|
||||
cyg_io_handle_t s_dev;
|
||||
|
||||
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
|
||||
cyg_mutex_t s_lock; // Lock the inode cache
|
||||
cyg_flag_t s_gc_thread_flags; // Communication with the gcthread
|
||||
cyg_handle_t s_gc_thread_handle;
|
||||
cyg_thread s_gc_thread;
|
||||
#if (CYGNUM_JFFS2_GC_THREAD_STACK_SIZE >= CYGNUM_HAL_STACK_SIZE_MINIMUM)
|
||||
char s_gc_thread_stack[CYGNUM_JFFS2_GC_THREAD_STACK_SIZE];
|
||||
#else
|
||||
char s_gc_thread_stack[CYGNUM_HAL_STACK_SIZE_MINIMUM];
|
||||
#endif
|
||||
cyg_mtab_entry *mte;
|
||||
#endif
|
||||
rtems_jffs2_flash_control *s_flash_control;
|
||||
rtems_jffs2_compressor_control *s_compressor_control;
|
||||
bool s_is_readonly;
|
||||
unsigned char s_gc_buffer[PAGE_CACHE_SIZE]; // Avoids malloc when user may be under memory pressure
|
||||
rtems_id s_mutex;
|
||||
char s_name_buf[JFFS2_MAX_NAME_LEN];
|
||||
};
|
||||
|
||||
#define sleep_on_spinunlock(wq, sl) spin_unlock(sl)
|
||||
#define EBADFD 32767
|
||||
|
||||
/* background.c */
|
||||
#ifdef CYGOPT_FS_JFFS2_GCTHREAD
|
||||
void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c);
|
||||
void jffs2_start_garbage_collect_thread(struct jffs2_sb_info *c);
|
||||
void jffs2_stop_garbage_collect_thread(struct jffs2_sb_info *c);
|
||||
#else
|
||||
static inline bool jffs2_is_readonly(struct jffs2_sb_info *c)
|
||||
{
|
||||
struct super_block *sb = OFNI_BS_2SFFJ(c);
|
||||
|
||||
return sb->s_is_readonly;
|
||||
}
|
||||
|
||||
static inline void jffs2_garbage_collect_trigger(struct jffs2_sb_info *c)
|
||||
{
|
||||
/* We don't have a GC thread in eCos (yet) */
|
||||
/* We don't have a GC thread in RTEMS (yet) */
|
||||
}
|
||||
#endif
|
||||
|
||||
/* fs-ecos.c */
|
||||
/* fs-rtems.c */
|
||||
struct _inode *jffs2_new_inode (struct _inode *dir_i, int mode, struct jffs2_raw_inode *ri);
|
||||
struct _inode *jffs2_iget(struct super_block *sb, cyg_uint32 ino);
|
||||
void jffs2_iput(struct _inode * i);
|
||||
@@ -167,30 +137,37 @@ unsigned char *jffs2_gc_fetch_page(struct jffs2_sb_info *c, struct jffs2_inode_i
|
||||
unsigned long offset, unsigned long *priv);
|
||||
void jffs2_gc_release_page(struct jffs2_sb_info *c, unsigned char *pg, unsigned long *priv);
|
||||
|
||||
/* Avoid polluting eCos namespace with names not starting in jffs2_ */
|
||||
/* Avoid polluting RTEMS namespace with names not starting in jffs2_ */
|
||||
#define os_to_jffs2_mode(x) jffs2_from_os_mode(x)
|
||||
uint32_t jffs2_from_os_mode(uint32_t osmode);
|
||||
uint32_t jffs2_to_os_mode (uint32_t jmode);
|
||||
static inline uint32_t jffs2_from_os_mode(uint32_t osmode)
|
||||
{
|
||||
return osmode & (S_IFMT | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
|
||||
static inline uint32_t jffs2_to_os_mode (uint32_t jmode)
|
||||
{
|
||||
return jmode & (S_IFMT | S_IRWXU | S_IRWXG | S_IRWXO);
|
||||
}
|
||||
|
||||
|
||||
/* flashio.c */
|
||||
cyg_bool jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset,
|
||||
int jffs2_flash_read(struct jffs2_sb_info *c, cyg_uint32 read_buffer_offset,
|
||||
const size_t size, size_t * return_size, unsigned char * write_buffer);
|
||||
cyg_bool jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset,
|
||||
int jffs2_flash_write(struct jffs2_sb_info *c, cyg_uint32 write_buffer_offset,
|
||||
const size_t size, size_t * return_size, unsigned char * read_buffer);
|
||||
int jffs2_flash_direct_writev(struct jffs2_sb_info *c, const struct iovec *vecs,
|
||||
unsigned long count, loff_t to, size_t *retlen);
|
||||
cyg_bool jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
|
||||
int jffs2_flash_erase(struct jffs2_sb_info *c, struct jffs2_eraseblock *jeb);
|
||||
|
||||
// dir-ecos.c
|
||||
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, int namelen);
|
||||
int jffs2_create(struct _inode *dir_i, const unsigned char *d_name, int mode, struct _inode **new_i);
|
||||
int jffs2_mkdir (struct _inode *dir_i, const unsigned char *d_name, int mode);
|
||||
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name);
|
||||
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
|
||||
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name);
|
||||
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name,
|
||||
struct _inode *new_dir_i, const unsigned char *new_d_name);
|
||||
// dir-rtems.c
|
||||
struct _inode *jffs2_lookup(struct _inode *dir_i, const unsigned char *name, size_t namelen);
|
||||
int jffs2_create(struct _inode *dir_i, const char *d_name, size_t d_namelen, int mode);
|
||||
int jffs2_mknod(struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen, int mode, const unsigned char *data, size_t datalen);
|
||||
int jffs2_link (struct _inode *old_d_inode, struct _inode *dir_i, const unsigned char *d_name, size_t d_namelen);
|
||||
int jffs2_unlink(struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen);
|
||||
int jffs2_rmdir (struct _inode *dir_i, struct _inode *d_inode, const unsigned char *d_name, size_t d_namelen);
|
||||
int jffs2_rename (struct _inode *old_dir_i, struct _inode *d_inode, const unsigned char *old_d_name, size_t old_d_namelen,
|
||||
struct _inode *new_dir_i, const unsigned char *new_d_name, size_t new_d_namelen);
|
||||
|
||||
/* erase.c */
|
||||
static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
|
||||
@@ -199,6 +176,7 @@ static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
|
||||
#ifndef CONFIG_JFFS2_FS_WRITEBUFFER
|
||||
#define SECTOR_ADDR(x) ( ((unsigned long)(x) & ~(c->sector_size-1)) )
|
||||
#define jffs2_can_mark_obsolete(c) (1)
|
||||
#define jffs2_is_writebuffered(c) (0)
|
||||
#define jffs2_cleanmarker_oob(c) (0)
|
||||
#define jffs2_write_nand_cleanmarker(c,jeb) (-EIO)
|
||||
|
||||
@@ -223,4 +201,4 @@ static inline void jffs2_erase_pending_trigger(struct jffs2_sb_info *c)
|
||||
|
||||
#define __init
|
||||
|
||||
#endif /* __JFFS2_OS_ECOS_H__ */
|
||||
#endif /* __JFFS2_OS_RTEMS_H__ */
|
||||
|
||||
@@ -416,7 +416,14 @@ static void eat_last(struct rb_root *root, struct rb_node *node)
|
||||
|
||||
*link = node->rb_left;
|
||||
if (node->rb_left)
|
||||
#ifndef __rtems__
|
||||
node->rb_left->__rb_parent_color = node->__rb_parent_color;
|
||||
#else /* __rtems__ */
|
||||
{
|
||||
node->rb_left->rb_parent = node->rb_parent;
|
||||
node->rb_left->rb_color = node->rb_color;
|
||||
}
|
||||
#endif /* __rtems__ */
|
||||
}
|
||||
|
||||
/* We put the version tree in reverse order, so we can use the same eat_last()
|
||||
|
||||
@@ -95,8 +95,9 @@ int jffs2_scan_medium(struct jffs2_sb_info *c)
|
||||
unsigned char *flashbuf = NULL;
|
||||
uint32_t buf_size = 0;
|
||||
struct jffs2_summary *s = NULL; /* summary info collected by the scan process */
|
||||
size_t try_size;
|
||||
#ifndef __ECOS
|
||||
size_t pointlen, try_size;
|
||||
size_t pointlen;
|
||||
|
||||
ret = mtd_point(c->mtd, 0, c->mtd->size, &pointlen,
|
||||
(void **)&flashbuf, NULL);
|
||||
|
||||
@@ -257,6 +257,10 @@ $(PROJECT_INCLUDE)/rtems/rfs/rtems-rfs-trace.h: libfs/src/rfs/rtems-rfs-trace.h
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/rfs/rtems-rfs-trace.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/rfs/rtems-rfs-trace.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/jffs2.h: libfs/src/jffs2/include/rtems/jffs2.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/jffs2.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/jffs2.h
|
||||
|
||||
$(PROJECT_INCLUDE)/rtems/bdbuf.h: libblock/include/rtems/bdbuf.h $(PROJECT_INCLUDE)/rtems/$(dirstamp)
|
||||
$(INSTALL_DATA) $< $(PROJECT_INCLUDE)/rtems/bdbuf.h
|
||||
PREINSTALL_FILES += $(PROJECT_INCLUDE)/rtems/bdbuf.h
|
||||
|
||||
@@ -237,6 +237,7 @@ const rtems_libio_helper rtems_fs_init_helper =
|
||||
* CONFIGURE_FILESYSTEM_NFS - Network File System, networking enabled
|
||||
* CONFIGURE_FILESYSTEM_DOSFS - DOS File System, uses libblock
|
||||
* CONFIGURE_FILESYSTEM_RFS - RTEMS File System (RFS), uses libblock
|
||||
* CONFIGURE_FILESYSTEM_JFFS2 - Journalling Flash File System, Version 2
|
||||
*
|
||||
* Combinations:
|
||||
*
|
||||
@@ -264,6 +265,7 @@ const rtems_libio_helper rtems_fs_init_helper =
|
||||
#define CONFIGURE_FILESYSTEM_NFS
|
||||
#define CONFIGURE_FILESYSTEM_DOSFS
|
||||
#define CONFIGURE_FILESYSTEM_RFS
|
||||
#define CONFIGURE_FILESYSTEM_JFFS2
|
||||
#endif
|
||||
|
||||
/*
|
||||
@@ -283,7 +285,8 @@ const rtems_libio_helper rtems_fs_init_helper =
|
||||
defined(CONFIGURE_FILESYSTEM_FTPFS) || \
|
||||
defined(CONFIGURE_FILESYSTEM_NFS) || \
|
||||
defined(CONFIGURE_FILESYSTEM_DOSFS) || \
|
||||
defined(CONFIGURE_FILESYSTEM_RFS)
|
||||
defined(CONFIGURE_FILESYSTEM_RFS) || \
|
||||
defined(CONFIGURE_FILESYSTEM_JFFS2)
|
||||
#error "Configured filesystems but root filesystem was not IMFS!"
|
||||
#error "Filesystems could be disabled, DEVFS is root, or"
|
||||
#error " miniIMFS is root!"
|
||||
@@ -440,6 +443,16 @@ const rtems_libio_helper rtems_fs_init_helper =
|
||||
{ RTEMS_FILESYSTEM_TYPE_RFS, rtems_rfs_rtems_initialise }
|
||||
#endif
|
||||
|
||||
/**
|
||||
* JFFS2
|
||||
*/
|
||||
#if !defined(CONFIGURE_FILESYSTEM_ENTRY_JFFS2) && \
|
||||
defined(CONFIGURE_FILESYSTEM_JFFS2)
|
||||
#include <rtems/jffs2.h>
|
||||
#define CONFIGURE_FILESYSTEM_ENTRY_JFFS2 \
|
||||
{ RTEMS_FILESYSTEM_TYPE_JFFS2, rtems_jffs2_initialize }
|
||||
#endif
|
||||
|
||||
#ifdef CONFIGURE_INIT
|
||||
|
||||
/**
|
||||
@@ -513,6 +526,10 @@ const rtems_libio_helper rtems_fs_init_helper =
|
||||
defined(CONFIGURE_FILESYSTEM_ENTRY_RFS)
|
||||
CONFIGURE_FILESYSTEM_ENTRY_RFS,
|
||||
#endif
|
||||
#if defined(CONFIGURE_FILESYSTEM_JFFS2) && \
|
||||
defined(CONFIGURE_FILESYSTEM_ENTRY_JFFS2)
|
||||
CONFIGURE_FILESYSTEM_ENTRY_JFFS2,
|
||||
#endif
|
||||
CONFIGURE_FILESYSTEM_NULL
|
||||
};
|
||||
#endif
|
||||
|
||||
@@ -27,6 +27,7 @@ TMP_LIBS += ../libfs/libdefaultfs.a
|
||||
TMP_LIBS += ../libfs/libdevfs.a
|
||||
TMP_LIBS += ../libfs/libimfs.a
|
||||
TMP_LIBS += ../libfs/librfs.a
|
||||
TMP_LIBS += ../libfs/libjffs2.a
|
||||
|
||||
TMP_LIBS += ../libmisc/libmonitor.a
|
||||
TMP_LIBS += ../libmisc/libuntar.a
|
||||
|
||||
Reference in New Issue
Block a user