|  | /* | 
|  | * 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) | 
|  | { | 
|  | 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) | 
|  | { | 
|  | 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(); | 
|  | } |