/*
* Copyright (c) 2013, 2016 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.org/license/LICENSE.
*/
#ifndef RTEMS_JFFS2_H
#define RTEMS_JFFS2_H
#include <rtems/fs.h>
#include <sys/param.h>
#include <sys/ioccom.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,
* .device_identifier = 0xc01dc0fe
* }
* };
*
* 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 Trigger garbage collection operation.
*
* An optional garbage collection thread may perform now a garbage collection
* using the RTEMS_JFFS2_ON_DEMAND_GARBAGE_COLLECTION IO control.
*
* The garbage collection must not run in the executing context.
*
* @param[in] self The flash control.
*/
typedef void (*rtems_jffs2_trigger_garbage_collection)(
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;
/**
* @brief The device identifier of the flash device.
*
* It is used in combination with the inode number to uniquely identify a
* file system node in the system.
*/
dev_t device_identifier;
/**
* @brief Trigger garbage collection operation.
*
* This operation is optional and may be NULL. This operation should wake up
* a garbage collection thread. The garbage collection thread should use the
* RTEMS_JFFS2_ON_DEMAND_GARBAGE_COLLECTION IO control to carry out the work.
*/
rtems_jffs2_trigger_garbage_collection trigger_garbage_collection;
};
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
);
/**
* @brief JFFS2 filesystem instance information.
*
* @see RTEMS_JFFS2_GET_INFO.
*/
typedef struct {
/**
* @brief Flash size in bytes.
*/
uint32_t flash_size;
/**
* @brief Count of flash blocks (erasable units).
*/
uint32_t flash_blocks;
/**
* @brief Size of a flash block in bytes.
*/
uint32_t flash_block_size;
/**
* @brief Used size in bytes.
*
* Used areas contain valid data.
*/
uint32_t used_size;
/**
* @brief Dirty size in bytes.
*
* Used areas contain no longer used data.
*/
uint32_t dirty_size;
/**
* @brief Wasted size in bytes.
*
* Wasted areas are unusable.
*/
uint32_t wasted_size;
/**
* @brief Free size in bytes.
*
* Free areas may be used to store new data.
*/
uint32_t free_size;
/**
* @brief Bad size in bytes.
*
* Bad areas indicate damaged flash blocks.
*/
uint32_t bad_size;
/**
* @brief Count of clean blocks.
*
* Clean blocks contain only used areas.
*/
uint32_t clean_blocks;
/**
* @brief Count of dirty blocks.
*
* Dirty blocks contain dirty and used areas.
*/
uint32_t dirty_blocks;
/**
* @brief Count of erasable blocks.
*
* Erase blocks contain only dirty or wasted areas.
*/
uint32_t erasable_blocks;
/**
* @brief Count of free blocks.
*
* Free blocks contain a free area.
*/
uint32_t free_blocks;
/**
* @brief Count of bad blocks.
*
* Bad blocks are damaged.
*/
uint32_t bad_blocks;
} rtems_jffs2_info;
/**
* @brief IO control to get the JFFS2 filesystem instance information.
*
* @see rtems_jffs2_info.
*/
#define RTEMS_JFFS2_GET_INFO _IOR('F', 1, rtems_jffs2_info)
/**
* @brief IO control to perform an on demand garbage collection in a JFFS2
* filesystem instance.
*
* This operation is intended to be used by an optional garbage collection
* thread. See rtems_jffs2_flash_control::trigger_garbage_collection.
*/
#define RTEMS_JFFS2_ON_DEMAND_GARBAGE_COLLECTION _IO('F', 2)
/**
* @brief IO control to force a garbage collection in a JFFS2 filesystem
* instance.
*
* Use this operation with care since it may wear out your flash.
*/
#define RTEMS_JFFS2_FORCE_GARBAGE_COLLECTION _IO('F', 3)
/** @} */
#ifdef __cplusplus
}
#endif /* __cplusplus */
#endif /* RTEMS_JFFS2_H */