summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-11-02 09:51:35 +0000
committerkaloz <kaloz@3c298f89-4303-0410-b956-a3cf2f4a3e73>2009-11-02 09:51:35 +0000
commit7e8dd669c9aa3a76c7b9855e824cfb2c9290a9fc (patch)
tree46674e60496abcaeb73c4401a2f25f25a50123e5
parentf7eef9ce534eedd9323aa9ec2af524c9d12aa0a5 (diff)
Switch to the squashfs-lzma code from the squashfs-devel git tree.
git-svn-id: svn://svn.openwrt.org/openwrt/trunk@18267 3c298f89-4303-0410-b956-a3cf2f4a3e73
-rw-r--r--target/linux/generic-2.6/config-2.6.303
-rw-r--r--target/linux/generic-2.6/config-2.6.313
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch113
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch244
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch317
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch426
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch54
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch42
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch216
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch165
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch280
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch234
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch901
-rw-r--r--target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch244
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch244
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch317
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch426
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch54
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch42
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch216
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch165
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch234
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch901
-rw-r--r--target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch244
24 files changed, 3045 insertions, 3040 deletions
diff --git a/target/linux/generic-2.6/config-2.6.30 b/target/linux/generic-2.6/config-2.6.30
index 403cc54d7..8e590b766 100644
--- a/target/linux/generic-2.6/config-2.6.30
+++ b/target/linux/generic-2.6/config-2.6.30
@@ -403,6 +403,7 @@ CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DECNET is not set
+CONFIG_DECOMPRESS_LZMA_NEEDED=y
# CONFIG_DEFAULT_AS is not set
# CONFIG_DEFAULT_BIC is not set
# CONFIG_DEFAULT_CFQ is not set
@@ -2059,7 +2060,7 @@ CONFIG_SND_VERBOSE_PROCFS=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_SQUASHFS_EMBEDDED is not set
CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-CONFIG_SQUASHFS_SUPPORT_LZMA=y
+CONFIG_SQUASHFS_LZMA=y
CONFIG_SQUASHFS_SUPPORT_ZLIB=y
# CONFIG_SQUASHFS_VMALLOC is not set
CONFIG_SQUASHFS=y
diff --git a/target/linux/generic-2.6/config-2.6.31 b/target/linux/generic-2.6/config-2.6.31
index e60f993a1..3b4bed5e4 100644
--- a/target/linux/generic-2.6/config-2.6.31
+++ b/target/linux/generic-2.6/config-2.6.31
@@ -420,6 +420,7 @@ CONFIG_DEBUG_FS=y
# CONFIG_DEBUG_KERNEL is not set
# CONFIG_DEBUG_MEMORY_INIT is not set
# CONFIG_DECNET is not set
+CONFIG_DECOMPRESS_LZMA_NEEDED=y
# CONFIG_DEFAULT_AS is not set
# CONFIG_DEFAULT_BIC is not set
# CONFIG_DEFAULT_CFQ is not set
@@ -2104,7 +2105,7 @@ CONFIG_SND_VERBOSE_PROCFS=y
CONFIG_SPLIT_PTLOCK_CPUS=4
# CONFIG_SQUASHFS_EMBEDDED is not set
CONFIG_SQUASHFS_FRAGMENT_CACHE_SIZE=3
-CONFIG_SQUASHFS_SUPPORT_LZMA=y
+CONFIG_SQUASHFS_LZMA=y
CONFIG_SQUASHFS_SUPPORT_ZLIB=y
# CONFIG_SQUASHFS_VMALLOC is not set
CONFIG_SQUASHFS=y
diff --git a/target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch b/target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch
new file mode 100644
index 000000000..33572b890
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch
@@ -0,0 +1,113 @@
+From b1af4315d823a2b6659c5b14bc17f7bc61878ef4 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Thu, 6 Aug 2009 15:09:31 -0700
+Subject: [PATCH] bzip2/lzma: remove nasty uncompressed size hack in pre-boot environment
+
+decompress_bunzip2 and decompress_unlzma have a nasty hack that subtracts
+4 from the input length if being called in the pre-boot environment.
+
+This is a nasty hack because it relies on the fact that flush = NULL only
+when called from the pre-boot environment (i.e.
+arch/x86/boot/compressed/misc.c). initramfs.c/do_mounts_rd.c pass in a
+flush buffer (flush != NULL).
+
+This hack prevents the decompressors from being used with flush = NULL by
+other callers unless knowledge of the hack is propagated to them.
+
+This patch removes the hack by making decompress (called only from the
+pre-boot environment) a wrapper function that subtracts 4 from the input
+length before calling the decompressor.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+Cc: "H. Peter Anvin" <hpa@zytor.com>
+Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
+Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
+---
+ lib/decompress_bunzip2.c | 22 ++++++++++++++++------
+ lib/decompress_unlzma.c | 21 ++++++++++++++++-----
+ 2 files changed, 32 insertions(+), 11 deletions(-)
+
+--- a/lib/decompress_bunzip2.c
++++ b/lib/decompress_bunzip2.c
+@@ -45,9 +45,11 @@
+ */
+
+
+-#ifndef STATIC
++#ifdef STATIC
++#define PREBOOT
++#else
+ #include <linux/decompress/bunzip2.h>
+-#endif /* !STATIC */
++#endif /* STATIC */
+
+ #include <linux/decompress/mm.h>
+ #include <linux/slab.h>
+@@ -681,9 +683,7 @@ STATIC int INIT bunzip2(unsigned char *b
+ set_error_fn(error_fn);
+ if (flush)
+ outbuf = malloc(BZIP2_IOBUF_SIZE);
+- else
+- len -= 4; /* Uncompressed size hack active in pre-boot
+- environment */
++
+ if (!outbuf) {
+ error("Could not allocate output bufer");
+ return -1;
+@@ -733,4 +733,14 @@ exit_0:
+ return i;
+ }
+
+-#define decompress bunzip2
++#ifdef PREBOOT
++STATIC int INIT decompress(unsigned char *buf, int len,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *outbuf,
++ int *pos,
++ void(*error_fn)(char *x))
++{
++ return bunzip2(buf, len - 4, fill, flush, outbuf, pos, error_fn);
++}
++#endif
+--- a/lib/decompress_unlzma.c
++++ b/lib/decompress_unlzma.c
+@@ -29,7 +29,9 @@
+ *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+-#ifndef STATIC
++#ifdef STATIC
++#define PREBOOT
++#else
+ #include <linux/decompress/unlzma.h>
+ #endif /* STATIC */
+
+@@ -543,9 +545,7 @@ STATIC inline int INIT unlzma(unsigned c
+ int ret = -1;
+
+ set_error_fn(error_fn);
+- if (!flush)
+- in_len -= 4; /* Uncompressed size hack active in pre-boot
+- environment */
++
+ if (buf)
+ inbuf = buf;
+ else
+@@ -645,4 +645,15 @@ exit_0:
+ return ret;
+ }
+
+-#define decompress unlzma
++#ifdef PREBOOT
++STATIC int INIT decompress(unsigned char *buf, int in_len,
++ int(*fill)(void*, unsigned int),
++ int(*flush)(void*, unsigned int),
++ unsigned char *output,
++ int *posp,
++ void(*error_fn)(char *x)
++ )
++{
++ return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn);
++}
++#endif
diff --git a/target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch b/target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch
new file mode 100644
index 000000000..94096791f
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch
@@ -0,0 +1,244 @@
+From 6c4419d997d4431bb62e73475cd6b084e83efbd1 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Tue, 22 Sep 2009 19:25:24 +0100
+Subject: [PATCH] Squashfs: move zlib decompression wrapper code into a separate file
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Makefile | 2 +-
+ fs/squashfs/block.c | 74 ++----------------------------
+ fs/squashfs/squashfs.h | 4 ++
+ fs/squashfs/zlib_wrapper.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 118 insertions(+), 71 deletions(-)
+ create mode 100644 fs/squashfs/zlib_wrapper.c
+
+--- a/fs/squashfs/Makefile
++++ b/fs/squashfs/Makefile
+@@ -4,4 +4,4 @@
+
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
+-squashfs-y += namei.o super.o symlink.o
++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o
+--- a/fs/squashfs/block.c
++++ b/fs/squashfs/block.c
+@@ -29,7 +29,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/mutex.h>
+ #include <linux/string.h>
+ #include <linux/buffer_head.h>
+ #include <linux/zlib.h>
+@@ -153,72 +152,10 @@ int squashfs_read_data(struct super_bloc
+ }
+
+ if (compressed) {
+- int zlib_err = 0, zlib_init = 0;
+-
+- /*
+- * Uncompress block.
+- */
+-
+- mutex_lock(&msblk->read_data_mutex);
+-
+- msblk->stream.avail_out = 0;
+- msblk->stream.avail_in = 0;
+-
+- bytes = length;
+- do {
+- if (msblk->stream.avail_in == 0 && k < b) {
+- avail = min(bytes, msblk->devblksize - offset);
+- bytes -= avail;
+- wait_on_buffer(bh[k]);
+- if (!buffer_uptodate(bh[k]))
+- goto release_mutex;
+-
+- if (avail == 0) {
+- offset = 0;
+- put_bh(bh[k++]);
+- continue;
+- }
+-
+- msblk->stream.next_in = bh[k]->b_data + offset;
+- msblk->stream.avail_in = avail;
+- offset = 0;
+- }
+-
+- if (msblk->stream.avail_out == 0 && page < pages) {
+- msblk->stream.next_out = buffer[page++];
+- msblk->stream.avail_out = PAGE_CACHE_SIZE;
+- }
+-
+- if (!zlib_init) {
+- zlib_err = zlib_inflateInit(&msblk->stream);
+- if (zlib_err != Z_OK) {
+- ERROR("zlib_inflateInit returned"
+- " unexpected result 0x%x,"
+- " srclength %d\n", zlib_err,
+- srclength);
+- goto release_mutex;
+- }
+- zlib_init = 1;
+- }
+-
+- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
+-
+- if (msblk->stream.avail_in == 0 && k < b)
+- put_bh(bh[k++]);
+- } while (zlib_err == Z_OK);
+-
+- if (zlib_err != Z_STREAM_END) {
+- ERROR("zlib_inflate error, data probably corrupt\n");
+- goto release_mutex;
+- }
+-
+- zlib_err = zlib_inflateEnd(&msblk->stream);
+- if (zlib_err != Z_OK) {
+- ERROR("zlib_inflate error, data probably corrupt\n");
+- goto release_mutex;
+- }
+- length = msblk->stream.total_out;
+- mutex_unlock(&msblk->read_data_mutex);
++ length = zlib_uncompress(msblk, buffer, bh, b, offset, length,
++ srclength, pages);
++ if (length < 0)
++ goto read_failure;
+ } else {
+ /*
+ * Block is uncompressed.
+@@ -255,9 +192,6 @@ int squashfs_read_data(struct super_bloc
+ kfree(bh);
+ return length;
+
+-release_mutex:
+- mutex_unlock(&msblk->read_data_mutex);
+-
+ block_release:
+ for (; k < b; k++)
+ put_bh(bh[k]);
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -70,6 +70,10 @@ extern struct inode *squashfs_iget(struc
+ unsigned int);
+ extern int squashfs_read_inode(struct inode *, long long);
+
++/* zlib_wrapper.c */
++extern int zlib_uncompress(struct squashfs_sb_info *, void **,
++ struct buffer_head **, int, int, int, int, int);
++
+ /*
+ * Inodes and files operations
+ */
+--- /dev/null
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -0,0 +1,109 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * zlib_wrapper.c
++ */
++
++
++#include <linux/mutex.h>
++#include <linux/buffer_head.h>
++#include <linux/zlib.h>
++
++#include "squashfs_fs.h"
++#include "squashfs_fs_sb.h"
++#include "squashfs_fs_i.h"
++#include "squashfs.h"
++
++int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
++ struct buffer_head **bh, int b, int offset, int length, int srclength,
++ int pages)
++{
++ int zlib_err = 0, zlib_init = 0;
++ int avail, bytes, k = 0, page = 0;
++
++ mutex_lock(&msblk->read_data_mutex);
++
++ msblk->stream.avail_out = 0;
++ msblk->stream.avail_in = 0;
++
++ bytes = length;
++ do {
++ if (msblk->stream.avail_in == 0 && k < b) {
++ avail = min(bytes, msblk->devblksize - offset);
++ bytes -= avail;
++ wait_on_buffer(bh[k]);
++ if (!buffer_uptodate(bh[k]))
++ goto release_mutex;
++
++ if (avail == 0) {
++ offset = 0;
++ put_bh(bh[k++]);
++ continue;
++ }
++
++ msblk->stream.next_in = bh[k]->b_data + offset;
++ msblk->stream.avail_in = avail;
++ offset = 0;
++ }
++
++ if (msblk->stream.avail_out == 0 && page < pages) {
++ msblk->stream.next_out = buffer[page++];
++ msblk->stream.avail_out = PAGE_CACHE_SIZE;
++ }
++
++ if (!zlib_init) {
++ zlib_err = zlib_inflateInit(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflateInit returned unexpected "
++ "result 0x%x, srclength %d\n",
++ zlib_err, srclength);
++ goto release_mutex;
++ }
++ zlib_init = 1;
++ }
++
++ zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
++
++ if (msblk->stream.avail_in == 0 && k < b)
++ put_bh(bh[k++]);
++ } while (zlib_err == Z_OK);
++
++ if (zlib_err != Z_STREAM_END) {
++ ERROR("zlib_inflate error, data probably corrupt\n");
++ goto release_mutex;
++ }
++
++ zlib_err = zlib_inflateEnd(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflate error, data probably corrupt\n");
++ goto release_mutex;
++ }
++
++ mutex_unlock(&msblk->read_data_mutex);
++ return msblk->stream.total_out;
++
++release_mutex:
++ mutex_unlock(&msblk->read_data_mutex);
++
++ for (; k < b; k++)
++ put_bh(bh[k]);
++
++ return -EIO;
++}
diff --git a/target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch b/target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch
new file mode 100644
index 000000000..857834f21
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch
@@ -0,0 +1,317 @@
+From 37c44e85fd49676ec15ccaeea065662c1fbcda7d Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Wed, 23 Sep 2009 19:04:49 +0100
+Subject: [PATCH] Squashfs: Factor out remaining zlib dependencies into separate wrapper file
+
+Move zlib buffer init/destroy code into separate wrapper file. Also
+make zlib z_stream field a void * removing the need to include zlib.h
+for most files.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/block.c | 1 -
+ fs/squashfs/cache.c | 1 -
+ fs/squashfs/dir.c | 1 -
+ fs/squashfs/export.c | 1 -
+ fs/squashfs/file.c | 1 -
+ fs/squashfs/fragment.c | 1 -
+ fs/squashfs/id.c | 1 -
+ fs/squashfs/inode.c | 1 -
+ fs/squashfs/namei.c | 1 -
+ fs/squashfs/squashfs.h | 2 +
+ fs/squashfs/squashfs_fs_sb.h | 2 +-
+ fs/squashfs/super.c | 14 +++------
+ fs/squashfs/symlink.c | 1 -
+ fs/squashfs/zlib_wrapper.c | 56 ++++++++++++++++++++++++++++++++---------
+ 14 files changed, 51 insertions(+), 33 deletions(-)
+
+--- a/fs/squashfs/block.c
++++ b/fs/squashfs/block.c
+@@ -31,7 +31,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/buffer_head.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/cache.c
++++ b/fs/squashfs/cache.c
+@@ -51,7 +51,6 @@
+ #include <linux/sched.h>
+ #include <linux/spinlock.h>
+ #include <linux/wait.h>
+-#include <linux/zlib.h>
+ #include <linux/pagemap.h>
+
+ #include "squashfs_fs.h"
+--- a/fs/squashfs/dir.c
++++ b/fs/squashfs/dir.c
+@@ -30,7 +30,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/export.c
++++ b/fs/squashfs/export.c
+@@ -39,7 +39,6 @@
+ #include <linux/vfs.h>
+ #include <linux/dcache.h>
+ #include <linux/exportfs.h>
+-#include <linux/zlib.h>
+ #include <linux/slab.h>
+
+ #include "squashfs_fs.h"
+--- a/fs/squashfs/file.c
++++ b/fs/squashfs/file.c
+@@ -47,7 +47,6 @@
+ #include <linux/string.h>
+ #include <linux/pagemap.h>
+ #include <linux/mutex.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/fragment.c
++++ b/fs/squashfs/fragment.c
+@@ -36,7 +36,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/id.c
++++ b/fs/squashfs/id.c
+@@ -34,7 +34,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/inode.c
++++ b/fs/squashfs/inode.c
+@@ -40,7 +40,6 @@
+
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/namei.c
++++ b/fs/squashfs/namei.c
+@@ -57,7 +57,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/dcache.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -71,6 +71,8 @@ extern struct inode *squashfs_iget(struc
+ extern int squashfs_read_inode(struct inode *, long long);
+
+ /* zlib_wrapper.c */
++extern void *zlib_init(void);
++extern void zlib_free(void *);
+ extern int zlib_uncompress(struct squashfs_sb_info *, void **,
+ struct buffer_head **, int, int, int, int, int);
+
+--- a/fs/squashfs/squashfs_fs_sb.h
++++ b/fs/squashfs/squashfs_fs_sb.h
+@@ -64,7 +64,7 @@ struct squashfs_sb_info {
+ struct mutex read_data_mutex;
+ struct mutex meta_index_mutex;
+ struct meta_index *meta_index;
+- z_stream stream;
++ void *stream;
+ __le64 *inode_lookup_table;
+ u64 inode_table;
+ u64 directory_table;
+--- a/fs/squashfs/super.c
++++ b/fs/squashfs/super.c
+@@ -34,7 +34,6 @@
+ #include <linux/pagemap.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/zlib.h>
+ #include <linux/magic.h>
+
+ #include "squashfs_fs.h"
+@@ -86,12 +85,9 @@ static int squashfs_fill_super(struct su
+ }
+ msblk = sb->s_fs_info;
+
+- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
+- GFP_KERNEL);
+- if (msblk->stream.workspace == NULL) {
+- ERROR("Failed to allocate zlib workspace\n");
++ msblk->stream = zlib_init();
++ if (msblk->stream == NULL)
+ goto failure;
+- }
+
+ sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
+ if (sblk == NULL) {
+@@ -291,17 +287,17 @@ failed_mount:
+ squashfs_cache_delete(msblk->block_cache);
+ squashfs_cache_delete(msblk->fragment_cache);
+ squashfs_cache_delete(msblk->read_page);
++ zlib_free(msblk->stream);
+ kfree(msblk->inode_lookup_table);
+ kfree(msblk->fragment_index);
+ kfree(msblk->id_table);
+- kfree(msblk->stream.workspace);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ kfree(sblk);
+ return err;
+
+ failure:
+- kfree(msblk->stream.workspace);
++ zlib_free(msblk->stream);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ return -ENOMEM;
+@@ -343,10 +339,10 @@ static void squashfs_put_super(struct su
+ squashfs_cache_delete(sbi->block_cache);
+ squashfs_cache_delete(sbi->fragment_cache);
+ squashfs_cache_delete(sbi->read_page);
++ zlib_free(sbi->stream);
+ kfree(sbi->id_table);
+ kfree(sbi->fragment_index);
+ kfree(sbi->meta_index);
+- kfree(sbi->stream.workspace);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ }
+--- a/fs/squashfs/symlink.c
++++ b/fs/squashfs/symlink.c
+@@ -36,7 +36,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/pagemap.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/zlib_wrapper.c
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -31,21 +31,51 @@
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
+
++void *zlib_init()
++{
++ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
++ if (stream == NULL)
++ goto failed;
++ stream->workspace = kmalloc(zlib_inflate_workspacesize(),
++ GFP_KERNEL);
++ if (stream->workspace == NULL)
++ goto failed;
++
++ return stream;
++
++failed:
++ ERROR("Failed to allocate zlib workspace\n");
++ kfree(stream);
++ return NULL;
++}
++
++
++void zlib_free(void *strm)
++{
++ z_stream *stream = strm;
++
++ if (stream)
++ kfree(stream->workspace);
++ kfree(stream);
++}
++
++
+ int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
+ struct buffer_head **bh, int b, int offset, int length, int srclength,
+ int pages)
+ {
+ int zlib_err = 0, zlib_init = 0;
+ int avail, bytes, k = 0, page = 0;
++ z_stream *stream = msblk->stream;
+
+ mutex_lock(&msblk->read_data_mutex);
+
+- msblk->stream.avail_out = 0;
+- msblk->stream.avail_in = 0;
++ stream->avail_out = 0;
++ stream->avail_in = 0;
+
+ bytes = length;
+ do {
+- if (msblk->stream.avail_in == 0 && k < b) {
++ if (stream->avail_in == 0 && k < b) {
+ avail = min(bytes, msblk->devblksize - offset);
+ bytes -= avail;
+ wait_on_buffer(bh[k]);
+@@ -58,18 +88,18 @@ int zlib_uncompress(struct squashfs_sb_i
+ continue;
+ }
+
+- msblk->stream.next_in = bh[k]->b_data + offset;
+- msblk->stream.avail_in = avail;
++ stream->next_in = bh[k]->b_data + offset;
++ stream->avail_in = avail;
+ offset = 0;
+ }
+
+- if (msblk->stream.avail_out == 0 && page < pages) {
+- msblk->stream.next_out = buffer[page++];
+- msblk->stream.avail_out = PAGE_CACHE_SIZE;
++ if (stream->avail_out == 0 && page < pages) {
++ stream->next_out = buffer[page++];
++ stream->avail_out = PAGE_CACHE_SIZE;
+ }
+
+ if (!zlib_init) {
+- zlib_err = zlib_inflateInit(&msblk->stream);
++ zlib_err = zlib_inflateInit(stream);
+ if (zlib_err != Z_OK) {
+ ERROR("zlib_inflateInit returned unexpected "
+ "result 0x%x, srclength %d\n",
+@@ -79,9 +109,9 @@ int zlib_uncompress(struct squashfs_sb_i
+ zlib_init = 1;
+ }
+
+- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
++ zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
+
+- if (msblk->stream.avail_in == 0 && k < b)
++ if (stream->avail_in == 0 && k < b)
+ put_bh(bh[k++]);
+ } while (zlib_err == Z_OK);
+
+@@ -90,14 +120,14 @@ int zlib_uncompress(struct squashfs_sb_i
+ goto release_mutex;
+ }
+
+- zlib_err = zlib_inflateEnd(&msblk->stream);
++ zlib_err = zlib_inflateEnd(stream);
+ if (zlib_err != Z_OK) {
+ ERROR("zlib_inflate error, data probably corrupt\n");
+ goto release_mutex;
+ }
+
+ mutex_unlock(&msblk->read_data_mutex);
+- return msblk->stream.total_out;
++ return stream->total_out;
+
+ release_mutex:
+ mutex_unlock(&msblk->read_data_mutex);
diff --git a/target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch b/target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch
new file mode 100644
index 000000000..db2fe538e
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch
@@ -0,0 +1,426 @@
+From 327fbf47a419befc6bff74f3ca42d2b6f0841903 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Tue, 6 Oct 2009 04:04:15 +0100
+Subject: [PATCH] Squashfs: add a decompressor framework
+
+This adds a decompressor framework which allows multiple compression
+algorithms to be cleanly supported.
+
+Also update zlib wrapper and other code to use the new framework.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Makefile | 2 +-
+ fs/squashfs/block.c | 6 ++--
+ fs/squashfs/decompressor.c | 58 ++++++++++++++++++++++++++++++++++++++++++
+ fs/squashfs/decompressor.h | 55 +++++++++++++++++++++++++++++++++++++++
+ fs/squashfs/squashfs.h | 14 +++++-----
+ fs/squashfs/squashfs_fs_sb.h | 41 +++++++++++++++--------------
+ fs/squashfs/super.c | 45 ++++++++++++++++++-------------
+ fs/squashfs/zlib_wrapper.c | 17 ++++++++++--
+ 8 files changed, 185 insertions(+), 53 deletions(-)
+ create mode 100644 fs/squashfs/decompressor.c
+ create mode 100644 fs/squashfs/decompressor.h
+
+--- a/fs/squashfs/Makefile
++++ b/fs/squashfs/Makefile
+@@ -4,4 +4,4 @@
+
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
+-squashfs-y += namei.o super.o symlink.o zlib_wrapper.o
++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
+--- a/fs/squashfs/block.c
++++ b/fs/squashfs/block.c
+@@ -36,7 +36,7 @@
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
+-
++#include "decompressor.h"
+ /*
+ * Read the metadata block length, this is stored in the first two
+ * bytes of the metadata block.
+@@ -151,8 +151,8 @@ int squashfs_read_data(struct super_bloc
+ }
+
+ if (compressed) {
+- length = zlib_uncompress(msblk, buffer, bh, b, offset, length,
+- srclength, pages);
++ length = squashfs_decompress(msblk, buffer, bh, b, offset,
++ length, srclength, pages);
+ if (length < 0)
+ goto read_failure;
+ } else {
+--- /dev/null
++++ b/fs/squashfs/decompressor.c
+@@ -0,0 +1,58 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * decompressor.c
++ */
++
++#include <linux/types.h>
++#include <linux/mutex.h>
++#include <linux/buffer_head.h>
++
++#include "squashfs_fs.h"
++#include "squashfs_fs_sb.h"
++#include "squashfs_fs_i.h"
++#include "decompressor.h"
++#include "squashfs.h"
++
++/*
++ * This file (and decompressor.h) implements a decompressor framework for
++ * Squashfs, allowing multiple decompressors to be easily supported
++ */
++
++static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
++ NULL, NULL, NULL, 0, "unknown", 0
++};
++
++static const struct squashfs_decompressor *decompressor[] = {
++ &squashfs_zlib_comp_ops,
++ &squashfs_unknown_comp_ops
++};
++
++
++const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
++{
++ int i;
++
++ for (i = 0; decompressor[i]->id; i++)
++ if (id == decompressor[i]->id)
++ break;
++
++ return decompressor[i];
++}
+--- /dev/null
++++ b/fs/squashfs/decompressor.h
+@@ -0,0 +1,55 @@
++#ifndef DECOMPRESSOR_H
++#define DECOMPRESSOR_H
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * decompressor.h
++ */
++
++struct squashfs_decompressor {
++ void *(*init)(void);
++ void (*free)(void *);
++ int (*decompress)(struct squashfs_sb_info *, void **,
++ struct buffer_head **, int, int, int, int, int);
++ int id;
++ char *name;
++ int supported;
++};
++
++static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
++{
++ return msblk->decompressor->init();
++}
++
++static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
++ void *s)
++{
++ if (msblk->decompressor)
++ msblk->decompressor->free(s);
++}
++
++static inline int squashfs_decompress(struct squashfs_sb_info *msblk,
++ void **buffer, struct buffer_head **bh, int b, int offset, int length,
++ int srclength, int pages)
++{
++ return msblk->decompressor->decompress(msblk, buffer, bh, b, offset,
++ length, srclength, pages);
++}
++#endif
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squa
+ u64, int);
+ extern int squashfs_read_table(struct super_block *, void *, u64, int);
+
++/* decompressor.c */
++extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
++
+ /* export.c */
+ extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
+ unsigned int);
+@@ -70,14 +73,8 @@ extern struct inode *squashfs_iget(struc
+ unsigned int);
+ extern int squashfs_read_inode(struct inode *, long long);
+
+-/* zlib_wrapper.c */
+-extern void *zlib_init(void);
+-extern void zlib_free(void *);
+-extern int zlib_uncompress(struct squashfs_sb_info *, void **,
+- struct buffer_head **, int, int, int, int, int);
+-
+ /*
+- * Inodes and files operations
++ * Inodes, files and decompressor operations
+ */
+
+ /* dir.c */
+@@ -94,3 +91,6 @@ extern const struct inode_operations squ
+
+ /* symlink.c */
+ extern const struct address_space_operations squashfs_symlink_aops;
++
++/* zlib_wrapper.c */
++extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
+--- a/fs/squashfs/squashfs_fs_sb.h
++++ b/fs/squashfs/squashfs_fs_sb.h
+@@ -52,25 +52,26 @@ struct squashfs_cache_entry {
+ };
+
+ struct squashfs_sb_info {
+- int devblksize;
+- int devblksize_log2;
+- struct squashfs_cache *block_cache;
+- struct squashfs_cache *fragment_cache;
+- struct squashfs_cache *read_page;
+- int next_meta_index;
+- __le64 *id_table;
+- __le64 *fragment_index;
+- unsigned int *fragment_index_2;
+- struct mutex read_data_mutex;
+- struct mutex meta_index_mutex;
+- struct meta_index *meta_index;
+- void *stream;
+- __le64 *inode_lookup_table;
+- u64 inode_table;
+- u64 directory_table;
+- unsigned int block_size;
+- unsigned short block_log;
+- long long bytes_used;
+- unsigned int inodes;
++ const struct squashfs_decompressor *decompressor;
++ int devblksize;
++ int devblksize_log2;
++ struct squashfs_cache *block_cache;
++ struct squashfs_cache *fragment_cache;
++ struct squashfs_cache *read_page;
++ int next_meta_index;
++ __le64 *id_table;
++ __le64 *fragment_index;
++ unsigned int *fragment_index_2;
++ struct mutex read_data_mutex;
++ struct mutex meta_index_mutex;
++ struct meta_index *meta_index;
++ void *stream;
++ __le64 *inode_lookup_table;
++ u64 inode_table;
++ u64 directory_table;
++ unsigned int block_size;
++ unsigned short block_log;
++ long long bytes_used;
++ unsigned int inodes;
+ };
+ #endif
+--- a/fs/squashfs/super.c
++++ b/fs/squashfs/super.c
+@@ -40,27 +40,35 @@
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
++#include "decompressor.h"
+
+ static struct file_system_type squashfs_fs_type;
+ static struct super_operations squashfs_super_ops;
+
+-static int supported_squashfs_filesystem(short major, short minor, short comp)
++static const struct squashfs_decompressor *supported_squashfs_filesystem(short
++ major, short minor, short id)
+ {
++ const struct squashfs_decompressor *decompressor;
++
+ if (major < SQUASHFS_MAJOR) {
+ ERROR("Major/Minor mismatch, older Squashfs %d.%d "
+ "filesystems are unsupported\n", major, minor);
+- return -EINVAL;
++ return NULL;
+ } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
+ ERROR("Major/Minor mismatch, trying to mount newer "
+ "%d.%d filesystem\n", major, minor);
+ ERROR("Please update your kernel\n");
+- return -EINVAL;
++ return NULL;
+ }
+
+- if (comp != ZLIB_COMPRESSION)
+- return -EINVAL;
++ decompressor = squashfs_lookup_decompressor(id);
++ if (!decompressor->supported) {
++ ERROR("Filesystem uses \"%s\" compression. This is not "
++ "supported\n", decompressor->name);
++ return NULL;
++ }
+
+- return 0;
++ return decompressor;
+ }
+
+
+@@ -85,10 +93,6 @@ static int squashfs_fill_super(struct su
+ }
+ msblk = sb->s_fs_info;
+
+- msblk->stream = zlib_init();
+- if (msblk->stream == NULL)
+- goto failure;
+-
+ sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
+ if (sblk == NULL) {
+ ERROR("Failed to allocate squashfs_super_block\n");
+@@ -115,25 +119,25 @@ static int squashfs_fill_super(struct su
+ goto failed_mount;
+ }
+
++ err = -EINVAL;
++
+ /* Check it is a SQUASHFS superblock */
+ sb->s_magic = le32_to_cpu(sblk->s_magic);
+ if (sb->s_magic != SQUASHFS_MAGIC) {
+ if (!silent)
+ ERROR("Can't find a SQUASHFS superblock on %s\n",
+ bdevname(sb->s_bdev, b));
+- err = -EINVAL;
+ goto failed_mount;
+ }
+
+- /* Check the MAJOR & MINOR versions and compression type */
+- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
++ /* Check the MAJOR & MINOR versions and lookup compression type */
++ msblk->decompressor = supported_squashfs_filesystem(
++ le16_to_cpu(sblk->s_major),
+ le16_to_cpu(sblk->s_minor),
+ le16_to_cpu(sblk->compression));
+- if (err < 0)
++ if (msblk->decompressor == NULL)
+ goto failed_mount;
+
+- err = -EINVAL;
+-
+ /*
+ * Check if there's xattrs in the filesystem. These are not
+ * supported in this version, so warn that they will be ignored.
+@@ -200,6 +204,10 @@ static int squashfs_fill_super(struct su
+
+ err = -ENOMEM;
+
++ msblk->stream = squashfs_decompressor_init(msblk);
++ if (msblk->stream == NULL)
++ goto failed_mount;
++
+ msblk->block_cache = squashfs_cache_init("metadata",
+ SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
+ if (msblk->block_cache == NULL)
+@@ -287,7 +295,7 @@ failed_mount:
+ squashfs_cache_delete(msblk->block_cache);
+ squashfs_cache_delete(msblk->fragment_cache);
+ squashfs_cache_delete(msblk->read_page);
+- zlib_free(msblk->stream);
++ squashfs_decompressor_free(msblk, msblk->stream);
+ kfree(msblk->inode_lookup_table);
+ kfree(msblk->fragment_index);
+ kfree(msblk->id_table);
+@@ -297,7 +305,6 @@ failed_mount:
+ return err;
+
+ failure:
+- zlib_free(msblk->stream);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ return -ENOMEM;
+@@ -339,7 +346,7 @@ static void squashfs_put_super(struct su
+ squashfs_cache_delete(sbi->block_cache);
+ squashfs_cache_delete(sbi->fragment_cache);
+ squashfs_cache_delete(sbi->read_page);
+- zlib_free(sbi->stream);
++ squashfs_decompressor_free(sbi, sbi->stream);
+ kfree(sbi->id_table);
+ kfree(sbi->fragment_index);
+ kfree(sbi->meta_index);
+--- a/fs/squashfs/zlib_wrapper.c
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -30,8 +30,9 @@
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
++#include "decompressor.h"
+
+-void *zlib_init()
++static void *zlib_init(void)
+ {
+ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
+ if (stream == NULL)
+@@ -50,7 +51,7 @@ failed:
+ }
+
+
+-void zlib_free(void *strm)
++static void zlib_free(void *strm)
+ {
+ z_stream *stream = strm;
+
+@@ -60,7 +61,7 @@ void zlib_free(void *strm)
+ }
+
+
+-int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
++static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
+ struct buffer_head **bh, int b, int offset, int length, int srclength,
+ int pages)
+ {
+@@ -137,3 +138,13 @@ release_mutex:
+
+ return -EIO;
+ }
++
++const struct squashfs_decompressor squashfs_zlib_comp_ops = {
++ .init = zlib_init,
++ .free = zlib_free,
++ .decompress = zlib_uncompress,
++ .id = ZLIB_COMPRESSION,
++ .name = "zlib",
++ .supported = 1
++};
++
diff --git a/target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch b/target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch
new file mode 100644
index 000000000..a378c0005
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch
@@ -0,0 +1,54 @@
+From 1885ca0a1973944684f252094a703b7c80dfc974 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Wed, 14 Oct 2009 03:58:11 +0100
+Subject: [PATCH] Squashfs: add decompressor entries for lzma and lzo
+
+Add knowledge of lzma/lzo compression formats to the decompressor
+framework. For now these are added as unsupported. Without
+these entries lzma/lzo compressed filesystems will be flagged as
+having unknown compression which is undesirable.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/decompressor.c | 10 ++++++++++
+ fs/squashfs/squashfs_fs.h | 4 +++-
+ 2 files changed, 13 insertions(+), 1 deletions(-)
+
+--- a/fs/squashfs/decompressor.c
++++ b/fs/squashfs/decompressor.c
+@@ -36,12 +36,22 @@
+ * Squashfs, allowing multiple decompressors to be easily supported
+ */
+
++static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
++ NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
++};
++
++static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = {
++ NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
++};
++
+ static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
+ NULL, NULL, NULL, 0, "unknown", 0
+ };
+
+ static const struct squashfs_decompressor *decompressor[] = {
+ &squashfs_zlib_comp_ops,
++ &squashfs_lzma_unsupported_comp_ops,
++ &squashfs_lzo_unsupported_comp_ops,
+ &squashfs_unknown_comp_ops
+ };
+
+--- a/fs/squashfs/squashfs_fs.h
++++ b/fs/squashfs/squashfs_fs.h
+@@ -211,7 +211,9 @@ struct meta_index {
+ /*
+ * definitions for structures on disk
+ */
+-#define ZLIB_COMPRESSION 1
++#define ZLIB_COMPRESSION 1
++#define LZMA_COMPRESSION 2
++#define LZO_COMPRESSION 3
+
+ struct squashfs_super_block {
+ __le32 s_magic;
diff --git a/target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch b/target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch
new file mode 100644
index 000000000..099168134
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch
@@ -0,0 +1,42 @@
+From 5f393ede3ddb5dd4cc2a9f243182fac45f1ce10b Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Wed, 14 Oct 2009 04:07:54 +0100
+Subject: [PATCH] Squashfs: add an extra parameter to the decompressor init function
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/decompressor.h | 4 ++--
+ fs/squashfs/zlib_wrapper.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/squashfs/decompressor.h
++++ b/fs/squashfs/decompressor.h
+@@ -24,7 +24,7 @@
+ */
+
+ struct squashfs_decompressor {
+- void *(*init)(void);
++ void *(*init)(struct squashfs_sb_info *);
+ void (*free)(void *);
+ int (*decompress)(struct squashfs_sb_info *, void **,
+ struct buffer_head **, int, int, int, int, int);
+@@ -35,7 +35,7 @@ struct squashfs_decompressor {
+
+ static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
+ {
+- return msblk->decompressor->init();
++ return msblk->decompressor->init(msblk);
+ }
+
+ static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
+--- a/fs/squashfs/zlib_wrapper.c
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -32,7 +32,7 @@
+ #include "squashfs.h"
+ #include "decompressor.h"
+
+-static void *zlib_init(void)
++static void *zlib_init(struct squashfs_sb_info *dummy)
+ {
+ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
+ if (stream == NULL)
diff --git a/target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch b/target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch
new file mode 100644
index 000000000..9fd57970f
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch
@@ -0,0 +1,216 @@
+From f49e1efdd179d54e814ff2a8e8f469496583062c Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Tue, 20 Oct 2009 10:54:36 +0100
+Subject: [PATCH] Squashfs: add LZMA compression
+
+Add support for LZMA compressed filesystems. This is an initial
+implementation.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Kconfig | 5 ++
+ fs/squashfs/Makefile | 1 +
+ fs/squashfs/decompressor.c | 4 +
+ fs/squashfs/lzma_wrapper.c | 151 ++++++++++++++++++++++++++++++++++++++++++++
+ fs/squashfs/squashfs.h | 3 +
+ 5 files changed, 164 insertions(+), 0 deletions(-)
+ create mode 100644 fs/squashfs/lzma_wrapper.c
+
+--- a/fs/squashfs/Kconfig
++++ b/fs/squashfs/Kconfig
+@@ -26,6 +26,11 @@ config SQUASHFS
+
+ If unsure, say N.
+
++config SQUASHFS_LZMA
++ bool "Include support for LZMA compressed file systems"
++ depends on SQUASHFS
++ select DECOMPRESS_LZMA
++
+ config SQUASHFS_EMBEDDED
+
+ bool "Additional option for memory-constrained systems"
+--- a/fs/squashfs/Makefile
++++ b/fs/squashfs/Makefile
+@@ -5,3 +5,4 @@
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
+ squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
++squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o
+--- a/fs/squashfs/decompressor.c
++++ b/fs/squashfs/decompressor.c
+@@ -50,7 +50,11 @@ static const struct squashfs_decompresso
+
+ static const struct squashfs_decompressor *decompressor[] = {
+ &squashfs_zlib_comp_ops,
++#ifdef CONFIG_SQUASHFS_LZMA
++ &squashfs_lzma_comp_ops,
++#else
+ &squashfs_lzma_unsupported_comp_ops,
++#endif
+ &squashfs_lzo_unsupported_comp_ops,
+ &squashfs_unknown_comp_ops
+ };
+--- /dev/null
++++ b/fs/squashfs/lzma_wrapper.c
+@@ -0,0 +1,151 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * lzma_wrapper.c
++ */
++
++#include <asm/unaligned.h>
++#include <linux/buffer_head.h>
++#include <linux/mutex.h>
++#include <linux/vmalloc.h>
++#include <linux/decompress/unlzma.h>
++
++#include "squashfs_fs.h"
++#include "squashfs_fs_sb.h"
++#include "squashfs_fs_i.h"
++#include "squashfs.h"
++#include "decompressor.h"
++
++struct squashfs_lzma {
++ void *input;
++ void *output;
++};
++
++/* decompress_unlzma.c is currently non re-entrant... */
++DEFINE_MUTEX(lzma_mutex);
++
++/* decompress_unlzma.c doesn't provide any context in its callbacks... */
++static int lzma_error;
++
++static void error(char *m)
++{
++ ERROR("unlzma error: %s\n", m);
++ lzma_error = 1;
++}
++
++
++static void *lzma_init(struct squashfs_sb_info *msblk)
++{
++ struct squashfs_lzma *stream = kzalloc(sizeof(*stream), GFP_KERNEL);
++ if (stream == NULL)
++ goto failed;
++ stream->input = vmalloc(msblk->block_size);
++ if (stream->input == NULL)
++ goto failed;
++ stream->output = vmalloc(msblk->block_size);
++ if (stream->output == NULL)
++ goto failed2;
++
++ return stream;
++
++failed2:
++ vfree(stream->input);
++failed:
++ ERROR("failed to allocate lzma workspace\n");
++ kfree(stream);
++ return NULL;
++}
++
++
++static void lzma_free(void *strm)
++{
++ struct squashfs_lzma *stream = strm;
++
++ if (stream) {
++ vfree(stream->input);
++ vfree(stream->output);
++ }
++ kfree(stream);
++}
++
++
++static int lzma_uncompress(struct squashfs_sb_info *msblk, void **buffer,
++ struct buffer_head **bh, int b, int offset, int length, int srclength,
++ int pages)
++{
++ struct squashfs_lzma *stream = msblk->stream;
++ void *buff = stream->input;
++ int avail, i, bytes = length, res;
++
++ mutex_lock(&lzma_mutex);
++
++ for (i = 0; i < b; i++) {
++ wait_on_buffer(bh[i]);
++ if (!buffer_uptodate(bh[i]))
++ goto block_release;
++
++ avail = min(bytes, msblk->devblksize - offset);
++ memcpy(buff, bh[i]->b_data + offset, avail);
++ buff += avail;
++ bytes -= avail;
++ offset = 0;
++ put_bh(bh[i]);
++ }
++
++ lzma_error = 0;
++ res = unlzma(stream->input, length, NULL, NULL, stream->output, NULL,
++ error);
++ if (res || lzma_error)
++ goto failed;
++
++ /* uncompressed size is stored in the LZMA header (5 byte offset) */
++ res = bytes = get_unaligned_le32(stream->input + 5);
++ for (i = 0, buff = stream->output; bytes && i < pages; i++) {
++ avail = min_t(int, bytes, PAGE_CACHE_SIZE);
++ memcpy(buffer[i], buff, avail);
++ buff += avail;
++ bytes -= avail;
++ }
++ if (bytes)
++ goto failed;
++
++ mutex_unlock(&lzma_mutex);
++ return res;
++
++block_release:
++ for (; i < b; i++)
++ put_bh(bh[i]);
++
++failed:
++ mutex_unlock(&lzma_mutex);
++
++ ERROR("lzma decompression failed, data probably corrupt\n");
++ return -EIO;
++}
++
++const struct squashfs_decompressor squashfs_lzma_comp_ops = {
++ .init = lzma_init,
++ .free = lzma_free,
++ .decompress = lzma_uncompress,
++ .id = LZMA_COMPRESSION,
++ .name = "lzma",
++ .supported = 1
++};
++
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -94,3 +94,6 @@ extern const struct address_space_operat
+
+ /* zlib_wrapper.c */
+ extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
++
++/* lzma wrapper.c */
++extern const struct squashfs_decompressor squashfs_lzma_comp_ops;
diff --git a/target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch b/target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch
new file mode 100644
index 000000000..64705d2a9
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch
@@ -0,0 +1,165 @@
+From fdf23ed283bc6ef5c25076ce2065f892120ff556 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Thu, 22 Oct 2009 04:57:38 +0100
+Subject: [PATCH] Squashfs: Make unlzma available to non initramfs/initrd code
+
+Add a config option DECOMPRESS_LZMA_NEEDED which allows subsystems to
+specify they need the unlzma code. Normally decompress_unlzma.c is
+compiled with __init and unlzma is not exported to modules.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Kconfig | 1 +
+ include/linux/decompress/bunzip2_mm.h | 12 ++++++++++++
+ include/linux/decompress/inflate_mm.h | 12 ++++++++++++
+ include/linux/decompress/mm.h | 3 ---
+ include/linux/decompress/unlzma_mm.h | 20 ++++++++++++++++++++
+ lib/Kconfig | 3 +++
+ lib/decompress_bunzip2.c | 1 +
+ lib/decompress_inflate.c | 1 +
+ lib/decompress_unlzma.c | 5 ++++-
+ 9 files changed, 54 insertions(+), 4 deletions(-)
+ create mode 100644 include/linux/decompress/bunzip2_mm.h
+ create mode 100644 include/linux/decompress/inflate_mm.h
+ create mode 100644 include/linux/decompress/unlzma_mm.h
+
+--- a/fs/squashfs/Kconfig
++++ b/fs/squashfs/Kconfig
+@@ -30,6 +30,7 @@ config SQUASHFS_LZMA
+ bool "Include support for LZMA compressed file systems"
+ depends on SQUASHFS
+ select DECOMPRESS_LZMA
++ select DECOMPRESS_LZMA_NEEDED
+
+ config SQUASHFS_EMBEDDED
+
+--- /dev/null
++++ b/include/linux/decompress/bunzip2_mm.h
+@@ -0,0 +1,12 @@
++#ifndef BUNZIP2_MM_H
++#define BUNZIP2_MM_H
++
++#ifdef STATIC
++/* Code active when included from pre-boot environment: */
++#define INIT
++#else
++/* Compile for initramfs/initrd code only */
++#define INIT __init
++#endif
++
++#endif
+--- /dev/null
++++ b/include/linux/decompress/inflate_mm.h
+@@ -0,0 +1,12 @@
++#ifndef INFLATE_MM_H
++#define INFLATE_MM_H
++
++#ifdef STATIC
++/* Code active when included from pre-boot environment: */
++#define INIT
++#else
++/* Compile for initramfs/initrd code only */
++#define INIT __init
++#endif
++
++#endif
+--- a/include/linux/decompress/mm.h
++++ b/include/linux/decompress/mm.h
+@@ -53,8 +53,6 @@ static void free(void *where)
+
+ #define set_error_fn(x)
+
+-#define INIT
+-
+ #else /* STATIC */
+
+ /* Code active when compiled standalone for use when loading ramdisk: */
+@@ -77,7 +75,6 @@ static void free(void *where)
+ static void(*error)(char *m);
+ #define set_error_fn(x) error = x;
+
+-#define INIT __init
+ #define STATIC
+
+ #include <linux/init.h>
+--- /dev/null
++++ b/include/linux/decompress/unlzma_mm.h
+@@ -0,0 +1,20 @@
++#ifndef UNLZMA_MM_H
++#define UNLZMA_MM_H
++
++#ifdef STATIC
++
++/* Code active when included from pre-boot environment: */
++#define INIT
++
++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
++
++/* Make it available to non initramfs/initrd code */
++#define INIT
++#include <linux/module.h>
++#else
++
++/* Compile for initramfs/initrd code only */
++#define INIT __init
++#endif
++
++#endif
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -114,6 +114,9 @@ config DECOMPRESS_BZIP2
+ config DECOMPRESS_LZMA
+ tristate
+
++config DECOMPRESS_LZMA_NEEDED
++ boolean
++
+ #
+ # Generic allocator support is selected if needed
+ #
+--- a/lib/decompress_bunzip2.c
++++ b/lib/decompress_bunzip2.c
+@@ -51,6 +51,7 @@
+ #include <linux/decompress/bunzip2.h>
+ #endif /* STATIC */
+
++#include <linux/decompress/bunzip2_mm.h>
+ #include <linux/decompress/mm.h>
+ #include <linux/slab.h>
+
+--- a/lib/decompress_inflate.c
++++ b/lib/decompress_inflate.c
+@@ -22,6 +22,7 @@
+
+ #endif /* STATIC */
+
++#include <linux/decompress/inflate_mm.h>
+ #include <linux/decompress/mm.h>
+ #include <linux/slab.h>
+
+--- a/lib/decompress_unlzma.c
++++ b/lib/decompress_unlzma.c
+@@ -35,6 +35,7 @@
+ #include <linux/decompress/unlzma.h>
+ #endif /* STATIC */
+
++#include <linux/decompress/unlzma_mm.h>
+ #include <linux/decompress/mm.h>
+ #include <linux/slab.h>
+
+@@ -523,7 +524,7 @@ static inline void INIT process_bit1(str
+
+
+
+-STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
++STATIC int INIT unlzma(unsigned char *buf, int in_len,
+ int(*fill)(void*, unsigned int),
+ int(*flush)(void*, unsigned int),
+ unsigned char *output,
+@@ -656,4 +657,6 @@ STATIC int INIT decompress(unsigned char
+ {
+ return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn);
+ }
++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
++EXPORT_SYMBOL(unlzma);
+ #endif
diff --git a/target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch b/target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch
deleted file mode 100644
index abad724f5..000000000
--- a/target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch
+++ /dev/null
@@ -1,280 +0,0 @@
---- a/crypto/testmgr.c
-+++ b/crypto/testmgr.c
-@@ -914,24 +914,25 @@ static int test_pcomp(struct crypto_pcom
- const char *algo = crypto_tfm_alg_driver_name(crypto_pcomp_tfm(tfm));
- unsigned int i;
- char result[COMP_BUF_SIZE];
-- int error;
-+ int res;
-
- for (i = 0; i < ctcount; i++) {
- struct comp_request req;
-+ unsigned int produced = 0;
-
-- error = crypto_compress_setup(tfm, ctemplate[i].params,
-- ctemplate[i].paramsize);
-- if (error) {
-+ res = crypto_compress_setup(tfm, ctemplate[i].params,
-+ ctemplate[i].paramsize);
-+ if (res) {
- pr_err("alg: pcomp: compression setup failed on test "
-- "%d for %s: error=%d\n", i + 1, algo, error);
-- return error;
-+ "%d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-
-- error = crypto_compress_init(tfm);
-- if (error) {
-+ res = crypto_compress_init(tfm);
-+ if (res) {
- pr_err("alg: pcomp: compression init failed on test "
-- "%d for %s: error=%d\n", i + 1, algo, error);
-- return error;
-+ "%d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-
- memset(result, 0, sizeof(result));
-@@ -941,32 +942,37 @@ static int test_pcomp(struct crypto_pcom
- req.next_out = result;
- req.avail_out = ctemplate[i].outlen / 2;
-
-- error = crypto_compress_update(tfm, &req);
-- if (error && (error != -EAGAIN || req.avail_in)) {
-+ res = crypto_compress_update(tfm, &req);
-+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
- pr_err("alg: pcomp: compression update failed on test "
-- "%d for %s: error=%d\n", i + 1, algo, error);
-- return error;
-+ "%d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-+ if (res > 0)
-+ produced += res;
-
- /* Add remaining input data */
- req.avail_in += (ctemplate[i].inlen + 1) / 2;
-
-- error = crypto_compress_update(tfm, &req);
-- if (error && (error != -EAGAIN || req.avail_in)) {
-+ res = crypto_compress_update(tfm, &req);
-+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
- pr_err("alg: pcomp: compression update failed on test "
-- "%d for %s: error=%d\n", i + 1, algo, error);
-- return error;
-+ "%d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-+ if (res > 0)
-+ produced += res;
-
- /* Provide remaining output space */
- req.avail_out += COMP_BUF_SIZE - ctemplate[i].outlen / 2;
-
-- error = crypto_compress_final(tfm, &req);
-- if (error) {
-+ res = crypto_compress_final(tfm, &req);
-+ if (res < 0) {
- pr_err("alg: pcomp: compression final failed on test "
-- "%d for %s: error=%d\n", i + 1, algo, error);
-- return error;
-+ "%d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-+ produced += res;
-
- if (COMP_BUF_SIZE - req.avail_out != ctemplate[i].outlen) {
- pr_err("alg: comp: Compression test %d failed for %s: "
-@@ -976,6 +982,13 @@ static int test_pcomp(struct crypto_pcom
- return -EINVAL;
- }
-
-+ if (produced != ctemplate[i].outlen) {
-+ pr_err("alg: comp: Compression test %d failed for %s: "
-+ "returned len = %u (expected %d)\n", i + 1,
-+ algo, produced, ctemplate[i].outlen);
-+ return -EINVAL;
-+ }
-+
- if (memcmp(result, ctemplate[i].output, ctemplate[i].outlen)) {
- pr_err("alg: pcomp: Compression test %d failed for "
- "%s\n", i + 1, algo);
-@@ -986,21 +999,21 @@ static int test_pcomp(struct crypto_pcom
-
- for (i = 0; i < dtcount; i++) {
- struct comp_request req;
-+ unsigned int produced = 0;
-
-- error = crypto_decompress_setup(tfm, dtemplate[i].params,
-- dtemplate[i].paramsize);
-- if (error) {
-+ res = crypto_decompress_setup(tfm, dtemplate[i].params,
-+ dtemplate[i].paramsize);
-+ if (res) {
- pr_err("alg: pcomp: decompression setup failed on "
-- "test %d for %s: error=%d\n", i + 1, algo,
-- error);
-- return error;
-+ "test %d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-
-- error = crypto_decompress_init(tfm);
-- if (error) {
-+ res = crypto_decompress_init(tfm);
-+ if (res) {
- pr_err("alg: pcomp: decompression init failed on test "
-- "%d for %s: error=%d\n", i + 1, algo, error);
-- return error;
-+ "%d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-
- memset(result, 0, sizeof(result));
-@@ -1010,35 +1023,38 @@ static int test_pcomp(struct crypto_pcom
- req.next_out = result;
- req.avail_out = dtemplate[i].outlen / 2;
-
-- error = crypto_decompress_update(tfm, &req);
-- if (error && (error != -EAGAIN || req.avail_in)) {
-+ res = crypto_decompress_update(tfm, &req);
-+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
- pr_err("alg: pcomp: decompression update failed on "
-- "test %d for %s: error=%d\n", i + 1, algo,
-- error);
-- return error;
-+ "test %d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-+ if (res > 0)
-+ produced += res;
-
- /* Add remaining input data */
- req.avail_in += (dtemplate[i].inlen + 1) / 2;
-
-- error = crypto_decompress_update(tfm, &req);
-- if (error && (error != -EAGAIN || req.avail_in)) {
-+ res = crypto_decompress_update(tfm, &req);
-+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
- pr_err("alg: pcomp: decompression update failed on "
-- "test %d for %s: error=%d\n", i + 1, algo,
-- error);
-- return error;
-+ "test %d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-+ if (res > 0)
-+ produced += res;
-
- /* Provide remaining output space */
- req.avail_out += COMP_BUF_SIZE - dtemplate[i].outlen / 2;
-
-- error = crypto_decompress_final(tfm, &req);
-- if (error && (error != -EAGAIN || req.avail_in)) {
-+ res = crypto_decompress_final(tfm, &req);
-+ if (res < 0 && (res != -EAGAIN || req.avail_in)) {
- pr_err("alg: pcomp: decompression final failed on "
-- "test %d for %s: error=%d\n", i + 1, algo,
-- error);
-- return error;
-+ "test %d for %s: error=%d\n", i + 1, algo, res);
-+ return res;
- }
-+ if (res > 0)
-+ produced += res;
-
- if (COMP_BUF_SIZE - req.avail_out != dtemplate[i].outlen) {
- pr_err("alg: comp: Decompression test %d failed for "
-@@ -1048,6 +1064,13 @@ static int test_pcomp(struct crypto_pcom
- return -EINVAL;
- }
-
-+ if (produced != dtemplate[i].outlen) {
-+ pr_err("alg: comp: Decompression test %d failed for "
-+ "%s: returned len = %u (expected %d)\n", i + 1,
-+ algo, produced, dtemplate[i].outlen);
-+ return -EINVAL;
-+ }
-+
- if (memcmp(result, dtemplate[i].output, dtemplate[i].outlen)) {
- pr_err("alg: pcomp: Decompression test %d failed for "
- "%s\n", i + 1, algo);
---- a/crypto/zlib.c
-+++ b/crypto/zlib.c
-@@ -165,15 +165,15 @@ static int zlib_compress_update(struct c
- return -EINVAL;
- }
-
-+ ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
- stream->avail_in, stream->avail_out,
-- req->avail_in - stream->avail_in,
-- req->avail_out - stream->avail_out);
-+ req->avail_in - stream->avail_in, ret);
- req->next_in = stream->next_in;
- req->avail_in = stream->avail_in;
- req->next_out = stream->next_out;
- req->avail_out = stream->avail_out;
-- return 0;
-+ return ret;
- }
-
- static int zlib_compress_final(struct crypto_pcomp *tfm,
-@@ -195,15 +195,15 @@ static int zlib_compress_final(struct cr
- return -EINVAL;
- }
-
-+ ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
- stream->avail_in, stream->avail_out,
-- req->avail_in - stream->avail_in,
-- req->avail_out - stream->avail_out);
-+ req->avail_in - stream->avail_in, ret);
- req->next_in = stream->next_in;
- req->avail_in = stream->avail_in;
- req->next_out = stream->next_out;
- req->avail_out = stream->avail_out;
-- return 0;
-+ return ret;
- }
-
-
-@@ -280,15 +280,15 @@ static int zlib_decompress_update(struct
- return -EINVAL;
- }
-
-+ ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
- stream->avail_in, stream->avail_out,
-- req->avail_in - stream->avail_in,
-- req->avail_out - stream->avail_out);
-+ req->avail_in - stream->avail_in, ret);
- req->next_in = stream->next_in;
- req->avail_in = stream->avail_in;
- req->next_out = stream->next_out;
- req->avail_out = stream->avail_out;
-- return 0;
-+ return ret;
- }
-
- static int zlib_decompress_final(struct crypto_pcomp *tfm,
-@@ -328,15 +328,15 @@ static int zlib_decompress_final(struct
- return -EINVAL;
- }
-
-+ ret = req->avail_out - stream->avail_out;
- pr_debug("avail_in %u, avail_out %u (consumed %u, produced %u)\n",
- stream->avail_in, stream->avail_out,
-- req->avail_in - stream->avail_in,
-- req->avail_out - stream->avail_out);
-+ req->avail_in - stream->avail_in, ret);
- req->next_in = stream->next_in;
- req->avail_in = stream->avail_in;
- req->next_out = stream->next_out;
- req->avail_out = stream->avail_out;
-- return 0;
-+ return ret;
- }
-
-
diff --git a/target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch b/target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch
deleted file mode 100644
index fc2a731dd..000000000
--- a/target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch
+++ /dev/null
@@ -1,234 +0,0 @@
---- a/fs/squashfs/Kconfig
-+++ b/fs/squashfs/Kconfig
-@@ -1,7 +1,8 @@
- config SQUASHFS
- tristate "SquashFS 4.0 - Squashed file system support"
- depends on BLOCK
-- select ZLIB_INFLATE
-+ select CRYPTO
-+ select CRYPTO_ZLIB
- help
- Saying Y here includes support for SquashFS 4.0 (a Compressed
- Read-Only File System). Squashfs is a highly compressed read-only
---- a/fs/squashfs/block.c
-+++ b/fs/squashfs/block.c
-@@ -32,7 +32,8 @@
- #include <linux/mutex.h>
- #include <linux/string.h>
- #include <linux/buffer_head.h>
--#include <linux/zlib.h>
-+
-+#include <crypto/compress.h>
-
- #include "squashfs_fs.h"
- #include "squashfs_fs_sb.h"
-@@ -153,7 +154,8 @@ int squashfs_read_data(struct super_bloc
- }
-
- if (compressed) {
-- int zlib_err = 0, zlib_init = 0;
-+ int res = 0, decomp_init = 0;
-+ struct comp_request req;
-
- /*
- * Uncompress block.
-@@ -161,12 +163,13 @@ int squashfs_read_data(struct super_bloc
-
- mutex_lock(&msblk->read_data_mutex);
-
-- msblk->stream.avail_out = 0;
-- msblk->stream.avail_in = 0;
-+ req.avail_out = 0;
-+ req.avail_in = 0;
-
- bytes = length;
-+ length = 0;
- do {
-- if (msblk->stream.avail_in == 0 && k < b) {
-+ if (req.avail_in == 0 && k < b) {
- avail = min(bytes, msblk->devblksize - offset);
- bytes -= avail;
- wait_on_buffer(bh[k]);
-@@ -179,45 +182,47 @@ int squashfs_read_data(struct super_bloc
- continue;
- }
-
-- msblk->stream.next_in = bh[k]->b_data + offset;
-- msblk->stream.avail_in = avail;
-+ req.next_in = bh[k]->b_data + offset;
-+ req.avail_in = avail;
- offset = 0;
- }
-
-- if (msblk->stream.avail_out == 0 && page < pages) {
-- msblk->stream.next_out = buffer[page++];
-- msblk->stream.avail_out = PAGE_CACHE_SIZE;
-+ if (req.avail_out == 0 && page < pages) {
-+ req.next_out = buffer[page++];
-+ req.avail_out = PAGE_CACHE_SIZE;
- }
-
-- if (!zlib_init) {
-- zlib_err = zlib_inflateInit(&msblk->stream);
-- if (zlib_err != Z_OK) {
-- ERROR("zlib_inflateInit returned"
-- " unexpected result 0x%x,"
-- " srclength %d\n", zlib_err,
-- srclength);
-+ if (!decomp_init) {
-+ res = crypto_decompress_init(msblk->tfm);
-+ if (res) {
-+ ERROR("crypto_decompress_init "
-+ "returned %d, srclength %d\n",
-+ res, srclength);
- goto release_mutex;
- }
-- zlib_init = 1;
-+ decomp_init = 1;
- }
-
-- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
-+ res = crypto_decompress_update(msblk->tfm, &req);
-+ if (res < 0) {
-+ ERROR("crypto_decompress_update returned %d, "
-+ "data probably corrupt\n", res);
-+ goto release_mutex;
-+ }
-+ length += res;
-
-- if (msblk->stream.avail_in == 0 && k < b)
-+ if (req.avail_in == 0 && k < b)
- put_bh(bh[k++]);
-- } while (zlib_err == Z_OK);
-+ } while (bytes || res);
-
-- if (zlib_err != Z_STREAM_END) {
-- ERROR("zlib_inflate error, data probably corrupt\n");
-+ res = crypto_decompress_final(msblk->tfm, &req);
-+ if (res < 0) {
-+ ERROR("crypto_decompress_final returned %d, data "
-+ "probably corrupt\n", res);
- goto release_mutex;
- }
-+ length += res;
-
-- zlib_err = zlib_inflateEnd(&msblk->stream);
-- if (zlib_err != Z_OK) {
-- ERROR("zlib_inflate error, data probably corrupt\n");
-- goto release_mutex;
-- }
-- length = msblk->stream.total_out;
- mutex_unlock(&msblk->read_data_mutex);
- } else {
- /*
---- a/fs/squashfs/squashfs_fs_sb.h
-+++ b/fs/squashfs/squashfs_fs_sb.h
-@@ -64,7 +64,7 @@ struct squashfs_sb_info {
- struct mutex read_data_mutex;
- struct mutex meta_index_mutex;
- struct meta_index *meta_index;
-- z_stream stream;
-+ struct crypto_pcomp *tfm;
- __le64 *inode_lookup_table;
- u64 inode_table;
- u64 directory_table;
---- a/fs/squashfs/super.c
-+++ b/fs/squashfs/super.c
-@@ -37,11 +37,19 @@
- #include <linux/zlib.h>
- #include <linux/magic.h>
-
-+#include <crypto/compress.h>
-+
-+#include <net/netlink.h>
-+
- #include "squashfs_fs.h"
- #include "squashfs_fs_sb.h"
- #include "squashfs_fs_i.h"
- #include "squashfs.h"
-
-+
-+#define SQUASHFS_CRYPTO_ALG "zlib"
-+
-+
- static struct file_system_type squashfs_fs_type;
- static struct super_operations squashfs_super_ops;
-
-@@ -75,6 +83,16 @@ static int squashfs_fill_super(struct su
- unsigned short flags;
- unsigned int fragments;
- u64 lookup_table_start;
-+ struct {
-+ struct nlattr nla;
-+ int val;
-+ } params = {
-+ .nla = {
-+ .nla_len = nla_attr_size(sizeof(int)),
-+ .nla_type = ZLIB_DECOMP_WINDOWBITS,
-+ },
-+ .val = DEF_WBITS,
-+ };
- int err;
-
- TRACE("Entered squashfs_fill_superblock\n");
-@@ -86,16 +104,25 @@ static int squashfs_fill_super(struct su
- }
- msblk = sb->s_fs_info;
-
-- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
-- GFP_KERNEL);
-- if (msblk->stream.workspace == NULL) {
-- ERROR("Failed to allocate zlib workspace\n");
-+ msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0,
-+ CRYPTO_ALG_ASYNC);
-+ if (IS_ERR(msblk->tfm)) {
-+ ERROR("Failed to load %s crypto module\n",
-+ SQUASHFS_CRYPTO_ALG);
-+ err = PTR_ERR(msblk->tfm);
-+ goto failed_pcomp;
-+ }
-+
-+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-+ if (err) {
-+ ERROR("Failed to set up decompression parameters\n");
- goto failure;
- }
-
- sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
- if (sblk == NULL) {
- ERROR("Failed to allocate squashfs_super_block\n");
-+ err = -ENOMEM;
- goto failure;
- }
-
-@@ -294,17 +321,18 @@ failed_mount:
- kfree(msblk->inode_lookup_table);
- kfree(msblk->fragment_index);
- kfree(msblk->id_table);
-- kfree(msblk->stream.workspace);
-+ crypto_free_pcomp(msblk->tfm);
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- kfree(sblk);
- return err;
-
- failure:
-- kfree(msblk->stream.workspace);
-+ crypto_free_pcomp(msblk->tfm);
-+failed_pcomp:
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
-- return -ENOMEM;
-+ return err;
- }
-
-
-@@ -346,7 +374,7 @@ static void squashfs_put_super(struct su
- kfree(sbi->id_table);
- kfree(sbi->fragment_index);
- kfree(sbi->meta_index);
-- kfree(sbi->stream.workspace);
-+ crypto_free_pcomp(sbi->tfm);
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- }
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
deleted file mode 100644
index d20285c5c..000000000
--- a/target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch
+++ /dev/null
@@ -1,901 +0,0 @@
---- /dev/null
-+++ b/crypto/unlzma.c
-@@ -0,0 +1,775 @@
-+/*
-+ * LZMA uncompresion module for pcomp
-+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-+ *
-+ * Based on:
-+ * Initial Linux kernel adaptation
-+ * Copyright (C) 2006 Alain < alain@knaff.lu >
-+ *
-+ * Based on small lzma deflate implementation/Small range coder
-+ * implementation for lzma.
-+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
-+ *
-+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
-+ * Copyright (C) 1999-2005 Igor Pavlov
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ *
-+ * FIXME: the current implementation assumes that the caller will
-+ * not free any output buffers until the whole decompression has been
-+ * completed. This is necessary, because LZMA looks back at old output
-+ * instead of doing a separate dictionary allocation, which saves RAM.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/vmalloc.h>
-+#include <linux/interrupt.h>
-+#include <linux/mm.h>
-+#include <linux/net.h>
-+#include <linux/slab.h>
-+#include <linux/kthread.h>
-+
-+#include <crypto/internal/compress.h>
-+#include <net/netlink.h>
-+#include "unlzma.h"
-+
-+static int instance = 0;
-+
-+struct unlzma_buffer {
-+ int offset;
-+ int size;
-+ u8 *ptr;
-+};
-+
-+struct unlzma_ctx {
-+ struct task_struct *thread;
-+ wait_queue_head_t next_req;
-+ wait_queue_head_t req_done;
-+ struct mutex mutex;
-+ bool waiting;
-+ bool active;
-+ bool cancel;
-+
-+ const u8 *next_in;
-+ int avail_in;
-+
-+ u8 *next_out;
-+ int avail_out;
-+
-+ /* reader state */
-+ u32 code;
-+ u32 range;
-+ u32 bound;
-+
-+ /* writer state */
-+ u8 previous_byte;
-+ ssize_t pos;
-+ int buf_full;
-+ int n_buffers;
-+ int buffers_max;
-+ struct unlzma_buffer *buffers;
-+
-+ /* cstate */
-+ int state;
-+ u32 rep0, rep1, rep2, rep3;
-+
-+ u32 dict_size;
-+
-+ void *workspace;
-+ int workspace_size;
-+};
-+
-+static inline bool
-+unlzma_should_stop(struct unlzma_ctx *ctx)
-+{
-+ return unlikely(kthread_should_stop() || ctx->cancel);
-+}
-+
-+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)
-+{
-+ do {
-+ ctx->waiting = true;
-+ mutex_unlock(&ctx->mutex);
-+ wake_up(&ctx->req_done);
-+ 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
-+rc_read(struct unlzma_ctx *ctx)
-+{
-+ if (unlikely(ctx->avail_in <= 0))
-+ unlzma_request_buffer(ctx, &ctx->avail_in);
-+
-+ if (unlzma_should_stop(ctx))
-+ return 0;
-+
-+ ctx->avail_in--;
-+ return *(ctx->next_in++);
-+}
-+
-+
-+static inline void
-+rc_get_code(struct unlzma_ctx *ctx)
-+{
-+ ctx->code = (ctx->code << 8) | rc_read(ctx);
-+}
-+
-+static void
-+rc_normalize(struct unlzma_ctx *ctx)
-+{
-+ if (ctx->range < (1 << RC_TOP_BITS)) {
-+ ctx->range <<= 8;
-+ rc_get_code(ctx);
-+ }
-+}
-+
-+static int
-+rc_is_bit_0(struct unlzma_ctx *ctx, u16 *p)
-+{
-+ rc_normalize(ctx);
-+ ctx->bound = *p * (ctx->range >> RC_MODEL_TOTAL_BITS);
-+ return ctx->code < ctx->bound;
-+}
-+
-+static void
-+rc_update_bit_0(struct unlzma_ctx *ctx, u16 *p)
-+{
-+ ctx->range = ctx->bound;
-+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
-+}
-+
-+static void
-+rc_update_bit_1(struct unlzma_ctx *ctx, u16 *p)
-+{
-+ ctx->range -= ctx->bound;
-+ ctx->code -= ctx->bound;
-+ *p -= *p >> RC_MOVE_BITS;
-+}
-+
-+static bool
-+rc_get_bit(struct unlzma_ctx *ctx, u16 *p, int *symbol)
-+{
-+ if (rc_is_bit_0(ctx, p)) {
-+ rc_update_bit_0(ctx, p);
-+ *symbol *= 2;
-+ return 0;
-+ } else {
-+ rc_update_bit_1(ctx, p);
-+ *symbol = *symbol * 2 + 1;
-+ return 1;
-+ }
-+}
-+
-+static int
-+rc_direct_bit(struct unlzma_ctx *ctx)
-+{
-+ rc_normalize(ctx);
-+ ctx->range >>= 1;
-+ if (ctx->code >= ctx->range) {
-+ ctx->code -= ctx->range;
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static void
-+rc_bit_tree_decode(struct unlzma_ctx *ctx, u16 *p, int num_levels, int *symbol)
-+{
-+ int i = num_levels;
-+
-+ *symbol = 1;
-+ while (i--)
-+ rc_get_bit(ctx, p + *symbol, symbol);
-+ *symbol -= 1 << num_levels;
-+}
-+
-+static u8
-+peek_old_byte(struct unlzma_ctx *ctx, u32 offs)
-+{
-+ struct unlzma_buffer *bh = &ctx->buffers[ctx->n_buffers - 1];
-+ int i = ctx->n_buffers;
-+ u32 pos;
-+
-+ if (!ctx->n_buffers) {
-+ printk(KERN_ERR "unlzma/%s: no buffer\n", __func__);
-+ goto error;
-+ }
-+
-+ pos = ctx->pos - offs;
-+ if (unlikely(pos >= ctx->dict_size))
-+ pos = ~pos & (ctx->dict_size - 1);
-+
-+ while (bh->offset > pos) {
-+ bh--;
-+ i--;
-+ if (!i) {
-+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos);
-+ goto error;
-+ }
-+ }
-+
-+ pos -= bh->offset;
-+ if (pos >= bh->size) {
-+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos);
-+ goto error;
-+ }
-+
-+ return bh->ptr[pos];
-+
-+error:
-+ ctx->cancel = true;
-+ return 0;
-+}
-+
-+static void
-+write_byte(struct unlzma_ctx *ctx, u8 byte)
-+{
-+ if (unlikely(ctx->avail_out <= 0)) {
-+ unlzma_request_buffer(ctx, &ctx->avail_out);
-+ }
-+
-+ if (!ctx->avail_out)
-+ return;
-+
-+ ctx->previous_byte = byte;
-+ *(ctx->next_out++) = byte;
-+ ctx->avail_out--;
-+ if (ctx->avail_out == 0)
-+ ctx->buf_full = 1;
-+ ctx->pos++;
-+}
-+
-+
-+static inline void
-+copy_byte(struct unlzma_ctx *ctx, u32 offs)
-+{
-+ write_byte(ctx, peek_old_byte(ctx, offs));
-+}
-+
-+static void
-+copy_bytes(struct unlzma_ctx *ctx, u32 rep0, int len)
-+{
-+ do {
-+ copy_byte(ctx, rep0);
-+ len--;
-+ if (unlzma_should_stop(ctx))
-+ break;
-+ } while (len != 0);
-+}
-+
-+static void
-+process_bit0(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob,
-+ int lc, u32 literal_pos_mask)
-+{
-+ int mi = 1;
-+ rc_update_bit_0(ctx, prob);
-+ prob = (p + LZMA_LITERAL +
-+ (LZMA_LIT_SIZE
-+ * (((ctx->pos & literal_pos_mask) << lc)
-+ + (ctx->previous_byte >> (8 - lc))))
-+ );
-+
-+ if (ctx->state >= LZMA_NUM_LIT_STATES) {
-+ int match_byte = peek_old_byte(ctx, ctx->rep0);
-+ do {
-+ u16 bit;
-+ u16 *prob_lit;
-+
-+ match_byte <<= 1;
-+ bit = match_byte & 0x100;
-+ prob_lit = prob + 0x100 + bit + mi;
-+ if (rc_get_bit(ctx, prob_lit, &mi) != !!bit)
-+ break;
-+ } while (mi < 0x100);
-+ }
-+ while (mi < 0x100) {
-+ u16 *prob_lit = prob + mi;
-+ rc_get_bit(ctx, prob_lit, &mi);
-+ }
-+ write_byte(ctx, mi);
-+ if (ctx->state < 4)
-+ ctx->state = 0;
-+ else if (ctx->state < 10)
-+ ctx->state -= 3;
-+ else
-+ ctx->state -= 6;
-+}
-+
-+static void
-+process_bit1(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob)
-+{
-+ int offset;
-+ u16 *prob_len;
-+ int num_bits;
-+ int len;
-+
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ ctx->rep3 = ctx->rep2;
-+ ctx->rep2 = ctx->rep1;
-+ ctx->rep1 = ctx->rep0;
-+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 0 : 3;
-+ prob = p + LZMA_LEN_CODER;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP_G0 + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ prob = (p + LZMA_IS_REP_0_LONG
-+ + (ctx->state <<
-+ LZMA_NUM_POS_BITS_MAX) +
-+ pos_state);
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+
-+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ?
-+ 9 : 11;
-+ copy_byte(ctx, ctx->rep0);
-+ return;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ }
-+ } else {
-+ u32 distance;
-+
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP_G1 + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ distance = ctx->rep1;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP_G2 + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ distance = ctx->rep2;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ distance = ctx->rep3;
-+ ctx->rep3 = ctx->rep2;
-+ }
-+ ctx->rep2 = ctx->rep1;
-+ }
-+ ctx->rep1 = ctx->rep0;
-+ ctx->rep0 = distance;
-+ }
-+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 8 : 11;
-+ prob = p + LZMA_REP_LEN_CODER;
-+ }
-+
-+ prob_len = prob + LZMA_LEN_CHOICE;
-+ if (rc_is_bit_0(ctx, prob_len)) {
-+ rc_update_bit_0(ctx, prob_len);
-+ prob_len = (prob + LZMA_LEN_LOW
-+ + (pos_state <<
-+ LZMA_LEN_NUM_LOW_BITS));
-+ offset = 0;
-+ num_bits = LZMA_LEN_NUM_LOW_BITS;
-+ } else {
-+ rc_update_bit_1(ctx, prob_len);
-+ prob_len = prob + LZMA_LEN_CHOICE_2;
-+ if (rc_is_bit_0(ctx, prob_len)) {
-+ rc_update_bit_0(ctx, prob_len);
-+ prob_len = (prob + LZMA_LEN_MID
-+ + (pos_state <<
-+ LZMA_LEN_NUM_MID_BITS));
-+ offset = 1 << LZMA_LEN_NUM_LOW_BITS;
-+ num_bits = LZMA_LEN_NUM_MID_BITS;
-+ } else {
-+ rc_update_bit_1(ctx, prob_len);
-+ prob_len = prob + LZMA_LEN_HIGH;
-+ offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
-+ + (1 << LZMA_LEN_NUM_MID_BITS));
-+ num_bits = LZMA_LEN_NUM_HIGH_BITS;
-+ }
-+ }
-+
-+ rc_bit_tree_decode(ctx, prob_len, num_bits, &len);
-+ len += offset;
-+
-+ if (ctx->state < 4) {
-+ int pos_slot;
-+
-+ ctx->state += LZMA_NUM_LIT_STATES;
-+ prob =
-+ p + LZMA_POS_SLOT +
-+ ((len <
-+ LZMA_NUM_LEN_TO_POS_STATES ? len :
-+ LZMA_NUM_LEN_TO_POS_STATES - 1)
-+ << LZMA_NUM_POS_SLOT_BITS);
-+ rc_bit_tree_decode(ctx, prob,
-+ LZMA_NUM_POS_SLOT_BITS,
-+ &pos_slot);
-+ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
-+ int i, mi;
-+ num_bits = (pos_slot >> 1) - 1;
-+ ctx->rep0 = 2 | (pos_slot & 1);
-+ if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
-+ ctx->rep0 <<= num_bits;
-+ prob = p + LZMA_SPEC_POS +
-+ ctx->rep0 - pos_slot - 1;
-+ } else {
-+ num_bits -= LZMA_NUM_ALIGN_BITS;
-+ while (num_bits--)
-+ ctx->rep0 = (ctx->rep0 << 1) |
-+ rc_direct_bit(ctx);
-+ prob = p + LZMA_ALIGN;
-+ ctx->rep0 <<= LZMA_NUM_ALIGN_BITS;
-+ num_bits = LZMA_NUM_ALIGN_BITS;
-+ }
-+ i = 1;
-+ mi = 1;
-+ while (num_bits--) {
-+ if (rc_get_bit(ctx, prob + mi, &mi))
-+ ctx->rep0 |= i;
-+ i <<= 1;
-+ }
-+ } else
-+ ctx->rep0 = pos_slot;
-+ if (++(ctx->rep0) == 0)
-+ return;
-+ }
-+
-+ len += LZMA_MATCH_MIN_LEN;
-+
-+ copy_bytes(ctx, ctx->rep0, len);
-+}
-+
-+
-+static int
-+do_unlzma(struct unlzma_ctx *ctx)
-+{
-+ u8 hdr_buf[sizeof(struct lzma_header)];
-+ struct lzma_header *header = (struct lzma_header *)hdr_buf;
-+ u32 pos_state_mask;
-+ u32 literal_pos_mask;
-+ int lc, pb, lp;
-+ int num_probs;
-+ int i, mi;
-+ u16 *p;
-+
-+ for (i = 0; i < sizeof(struct lzma_header); i++) {
-+ hdr_buf[i] = rc_read(ctx);
-+ }
-+
-+ ctx->n_buffers = 0;
-+ ctx->pos = 0;
-+ get_buffer(ctx);
-+ ctx->active = true;
-+ ctx->state = 0;
-+ ctx->rep0 = ctx->rep1 = ctx->rep2 = ctx->rep3 = 1;
-+
-+ ctx->previous_byte = 0;
-+ ctx->code = 0;
-+ ctx->range = 0xFFFFFFFF;
-+
-+ ctx->dict_size = le32_to_cpu(header->dict_size);
-+
-+ if (header->pos >= (9 * 5 * 5))
-+ return -1;
-+
-+ mi = 0;
-+ lc = header->pos;
-+ while (lc >= 9) {
-+ mi++;
-+ lc -= 9;
-+ }
-+ pb = 0;
-+ lp = mi;
-+ while (lp >= 5) {
-+ pb++;
-+ lp -= 5;
-+ }
-+ pos_state_mask = (1 << pb) - 1;
-+ literal_pos_mask = (1 << lp) - 1;
-+
-+ if (ctx->dict_size == 0)
-+ ctx->dict_size = 1;
-+
-+ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
-+ if (ctx->workspace_size < num_probs * sizeof(*p)) {
-+ if (ctx->workspace)
-+ vfree(ctx->workspace);
-+ ctx->workspace_size = num_probs * sizeof(*p);
-+ ctx->workspace = vmalloc(ctx->workspace_size);
-+ }
-+ p = (u16 *) ctx->workspace;
-+ if (!p)
-+ return -1;
-+
-+ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp));
-+ for (i = 0; i < num_probs; i++)
-+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
-+
-+ for (i = 0; i < 5; i++)
-+ rc_get_code(ctx);
-+
-+ while (1) {
-+ int pos_state = ctx->pos & pos_state_mask;
-+ u16 *prob = p + LZMA_IS_MATCH +
-+ (ctx->state << LZMA_NUM_POS_BITS_MAX) + pos_state;
-+ if (rc_is_bit_0(ctx, prob))
-+ process_bit0(ctx, p, pos_state, prob,
-+ lc, literal_pos_mask);
-+ else {
-+ process_bit1(ctx, p, pos_state, prob);
-+ if (ctx->rep0 == 0)
-+ break;
-+ }
-+ if (unlzma_should_stop(ctx))
-+ break;
-+ }
-+ if (likely(!unlzma_should_stop(ctx)))
-+ rc_normalize(ctx);
-+
-+ return ctx->pos;
-+}
-+
-+
-+static void
-+unlzma_reset_buf(struct unlzma_ctx *ctx)
-+{
-+ ctx->avail_in = 0;
-+ ctx->next_in = NULL;
-+ ctx->avail_out = 0;
-+ ctx->next_out = NULL;
-+}
-+
-+static int
-+unlzma_thread(void *data)
-+{
-+ struct unlzma_ctx *ctx = data;
-+
-+ mutex_lock(&ctx->mutex);
-+ do {
-+ if (do_unlzma(ctx) < 0)
-+ ctx->pos = 0;
-+ unlzma_reset_buf(ctx);
-+ ctx->cancel = false;
-+ ctx->active = false;
-+ } while (!kthread_should_stop());
-+ mutex_unlock(&ctx->mutex);
-+ return 0;
-+}
-+
-+
-+static int
-+unlzma_init(struct crypto_tfm *tfm)
-+{
-+ return 0;
-+}
-+
-+static void
-+unlzma_cancel(struct unlzma_ctx *ctx)
-+{
-+ unlzma_reset_buf(ctx);
-+
-+ if (!ctx->active)
-+ return;
-+
-+ ctx->cancel = true;
-+ do {
-+ mutex_unlock(&ctx->mutex);
-+ wake_up(&ctx->next_req);
-+ schedule();
-+ mutex_lock(&ctx->mutex);
-+ } while (ctx->cancel);
-+}
-+
-+
-+static void
-+unlzma_exit(struct crypto_tfm *tfm)
-+{
-+ struct unlzma_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+ if (ctx->thread) {
-+ unlzma_cancel(ctx);
-+ kthread_stop(ctx->thread);
-+ ctx->thread = NULL;
-+ if (ctx->buffers)
-+ kfree(ctx->buffers);
-+ ctx->buffers_max = 0;
-+ ctx->buffers = NULL;
-+ }
-+}
-+
-+static int
-+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 -EINVAL;
-+
-+ if (!p)
-+ return -EINVAL;
-+
-+ ret = nla_parse(tb, UNLZMA_DECOMP_MAX, p, len, NULL);
-+ if (ret)
-+ return ret;
-+
-+ 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;
-+
-+ ctx->waiting = false;
-+ mutex_init(&ctx->mutex);
-+ init_waitqueue_head(&ctx->next_req);
-+ init_waitqueue_head(&ctx->req_done);
-+ ctx->thread = kthread_run(unlzma_thread, ctx, "unlzma/%d", instance++);
-+ if (IS_ERR(ctx->thread)) {
-+ ret = PTR_ERR(ctx->thread);
-+ ctx->thread = NULL;
-+ }
-+
-+ return ret;
-+}
-+
-+static int
-+unlzma_decompress_init(struct crypto_pcomp *tfm)
-+{
-+ return 0;
-+}
-+
-+static void
-+unlzma_wait_complete(struct unlzma_ctx *ctx, bool finish)
-+{
-+ DEFINE_WAIT(__wait);
-+
-+ do {
-+ wake_up(&ctx->next_req);
-+ prepare_to_wait(&ctx->req_done, &__wait, TASK_INTERRUPTIBLE);
-+ mutex_unlock(&ctx->mutex);
-+ schedule();
-+ mutex_lock(&ctx->mutex);
-+ } while (!ctx->waiting && ctx->active);
-+ finish_wait(&ctx->req_done, &__wait);
-+}
-+
-+static int
-+unlzma_decompress_update(struct crypto_pcomp *tfm, struct comp_request *req)
-+{
-+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
-+ size_t pos = 0;
-+
-+ mutex_lock(&ctx->mutex);
-+ if (!ctx->active && !req->avail_in)
-+ goto out;
-+
-+ pos = ctx->pos;
-+ ctx->waiting = false;
-+ ctx->next_in = req->next_in;
-+ ctx->avail_in = req->avail_in;
-+ ctx->next_out = req->next_out;
-+ ctx->avail_out = req->avail_out;
-+
-+ unlzma_wait_complete(ctx, false);
-+
-+ req->next_in = ctx->next_in;
-+ 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:
-+ mutex_unlock(&ctx->mutex);
-+ if (ctx->cancel)
-+ return -EINVAL;
-+
-+ return pos;
-+}
-+
-+static int
-+unlzma_decompress_final(struct crypto_pcomp *tfm, struct comp_request *req)
-+{
-+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
-+ int ret = 0;
-+
-+ /* cancel pending operation */
-+ mutex_lock(&ctx->mutex);
-+ if (ctx->active) {
-+ // ret = -EINVAL;
-+ unlzma_cancel(ctx);
-+ }
-+ ctx->pos = 0;
-+ mutex_unlock(&ctx->mutex);
-+ return ret;
-+}
-+
-+
-+static struct pcomp_alg unlzma_alg = {
-+ .decompress_setup = unlzma_decompress_setup,
-+ .decompress_init = unlzma_decompress_init,
-+ .decompress_update = unlzma_decompress_update,
-+ .decompress_final = unlzma_decompress_final,
-+
-+ .base = {
-+ .cra_name = "lzma",
-+ .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS,
-+ .cra_ctxsize = sizeof(struct unlzma_ctx),
-+ .cra_module = THIS_MODULE,
-+ .cra_init = unlzma_init,
-+ .cra_exit = unlzma_exit,
-+ }
-+};
-+
-+static int __init
-+unlzma_mod_init(void)
-+{
-+ return crypto_register_pcomp(&unlzma_alg);
-+}
-+
-+static void __exit
-+unlzma_mod_exit(void)
-+{
-+ crypto_unregister_pcomp(&unlzma_alg);
-+}
-+
-+module_init(unlzma_mod_init);
-+module_exit(unlzma_mod_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("LZMA Decompression Algorithm");
-+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
---- a/crypto/Kconfig
-+++ b/crypto/Kconfig
-@@ -758,6 +758,12 @@ config CRYPTO_ZLIB
- help
- This is the zlib algorithm.
-
-+config CRYPTO_UNLZMA
-+ tristate "LZMA decompression"
-+ select CRYPTO_PCOMP
-+ help
-+ This is the lzma decompression module.
-+
- config CRYPTO_LZO
- tristate "LZO compression algorithm"
- select CRYPTO_ALGAPI
---- a/crypto/Makefile
-+++ b/crypto/Makefile
-@@ -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
-+obj-$(CONFIG_CRYPTO_UNLZMA) += unlzma.o
- obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
- obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
- obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
---- /dev/null
-+++ b/crypto/unlzma.h
-@@ -0,0 +1,80 @@
-+/* LZMA uncompresion module for pcomp
-+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-+ *
-+ * Based on:
-+ * Initial Linux kernel adaptation
-+ * Copyright (C) 2006 Alain < alain@knaff.lu >
-+ *
-+ * Based on small lzma deflate implementation/Small range coder
-+ * implementation for lzma.
-+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
-+ *
-+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
-+ * Copyright (C) 1999-2005 Igor Pavlov
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+#ifndef __UNLZMA_H
-+#define __UNLZMA_H
-+
-+struct lzma_header {
-+ __u8 pos;
-+ __le32 dict_size;
-+} __attribute__ ((packed)) ;
-+
-+
-+#define RC_TOP_BITS 24
-+#define RC_MOVE_BITS 5
-+#define RC_MODEL_TOTAL_BITS 11
-+
-+#define LZMA_BASE_SIZE 1846
-+#define LZMA_LIT_SIZE 768
-+
-+#define LZMA_NUM_POS_BITS_MAX 4
-+
-+#define LZMA_LEN_NUM_LOW_BITS 3
-+#define LZMA_LEN_NUM_MID_BITS 3
-+#define LZMA_LEN_NUM_HIGH_BITS 8
-+
-+#define LZMA_LEN_CHOICE 0
-+#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1)
-+#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1)
-+#define LZMA_LEN_MID (LZMA_LEN_LOW \
-+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS)))
-+#define LZMA_LEN_HIGH (LZMA_LEN_MID \
-+ +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS)))
-+#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS))
-+
-+#define LZMA_NUM_STATES 12
-+#define LZMA_NUM_LIT_STATES 7
-+
-+#define LZMA_START_POS_MODEL_INDEX 4
-+#define LZMA_END_POS_MODEL_INDEX 14
-+#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1))
-+
-+#define LZMA_NUM_POS_SLOT_BITS 6
-+#define LZMA_NUM_LEN_TO_POS_STATES 4
-+
-+#define LZMA_NUM_ALIGN_BITS 4
-+
-+#define LZMA_MATCH_MIN_LEN 2
-+
-+#define LZMA_IS_MATCH 0
-+#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
-+#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES)
-+#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES)
-+#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES)
-+#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES)
-+#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \
-+ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
-+#define LZMA_SPEC_POS (LZMA_POS_SLOT \
-+ +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS))
-+#define LZMA_ALIGN (LZMA_SPEC_POS \
-+ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX)
-+#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS))
-+#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS)
-+#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;
diff --git a/target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch b/target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch
deleted file mode 100644
index 19deb7335..000000000
--- a/target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch
+++ /dev/null
@@ -1,244 +0,0 @@
---- a/fs/squashfs/Kconfig
-+++ b/fs/squashfs/Kconfig
-@@ -2,7 +2,6 @@ config SQUASHFS
- tristate "SquashFS 4.0 - Squashed file system support"
- depends on BLOCK
- select CRYPTO
-- select CRYPTO_ZLIB
- help
- Saying Y here includes support for SquashFS 4.0 (a Compressed
- Read-Only File System). Squashfs is a highly compressed read-only
-@@ -37,6 +36,26 @@ config SQUASHFS_EMBEDDED
-
- If unsure, say N.
-
-+config SQUASHFS_SUPPORT_ZLIB
-+ bool
-+ prompt "Support ZLIB compression" if SQUASHFS_SUPPORT_LZMA
-+ depends on SQUASHFS
-+ select CRYPTO_ZLIB
-+ default y
-+ help
-+ ZLIB is the default compression used in squashfs. If you are
-+ using LZMA compression instead, you can remove support for ZLIB
-+ entirely.
-+
-+config SQUASHFS_SUPPORT_LZMA
-+ bool "Support LZMA compression"
-+ depends on SQUASHFS
-+ select CRYPTO_UNLZMA
-+ help
-+ By default SquashFS uses ZLIB compression, however (if your tools
-+ support it, you can use LZMA instead, which saves space.
-+
-+
- config SQUASHFS_FRAGMENT_CACHE_SIZE
- int "Number of fragments cached" if SQUASHFS_EMBEDDED
- depends on SQUASHFS
---- a/fs/squashfs/squashfs_fs.h
-+++ b/fs/squashfs/squashfs_fs.h
-@@ -212,6 +212,7 @@ struct meta_index {
- * definitions for structures on disk
- */
- #define ZLIB_COMPRESSION 1
-+#define LZMA_COMPRESSION 2
-
- struct squashfs_super_block {
- __le32 s_magic;
---- a/fs/squashfs/super.c
-+++ b/fs/squashfs/super.c
-@@ -47,13 +47,76 @@
- #include "squashfs.h"
-
-
--#define SQUASHFS_CRYPTO_ALG "zlib"
-+static int squashfs_setup_zlib(struct squashfs_sb_info *msblk)
-+{
-+ int err = -EOPNOTSUPP;
-+
-+#ifdef CONFIG_SQUASHFS_SUPPORT_ZLIB
-+ struct {
-+ struct nlattr nla;
-+ int val;
-+ } params = {
-+ .nla = {
-+ .nla_len = nla_attr_size(sizeof(int)),
-+ .nla_type = ZLIB_DECOMP_WINDOWBITS,
-+ },
-+ .val = DEF_WBITS,
-+ };
-+
-+ msblk->tfm = crypto_alloc_pcomp("zlib", 0,
-+ CRYPTO_ALG_ASYNC);
-+ if (IS_ERR(msblk->tfm)) {
-+ ERROR("Failed to load zlib crypto module\n");
-+ return PTR_ERR(msblk->tfm);
-+ }
-+
-+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-+ if (err) {
-+ ERROR("Failed to set up decompression parameters\n");
-+ crypto_free_pcomp(msblk->tfm);
-+ }
-+#endif
-+
-+ return err;
-+}
-+
-+static int squashfs_setup_lzma(struct squashfs_sb_info *msblk)
-+{
-+ int err = -EOPNOTSUPP;
-+
-+#ifdef CONFIG_SQUASHFS_SUPPORT_LZMA
-+ struct {
-+ struct nlattr nla;
-+ int val;
-+ } params = {
-+ .nla = {
-+ .nla_len = nla_attr_size(sizeof(int)),
-+ .nla_type = UNLZMA_DECOMP_OUT_BUFFERS,
-+ },
-+ .val = (msblk->block_size / PAGE_CACHE_SIZE) + 1
-+ };
-
-+ msblk->tfm = crypto_alloc_pcomp("lzma", 0,
-+ CRYPTO_ALG_ASYNC);
-+ if (IS_ERR(msblk->tfm)) {
-+ ERROR("Failed to load lzma crypto module\n");
-+ return PTR_ERR(msblk->tfm);
-+ }
-+
-+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-+ if (err) {
-+ ERROR("Failed to set up decompression parameters\n");
-+ crypto_free_pcomp(msblk->tfm);
-+ }
-+#endif
-+
-+ return err;
-+}
-
- static struct file_system_type squashfs_fs_type;
- static struct super_operations squashfs_super_ops;
-
--static int supported_squashfs_filesystem(short major, short minor, short comp)
-+static int supported_squashfs_filesystem(short major, short minor)
- {
- if (major < SQUASHFS_MAJOR) {
- ERROR("Major/Minor mismatch, older Squashfs %d.%d "
-@@ -66,9 +129,6 @@ static int supported_squashfs_filesystem
- return -EINVAL;
- }
-
-- if (comp != ZLIB_COMPRESSION)
-- return -EINVAL;
--
- return 0;
- }
-
-@@ -83,16 +143,6 @@ static int squashfs_fill_super(struct su
- unsigned short flags;
- unsigned int fragments;
- u64 lookup_table_start;
-- struct {
-- struct nlattr nla;
-- int val;
-- } params = {
-- .nla = {
-- .nla_len = nla_attr_size(sizeof(int)),
-- .nla_type = ZLIB_DECOMP_WINDOWBITS,
-- },
-- .val = DEF_WBITS,
-- };
- int err;
-
- TRACE("Entered squashfs_fill_superblock\n");
-@@ -104,21 +154,6 @@ static int squashfs_fill_super(struct su
- }
- msblk = sb->s_fs_info;
-
-- msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0,
-- CRYPTO_ALG_ASYNC);
-- if (IS_ERR(msblk->tfm)) {
-- ERROR("Failed to load %s crypto module\n",
-- SQUASHFS_CRYPTO_ALG);
-- err = PTR_ERR(msblk->tfm);
-- goto failed_pcomp;
-- }
--
-- err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-- if (err) {
-- ERROR("Failed to set up decompression parameters\n");
-- goto failure;
-- }
--
- sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
- if (sblk == NULL) {
- ERROR("Failed to allocate squashfs_super_block\n");
-@@ -156,10 +191,28 @@ static int squashfs_fill_super(struct su
- goto failed_mount;
- }
-
-+ /* Check block size for sanity */
-+ msblk->block_size = le32_to_cpu(sblk->block_size);
-+ if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
-+ goto failed_mount;
-+
- /* Check the MAJOR & MINOR versions and compression type */
- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
-- le16_to_cpu(sblk->s_minor),
-- le16_to_cpu(sblk->compression));
-+ le16_to_cpu(sblk->s_minor));
-+ if (err < 0)
-+ goto failed_mount;
-+
-+ switch(le16_to_cpu(sblk->compression)) {
-+ case ZLIB_COMPRESSION:
-+ err = squashfs_setup_zlib(msblk);
-+ break;
-+ case LZMA_COMPRESSION:
-+ err = squashfs_setup_lzma(msblk);
-+ break;
-+ default:
-+ err = -EINVAL;
-+ break;
-+ }
- if (err < 0)
- goto failed_mount;
-
-@@ -179,11 +232,6 @@ static int squashfs_fill_super(struct su
- i_size_read(sb->s_bdev->bd_inode))
- goto failed_mount;
-
-- /* Check block size for sanity */
-- msblk->block_size = le32_to_cpu(sblk->block_size);
-- if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
-- goto failed_mount;
--
- /*
- * Check the system page size is not larger than the filesystem
- * block size (by default 128K). This is currently not supported.
-@@ -315,21 +363,16 @@ allocate_root:
- return 0;
-
- failed_mount:
-+ if (msblk->tfm)
-+ crypto_free_pcomp(msblk->tfm);
- squashfs_cache_delete(msblk->block_cache);
- squashfs_cache_delete(msblk->fragment_cache);
- squashfs_cache_delete(msblk->read_page);
- kfree(msblk->inode_lookup_table);
- kfree(msblk->fragment_index);
- kfree(msblk->id_table);
-- crypto_free_pcomp(msblk->tfm);
-- kfree(sb->s_fs_info);
-- sb->s_fs_info = NULL;
- kfree(sblk);
-- return err;
--
- failure:
-- crypto_free_pcomp(msblk->tfm);
--failed_pcomp:
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- return err;
diff --git a/target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch b/target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch
new file mode 100644
index 000000000..94096791f
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch
@@ -0,0 +1,244 @@
+From 6c4419d997d4431bb62e73475cd6b084e83efbd1 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Tue, 22 Sep 2009 19:25:24 +0100
+Subject: [PATCH] Squashfs: move zlib decompression wrapper code into a separate file
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Makefile | 2 +-
+ fs/squashfs/block.c | 74 ++----------------------------
+ fs/squashfs/squashfs.h | 4 ++
+ fs/squashfs/zlib_wrapper.c | 109 ++++++++++++++++++++++++++++++++++++++++++++
+ 4 files changed, 118 insertions(+), 71 deletions(-)
+ create mode 100644 fs/squashfs/zlib_wrapper.c
+
+--- a/fs/squashfs/Makefile
++++ b/fs/squashfs/Makefile
+@@ -4,4 +4,4 @@
+
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
+-squashfs-y += namei.o super.o symlink.o
++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o
+--- a/fs/squashfs/block.c
++++ b/fs/squashfs/block.c
+@@ -29,7 +29,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/mutex.h>
+ #include <linux/string.h>
+ #include <linux/buffer_head.h>
+ #include <linux/zlib.h>
+@@ -153,72 +152,10 @@ int squashfs_read_data(struct super_bloc
+ }
+
+ if (compressed) {
+- int zlib_err = 0, zlib_init = 0;
+-
+- /*
+- * Uncompress block.
+- */
+-
+- mutex_lock(&msblk->read_data_mutex);
+-
+- msblk->stream.avail_out = 0;
+- msblk->stream.avail_in = 0;
+-
+- bytes = length;
+- do {
+- if (msblk->stream.avail_in == 0 && k < b) {
+- avail = min(bytes, msblk->devblksize - offset);
+- bytes -= avail;
+- wait_on_buffer(bh[k]);
+- if (!buffer_uptodate(bh[k]))
+- goto release_mutex;
+-
+- if (avail == 0) {
+- offset = 0;
+- put_bh(bh[k++]);
+- continue;
+- }
+-
+- msblk->stream.next_in = bh[k]->b_data + offset;
+- msblk->stream.avail_in = avail;
+- offset = 0;
+- }
+-
+- if (msblk->stream.avail_out == 0 && page < pages) {
+- msblk->stream.next_out = buffer[page++];
+- msblk->stream.avail_out = PAGE_CACHE_SIZE;
+- }
+-
+- if (!zlib_init) {
+- zlib_err = zlib_inflateInit(&msblk->stream);
+- if (zlib_err != Z_OK) {
+- ERROR("zlib_inflateInit returned"
+- " unexpected result 0x%x,"
+- " srclength %d\n", zlib_err,
+- srclength);
+- goto release_mutex;
+- }
+- zlib_init = 1;
+- }
+-
+- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
+-
+- if (msblk->stream.avail_in == 0 && k < b)
+- put_bh(bh[k++]);
+- } while (zlib_err == Z_OK);
+-
+- if (zlib_err != Z_STREAM_END) {
+- ERROR("zlib_inflate error, data probably corrupt\n");
+- goto release_mutex;
+- }
+-
+- zlib_err = zlib_inflateEnd(&msblk->stream);
+- if (zlib_err != Z_OK) {
+- ERROR("zlib_inflate error, data probably corrupt\n");
+- goto release_mutex;
+- }
+- length = msblk->stream.total_out;
+- mutex_unlock(&msblk->read_data_mutex);
++ length = zlib_uncompress(msblk, buffer, bh, b, offset, length,
++ srclength, pages);
++ if (length < 0)
++ goto read_failure;
+ } else {
+ /*
+ * Block is uncompressed.
+@@ -255,9 +192,6 @@ int squashfs_read_data(struct super_bloc
+ kfree(bh);
+ return length;
+
+-release_mutex:
+- mutex_unlock(&msblk->read_data_mutex);
+-
+ block_release:
+ for (; k < b; k++)
+ put_bh(bh[k]);
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -70,6 +70,10 @@ extern struct inode *squashfs_iget(struc
+ unsigned int);
+ extern int squashfs_read_inode(struct inode *, long long);
+
++/* zlib_wrapper.c */
++extern int zlib_uncompress(struct squashfs_sb_info *, void **,
++ struct buffer_head **, int, int, int, int, int);
++
+ /*
+ * Inodes and files operations
+ */
+--- /dev/null
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -0,0 +1,109 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * zlib_wrapper.c
++ */
++
++
++#include <linux/mutex.h>
++#include <linux/buffer_head.h>
++#include <linux/zlib.h>
++
++#include "squashfs_fs.h"
++#include "squashfs_fs_sb.h"
++#include "squashfs_fs_i.h"
++#include "squashfs.h"
++
++int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
++ struct buffer_head **bh, int b, int offset, int length, int srclength,
++ int pages)
++{
++ int zlib_err = 0, zlib_init = 0;
++ int avail, bytes, k = 0, page = 0;
++
++ mutex_lock(&msblk->read_data_mutex);
++
++ msblk->stream.avail_out = 0;
++ msblk->stream.avail_in = 0;
++
++ bytes = length;
++ do {
++ if (msblk->stream.avail_in == 0 && k < b) {
++ avail = min(bytes, msblk->devblksize - offset);
++ bytes -= avail;
++ wait_on_buffer(bh[k]);
++ if (!buffer_uptodate(bh[k]))
++ goto release_mutex;
++
++ if (avail == 0) {
++ offset = 0;
++ put_bh(bh[k++]);
++ continue;
++ }
++
++ msblk->stream.next_in = bh[k]->b_data + offset;
++ msblk->stream.avail_in = avail;
++ offset = 0;
++ }
++
++ if (msblk->stream.avail_out == 0 && page < pages) {
++ msblk->stream.next_out = buffer[page++];
++ msblk->stream.avail_out = PAGE_CACHE_SIZE;
++ }
++
++ if (!zlib_init) {
++ zlib_err = zlib_inflateInit(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflateInit returned unexpected "
++ "result 0x%x, srclength %d\n",
++ zlib_err, srclength);
++ goto release_mutex;
++ }
++ zlib_init = 1;
++ }
++
++ zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
++
++ if (msblk->stream.avail_in == 0 && k < b)
++ put_bh(bh[k++]);
++ } while (zlib_err == Z_OK);
++
++ if (zlib_err != Z_STREAM_END) {
++ ERROR("zlib_inflate error, data probably corrupt\n");
++ goto release_mutex;
++ }
++
++ zlib_err = zlib_inflateEnd(&msblk->stream);
++ if (zlib_err != Z_OK) {
++ ERROR("zlib_inflate error, data probably corrupt\n");
++ goto release_mutex;
++ }
++
++ mutex_unlock(&msblk->read_data_mutex);
++ return msblk->stream.total_out;
++
++release_mutex:
++ mutex_unlock(&msblk->read_data_mutex);
++
++ for (; k < b; k++)
++ put_bh(bh[k]);
++
++ return -EIO;
++}
diff --git a/target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch b/target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch
new file mode 100644
index 000000000..eacbb97ae
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch
@@ -0,0 +1,317 @@
+From 37c44e85fd49676ec15ccaeea065662c1fbcda7d Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Wed, 23 Sep 2009 19:04:49 +0100
+Subject: [PATCH] Squashfs: Factor out remaining zlib dependencies into separate wrapper file
+
+Move zlib buffer init/destroy code into separate wrapper file. Also
+make zlib z_stream field a void * removing the need to include zlib.h
+for most files.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/block.c | 1 -
+ fs/squashfs/cache.c | 1 -
+ fs/squashfs/dir.c | 1 -
+ fs/squashfs/export.c | 1 -
+ fs/squashfs/file.c | 1 -
+ fs/squashfs/fragment.c | 1 -
+ fs/squashfs/id.c | 1 -
+ fs/squashfs/inode.c | 1 -
+ fs/squashfs/namei.c | 1 -
+ fs/squashfs/squashfs.h | 2 +
+ fs/squashfs/squashfs_fs_sb.h | 2 +-
+ fs/squashfs/super.c | 14 +++------
+ fs/squashfs/symlink.c | 1 -
+ fs/squashfs/zlib_wrapper.c | 56 ++++++++++++++++++++++++++++++++---------
+ 14 files changed, 51 insertions(+), 33 deletions(-)
+
+--- a/fs/squashfs/block.c
++++ b/fs/squashfs/block.c
+@@ -31,7 +31,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/buffer_head.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/cache.c
++++ b/fs/squashfs/cache.c
+@@ -51,7 +51,6 @@
+ #include <linux/sched.h>
+ #include <linux/spinlock.h>
+ #include <linux/wait.h>
+-#include <linux/zlib.h>
+ #include <linux/pagemap.h>
+
+ #include "squashfs_fs.h"
+--- a/fs/squashfs/dir.c
++++ b/fs/squashfs/dir.c
+@@ -30,7 +30,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/export.c
++++ b/fs/squashfs/export.c
+@@ -39,7 +39,6 @@
+ #include <linux/vfs.h>
+ #include <linux/dcache.h>
+ #include <linux/exportfs.h>
+-#include <linux/zlib.h>
+ #include <linux/slab.h>
+
+ #include "squashfs_fs.h"
+--- a/fs/squashfs/file.c
++++ b/fs/squashfs/file.c
+@@ -47,7 +47,6 @@
+ #include <linux/string.h>
+ #include <linux/pagemap.h>
+ #include <linux/mutex.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/fragment.c
++++ b/fs/squashfs/fragment.c
+@@ -36,7 +36,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/id.c
++++ b/fs/squashfs/id.c
+@@ -34,7 +34,6 @@
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+ #include <linux/slab.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/inode.c
++++ b/fs/squashfs/inode.c
+@@ -40,7 +40,6 @@
+
+ #include <linux/fs.h>
+ #include <linux/vfs.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/namei.c
++++ b/fs/squashfs/namei.c
+@@ -57,7 +57,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/dcache.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -71,6 +71,8 @@ extern struct inode *squashfs_iget(struc
+ extern int squashfs_read_inode(struct inode *, long long);
+
+ /* zlib_wrapper.c */
++extern void *zlib_init(void);
++extern void zlib_free(void *);
+ extern int zlib_uncompress(struct squashfs_sb_info *, void **,
+ struct buffer_head **, int, int, int, int, int);
+
+--- a/fs/squashfs/squashfs_fs_sb.h
++++ b/fs/squashfs/squashfs_fs_sb.h
+@@ -64,7 +64,7 @@ struct squashfs_sb_info {
+ struct mutex read_data_mutex;
+ struct mutex meta_index_mutex;
+ struct meta_index *meta_index;
+- z_stream stream;
++ void *stream;
+ __le64 *inode_lookup_table;
+ u64 inode_table;
+ u64 directory_table;
+--- a/fs/squashfs/super.c
++++ b/fs/squashfs/super.c
+@@ -35,7 +35,6 @@
+ #include <linux/pagemap.h>
+ #include <linux/init.h>
+ #include <linux/module.h>
+-#include <linux/zlib.h>
+ #include <linux/magic.h>
+
+ #include "squashfs_fs.h"
+@@ -87,12 +86,9 @@ static int squashfs_fill_super(struct su
+ }
+ msblk = sb->s_fs_info;
+
+- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
+- GFP_KERNEL);
+- if (msblk->stream.workspace == NULL) {
+- ERROR("Failed to allocate zlib workspace\n");
++ msblk->stream = zlib_init();
++ if (msblk->stream == NULL)
+ goto failure;
+- }
+
+ sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
+ if (sblk == NULL) {
+@@ -292,17 +288,17 @@ failed_mount:
+ squashfs_cache_delete(msblk->block_cache);
+ squashfs_cache_delete(msblk->fragment_cache);
+ squashfs_cache_delete(msblk->read_page);
++ zlib_free(msblk->stream);
+ kfree(msblk->inode_lookup_table);
+ kfree(msblk->fragment_index);
+ kfree(msblk->id_table);
+- kfree(msblk->stream.workspace);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ kfree(sblk);
+ return err;
+
+ failure:
+- kfree(msblk->stream.workspace);
++ zlib_free(msblk->stream);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ return -ENOMEM;
+@@ -346,10 +342,10 @@ static void squashfs_put_super(struct su
+ squashfs_cache_delete(sbi->block_cache);
+ squashfs_cache_delete(sbi->fragment_cache);
+ squashfs_cache_delete(sbi->read_page);
++ zlib_free(sbi->stream);
+ kfree(sbi->id_table);
+ kfree(sbi->fragment_index);
+ kfree(sbi->meta_index);
+- kfree(sbi->stream.workspace);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ }
+--- a/fs/squashfs/symlink.c
++++ b/fs/squashfs/symlink.c
+@@ -36,7 +36,6 @@
+ #include <linux/slab.h>
+ #include <linux/string.h>
+ #include <linux/pagemap.h>
+-#include <linux/zlib.h>
+
+ #include "squashfs_fs.h"
+ #include "squashfs_fs_sb.h"
+--- a/fs/squashfs/zlib_wrapper.c
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -31,21 +31,51 @@
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
+
++void *zlib_init()
++{
++ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
++ if (stream == NULL)
++ goto failed;
++ stream->workspace = kmalloc(zlib_inflate_workspacesize(),
++ GFP_KERNEL);
++ if (stream->workspace == NULL)
++ goto failed;
++
++ return stream;
++
++failed:
++ ERROR("Failed to allocate zlib workspace\n");
++ kfree(stream);
++ return NULL;
++}
++
++
++void zlib_free(void *strm)
++{
++ z_stream *stream = strm;
++
++ if (stream)
++ kfree(stream->workspace);
++ kfree(stream);
++}
++
++
+ int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
+ struct buffer_head **bh, int b, int offset, int length, int srclength,
+ int pages)
+ {
+ int zlib_err = 0, zlib_init = 0;
+ int avail, bytes, k = 0, page = 0;
++ z_stream *stream = msblk->stream;
+
+ mutex_lock(&msblk->read_data_mutex);
+
+- msblk->stream.avail_out = 0;
+- msblk->stream.avail_in = 0;
++ stream->avail_out = 0;
++ stream->avail_in = 0;
+
+ bytes = length;
+ do {
+- if (msblk->stream.avail_in == 0 && k < b) {
++ if (stream->avail_in == 0 && k < b) {
+ avail = min(bytes, msblk->devblksize - offset);
+ bytes -= avail;
+ wait_on_buffer(bh[k]);
+@@ -58,18 +88,18 @@ int zlib_uncompress(struct squashfs_sb_i
+ continue;
+ }
+
+- msblk->stream.next_in = bh[k]->b_data + offset;
+- msblk->stream.avail_in = avail;
++ stream->next_in = bh[k]->b_data + offset;
++ stream->avail_in = avail;
+ offset = 0;
+ }
+
+- if (msblk->stream.avail_out == 0 && page < pages) {
+- msblk->stream.next_out = buffer[page++];
+- msblk->stream.avail_out = PAGE_CACHE_SIZE;
++ if (stream->avail_out == 0 && page < pages) {
++ stream->next_out = buffer[page++];
++ stream->avail_out = PAGE_CACHE_SIZE;
+ }
+
+ if (!zlib_init) {
+- zlib_err = zlib_inflateInit(&msblk->stream);
++ zlib_err = zlib_inflateInit(stream);
+ if (zlib_err != Z_OK) {
+ ERROR("zlib_inflateInit returned unexpected "
+ "result 0x%x, srclength %d\n",
+@@ -79,9 +109,9 @@ int zlib_uncompress(struct squashfs_sb_i
+ zlib_init = 1;
+ }
+
+- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
++ zlib_err = zlib_inflate(stream, Z_SYNC_FLUSH);
+
+- if (msblk->stream.avail_in == 0 && k < b)
++ if (stream->avail_in == 0 && k < b)
+ put_bh(bh[k++]);
+ } while (zlib_err == Z_OK);
+
+@@ -90,14 +120,14 @@ int zlib_uncompress(struct squashfs_sb_i
+ goto release_mutex;
+ }
+
+- zlib_err = zlib_inflateEnd(&msblk->stream);
++ zlib_err = zlib_inflateEnd(stream);
+ if (zlib_err != Z_OK) {
+ ERROR("zlib_inflate error, data probably corrupt\n");
+ goto release_mutex;
+ }
+
+ mutex_unlock(&msblk->read_data_mutex);
+- return msblk->stream.total_out;
++ return stream->total_out;
+
+ release_mutex:
+ mutex_unlock(&msblk->read_data_mutex);
diff --git a/target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch b/target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch
new file mode 100644
index 000000000..cbfbf5369
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch
@@ -0,0 +1,426 @@
+From 327fbf47a419befc6bff74f3ca42d2b6f0841903 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Tue, 6 Oct 2009 04:04:15 +0100
+Subject: [PATCH] Squashfs: add a decompressor framework
+
+This adds a decompressor framework which allows multiple compression
+algorithms to be cleanly supported.
+
+Also update zlib wrapper and other code to use the new framework.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Makefile | 2 +-
+ fs/squashfs/block.c | 6 ++--
+ fs/squashfs/decompressor.c | 58 ++++++++++++++++++++++++++++++++++++++++++
+ fs/squashfs/decompressor.h | 55 +++++++++++++++++++++++++++++++++++++++
+ fs/squashfs/squashfs.h | 14 +++++-----
+ fs/squashfs/squashfs_fs_sb.h | 41 +++++++++++++++--------------
+ fs/squashfs/super.c | 45 ++++++++++++++++++-------------
+ fs/squashfs/zlib_wrapper.c | 17 ++++++++++--
+ 8 files changed, 185 insertions(+), 53 deletions(-)
+ create mode 100644 fs/squashfs/decompressor.c
+ create mode 100644 fs/squashfs/decompressor.h
+
+--- a/fs/squashfs/Makefile
++++ b/fs/squashfs/Makefile
+@@ -4,4 +4,4 @@
+
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
+-squashfs-y += namei.o super.o symlink.o zlib_wrapper.o
++squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
+--- a/fs/squashfs/block.c
++++ b/fs/squashfs/block.c
+@@ -36,7 +36,7 @@
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
+-
++#include "decompressor.h"
+ /*
+ * Read the metadata block length, this is stored in the first two
+ * bytes of the metadata block.
+@@ -151,8 +151,8 @@ int squashfs_read_data(struct super_bloc
+ }
+
+ if (compressed) {
+- length = zlib_uncompress(msblk, buffer, bh, b, offset, length,
+- srclength, pages);
++ length = squashfs_decompress(msblk, buffer, bh, b, offset,
++ length, srclength, pages);
+ if (length < 0)
+ goto read_failure;
+ } else {
+--- /dev/null
++++ b/fs/squashfs/decompressor.c
+@@ -0,0 +1,58 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * decompressor.c
++ */
++
++#include <linux/types.h>
++#include <linux/mutex.h>
++#include <linux/buffer_head.h>
++
++#include "squashfs_fs.h"
++#include "squashfs_fs_sb.h"
++#include "squashfs_fs_i.h"
++#include "decompressor.h"
++#include "squashfs.h"
++
++/*
++ * This file (and decompressor.h) implements a decompressor framework for
++ * Squashfs, allowing multiple decompressors to be easily supported
++ */
++
++static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
++ NULL, NULL, NULL, 0, "unknown", 0
++};
++
++static const struct squashfs_decompressor *decompressor[] = {
++ &squashfs_zlib_comp_ops,
++ &squashfs_unknown_comp_ops
++};
++
++
++const struct squashfs_decompressor *squashfs_lookup_decompressor(int id)
++{
++ int i;
++
++ for (i = 0; decompressor[i]->id; i++)
++ if (id == decompressor[i]->id)
++ break;
++
++ return decompressor[i];
++}
+--- /dev/null
++++ b/fs/squashfs/decompressor.h
+@@ -0,0 +1,55 @@
++#ifndef DECOMPRESSOR_H
++#define DECOMPRESSOR_H
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * decompressor.h
++ */
++
++struct squashfs_decompressor {
++ void *(*init)(void);
++ void (*free)(void *);
++ int (*decompress)(struct squashfs_sb_info *, void **,
++ struct buffer_head **, int, int, int, int, int);
++ int id;
++ char *name;
++ int supported;
++};
++
++static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
++{
++ return msblk->decompressor->init();
++}
++
++static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
++ void *s)
++{
++ if (msblk->decompressor)
++ msblk->decompressor->free(s);
++}
++
++static inline int squashfs_decompress(struct squashfs_sb_info *msblk,
++ void **buffer, struct buffer_head **bh, int b, int offset, int length,
++ int srclength, int pages)
++{
++ return msblk->decompressor->decompress(msblk, buffer, bh, b, offset,
++ length, srclength, pages);
++}
++#endif
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -51,6 +51,9 @@ extern struct squashfs_cache_entry *squa
+ u64, int);
+ extern int squashfs_read_table(struct super_block *, void *, u64, int);
+
++/* decompressor.c */
++extern const struct squashfs_decompressor *squashfs_lookup_decompressor(int);
++
+ /* export.c */
+ extern __le64 *squashfs_read_inode_lookup_table(struct super_block *, u64,
+ unsigned int);
+@@ -70,14 +73,8 @@ extern struct inode *squashfs_iget(struc
+ unsigned int);
+ extern int squashfs_read_inode(struct inode *, long long);
+
+-/* zlib_wrapper.c */
+-extern void *zlib_init(void);
+-extern void zlib_free(void *);
+-extern int zlib_uncompress(struct squashfs_sb_info *, void **,
+- struct buffer_head **, int, int, int, int, int);
+-
+ /*
+- * Inodes and files operations
++ * Inodes, files and decompressor operations
+ */
+
+ /* dir.c */
+@@ -94,3 +91,6 @@ extern const struct inode_operations squ
+
+ /* symlink.c */
+ extern const struct address_space_operations squashfs_symlink_aops;
++
++/* zlib_wrapper.c */
++extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
+--- a/fs/squashfs/squashfs_fs_sb.h
++++ b/fs/squashfs/squashfs_fs_sb.h
+@@ -52,25 +52,26 @@ struct squashfs_cache_entry {
+ };
+
+ struct squashfs_sb_info {
+- int devblksize;
+- int devblksize_log2;
+- struct squashfs_cache *block_cache;
+- struct squashfs_cache *fragment_cache;
+- struct squashfs_cache *read_page;
+- int next_meta_index;
+- __le64 *id_table;
+- __le64 *fragment_index;
+- unsigned int *fragment_index_2;
+- struct mutex read_data_mutex;
+- struct mutex meta_index_mutex;
+- struct meta_index *meta_index;
+- void *stream;
+- __le64 *inode_lookup_table;
+- u64 inode_table;
+- u64 directory_table;
+- unsigned int block_size;
+- unsigned short block_log;
+- long long bytes_used;
+- unsigned int inodes;
++ const struct squashfs_decompressor *decompressor;
++ int devblksize;
++ int devblksize_log2;
++ struct squashfs_cache *block_cache;
++ struct squashfs_cache *fragment_cache;
++ struct squashfs_cache *read_page;
++ int next_meta_index;
++ __le64 *id_table;
++ __le64 *fragment_index;
++ unsigned int *fragment_index_2;
++ struct mutex read_data_mutex;
++ struct mutex meta_index_mutex;
++ struct meta_index *meta_index;
++ void *stream;
++ __le64 *inode_lookup_table;
++ u64 inode_table;
++ u64 directory_table;
++ unsigned int block_size;
++ unsigned short block_log;
++ long long bytes_used;
++ unsigned int inodes;
+ };
+ #endif
+--- a/fs/squashfs/super.c
++++ b/fs/squashfs/super.c
+@@ -41,27 +41,35 @@
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
++#include "decompressor.h"
+
+ static struct file_system_type squashfs_fs_type;
+ static struct super_operations squashfs_super_ops;
+
+-static int supported_squashfs_filesystem(short major, short minor, short comp)
++static const struct squashfs_decompressor *supported_squashfs_filesystem(short
++ major, short minor, short id)
+ {
++ const struct squashfs_decompressor *decompressor;
++
+ if (major < SQUASHFS_MAJOR) {
+ ERROR("Major/Minor mismatch, older Squashfs %d.%d "
+ "filesystems are unsupported\n", major, minor);
+- return -EINVAL;
++ return NULL;
+ } else if (major > SQUASHFS_MAJOR || minor > SQUASHFS_MINOR) {
+ ERROR("Major/Minor mismatch, trying to mount newer "
+ "%d.%d filesystem\n", major, minor);
+ ERROR("Please update your kernel\n");
+- return -EINVAL;
++ return NULL;
+ }
+
+- if (comp != ZLIB_COMPRESSION)
+- return -EINVAL;
++ decompressor = squashfs_lookup_decompressor(id);
++ if (!decompressor->supported) {
++ ERROR("Filesystem uses \"%s\" compression. This is not "
++ "supported\n", decompressor->name);
++ return NULL;
++ }
+
+- return 0;
++ return decompressor;
+ }
+
+
+@@ -86,10 +94,6 @@ static int squashfs_fill_super(struct su
+ }
+ msblk = sb->s_fs_info;
+
+- msblk->stream = zlib_init();
+- if (msblk->stream == NULL)
+- goto failure;
+-
+ sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
+ if (sblk == NULL) {
+ ERROR("Failed to allocate squashfs_super_block\n");
+@@ -116,25 +120,25 @@ static int squashfs_fill_super(struct su
+ goto failed_mount;
+ }
+
++ err = -EINVAL;
++
+ /* Check it is a SQUASHFS superblock */
+ sb->s_magic = le32_to_cpu(sblk->s_magic);
+ if (sb->s_magic != SQUASHFS_MAGIC) {
+ if (!silent)
+ ERROR("Can't find a SQUASHFS superblock on %s\n",
+ bdevname(sb->s_bdev, b));
+- err = -EINVAL;
+ goto failed_mount;
+ }
+
+- /* Check the MAJOR & MINOR versions and compression type */
+- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
++ /* Check the MAJOR & MINOR versions and lookup compression type */
++ msblk->decompressor = supported_squashfs_filesystem(
++ le16_to_cpu(sblk->s_major),
+ le16_to_cpu(sblk->s_minor),
+ le16_to_cpu(sblk->compression));
+- if (err < 0)
++ if (msblk->decompressor == NULL)
+ goto failed_mount;
+
+- err = -EINVAL;
+-
+ /*
+ * Check if there's xattrs in the filesystem. These are not
+ * supported in this version, so warn that they will be ignored.
+@@ -201,6 +205,10 @@ static int squashfs_fill_super(struct su
+
+ err = -ENOMEM;
+
++ msblk->stream = squashfs_decompressor_init(msblk);
++ if (msblk->stream == NULL)
++ goto failed_mount;
++
+ msblk->block_cache = squashfs_cache_init("metadata",
+ SQUASHFS_CACHED_BLKS, SQUASHFS_METADATA_SIZE);
+ if (msblk->block_cache == NULL)
+@@ -288,7 +296,7 @@ failed_mount:
+ squashfs_cache_delete(msblk->block_cache);
+ squashfs_cache_delete(msblk->fragment_cache);
+ squashfs_cache_delete(msblk->read_page);
+- zlib_free(msblk->stream);
++ squashfs_decompressor_free(msblk, msblk->stream);
+ kfree(msblk->inode_lookup_table);
+ kfree(msblk->fragment_index);
+ kfree(msblk->id_table);
+@@ -298,7 +306,6 @@ failed_mount:
+ return err;
+
+ failure:
+- zlib_free(msblk->stream);
+ kfree(sb->s_fs_info);
+ sb->s_fs_info = NULL;
+ return -ENOMEM;
+@@ -342,7 +349,7 @@ static void squashfs_put_super(struct su
+ squashfs_cache_delete(sbi->block_cache);
+ squashfs_cache_delete(sbi->fragment_cache);
+ squashfs_cache_delete(sbi->read_page);
+- zlib_free(sbi->stream);
++ squashfs_decompressor_free(sbi, sbi->stream);
+ kfree(sbi->id_table);
+ kfree(sbi->fragment_index);
+ kfree(sbi->meta_index);
+--- a/fs/squashfs/zlib_wrapper.c
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -30,8 +30,9 @@
+ #include "squashfs_fs_sb.h"
+ #include "squashfs_fs_i.h"
+ #include "squashfs.h"
++#include "decompressor.h"
+
+-void *zlib_init()
++static void *zlib_init(void)
+ {
+ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
+ if (stream == NULL)
+@@ -50,7 +51,7 @@ failed:
+ }
+
+
+-void zlib_free(void *strm)
++static void zlib_free(void *strm)
+ {
+ z_stream *stream = strm;
+
+@@ -60,7 +61,7 @@ void zlib_free(void *strm)
+ }
+
+
+-int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
++static int zlib_uncompress(struct squashfs_sb_info *msblk, void **buffer,
+ struct buffer_head **bh, int b, int offset, int length, int srclength,
+ int pages)
+ {
+@@ -137,3 +138,13 @@ release_mutex:
+
+ return -EIO;
+ }
++
++const struct squashfs_decompressor squashfs_zlib_comp_ops = {
++ .init = zlib_init,
++ .free = zlib_free,
++ .decompress = zlib_uncompress,
++ .id = ZLIB_COMPRESSION,
++ .name = "zlib",
++ .supported = 1
++};
++
diff --git a/target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch b/target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch
new file mode 100644
index 000000000..a378c0005
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch
@@ -0,0 +1,54 @@
+From 1885ca0a1973944684f252094a703b7c80dfc974 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Wed, 14 Oct 2009 03:58:11 +0100
+Subject: [PATCH] Squashfs: add decompressor entries for lzma and lzo
+
+Add knowledge of lzma/lzo compression formats to the decompressor
+framework. For now these are added as unsupported. Without
+these entries lzma/lzo compressed filesystems will be flagged as
+having unknown compression which is undesirable.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/decompressor.c | 10 ++++++++++
+ fs/squashfs/squashfs_fs.h | 4 +++-
+ 2 files changed, 13 insertions(+), 1 deletions(-)
+
+--- a/fs/squashfs/decompressor.c
++++ b/fs/squashfs/decompressor.c
+@@ -36,12 +36,22 @@
+ * Squashfs, allowing multiple decompressors to be easily supported
+ */
+
++static const struct squashfs_decompressor squashfs_lzma_unsupported_comp_ops = {
++ NULL, NULL, NULL, LZMA_COMPRESSION, "lzma", 0
++};
++
++static const struct squashfs_decompressor squashfs_lzo_unsupported_comp_ops = {
++ NULL, NULL, NULL, LZO_COMPRESSION, "lzo", 0
++};
++
+ static const struct squashfs_decompressor squashfs_unknown_comp_ops = {
+ NULL, NULL, NULL, 0, "unknown", 0
+ };
+
+ static const struct squashfs_decompressor *decompressor[] = {
+ &squashfs_zlib_comp_ops,
++ &squashfs_lzma_unsupported_comp_ops,
++ &squashfs_lzo_unsupported_comp_ops,
+ &squashfs_unknown_comp_ops
+ };
+
+--- a/fs/squashfs/squashfs_fs.h
++++ b/fs/squashfs/squashfs_fs.h
+@@ -211,7 +211,9 @@ struct meta_index {
+ /*
+ * definitions for structures on disk
+ */
+-#define ZLIB_COMPRESSION 1
++#define ZLIB_COMPRESSION 1
++#define LZMA_COMPRESSION 2
++#define LZO_COMPRESSION 3
+
+ struct squashfs_super_block {
+ __le32 s_magic;
diff --git a/target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch b/target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch
new file mode 100644
index 000000000..099168134
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch
@@ -0,0 +1,42 @@
+From 5f393ede3ddb5dd4cc2a9f243182fac45f1ce10b Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Wed, 14 Oct 2009 04:07:54 +0100
+Subject: [PATCH] Squashfs: add an extra parameter to the decompressor init function
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/decompressor.h | 4 ++--
+ fs/squashfs/zlib_wrapper.c | 2 +-
+ 2 files changed, 3 insertions(+), 3 deletions(-)
+
+--- a/fs/squashfs/decompressor.h
++++ b/fs/squashfs/decompressor.h
+@@ -24,7 +24,7 @@
+ */
+
+ struct squashfs_decompressor {
+- void *(*init)(void);
++ void *(*init)(struct squashfs_sb_info *);
+ void (*free)(void *);
+ int (*decompress)(struct squashfs_sb_info *, void **,
+ struct buffer_head **, int, int, int, int, int);
+@@ -35,7 +35,7 @@ struct squashfs_decompressor {
+
+ static inline void *squashfs_decompressor_init(struct squashfs_sb_info *msblk)
+ {
+- return msblk->decompressor->init();
++ return msblk->decompressor->init(msblk);
+ }
+
+ static inline void squashfs_decompressor_free(struct squashfs_sb_info *msblk,
+--- a/fs/squashfs/zlib_wrapper.c
++++ b/fs/squashfs/zlib_wrapper.c
+@@ -32,7 +32,7 @@
+ #include "squashfs.h"
+ #include "decompressor.h"
+
+-static void *zlib_init(void)
++static void *zlib_init(struct squashfs_sb_info *dummy)
+ {
+ z_stream *stream = kmalloc(sizeof(z_stream), GFP_KERNEL);
+ if (stream == NULL)
diff --git a/target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch b/target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch
new file mode 100644
index 000000000..9fd57970f
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch
@@ -0,0 +1,216 @@
+From f49e1efdd179d54e814ff2a8e8f469496583062c Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Tue, 20 Oct 2009 10:54:36 +0100
+Subject: [PATCH] Squashfs: add LZMA compression
+
+Add support for LZMA compressed filesystems. This is an initial
+implementation.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Kconfig | 5 ++
+ fs/squashfs/Makefile | 1 +
+ fs/squashfs/decompressor.c | 4 +
+ fs/squashfs/lzma_wrapper.c | 151 ++++++++++++++++++++++++++++++++++++++++++++
+ fs/squashfs/squashfs.h | 3 +
+ 5 files changed, 164 insertions(+), 0 deletions(-)
+ create mode 100644 fs/squashfs/lzma_wrapper.c
+
+--- a/fs/squashfs/Kconfig
++++ b/fs/squashfs/Kconfig
+@@ -26,6 +26,11 @@ config SQUASHFS
+
+ If unsure, say N.
+
++config SQUASHFS_LZMA
++ bool "Include support for LZMA compressed file systems"
++ depends on SQUASHFS
++ select DECOMPRESS_LZMA
++
+ config SQUASHFS_EMBEDDED
+
+ bool "Additional option for memory-constrained systems"
+--- a/fs/squashfs/Makefile
++++ b/fs/squashfs/Makefile
+@@ -5,3 +5,4 @@
+ obj-$(CONFIG_SQUASHFS) += squashfs.o
+ squashfs-y += block.o cache.o dir.o export.o file.o fragment.o id.o inode.o
+ squashfs-y += namei.o super.o symlink.o zlib_wrapper.o decompressor.o
++squashfs-$(CONFIG_SQUASHFS_LZMA) += lzma_wrapper.o
+--- a/fs/squashfs/decompressor.c
++++ b/fs/squashfs/decompressor.c
+@@ -50,7 +50,11 @@ static const struct squashfs_decompresso
+
+ static const struct squashfs_decompressor *decompressor[] = {
+ &squashfs_zlib_comp_ops,
++#ifdef CONFIG_SQUASHFS_LZMA
++ &squashfs_lzma_comp_ops,
++#else
+ &squashfs_lzma_unsupported_comp_ops,
++#endif
+ &squashfs_lzo_unsupported_comp_ops,
+ &squashfs_unknown_comp_ops
+ };
+--- /dev/null
++++ b/fs/squashfs/lzma_wrapper.c
+@@ -0,0 +1,151 @@
++/*
++ * Squashfs - a compressed read only filesystem for Linux
++ *
++ * Copyright (c) 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
++ * Phillip Lougher <phillip@lougher.demon.co.uk>
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License
++ * as published by the Free Software Foundation; either version 2,
++ * or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
++ *
++ * lzma_wrapper.c
++ */
++
++#include <asm/unaligned.h>
++#include <linux/buffer_head.h>
++#include <linux/mutex.h>
++#include <linux/vmalloc.h>
++#include <linux/decompress/unlzma.h>
++
++#include "squashfs_fs.h"
++#include "squashfs_fs_sb.h"
++#include "squashfs_fs_i.h"
++#include "squashfs.h"
++#include "decompressor.h"
++
++struct squashfs_lzma {
++ void *input;
++ void *output;
++};
++
++/* decompress_unlzma.c is currently non re-entrant... */
++DEFINE_MUTEX(lzma_mutex);
++
++/* decompress_unlzma.c doesn't provide any context in its callbacks... */
++static int lzma_error;
++
++static void error(char *m)
++{
++ ERROR("unlzma error: %s\n", m);
++ lzma_error = 1;
++}
++
++
++static void *lzma_init(struct squashfs_sb_info *msblk)
++{
++ struct squashfs_lzma *stream = kzalloc(sizeof(*stream), GFP_KERNEL);
++ if (stream == NULL)
++ goto failed;
++ stream->input = vmalloc(msblk->block_size);
++ if (stream->input == NULL)
++ goto failed;
++ stream->output = vmalloc(msblk->block_size);
++ if (stream->output == NULL)
++ goto failed2;
++
++ return stream;
++
++failed2:
++ vfree(stream->input);
++failed:
++ ERROR("failed to allocate lzma workspace\n");
++ kfree(stream);
++ return NULL;
++}
++
++
++static void lzma_free(void *strm)
++{
++ struct squashfs_lzma *stream = strm;
++
++ if (stream) {
++ vfree(stream->input);
++ vfree(stream->output);
++ }
++ kfree(stream);
++}
++
++
++static int lzma_uncompress(struct squashfs_sb_info *msblk, void **buffer,
++ struct buffer_head **bh, int b, int offset, int length, int srclength,
++ int pages)
++{
++ struct squashfs_lzma *stream = msblk->stream;
++ void *buff = stream->input;
++ int avail, i, bytes = length, res;
++
++ mutex_lock(&lzma_mutex);
++
++ for (i = 0; i < b; i++) {
++ wait_on_buffer(bh[i]);
++ if (!buffer_uptodate(bh[i]))
++ goto block_release;
++
++ avail = min(bytes, msblk->devblksize - offset);
++ memcpy(buff, bh[i]->b_data + offset, avail);
++ buff += avail;
++ bytes -= avail;
++ offset = 0;
++ put_bh(bh[i]);
++ }
++
++ lzma_error = 0;
++ res = unlzma(stream->input, length, NULL, NULL, stream->output, NULL,
++ error);
++ if (res || lzma_error)
++ goto failed;
++
++ /* uncompressed size is stored in the LZMA header (5 byte offset) */
++ res = bytes = get_unaligned_le32(stream->input + 5);
++ for (i = 0, buff = stream->output; bytes && i < pages; i++) {
++ avail = min_t(int, bytes, PAGE_CACHE_SIZE);
++ memcpy(buffer[i], buff, avail);
++ buff += avail;
++ bytes -= avail;
++ }
++ if (bytes)
++ goto failed;
++
++ mutex_unlock(&lzma_mutex);
++ return res;
++
++block_release:
++ for (; i < b; i++)
++ put_bh(bh[i]);
++
++failed:
++ mutex_unlock(&lzma_mutex);
++
++ ERROR("lzma decompression failed, data probably corrupt\n");
++ return -EIO;
++}
++
++const struct squashfs_decompressor squashfs_lzma_comp_ops = {
++ .init = lzma_init,
++ .free = lzma_free,
++ .decompress = lzma_uncompress,
++ .id = LZMA_COMPRESSION,
++ .name = "lzma",
++ .supported = 1
++};
++
+--- a/fs/squashfs/squashfs.h
++++ b/fs/squashfs/squashfs.h
+@@ -94,3 +94,6 @@ extern const struct address_space_operat
+
+ /* zlib_wrapper.c */
+ extern const struct squashfs_decompressor squashfs_zlib_comp_ops;
++
++/* lzma wrapper.c */
++extern const struct squashfs_decompressor squashfs_lzma_comp_ops;
diff --git a/target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch b/target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch
new file mode 100644
index 000000000..aa6c11012
--- /dev/null
+++ b/target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch
@@ -0,0 +1,165 @@
+From fdf23ed283bc6ef5c25076ce2065f892120ff556 Mon Sep 17 00:00:00 2001
+From: Phillip Lougher <phillip@lougher.demon.co.uk>
+Date: Thu, 22 Oct 2009 04:57:38 +0100
+Subject: [PATCH] Squashfs: Make unlzma available to non initramfs/initrd code
+
+Add a config option DECOMPRESS_LZMA_NEEDED which allows subsystems to
+specify they need the unlzma code. Normally decompress_unlzma.c is
+compiled with __init and unlzma is not exported to modules.
+
+Signed-off-by: Phillip Lougher <phillip@lougher.demon.co.uk>
+---
+ fs/squashfs/Kconfig | 1 +
+ include/linux/decompress/bunzip2_mm.h | 12 ++++++++++++
+ include/linux/decompress/inflate_mm.h | 12 ++++++++++++
+ include/linux/decompress/mm.h | 3 ---
+ include/linux/decompress/unlzma_mm.h | 20 ++++++++++++++++++++
+ lib/Kconfig | 3 +++
+ lib/decompress_bunzip2.c | 1 +
+ lib/decompress_inflate.c | 1 +
+ lib/decompress_unlzma.c | 5 ++++-
+ 9 files changed, 54 insertions(+), 4 deletions(-)
+ create mode 100644 include/linux/decompress/bunzip2_mm.h
+ create mode 100644 include/linux/decompress/inflate_mm.h
+ create mode 100644 include/linux/decompress/unlzma_mm.h
+
+--- a/fs/squashfs/Kconfig
++++ b/fs/squashfs/Kconfig
+@@ -30,6 +30,7 @@ config SQUASHFS_LZMA
+ bool "Include support for LZMA compressed file systems"
+ depends on SQUASHFS
+ select DECOMPRESS_LZMA
++ select DECOMPRESS_LZMA_NEEDED
+
+ config SQUASHFS_EMBEDDED
+
+--- /dev/null
++++ b/include/linux/decompress/bunzip2_mm.h
+@@ -0,0 +1,12 @@
++#ifndef BUNZIP2_MM_H
++#define BUNZIP2_MM_H
++
++#ifdef STATIC
++/* Code active when included from pre-boot environment: */
++#define INIT
++#else
++/* Compile for initramfs/initrd code only */
++#define INIT __init
++#endif
++
++#endif
+--- /dev/null
++++ b/include/linux/decompress/inflate_mm.h
+@@ -0,0 +1,12 @@
++#ifndef INFLATE_MM_H
++#define INFLATE_MM_H
++
++#ifdef STATIC
++/* Code active when included from pre-boot environment: */
++#define INIT
++#else
++/* Compile for initramfs/initrd code only */
++#define INIT __init
++#endif
++
++#endif
+--- a/include/linux/decompress/mm.h
++++ b/include/linux/decompress/mm.h
+@@ -53,8 +53,6 @@ static void free(void *where)
+
+ #define set_error_fn(x)
+
+-#define INIT
+-
+ #else /* STATIC */
+
+ /* Code active when compiled standalone for use when loading ramdisk: */
+@@ -77,7 +75,6 @@ static void free(void *where)
+ static void(*error)(char *m);
+ #define set_error_fn(x) error = x;
+
+-#define INIT __init
+ #define STATIC
+
+ #include <linux/init.h>
+--- /dev/null
++++ b/include/linux/decompress/unlzma_mm.h
+@@ -0,0 +1,20 @@
++#ifndef UNLZMA_MM_H
++#define UNLZMA_MM_H
++
++#ifdef STATIC
++
++/* Code active when included from pre-boot environment: */
++#define INIT
++
++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
++
++/* Make it available to non initramfs/initrd code */
++#define INIT
++#include <linux/module.h>
++#else
++
++/* Compile for initramfs/initrd code only */
++#define INIT __init
++#endif
++
++#endif
+--- a/lib/Kconfig
++++ b/lib/Kconfig
+@@ -117,6 +117,9 @@ config DECOMPRESS_BZIP2
+ config DECOMPRESS_LZMA
+ tristate
+
++config DECOMPRESS_LZMA_NEEDED
++ boolean
++
+ #
+ # Generic allocator support is selected if needed
+ #
+--- a/lib/decompress_bunzip2.c
++++ b/lib/decompress_bunzip2.c
+@@ -52,6 +52,7 @@
+ #include <linux/slab.h>
+ #endif /* STATIC */
+
++#include <linux/decompress/bunzip2_mm.h>
+ #include <linux/decompress/mm.h>
+
+ #ifndef INT_MAX
+--- a/lib/decompress_inflate.c
++++ b/lib/decompress_inflate.c
+@@ -23,6 +23,7 @@
+
+ #endif /* STATIC */
+
++#include <linux/decompress/inflate_mm.h>
+ #include <linux/decompress/mm.h>
+
+ #define GZIP_IOBUF_SIZE (16*1024)
+--- a/lib/decompress_unlzma.c
++++ b/lib/decompress_unlzma.c
+@@ -36,6 +36,7 @@
+ #include <linux/slab.h>
+ #endif /* STATIC */
+
++#include <linux/decompress/unlzma_mm.h>
+ #include <linux/decompress/mm.h>
+
+ #define MIN(a, b) (((a) < (b)) ? (a) : (b))
+@@ -523,7 +524,7 @@ static inline void INIT process_bit1(str
+
+
+
+-STATIC inline int INIT unlzma(unsigned char *buf, int in_len,
++STATIC int INIT unlzma(unsigned char *buf, int in_len,
+ int(*fill)(void*, unsigned int),
+ int(*flush)(void*, unsigned int),
+ unsigned char *output,
+@@ -656,4 +657,6 @@ STATIC int INIT decompress(unsigned char
+ {
+ return unlzma(buf, in_len - 4, fill, flush, output, posp, error_fn);
+ }
++#elif defined(CONFIG_DECOMPRESS_LZMA_NEEDED)
++EXPORT_SYMBOL(unlzma);
+ #endif
diff --git a/target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch b/target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch
deleted file mode 100644
index 086adf651..000000000
--- a/target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch
+++ /dev/null
@@ -1,234 +0,0 @@
---- a/fs/squashfs/Kconfig
-+++ b/fs/squashfs/Kconfig
-@@ -1,7 +1,8 @@
- config SQUASHFS
- tristate "SquashFS 4.0 - Squashed file system support"
- depends on BLOCK
-- select ZLIB_INFLATE
-+ select CRYPTO
-+ select CRYPTO_ZLIB
- help
- Saying Y here includes support for SquashFS 4.0 (a Compressed
- Read-Only File System). Squashfs is a highly compressed read-only
---- a/fs/squashfs/block.c
-+++ b/fs/squashfs/block.c
-@@ -32,7 +32,8 @@
- #include <linux/mutex.h>
- #include <linux/string.h>
- #include <linux/buffer_head.h>
--#include <linux/zlib.h>
-+
-+#include <crypto/compress.h>
-
- #include "squashfs_fs.h"
- #include "squashfs_fs_sb.h"
-@@ -153,7 +154,8 @@ int squashfs_read_data(struct super_bloc
- }
-
- if (compressed) {
-- int zlib_err = 0, zlib_init = 0;
-+ int res = 0, decomp_init = 0;
-+ struct comp_request req;
-
- /*
- * Uncompress block.
-@@ -161,12 +163,13 @@ int squashfs_read_data(struct super_bloc
-
- mutex_lock(&msblk->read_data_mutex);
-
-- msblk->stream.avail_out = 0;
-- msblk->stream.avail_in = 0;
-+ req.avail_out = 0;
-+ req.avail_in = 0;
-
- bytes = length;
-+ length = 0;
- do {
-- if (msblk->stream.avail_in == 0 && k < b) {
-+ if (req.avail_in == 0 && k < b) {
- avail = min(bytes, msblk->devblksize - offset);
- bytes -= avail;
- wait_on_buffer(bh[k]);
-@@ -179,45 +182,47 @@ int squashfs_read_data(struct super_bloc
- continue;
- }
-
-- msblk->stream.next_in = bh[k]->b_data + offset;
-- msblk->stream.avail_in = avail;
-+ req.next_in = bh[k]->b_data + offset;
-+ req.avail_in = avail;
- offset = 0;
- }
-
-- if (msblk->stream.avail_out == 0 && page < pages) {
-- msblk->stream.next_out = buffer[page++];
-- msblk->stream.avail_out = PAGE_CACHE_SIZE;
-+ if (req.avail_out == 0 && page < pages) {
-+ req.next_out = buffer[page++];
-+ req.avail_out = PAGE_CACHE_SIZE;
- }
-
-- if (!zlib_init) {
-- zlib_err = zlib_inflateInit(&msblk->stream);
-- if (zlib_err != Z_OK) {
-- ERROR("zlib_inflateInit returned"
-- " unexpected result 0x%x,"
-- " srclength %d\n", zlib_err,
-- srclength);
-+ if (!decomp_init) {
-+ res = crypto_decompress_init(msblk->tfm);
-+ if (res) {
-+ ERROR("crypto_decompress_init "
-+ "returned %d, srclength %d\n",
-+ res, srclength);
- goto release_mutex;
- }
-- zlib_init = 1;
-+ decomp_init = 1;
- }
-
-- zlib_err = zlib_inflate(&msblk->stream, Z_SYNC_FLUSH);
-+ res = crypto_decompress_update(msblk->tfm, &req);
-+ if (res < 0) {
-+ ERROR("crypto_decompress_update returned %d, "
-+ "data probably corrupt\n", res);
-+ goto release_mutex;
-+ }
-+ length += res;
-
-- if (msblk->stream.avail_in == 0 && k < b)
-+ if (req.avail_in == 0 && k < b)
- put_bh(bh[k++]);
-- } while (zlib_err == Z_OK);
-+ } while (bytes || res);
-
-- if (zlib_err != Z_STREAM_END) {
-- ERROR("zlib_inflate error, data probably corrupt\n");
-+ res = crypto_decompress_final(msblk->tfm, &req);
-+ if (res < 0) {
-+ ERROR("crypto_decompress_final returned %d, data "
-+ "probably corrupt\n", res);
- goto release_mutex;
- }
-+ length += res;
-
-- zlib_err = zlib_inflateEnd(&msblk->stream);
-- if (zlib_err != Z_OK) {
-- ERROR("zlib_inflate error, data probably corrupt\n");
-- goto release_mutex;
-- }
-- length = msblk->stream.total_out;
- mutex_unlock(&msblk->read_data_mutex);
- } else {
- /*
---- a/fs/squashfs/squashfs_fs_sb.h
-+++ b/fs/squashfs/squashfs_fs_sb.h
-@@ -64,7 +64,7 @@ struct squashfs_sb_info {
- struct mutex read_data_mutex;
- struct mutex meta_index_mutex;
- struct meta_index *meta_index;
-- z_stream stream;
-+ struct crypto_pcomp *tfm;
- __le64 *inode_lookup_table;
- u64 inode_table;
- u64 directory_table;
---- a/fs/squashfs/super.c
-+++ b/fs/squashfs/super.c
-@@ -38,11 +38,19 @@
- #include <linux/zlib.h>
- #include <linux/magic.h>
-
-+#include <crypto/compress.h>
-+
-+#include <net/netlink.h>
-+
- #include "squashfs_fs.h"
- #include "squashfs_fs_sb.h"
- #include "squashfs_fs_i.h"
- #include "squashfs.h"
-
-+
-+#define SQUASHFS_CRYPTO_ALG "zlib"
-+
-+
- static struct file_system_type squashfs_fs_type;
- static struct super_operations squashfs_super_ops;
-
-@@ -76,6 +84,16 @@ static int squashfs_fill_super(struct su
- unsigned short flags;
- unsigned int fragments;
- u64 lookup_table_start;
-+ struct {
-+ struct nlattr nla;
-+ int val;
-+ } params = {
-+ .nla = {
-+ .nla_len = nla_attr_size(sizeof(int)),
-+ .nla_type = ZLIB_DECOMP_WINDOWBITS,
-+ },
-+ .val = DEF_WBITS,
-+ };
- int err;
-
- TRACE("Entered squashfs_fill_superblock\n");
-@@ -87,16 +105,25 @@ static int squashfs_fill_super(struct su
- }
- msblk = sb->s_fs_info;
-
-- msblk->stream.workspace = kmalloc(zlib_inflate_workspacesize(),
-- GFP_KERNEL);
-- if (msblk->stream.workspace == NULL) {
-- ERROR("Failed to allocate zlib workspace\n");
-+ msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0,
-+ CRYPTO_ALG_ASYNC);
-+ if (IS_ERR(msblk->tfm)) {
-+ ERROR("Failed to load %s crypto module\n",
-+ SQUASHFS_CRYPTO_ALG);
-+ err = PTR_ERR(msblk->tfm);
-+ goto failed_pcomp;
-+ }
-+
-+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-+ if (err) {
-+ ERROR("Failed to set up decompression parameters\n");
- goto failure;
- }
-
- sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
- if (sblk == NULL) {
- ERROR("Failed to allocate squashfs_super_block\n");
-+ err = -ENOMEM;
- goto failure;
- }
-
-@@ -295,17 +322,18 @@ failed_mount:
- kfree(msblk->inode_lookup_table);
- kfree(msblk->fragment_index);
- kfree(msblk->id_table);
-- kfree(msblk->stream.workspace);
-+ crypto_free_pcomp(msblk->tfm);
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- kfree(sblk);
- return err;
-
- failure:
-- kfree(msblk->stream.workspace);
-+ crypto_free_pcomp(msblk->tfm);
-+failed_pcomp:
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
-- return -ENOMEM;
-+ return err;
- }
-
-
-@@ -349,7 +377,7 @@ static void squashfs_put_super(struct su
- kfree(sbi->id_table);
- kfree(sbi->fragment_index);
- kfree(sbi->meta_index);
-- kfree(sbi->stream.workspace);
-+ crypto_free_pcomp(sbi->tfm);
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- }
diff --git a/target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch b/target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch
deleted file mode 100644
index 48eb07de7..000000000
--- a/target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch
+++ /dev/null
@@ -1,901 +0,0 @@
---- /dev/null
-+++ b/crypto/unlzma.c
-@@ -0,0 +1,775 @@
-+/*
-+ * LZMA uncompresion module for pcomp
-+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-+ *
-+ * Based on:
-+ * Initial Linux kernel adaptation
-+ * Copyright (C) 2006 Alain < alain@knaff.lu >
-+ *
-+ * Based on small lzma deflate implementation/Small range coder
-+ * implementation for lzma.
-+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
-+ *
-+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
-+ * Copyright (C) 1999-2005 Igor Pavlov
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ *
-+ * FIXME: the current implementation assumes that the caller will
-+ * not free any output buffers until the whole decompression has been
-+ * completed. This is necessary, because LZMA looks back at old output
-+ * instead of doing a separate dictionary allocation, which saves RAM.
-+ */
-+
-+#include <linux/init.h>
-+#include <linux/module.h>
-+#include <linux/vmalloc.h>
-+#include <linux/interrupt.h>
-+#include <linux/mm.h>
-+#include <linux/net.h>
-+#include <linux/slab.h>
-+#include <linux/kthread.h>
-+
-+#include <crypto/internal/compress.h>
-+#include <net/netlink.h>
-+#include "unlzma.h"
-+
-+static int instance = 0;
-+
-+struct unlzma_buffer {
-+ int offset;
-+ int size;
-+ u8 *ptr;
-+};
-+
-+struct unlzma_ctx {
-+ struct task_struct *thread;
-+ wait_queue_head_t next_req;
-+ wait_queue_head_t req_done;
-+ struct mutex mutex;
-+ bool waiting;
-+ bool active;
-+ bool cancel;
-+
-+ const u8 *next_in;
-+ int avail_in;
-+
-+ u8 *next_out;
-+ int avail_out;
-+
-+ /* reader state */
-+ u32 code;
-+ u32 range;
-+ u32 bound;
-+
-+ /* writer state */
-+ u8 previous_byte;
-+ ssize_t pos;
-+ int buf_full;
-+ int n_buffers;
-+ int buffers_max;
-+ struct unlzma_buffer *buffers;
-+
-+ /* cstate */
-+ int state;
-+ u32 rep0, rep1, rep2, rep3;
-+
-+ u32 dict_size;
-+
-+ void *workspace;
-+ int workspace_size;
-+};
-+
-+static inline bool
-+unlzma_should_stop(struct unlzma_ctx *ctx)
-+{
-+ return unlikely(kthread_should_stop() || ctx->cancel);
-+}
-+
-+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)
-+{
-+ do {
-+ ctx->waiting = true;
-+ mutex_unlock(&ctx->mutex);
-+ wake_up(&ctx->req_done);
-+ 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
-+rc_read(struct unlzma_ctx *ctx)
-+{
-+ if (unlikely(ctx->avail_in <= 0))
-+ unlzma_request_buffer(ctx, &ctx->avail_in);
-+
-+ if (unlzma_should_stop(ctx))
-+ return 0;
-+
-+ ctx->avail_in--;
-+ return *(ctx->next_in++);
-+}
-+
-+
-+static inline void
-+rc_get_code(struct unlzma_ctx *ctx)
-+{
-+ ctx->code = (ctx->code << 8) | rc_read(ctx);
-+}
-+
-+static void
-+rc_normalize(struct unlzma_ctx *ctx)
-+{
-+ if (ctx->range < (1 << RC_TOP_BITS)) {
-+ ctx->range <<= 8;
-+ rc_get_code(ctx);
-+ }
-+}
-+
-+static int
-+rc_is_bit_0(struct unlzma_ctx *ctx, u16 *p)
-+{
-+ rc_normalize(ctx);
-+ ctx->bound = *p * (ctx->range >> RC_MODEL_TOTAL_BITS);
-+ return ctx->code < ctx->bound;
-+}
-+
-+static void
-+rc_update_bit_0(struct unlzma_ctx *ctx, u16 *p)
-+{
-+ ctx->range = ctx->bound;
-+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
-+}
-+
-+static void
-+rc_update_bit_1(struct unlzma_ctx *ctx, u16 *p)
-+{
-+ ctx->range -= ctx->bound;
-+ ctx->code -= ctx->bound;
-+ *p -= *p >> RC_MOVE_BITS;
-+}
-+
-+static bool
-+rc_get_bit(struct unlzma_ctx *ctx, u16 *p, int *symbol)
-+{
-+ if (rc_is_bit_0(ctx, p)) {
-+ rc_update_bit_0(ctx, p);
-+ *symbol *= 2;
-+ return 0;
-+ } else {
-+ rc_update_bit_1(ctx, p);
-+ *symbol = *symbol * 2 + 1;
-+ return 1;
-+ }
-+}
-+
-+static int
-+rc_direct_bit(struct unlzma_ctx *ctx)
-+{
-+ rc_normalize(ctx);
-+ ctx->range >>= 1;
-+ if (ctx->code >= ctx->range) {
-+ ctx->code -= ctx->range;
-+ return 1;
-+ }
-+ return 0;
-+}
-+
-+static void
-+rc_bit_tree_decode(struct unlzma_ctx *ctx, u16 *p, int num_levels, int *symbol)
-+{
-+ int i = num_levels;
-+
-+ *symbol = 1;
-+ while (i--)
-+ rc_get_bit(ctx, p + *symbol, symbol);
-+ *symbol -= 1 << num_levels;
-+}
-+
-+static u8
-+peek_old_byte(struct unlzma_ctx *ctx, u32 offs)
-+{
-+ struct unlzma_buffer *bh = &ctx->buffers[ctx->n_buffers - 1];
-+ int i = ctx->n_buffers;
-+ u32 pos;
-+
-+ if (!ctx->n_buffers) {
-+ printk(KERN_ERR "unlzma/%s: no buffer\n", __func__);
-+ goto error;
-+ }
-+
-+ pos = ctx->pos - offs;
-+ if (unlikely(pos >= ctx->dict_size))
-+ pos = ~pos & (ctx->dict_size - 1);
-+
-+ while (bh->offset > pos) {
-+ bh--;
-+ i--;
-+ if (!i) {
-+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos);
-+ goto error;
-+ }
-+ }
-+
-+ pos -= bh->offset;
-+ if (pos >= bh->size) {
-+ printk(KERN_ERR "unlzma/%s: position %d out of range\n", __func__, pos);
-+ goto error;
-+ }
-+
-+ return bh->ptr[pos];
-+
-+error:
-+ ctx->cancel = true;
-+ return 0;
-+}
-+
-+static void
-+write_byte(struct unlzma_ctx *ctx, u8 byte)
-+{
-+ if (unlikely(ctx->avail_out <= 0)) {
-+ unlzma_request_buffer(ctx, &ctx->avail_out);
-+ }
-+
-+ if (!ctx->avail_out)
-+ return;
-+
-+ ctx->previous_byte = byte;
-+ *(ctx->next_out++) = byte;
-+ ctx->avail_out--;
-+ if (ctx->avail_out == 0)
-+ ctx->buf_full = 1;
-+ ctx->pos++;
-+}
-+
-+
-+static inline void
-+copy_byte(struct unlzma_ctx *ctx, u32 offs)
-+{
-+ write_byte(ctx, peek_old_byte(ctx, offs));
-+}
-+
-+static void
-+copy_bytes(struct unlzma_ctx *ctx, u32 rep0, int len)
-+{
-+ do {
-+ copy_byte(ctx, rep0);
-+ len--;
-+ if (unlzma_should_stop(ctx))
-+ break;
-+ } while (len != 0);
-+}
-+
-+static void
-+process_bit0(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob,
-+ int lc, u32 literal_pos_mask)
-+{
-+ int mi = 1;
-+ rc_update_bit_0(ctx, prob);
-+ prob = (p + LZMA_LITERAL +
-+ (LZMA_LIT_SIZE
-+ * (((ctx->pos & literal_pos_mask) << lc)
-+ + (ctx->previous_byte >> (8 - lc))))
-+ );
-+
-+ if (ctx->state >= LZMA_NUM_LIT_STATES) {
-+ int match_byte = peek_old_byte(ctx, ctx->rep0);
-+ do {
-+ u16 bit;
-+ u16 *prob_lit;
-+
-+ match_byte <<= 1;
-+ bit = match_byte & 0x100;
-+ prob_lit = prob + 0x100 + bit + mi;
-+ if (rc_get_bit(ctx, prob_lit, &mi) != !!bit)
-+ break;
-+ } while (mi < 0x100);
-+ }
-+ while (mi < 0x100) {
-+ u16 *prob_lit = prob + mi;
-+ rc_get_bit(ctx, prob_lit, &mi);
-+ }
-+ write_byte(ctx, mi);
-+ if (ctx->state < 4)
-+ ctx->state = 0;
-+ else if (ctx->state < 10)
-+ ctx->state -= 3;
-+ else
-+ ctx->state -= 6;
-+}
-+
-+static void
-+process_bit1(struct unlzma_ctx *ctx, u16 *p, int pos_state, u16 *prob)
-+{
-+ int offset;
-+ u16 *prob_len;
-+ int num_bits;
-+ int len;
-+
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ ctx->rep3 = ctx->rep2;
-+ ctx->rep2 = ctx->rep1;
-+ ctx->rep1 = ctx->rep0;
-+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 0 : 3;
-+ prob = p + LZMA_LEN_CODER;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP_G0 + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ prob = (p + LZMA_IS_REP_0_LONG
-+ + (ctx->state <<
-+ LZMA_NUM_POS_BITS_MAX) +
-+ pos_state);
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+
-+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ?
-+ 9 : 11;
-+ copy_byte(ctx, ctx->rep0);
-+ return;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ }
-+ } else {
-+ u32 distance;
-+
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP_G1 + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ distance = ctx->rep1;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ prob = p + LZMA_IS_REP_G2 + ctx->state;
-+ if (rc_is_bit_0(ctx, prob)) {
-+ rc_update_bit_0(ctx, prob);
-+ distance = ctx->rep2;
-+ } else {
-+ rc_update_bit_1(ctx, prob);
-+ distance = ctx->rep3;
-+ ctx->rep3 = ctx->rep2;
-+ }
-+ ctx->rep2 = ctx->rep1;
-+ }
-+ ctx->rep1 = ctx->rep0;
-+ ctx->rep0 = distance;
-+ }
-+ ctx->state = ctx->state < LZMA_NUM_LIT_STATES ? 8 : 11;
-+ prob = p + LZMA_REP_LEN_CODER;
-+ }
-+
-+ prob_len = prob + LZMA_LEN_CHOICE;
-+ if (rc_is_bit_0(ctx, prob_len)) {
-+ rc_update_bit_0(ctx, prob_len);
-+ prob_len = (prob + LZMA_LEN_LOW
-+ + (pos_state <<
-+ LZMA_LEN_NUM_LOW_BITS));
-+ offset = 0;
-+ num_bits = LZMA_LEN_NUM_LOW_BITS;
-+ } else {
-+ rc_update_bit_1(ctx, prob_len);
-+ prob_len = prob + LZMA_LEN_CHOICE_2;
-+ if (rc_is_bit_0(ctx, prob_len)) {
-+ rc_update_bit_0(ctx, prob_len);
-+ prob_len = (prob + LZMA_LEN_MID
-+ + (pos_state <<
-+ LZMA_LEN_NUM_MID_BITS));
-+ offset = 1 << LZMA_LEN_NUM_LOW_BITS;
-+ num_bits = LZMA_LEN_NUM_MID_BITS;
-+ } else {
-+ rc_update_bit_1(ctx, prob_len);
-+ prob_len = prob + LZMA_LEN_HIGH;
-+ offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
-+ + (1 << LZMA_LEN_NUM_MID_BITS));
-+ num_bits = LZMA_LEN_NUM_HIGH_BITS;
-+ }
-+ }
-+
-+ rc_bit_tree_decode(ctx, prob_len, num_bits, &len);
-+ len += offset;
-+
-+ if (ctx->state < 4) {
-+ int pos_slot;
-+
-+ ctx->state += LZMA_NUM_LIT_STATES;
-+ prob =
-+ p + LZMA_POS_SLOT +
-+ ((len <
-+ LZMA_NUM_LEN_TO_POS_STATES ? len :
-+ LZMA_NUM_LEN_TO_POS_STATES - 1)
-+ << LZMA_NUM_POS_SLOT_BITS);
-+ rc_bit_tree_decode(ctx, prob,
-+ LZMA_NUM_POS_SLOT_BITS,
-+ &pos_slot);
-+ if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
-+ int i, mi;
-+ num_bits = (pos_slot >> 1) - 1;
-+ ctx->rep0 = 2 | (pos_slot & 1);
-+ if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
-+ ctx->rep0 <<= num_bits;
-+ prob = p + LZMA_SPEC_POS +
-+ ctx->rep0 - pos_slot - 1;
-+ } else {
-+ num_bits -= LZMA_NUM_ALIGN_BITS;
-+ while (num_bits--)
-+ ctx->rep0 = (ctx->rep0 << 1) |
-+ rc_direct_bit(ctx);
-+ prob = p + LZMA_ALIGN;
-+ ctx->rep0 <<= LZMA_NUM_ALIGN_BITS;
-+ num_bits = LZMA_NUM_ALIGN_BITS;
-+ }
-+ i = 1;
-+ mi = 1;
-+ while (num_bits--) {
-+ if (rc_get_bit(ctx, prob + mi, &mi))
-+ ctx->rep0 |= i;
-+ i <<= 1;
-+ }
-+ } else
-+ ctx->rep0 = pos_slot;
-+ if (++(ctx->rep0) == 0)
-+ return;
-+ }
-+
-+ len += LZMA_MATCH_MIN_LEN;
-+
-+ copy_bytes(ctx, ctx->rep0, len);
-+}
-+
-+
-+static int
-+do_unlzma(struct unlzma_ctx *ctx)
-+{
-+ u8 hdr_buf[sizeof(struct lzma_header)];
-+ struct lzma_header *header = (struct lzma_header *)hdr_buf;
-+ u32 pos_state_mask;
-+ u32 literal_pos_mask;
-+ int lc, pb, lp;
-+ int num_probs;
-+ int i, mi;
-+ u16 *p;
-+
-+ for (i = 0; i < sizeof(struct lzma_header); i++) {
-+ hdr_buf[i] = rc_read(ctx);
-+ }
-+
-+ ctx->n_buffers = 0;
-+ ctx->pos = 0;
-+ get_buffer(ctx);
-+ ctx->active = true;
-+ ctx->state = 0;
-+ ctx->rep0 = ctx->rep1 = ctx->rep2 = ctx->rep3 = 1;
-+
-+ ctx->previous_byte = 0;
-+ ctx->code = 0;
-+ ctx->range = 0xFFFFFFFF;
-+
-+ ctx->dict_size = le32_to_cpu(header->dict_size);
-+
-+ if (header->pos >= (9 * 5 * 5))
-+ return -1;
-+
-+ mi = 0;
-+ lc = header->pos;
-+ while (lc >= 9) {
-+ mi++;
-+ lc -= 9;
-+ }
-+ pb = 0;
-+ lp = mi;
-+ while (lp >= 5) {
-+ pb++;
-+ lp -= 5;
-+ }
-+ pos_state_mask = (1 << pb) - 1;
-+ literal_pos_mask = (1 << lp) - 1;
-+
-+ if (ctx->dict_size == 0)
-+ ctx->dict_size = 1;
-+
-+ num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
-+ if (ctx->workspace_size < num_probs * sizeof(*p)) {
-+ if (ctx->workspace)
-+ vfree(ctx->workspace);
-+ ctx->workspace_size = num_probs * sizeof(*p);
-+ ctx->workspace = vmalloc(ctx->workspace_size);
-+ }
-+ p = (u16 *) ctx->workspace;
-+ if (!p)
-+ return -1;
-+
-+ num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp));
-+ for (i = 0; i < num_probs; i++)
-+ p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
-+
-+ for (i = 0; i < 5; i++)
-+ rc_get_code(ctx);
-+
-+ while (1) {
-+ int pos_state = ctx->pos & pos_state_mask;
-+ u16 *prob = p + LZMA_IS_MATCH +
-+ (ctx->state << LZMA_NUM_POS_BITS_MAX) + pos_state;
-+ if (rc_is_bit_0(ctx, prob))
-+ process_bit0(ctx, p, pos_state, prob,
-+ lc, literal_pos_mask);
-+ else {
-+ process_bit1(ctx, p, pos_state, prob);
-+ if (ctx->rep0 == 0)
-+ break;
-+ }
-+ if (unlzma_should_stop(ctx))
-+ break;
-+ }
-+ if (likely(!unlzma_should_stop(ctx)))
-+ rc_normalize(ctx);
-+
-+ return ctx->pos;
-+}
-+
-+
-+static void
-+unlzma_reset_buf(struct unlzma_ctx *ctx)
-+{
-+ ctx->avail_in = 0;
-+ ctx->next_in = NULL;
-+ ctx->avail_out = 0;
-+ ctx->next_out = NULL;
-+}
-+
-+static int
-+unlzma_thread(void *data)
-+{
-+ struct unlzma_ctx *ctx = data;
-+
-+ mutex_lock(&ctx->mutex);
-+ do {
-+ if (do_unlzma(ctx) < 0)
-+ ctx->pos = 0;
-+ unlzma_reset_buf(ctx);
-+ ctx->cancel = false;
-+ ctx->active = false;
-+ } while (!kthread_should_stop());
-+ mutex_unlock(&ctx->mutex);
-+ return 0;
-+}
-+
-+
-+static int
-+unlzma_init(struct crypto_tfm *tfm)
-+{
-+ return 0;
-+}
-+
-+static void
-+unlzma_cancel(struct unlzma_ctx *ctx)
-+{
-+ unlzma_reset_buf(ctx);
-+
-+ if (!ctx->active)
-+ return;
-+
-+ ctx->cancel = true;
-+ do {
-+ mutex_unlock(&ctx->mutex);
-+ wake_up(&ctx->next_req);
-+ schedule();
-+ mutex_lock(&ctx->mutex);
-+ } while (ctx->cancel);
-+}
-+
-+
-+static void
-+unlzma_exit(struct crypto_tfm *tfm)
-+{
-+ struct unlzma_ctx *ctx = crypto_tfm_ctx(tfm);
-+
-+ if (ctx->thread) {
-+ unlzma_cancel(ctx);
-+ kthread_stop(ctx->thread);
-+ ctx->thread = NULL;
-+ if (ctx->buffers)
-+ kfree(ctx->buffers);
-+ ctx->buffers_max = 0;
-+ ctx->buffers = NULL;
-+ }
-+}
-+
-+static int
-+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 -EINVAL;
-+
-+ if (!p)
-+ return -EINVAL;
-+
-+ ret = nla_parse(tb, UNLZMA_DECOMP_MAX, p, len, NULL);
-+ if (ret)
-+ return ret;
-+
-+ 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;
-+
-+ ctx->waiting = false;
-+ mutex_init(&ctx->mutex);
-+ init_waitqueue_head(&ctx->next_req);
-+ init_waitqueue_head(&ctx->req_done);
-+ ctx->thread = kthread_run(unlzma_thread, ctx, "unlzma/%d", instance++);
-+ if (IS_ERR(ctx->thread)) {
-+ ret = PTR_ERR(ctx->thread);
-+ ctx->thread = NULL;
-+ }
-+
-+ return ret;
-+}
-+
-+static int
-+unlzma_decompress_init(struct crypto_pcomp *tfm)
-+{
-+ return 0;
-+}
-+
-+static void
-+unlzma_wait_complete(struct unlzma_ctx *ctx, bool finish)
-+{
-+ DEFINE_WAIT(__wait);
-+
-+ do {
-+ wake_up(&ctx->next_req);
-+ prepare_to_wait(&ctx->req_done, &__wait, TASK_INTERRUPTIBLE);
-+ mutex_unlock(&ctx->mutex);
-+ schedule();
-+ mutex_lock(&ctx->mutex);
-+ } while (!ctx->waiting && ctx->active);
-+ finish_wait(&ctx->req_done, &__wait);
-+}
-+
-+static int
-+unlzma_decompress_update(struct crypto_pcomp *tfm, struct comp_request *req)
-+{
-+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
-+ size_t pos = 0;
-+
-+ mutex_lock(&ctx->mutex);
-+ if (!ctx->active && !req->avail_in)
-+ goto out;
-+
-+ pos = ctx->pos;
-+ ctx->waiting = false;
-+ ctx->next_in = req->next_in;
-+ ctx->avail_in = req->avail_in;
-+ ctx->next_out = req->next_out;
-+ ctx->avail_out = req->avail_out;
-+
-+ unlzma_wait_complete(ctx, false);
-+
-+ req->next_in = ctx->next_in;
-+ 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:
-+ mutex_unlock(&ctx->mutex);
-+ if (ctx->cancel)
-+ return -EINVAL;
-+
-+ return pos;
-+}
-+
-+static int
-+unlzma_decompress_final(struct crypto_pcomp *tfm, struct comp_request *req)
-+{
-+ struct unlzma_ctx *ctx = crypto_tfm_ctx(crypto_pcomp_tfm(tfm));
-+ int ret = 0;
-+
-+ /* cancel pending operation */
-+ mutex_lock(&ctx->mutex);
-+ if (ctx->active) {
-+ // ret = -EINVAL;
-+ unlzma_cancel(ctx);
-+ }
-+ ctx->pos = 0;
-+ mutex_unlock(&ctx->mutex);
-+ return ret;
-+}
-+
-+
-+static struct pcomp_alg unlzma_alg = {
-+ .decompress_setup = unlzma_decompress_setup,
-+ .decompress_init = unlzma_decompress_init,
-+ .decompress_update = unlzma_decompress_update,
-+ .decompress_final = unlzma_decompress_final,
-+
-+ .base = {
-+ .cra_name = "lzma",
-+ .cra_flags = CRYPTO_ALG_TYPE_PCOMPRESS,
-+ .cra_ctxsize = sizeof(struct unlzma_ctx),
-+ .cra_module = THIS_MODULE,
-+ .cra_init = unlzma_init,
-+ .cra_exit = unlzma_exit,
-+ }
-+};
-+
-+static int __init
-+unlzma_mod_init(void)
-+{
-+ return crypto_register_pcomp(&unlzma_alg);
-+}
-+
-+static void __exit
-+unlzma_mod_exit(void)
-+{
-+ crypto_unregister_pcomp(&unlzma_alg);
-+}
-+
-+module_init(unlzma_mod_init);
-+module_exit(unlzma_mod_exit);
-+
-+MODULE_LICENSE("GPL");
-+MODULE_DESCRIPTION("LZMA Decompression Algorithm");
-+MODULE_AUTHOR("Felix Fietkau <nbd@openwrt.org>");
---- a/crypto/Kconfig
-+++ b/crypto/Kconfig
-@@ -768,6 +768,12 @@ config CRYPTO_ZLIB
- help
- This is the zlib algorithm.
-
-+config CRYPTO_UNLZMA
-+ tristate "LZMA decompression"
-+ select CRYPTO_PCOMP
-+ help
-+ This is the lzma decompression module.
-+
- config CRYPTO_LZO
- tristate "LZO compression algorithm"
- select CRYPTO_ALGAPI
---- a/crypto/Makefile
-+++ b/crypto/Makefile
-@@ -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
-+obj-$(CONFIG_CRYPTO_UNLZMA) += unlzma.o
- obj-$(CONFIG_CRYPTO_MICHAEL_MIC) += michael_mic.o
- obj-$(CONFIG_CRYPTO_CRC32C) += crc32c.o
- obj-$(CONFIG_CRYPTO_AUTHENC) += authenc.o
---- /dev/null
-+++ b/crypto/unlzma.h
-@@ -0,0 +1,80 @@
-+/* LZMA uncompresion module for pcomp
-+ * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org>
-+ *
-+ * Based on:
-+ * Initial Linux kernel adaptation
-+ * Copyright (C) 2006 Alain < alain@knaff.lu >
-+ *
-+ * Based on small lzma deflate implementation/Small range coder
-+ * implementation for lzma.
-+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
-+ *
-+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
-+ * Copyright (C) 1999-2005 Igor Pavlov
-+ *
-+ * This program is free software; you can redistribute it and/or modify it
-+ * under the terms of the GNU General Public License version 2 as published
-+ * by the Free Software Foundation.
-+ */
-+#ifndef __UNLZMA_H
-+#define __UNLZMA_H
-+
-+struct lzma_header {
-+ __u8 pos;
-+ __le32 dict_size;
-+} __attribute__ ((packed)) ;
-+
-+
-+#define RC_TOP_BITS 24
-+#define RC_MOVE_BITS 5
-+#define RC_MODEL_TOTAL_BITS 11
-+
-+#define LZMA_BASE_SIZE 1846
-+#define LZMA_LIT_SIZE 768
-+
-+#define LZMA_NUM_POS_BITS_MAX 4
-+
-+#define LZMA_LEN_NUM_LOW_BITS 3
-+#define LZMA_LEN_NUM_MID_BITS 3
-+#define LZMA_LEN_NUM_HIGH_BITS 8
-+
-+#define LZMA_LEN_CHOICE 0
-+#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1)
-+#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1)
-+#define LZMA_LEN_MID (LZMA_LEN_LOW \
-+ + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS)))
-+#define LZMA_LEN_HIGH (LZMA_LEN_MID \
-+ +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS)))
-+#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS))
-+
-+#define LZMA_NUM_STATES 12
-+#define LZMA_NUM_LIT_STATES 7
-+
-+#define LZMA_START_POS_MODEL_INDEX 4
-+#define LZMA_END_POS_MODEL_INDEX 14
-+#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1))
-+
-+#define LZMA_NUM_POS_SLOT_BITS 6
-+#define LZMA_NUM_LEN_TO_POS_STATES 4
-+
-+#define LZMA_NUM_ALIGN_BITS 4
-+
-+#define LZMA_MATCH_MIN_LEN 2
-+
-+#define LZMA_IS_MATCH 0
-+#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
-+#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES)
-+#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES)
-+#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES)
-+#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES)
-+#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \
-+ + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
-+#define LZMA_SPEC_POS (LZMA_POS_SLOT \
-+ +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS))
-+#define LZMA_ALIGN (LZMA_SPEC_POS \
-+ + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX)
-+#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS))
-+#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS)
-+#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;
diff --git a/target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch b/target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch
deleted file mode 100644
index 2725f0669..000000000
--- a/target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch
+++ /dev/null
@@ -1,244 +0,0 @@
---- a/fs/squashfs/Kconfig
-+++ b/fs/squashfs/Kconfig
-@@ -2,7 +2,6 @@ config SQUASHFS
- tristate "SquashFS 4.0 - Squashed file system support"
- depends on BLOCK
- select CRYPTO
-- select CRYPTO_ZLIB
- help
- Saying Y here includes support for SquashFS 4.0 (a Compressed
- Read-Only File System). Squashfs is a highly compressed read-only
-@@ -37,6 +36,26 @@ config SQUASHFS_EMBEDDED
-
- If unsure, say N.
-
-+config SQUASHFS_SUPPORT_ZLIB
-+ bool
-+ prompt "Support ZLIB compression" if SQUASHFS_SUPPORT_LZMA
-+ depends on SQUASHFS
-+ select CRYPTO_ZLIB
-+ default y
-+ help
-+ ZLIB is the default compression used in squashfs. If you are
-+ using LZMA compression instead, you can remove support for ZLIB
-+ entirely.
-+
-+config SQUASHFS_SUPPORT_LZMA
-+ bool "Support LZMA compression"
-+ depends on SQUASHFS
-+ select CRYPTO_UNLZMA
-+ help
-+ By default SquashFS uses ZLIB compression, however (if your tools
-+ support it, you can use LZMA instead, which saves space.
-+
-+
- config SQUASHFS_FRAGMENT_CACHE_SIZE
- int "Number of fragments cached" if SQUASHFS_EMBEDDED
- depends on SQUASHFS
---- a/fs/squashfs/squashfs_fs.h
-+++ b/fs/squashfs/squashfs_fs.h
-@@ -212,6 +212,7 @@ struct meta_index {
- * definitions for structures on disk
- */
- #define ZLIB_COMPRESSION 1
-+#define LZMA_COMPRESSION 2
-
- struct squashfs_super_block {
- __le32 s_magic;
---- a/fs/squashfs/super.c
-+++ b/fs/squashfs/super.c
-@@ -48,13 +48,76 @@
- #include "squashfs.h"
-
-
--#define SQUASHFS_CRYPTO_ALG "zlib"
-+static int squashfs_setup_zlib(struct squashfs_sb_info *msblk)
-+{
-+ int err = -EOPNOTSUPP;
-+
-+#ifdef CONFIG_SQUASHFS_SUPPORT_ZLIB
-+ struct {
-+ struct nlattr nla;
-+ int val;
-+ } params = {
-+ .nla = {
-+ .nla_len = nla_attr_size(sizeof(int)),
-+ .nla_type = ZLIB_DECOMP_WINDOWBITS,
-+ },
-+ .val = DEF_WBITS,
-+ };
-+
-+ msblk->tfm = crypto_alloc_pcomp("zlib", 0,
-+ CRYPTO_ALG_ASYNC);
-+ if (IS_ERR(msblk->tfm)) {
-+ ERROR("Failed to load zlib crypto module\n");
-+ return PTR_ERR(msblk->tfm);
-+ }
-+
-+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-+ if (err) {
-+ ERROR("Failed to set up decompression parameters\n");
-+ crypto_free_pcomp(msblk->tfm);
-+ }
-+#endif
-+
-+ return err;
-+}
-+
-+static int squashfs_setup_lzma(struct squashfs_sb_info *msblk)
-+{
-+ int err = -EOPNOTSUPP;
-+
-+#ifdef CONFIG_SQUASHFS_SUPPORT_LZMA
-+ struct {
-+ struct nlattr nla;
-+ int val;
-+ } params = {
-+ .nla = {
-+ .nla_len = nla_attr_size(sizeof(int)),
-+ .nla_type = UNLZMA_DECOMP_OUT_BUFFERS,
-+ },
-+ .val = (msblk->block_size / PAGE_CACHE_SIZE) + 1
-+ };
-
-+ msblk->tfm = crypto_alloc_pcomp("lzma", 0,
-+ CRYPTO_ALG_ASYNC);
-+ if (IS_ERR(msblk->tfm)) {
-+ ERROR("Failed to load lzma crypto module\n");
-+ return PTR_ERR(msblk->tfm);
-+ }
-+
-+ err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-+ if (err) {
-+ ERROR("Failed to set up decompression parameters\n");
-+ crypto_free_pcomp(msblk->tfm);
-+ }
-+#endif
-+
-+ return err;
-+}
-
- static struct file_system_type squashfs_fs_type;
- static struct super_operations squashfs_super_ops;
-
--static int supported_squashfs_filesystem(short major, short minor, short comp)
-+static int supported_squashfs_filesystem(short major, short minor)
- {
- if (major < SQUASHFS_MAJOR) {
- ERROR("Major/Minor mismatch, older Squashfs %d.%d "
-@@ -67,9 +130,6 @@ static int supported_squashfs_filesystem
- return -EINVAL;
- }
-
-- if (comp != ZLIB_COMPRESSION)
-- return -EINVAL;
--
- return 0;
- }
-
-@@ -84,16 +144,6 @@ static int squashfs_fill_super(struct su
- unsigned short flags;
- unsigned int fragments;
- u64 lookup_table_start;
-- struct {
-- struct nlattr nla;
-- int val;
-- } params = {
-- .nla = {
-- .nla_len = nla_attr_size(sizeof(int)),
-- .nla_type = ZLIB_DECOMP_WINDOWBITS,
-- },
-- .val = DEF_WBITS,
-- };
- int err;
-
- TRACE("Entered squashfs_fill_superblock\n");
-@@ -105,21 +155,6 @@ static int squashfs_fill_super(struct su
- }
- msblk = sb->s_fs_info;
-
-- msblk->tfm = crypto_alloc_pcomp(SQUASHFS_CRYPTO_ALG, 0,
-- CRYPTO_ALG_ASYNC);
-- if (IS_ERR(msblk->tfm)) {
-- ERROR("Failed to load %s crypto module\n",
-- SQUASHFS_CRYPTO_ALG);
-- err = PTR_ERR(msblk->tfm);
-- goto failed_pcomp;
-- }
--
-- err = crypto_decompress_setup(msblk->tfm, &params, sizeof(params));
-- if (err) {
-- ERROR("Failed to set up decompression parameters\n");
-- goto failure;
-- }
--
- sblk = kzalloc(sizeof(*sblk), GFP_KERNEL);
- if (sblk == NULL) {
- ERROR("Failed to allocate squashfs_super_block\n");
-@@ -157,10 +192,28 @@ static int squashfs_fill_super(struct su
- goto failed_mount;
- }
-
-+ /* Check block size for sanity */
-+ msblk->block_size = le32_to_cpu(sblk->block_size);
-+ if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
-+ goto failed_mount;
-+
- /* Check the MAJOR & MINOR versions and compression type */
- err = supported_squashfs_filesystem(le16_to_cpu(sblk->s_major),
-- le16_to_cpu(sblk->s_minor),
-- le16_to_cpu(sblk->compression));
-+ le16_to_cpu(sblk->s_minor));
-+ if (err < 0)
-+ goto failed_mount;
-+
-+ switch(le16_to_cpu(sblk->compression)) {
-+ case ZLIB_COMPRESSION:
-+ err = squashfs_setup_zlib(msblk);
-+ break;
-+ case LZMA_COMPRESSION:
-+ err = squashfs_setup_lzma(msblk);
-+ break;
-+ default:
-+ err = -EINVAL;
-+ break;
-+ }
- if (err < 0)
- goto failed_mount;
-
-@@ -180,11 +233,6 @@ static int squashfs_fill_super(struct su
- i_size_read(sb->s_bdev->bd_inode))
- goto failed_mount;
-
-- /* Check block size for sanity */
-- msblk->block_size = le32_to_cpu(sblk->block_size);
-- if (msblk->block_size > SQUASHFS_FILE_MAX_SIZE)
-- goto failed_mount;
--
- /*
- * Check the system page size is not larger than the filesystem
- * block size (by default 128K). This is currently not supported.
-@@ -316,21 +364,16 @@ allocate_root:
- return 0;
-
- failed_mount:
-+ if (msblk->tfm)
-+ crypto_free_pcomp(msblk->tfm);
- squashfs_cache_delete(msblk->block_cache);
- squashfs_cache_delete(msblk->fragment_cache);
- squashfs_cache_delete(msblk->read_page);
- kfree(msblk->inode_lookup_table);
- kfree(msblk->fragment_index);
- kfree(msblk->id_table);
-- crypto_free_pcomp(msblk->tfm);
-- kfree(sb->s_fs_info);
-- sb->s_fs_info = NULL;
- kfree(sblk);
-- return err;
--
- failure:
-- crypto_free_pcomp(msblk->tfm);
--failed_pcomp:
- kfree(sb->s_fs_info);
- sb->s_fs_info = NULL;
- return err;