X-Git-Url: http://git.rohieb.name/openwrt.git/blobdiff_plain/989c09b9d964fc04e43977f9d35640fa38b7ee54..f5f32330629db59c334e7040dc36c0743b843bdb:/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch?ds=inline diff --git a/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch b/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch index c5265e9b2..afb37a80c 100644 --- a/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch +++ b/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch @@ -1,6 +1,6 @@ --- /dev/null +++ b/crypto/unlzma.c -@@ -0,0 +1,710 @@ +@@ -0,0 +1,748 @@ +/* + * LZMA uncompresion module for pcomp + * Copyright (C) 2009 Felix Fietkau @@ -36,12 +36,12 @@ +#include + +#include ++#include +#include "unlzma.h" + +static int instance = 0; + +struct unlzma_buffer { -+ struct unlzma_buffer *last; + int offset; + int size; + u8 *ptr; @@ -68,7 +68,10 @@ + /* writer state */ + u8 previous_byte; + ssize_t pos; -+ struct unlzma_buffer *head; ++ int buf_full; ++ int n_buffers; ++ int buffers_max; ++ struct unlzma_buffer *buffers; + + /* cstate */ + int state; @@ -87,11 +90,31 @@ +} + +static void ++get_buffer(struct unlzma_ctx *ctx) ++{ ++ struct unlzma_buffer *bh; ++ ++ BUG_ON(ctx->n_buffers >= ctx->buffers_max); ++ bh = &ctx->buffers[ctx->n_buffers++]; ++ bh->ptr = ctx->next_out; ++ bh->offset = ctx->pos; ++ bh->size = ctx->avail_out; ++ ctx->buf_full = 0; ++} ++ ++static void +unlzma_request_buffer(struct unlzma_ctx *ctx, int *avail) +{ -+ mutex_unlock(&ctx->mutex); -+ wait_event(ctx->next_req, unlzma_should_stop(ctx) || (*avail > 0)); -+ mutex_lock(&ctx->mutex); ++ do { ++ mutex_unlock(&ctx->mutex); ++ if (wait_event_interruptible(ctx->next_req, ++ unlzma_should_stop(ctx) || (*avail > 0))) ++ schedule(); ++ mutex_lock(&ctx->mutex); ++ } while (*avail <= 0 && !unlzma_should_stop(ctx)); ++ ++ if (!unlzma_should_stop(ctx) && ctx->buf_full) ++ get_buffer(ctx); +} + +static u8 @@ -186,46 +209,33 @@ +static u8 +peek_old_byte(struct unlzma_ctx *ctx, u32 offs) +{ -+ struct unlzma_buffer *bh = ctx->head; ++ struct unlzma_buffer *bh = &ctx->buffers[ctx->n_buffers - 1]; ++ int i = ctx->n_buffers; + u32 pos; + ++ BUG_ON(!ctx->n_buffers); + pos = ctx->pos - offs; + if (pos >= ctx->dict_size) { + pos = (~pos % ctx->dict_size); + } + + while (bh->offset > pos) { -+ bh = bh->last; -+ if (!bh) -+ return 0; ++ bh--; ++ i--; ++ BUG_ON(!i); + } + + pos -= bh->offset; -+ if (pos > bh->size) -+ return 0; ++ BUG_ON(pos >= bh->size); + + return bh->ptr[pos]; +} + +static void -+get_buffer(struct unlzma_ctx *ctx) -+{ -+ struct unlzma_buffer *bh; -+ -+ bh = kzalloc(sizeof(struct unlzma_buffer), GFP_KERNEL); -+ bh->ptr = ctx->next_out; -+ bh->offset = ctx->pos; -+ bh->last = ctx->head; -+ bh->size = ctx->avail_out; -+ ctx->head = bh; -+} -+ -+static void +write_byte(struct unlzma_ctx *ctx, u8 byte) +{ + if (unlikely(ctx->avail_out <= 0)) { + unlzma_request_buffer(ctx, &ctx->avail_out); -+ get_buffer(ctx); + } + + if (!ctx->avail_out) @@ -234,6 +244,8 @@ + ctx->previous_byte = byte; + *(ctx->next_out++) = byte; + ctx->avail_out--; ++ if (ctx->avail_out == 0) ++ ctx->buf_full = 1; + ctx->pos++; +} + @@ -452,6 +464,7 @@ + hdr_buf[i] = rc_read(ctx); + } + ++ ctx->n_buffers = 0; + ctx->pos = 0; + get_buffer(ctx); + ctx->active = true; @@ -489,7 +502,8 @@ + if (ctx->workspace_size < num_probs * sizeof(*p)) { + if (ctx->workspace) + vfree(ctx->workspace); -+ ctx->workspace = vmalloc(num_probs * sizeof(*p)); ++ ctx->workspace_size = num_probs * sizeof(*p); ++ ctx->workspace = vmalloc(ctx->workspace_size); + } + p = (u16 *) ctx->workspace; + if (!p) @@ -517,6 +531,8 @@ + if (unlzma_should_stop(ctx)) + break; + } ++ if (likely(!unlzma_should_stop(ctx))) ++ rc_normalize(ctx); + + return ctx->pos; +} @@ -543,11 +559,6 @@ + unlzma_reset_buf(ctx); + ctx->cancel = false; + ctx->active = false; -+ while (ctx->head) { -+ struct unlzma_buffer *bh = ctx->head; -+ ctx->head = bh->last; -+ kfree(bh); -+ } + } while (!kthread_should_stop()); + mutex_unlock(&ctx->mutex); + return 0; @@ -587,6 +598,10 @@ + unlzma_cancel(ctx); + kthread_stop(ctx->thread); + ctx->thread = NULL; ++ if (ctx->buffers) ++ kfree(ctx->buffers); ++ ctx->buffers_max = 0; ++ ctx->buffers = NULL; + } +} + @@ -594,10 +609,31 @@ +unlzma_decompress_setup(struct crypto_pcomp *tfm, void *p, unsigned int len) +{ + struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm)); ++ struct nlattr *tb[UNLZMA_DECOMP_MAX + 1]; + int ret = 0; + + if (ctx->thread) -+ return 0; ++ return -EINVAL; ++ ++ if (!p) ++ return -EINVAL; ++ ++ ret = nla_parse(tb, UNLZMA_DECOMP_MAX, p, len, NULL); ++ if (!tb[UNLZMA_DECOMP_OUT_BUFFERS]) ++ return -EINVAL; ++ ++ if (ctx->buffers_max && (ctx->buffers_max < ++ nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]))) { ++ kfree(ctx->buffers); ++ ctx->buffers_max = 0; ++ ctx->buffers = NULL; ++ } ++ if (!ctx->buffers) { ++ ctx->buffers_max = nla_get_u32(tb[UNLZMA_DECOMP_OUT_BUFFERS]); ++ ctx->buffers = kzalloc(sizeof(struct unlzma_buffer) * ctx->buffers_max, GFP_KERNEL); ++ } ++ if (!ctx->buffers) ++ return -ENOMEM; + + mutex_init(&ctx->mutex); + init_waitqueue_head(&ctx->next_req); @@ -652,6 +688,8 @@ + req->avail_in = ctx->avail_in; + req->next_out = ctx->next_out; + req->avail_out = ctx->avail_out; ++ ctx->next_in = 0; ++ ctx->avail_in = 0; + pos = ctx->pos - pos; + +out: @@ -713,7 +751,7 @@ +MODULE_AUTHOR("Felix Fietkau "); --- a/crypto/Kconfig +++ b/crypto/Kconfig -@@ -728,6 +728,12 @@ config CRYPTO_ZLIB +@@ -758,6 +758,12 @@ config CRYPTO_ZLIB help This is the zlib algorithm. @@ -728,7 +766,7 @@ select CRYPTO_ALGAPI --- a/crypto/Makefile +++ b/crypto/Makefile -@@ -73,6 +73,7 @@ obj-$(CONFIG_CRYPTO_SEED) += seed.o +@@ -75,6 +75,7 @@ obj-$(CONFIG_CRYPTO_SEED) += seed.o obj-$(CONFIG_CRYPTO_SALSA20) += salsa20_generic.o obj-$(CONFIG_CRYPTO_DEFLATE) += deflate.o obj-$(CONFIG_CRYPTO_ZLIB) += zlib.o @@ -819,3 +857,18 @@ +#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) + +#endif +--- a/include/crypto/compress.h ++++ b/include/crypto/compress.h +@@ -49,6 +49,12 @@ enum zlib_decomp_params { + + #define ZLIB_DECOMP_MAX (__ZLIB_DECOMP_MAX - 1) + ++enum unlzma_decomp_params { ++ UNLZMA_DECOMP_OUT_BUFFERS = 1, /* naximum number of output buffers */ ++ __UNLZMA_DECOMP_MAX, ++}; ++#define UNLZMA_DECOMP_MAX (__UNLZMA_DECOMP_MAX - 1) ++ + + struct crypto_pcomp { + struct crypto_tfm base;