Просмотр исходного кода

Switch to the squashfs-lzma code from the squashfs-devel git tree.

SVN-Revision: 18267
Imre Kaloz 16 лет назад
Родитель
Сommit
f4afe053da
24 измененных файлов с 3045 добавлено и 3040 удалено
  1. 2 1
      target/linux/generic-2.6/config-2.6.30
  2. 2 1
      target/linux/generic-2.6/config-2.6.31
  3. 113 0
      target/linux/generic-2.6/patches-2.6.30/000-bzip_lzma_remove_nasty_hack.patch
  4. 244 0
      target/linux/generic-2.6/patches-2.6.30/001-squashfs_move_zlib_decomp.patch
  5. 317 0
      target/linux/generic-2.6/patches-2.6.30/002-squashfs_factor_out_remaining_zlib.patch
  6. 426 0
      target/linux/generic-2.6/patches-2.6.30/003-squashfs_add_decompressor_framework.patch
  7. 54 0
      target/linux/generic-2.6/patches-2.6.30/004-squashfs_add_decompressor_lzma_lzo.patch
  8. 42 0
      target/linux/generic-2.6/patches-2.6.30/005-squashfs_extra_parameter.patch
  9. 216 0
      target/linux/generic-2.6/patches-2.6.30/006-squashfs_add_lzma.patch
  10. 165 0
      target/linux/generic-2.6/patches-2.6.30/007-squashfs_make_lzma_available.patch
  11. 0 280
      target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch
  12. 0 234
      target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch
  13. 0 901
      target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch
  14. 0 244
      target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch
  15. 244 0
      target/linux/generic-2.6/patches-2.6.31/001-squashfs_move_zlib_decomp.patch
  16. 317 0
      target/linux/generic-2.6/patches-2.6.31/002-squashfs_factor_out_remaining_zlib.patch
  17. 426 0
      target/linux/generic-2.6/patches-2.6.31/003-squashfs_add_decompressor_framework.patch
  18. 54 0
      target/linux/generic-2.6/patches-2.6.31/004-squashfs_add_decompressor_lzma_lzo.patch
  19. 42 0
      target/linux/generic-2.6/patches-2.6.31/005-squashfs_extra_parameter.patch
  20. 216 0
      target/linux/generic-2.6/patches-2.6.31/006-squashfs_add_lzma.patch
  21. 165 0
      target/linux/generic-2.6/patches-2.6.31/007-squashfs_make_lzma_available.patch
  22. 0 234
      target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch
  23. 0 901
      target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch
  24. 0 244
      target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch

+ 2 - 1
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

+ 2 - 1
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

+ 113 - 0
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 <[email protected]>
+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 <[email protected]>
+Cc: "H. Peter Anvin" <[email protected]>
+Signed-off-by: Andrew Morton <[email protected]>
+Signed-off-by: Linus Torvalds <[email protected]>
+---
+ 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

+ 244 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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 <[email protected]>
++ *
++ * 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;
++}

+ 317 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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);

+ 426 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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 <[email protected]>
++ *
++ * 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 <[email protected]>
++ *
++ * 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
++};
++

+ 54 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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;

+ 42 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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)

+ 216 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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 <[email protected]>
++ *
++ * 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;

+ 165 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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

+ 0 - 280
target/linux/generic-2.6/patches-2.6.30/050-pcomp_update.patch

@@ -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;
- }
- 
- 

+ 0 - 234
target/linux/generic-2.6/patches-2.6.30/051-squashfs_pcomp.patch

@@ -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;
- 	}

+ 0 - 901
target/linux/generic-2.6/patches-2.6.30/052-pcomp_lzma_support.patch

@@ -1,901 +0,0 @@
---- /dev/null
-+++ b/crypto/unlzma.c
-@@ -0,0 +1,775 @@
-+/*
-+ * LZMA uncompresion module for pcomp
-+ * Copyright (C) 2009  Felix Fietkau <[email protected]>
-+ *
-+ * Based on:
-+ *  Initial Linux kernel adaptation
-+ *  Copyright (C) 2006  Alain < [email protected] >
-+ *
-+ *  Based on small lzma deflate implementation/Small range coder
-+ *  implementation for lzma.
-+ *  Copyright (C) 2006  Aurelien Jacobs < [email protected] >
-+ *
-+ *  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 <[email protected]>");
---- 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 <[email protected]>
-+ *
-+ * Based on:
-+ *  Initial Linux kernel adaptation
-+ *  Copyright (C) 2006  Alain < [email protected] >
-+ *
-+ *  Based on small lzma deflate implementation/Small range coder
-+ *  implementation for lzma.
-+ *  Copyright (C) 2006  Aurelien Jacobs < [email protected] >
-+ *
-+ *  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;

+ 0 - 244
target/linux/generic-2.6/patches-2.6.30/053-squashfs_lzma.patch

@@ -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;

+ 244 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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 <[email protected]>
++ *
++ * 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;
++}

+ 317 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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);

+ 426 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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 <[email protected]>
++ *
++ * 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 <[email protected]>
++ *
++ * 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
++};
++

+ 54 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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;

+ 42 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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)

+ 216 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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 <[email protected]>
++ *
++ * 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;

+ 165 - 0
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 <[email protected]>
+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 <[email protected]>
+---
+ 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

+ 0 - 234
target/linux/generic-2.6/patches-2.6.31/051-squashfs_pcomp.patch

@@ -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;
- 	}

+ 0 - 901
target/linux/generic-2.6/patches-2.6.31/052-pcomp_lzma_support.patch

@@ -1,901 +0,0 @@
---- /dev/null
-+++ b/crypto/unlzma.c
-@@ -0,0 +1,775 @@
-+/*
-+ * LZMA uncompresion module for pcomp
-+ * Copyright (C) 2009  Felix Fietkau <[email protected]>
-+ *
-+ * Based on:
-+ *  Initial Linux kernel adaptation
-+ *  Copyright (C) 2006  Alain < [email protected] >
-+ *
-+ *  Based on small lzma deflate implementation/Small range coder
-+ *  implementation for lzma.
-+ *  Copyright (C) 2006  Aurelien Jacobs < [email protected] >
-+ *
-+ *  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 <[email protected]>");
---- 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 <[email protected]>
-+ *
-+ * Based on:
-+ *  Initial Linux kernel adaptation
-+ *  Copyright (C) 2006  Alain < [email protected] >
-+ *
-+ *  Based on small lzma deflate implementation/Small range coder
-+ *  implementation for lzma.
-+ *  Copyright (C) 2006  Aurelien Jacobs < [email protected] >
-+ *
-+ *  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;

+ 0 - 244
target/linux/generic-2.6/patches-2.6.31/053-squashfs_lzma.patch

@@ -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;