| /* |
| * JFFS2 -- Journalling Flash File System, Version 2. |
| * |
| * For licensing information, see the file 'LICENCE' in this directory. |
| * |
| * JFFS2 wrapper to the LZMA C SDK |
| * |
| */ |
| |
| #include <linux/lzma.h> |
| #include "compr.h" |
| |
| #ifdef __KERNEL__ |
| static DEFINE_MUTEX(deflate_mutex); |
| #endif |
| |
| CLzmaEncHandle *p; |
| Byte propsEncoded[LZMA_PROPS_SIZE]; |
| SizeT propsSize = sizeof(propsEncoded); |
| |
| STATIC void lzma_free_workspace(void) |
| { |
| LzmaEnc_Destroy(p, &lzma_alloc, &lzma_alloc); |
| } |
| |
| STATIC int INIT lzma_alloc_workspace(CLzmaEncProps *props) |
| { |
| if ((p = (CLzmaEncHandle *)LzmaEnc_Create(&lzma_alloc)) == NULL) |
| { |
| PRINT_ERROR("Failed to allocate lzma deflate workspace\n"); |
| return -ENOMEM; |
| } |
| |
| if (LzmaEnc_SetProps(p, props) != SZ_OK) |
| { |
| lzma_free_workspace(); |
| return -1; |
| } |
| |
| if (LzmaEnc_WriteProperties(p, propsEncoded, &propsSize) != SZ_OK) |
| { |
| lzma_free_workspace(); |
| return -1; |
| } |
| |
| return 0; |
| } |
| |
| STATIC int jffs2_lzma_compress(unsigned char *data_in, unsigned char *cpage_out, |
| uint32_t *sourcelen, uint32_t *dstlen, void *model) |
| { |
| SizeT compress_size = (SizeT)(*dstlen); |
| int ret; |
| |
| #ifdef __KERNEL__ |
| mutex_lock(&deflate_mutex); |
| #endif |
| |
| ret = LzmaEnc_MemEncode(p, cpage_out, &compress_size, data_in, *sourcelen, |
| 0, NULL, &lzma_alloc, &lzma_alloc); |
| |
| #ifdef __KERNEL__ |
| mutex_unlock(&deflate_mutex); |
| #endif |
| |
| if (ret != SZ_OK) |
| return -1; |
| |
| *dstlen = (uint32_t)compress_size; |
| |
| return 0; |
| } |
| |
| STATIC int jffs2_lzma_decompress(unsigned char *data_in, unsigned char *cpage_out, |
| uint32_t srclen, uint32_t destlen, void *model) |
| { |
| int ret; |
| SizeT dl = (SizeT)destlen; |
| SizeT sl = (SizeT)srclen; |
| ELzmaStatus status; |
| |
| ret = LzmaDecode(cpage_out, &dl, data_in, &sl, propsEncoded, |
| propsSize, LZMA_FINISH_ANY, &status, &lzma_alloc); |
| |
| if (ret != SZ_OK || status == LZMA_STATUS_NOT_FINISHED || dl != (SizeT)destlen) |
| return -1; |
| |
| return 0; |
| } |
| |
| static struct jffs2_compressor jffs2_lzma_comp = { |
| .priority = JFFS2_LZMA_PRIORITY, |
| .name = "lzma", |
| .compr = JFFS2_COMPR_LZMA, |
| .compress = &jffs2_lzma_compress, |
| .decompress = &jffs2_lzma_decompress, |
| .disabled = 0, |
| }; |
| |
| int INIT jffs2_lzma_init(void) |
| { |
| int ret; |
| CLzmaEncProps props; |
| LzmaEncProps_Init(&props); |
| |
| props.dictSize = LZMA_BEST_DICT(0x2000); |
| props.level = LZMA_BEST_LEVEL; |
| props.lc = LZMA_BEST_LC; |
| props.lp = LZMA_BEST_LP; |
| props.pb = LZMA_BEST_PB; |
| props.fb = LZMA_BEST_FB; |
| |
| ret = lzma_alloc_workspace(&props); |
| if (ret < 0) |
| return ret; |
| |
| ret = jffs2_register_compressor(&jffs2_lzma_comp); |
| if (ret) |
| lzma_free_workspace(); |
| |
| return ret; |
| } |
| |
| void jffs2_lzma_exit(void) |
| { |
| jffs2_unregister_compressor(&jffs2_lzma_comp); |
| lzma_free_workspace(); |
| } |