/* * Copyright (c) 2013, 2016 embedded brains GmbH. All rights reserved. * * embedded brains GmbH * Dornierstr. 4 * 82178 Puchheim * Germany * * * 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 #include #include #include #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 . * * An example mount with a simple memory based flash device simulation follows. * The zlib is used for as the compressor. * * @code * #include * * #include * #include * * #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 */