From: Imre Kaloz Date: Tue, 17 Nov 2009 10:04:41 +0000 (+0000) Subject: replace our arm LZMA loader with the one that goes upstream X-Git-Tag: reboot~21868 X-Git-Url: https://git.librecmc.org/?a=commitdiff_plain;h=294551ca73acd677fba4a4fdddd35d6567874dd4;p=oweals%2Fopenwrt.git replace our arm LZMA loader with the one that goes upstream SVN-Revision: 18439 --- diff --git a/target/linux/generic-2.6/config-2.6.31 b/target/linux/generic-2.6/config-2.6.31 index 86647470a6..2fec409665 100644 --- a/target/linux/generic-2.6/config-2.6.31 +++ b/target/linux/generic-2.6/config-2.6.31 @@ -1026,6 +1026,9 @@ CONFIG_JOLIET=y # CONFIG_KALLSYMS is not set # CONFIG_KARMA_PARTITION is not set # CONFIG_KEXEC is not set +# CONFIG_KERNEL_GZIP is not set +CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZO is not set # CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYS is not set # CONFIG_KMEMTRACE is not set @@ -1673,6 +1676,7 @@ CONFIG_RAMFS=y # CONFIG_RDC_17F3101X is not set # CONFIG_RD_GZIP is not set CONFIG_RD_LZMA=y +# CONFIG_RD_LZO is not set # CONFIG_REALTEK_PHY is not set # CONFIG_REDWOOD is not set # CONFIG_REGULATOR_BQ24022 is not set diff --git a/target/linux/generic-2.6/config-2.6.32 b/target/linux/generic-2.6/config-2.6.32 index 2da564028a..b99d864970 100644 --- a/target/linux/generic-2.6/config-2.6.32 +++ b/target/linux/generic-2.6/config-2.6.32 @@ -1036,6 +1036,9 @@ CONFIG_JOLIET=y # CONFIG_KALLSYMS is not set # CONFIG_KARMA_PARTITION is not set # CONFIG_KEXEC is not set +# CONFIG_KERNEL_GZIP is not set +CONFIG_KERNEL_LZMA=y +# CONFIG_KERNEL_LZO is not set # CONFIG_KEYBOARD_LM8323 is not set # CONFIG_KEYS is not set # CONFIG_KMEMTRACE is not set @@ -1688,6 +1691,7 @@ CONFIG_RCU_FANOUT=32 # CONFIG_RDC_17F3101X is not set # CONFIG_RD_GZIP is not set CONFIG_RD_LZMA=y +# CONFIG_RD_LZO is not set # CONFIG_RDS is not set # CONFIG_REALTEK_PHY is not set # CONFIG_REDWOOD is not set diff --git a/target/linux/generic-2.6/patches-2.6.31/049-byteshift_h_fix_usage_for_compressed_kernels.patch b/target/linux/generic-2.6/patches-2.6.31/049-byteshift_h_fix_usage_for_compressed_kernels.patch new file mode 100644 index 0000000000..102a829828 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/049-byteshift_h_fix_usage_for_compressed_kernels.patch @@ -0,0 +1,79 @@ +From 2fa4341074cd02fb39aa23410740764948755635 Mon Sep 17 00:00:00 2001 +From: Albin Tonnerre +Date: Wed, 23 Sep 2009 15:57:38 -0700 +Subject: [PATCH] include/linux/unaligned/{l,b}e_byteshift.h: fix usage for compressed kernels + +When unaligned accesses are required for uncompressing a kernel (such as +for LZO decompression on ARM in a patch that follows), including + causes issues as it brings in a lot of things that are +not available in the decompression environment. + +linux/kernel.h brings at least: +extern int console_printk[]; +extern const char hex_asc[]; +which causes errors at link-time as they are not available when +compiling the pre-boot environement. There are also a few others: + + arch/arm/boot/compressed/misc.o: In function `valid_user_regs': + arch/arm/include/asm/ptrace.h:158: undefined reference to `elf_hwcap' + arch/arm/boot/compressed/misc.o: In function `console_silent': + include/linux/kernel.h:292: undefined reference to `console_printk' + arch/arm/boot/compressed/misc.o: In function `console_verbose': + include/linux/kernel.h:297: undefined reference to `console_printk' + arch/arm/boot/compressed/misc.o: In function `pack_hex_byte': + include/linux/kernel.h:360: undefined reference to `hex_asc' + arch/arm/boot/compressed/misc.o: In function `hweight_long': + include/linux/bitops.h:45: undefined reference to `hweight32' + arch/arm/boot/compressed/misc.o: In function `__cmpxchg_local_generic': + include/asm-generic/cmpxchg-local.h:21: undefined reference to `wrong_size_cmpxchg' + include/asm-generic/cmpxchg-local.h:42: undefined reference to `wrong_size_cmpxchg' + arch/arm/boot/compressed/misc.o: In function `__xchg': + arch/arm/include/asm/system.h:309: undefined reference to `__bad_xchg' + +However, those files apparently use nothing from , all +they need is the declaration of types such as u32 or u64, so + should be enough + +Signed-off-by: Albin Tonnerre +Cc: Sam Ravnborg +Cc: Russell King +Cc: Ingo Molnar +Cc: Thomas Gleixner +Cc: "H. Peter Anvin" +Cc: Phillip Lougher +Signed-off-by: Andrew Morton +Signed-off-by: Linus Torvalds +--- + include/linux/unaligned/be_byteshift.h | 2 +- + include/linux/unaligned/le_byteshift.h | 2 +- + 2 files changed, 2 insertions(+), 2 deletions(-) + +diff --git a/include/linux/unaligned/be_byteshift.h b/include/linux/unaligned/be_byteshift.h +index 46dd12c..9356b24 100644 +--- a/include/linux/unaligned/be_byteshift.h ++++ b/include/linux/unaligned/be_byteshift.h +@@ -1,7 +1,7 @@ + #ifndef _LINUX_UNALIGNED_BE_BYTESHIFT_H + #define _LINUX_UNALIGNED_BE_BYTESHIFT_H + +-#include ++#include + + static inline u16 __get_unaligned_be16(const u8 *p) + { +diff --git a/include/linux/unaligned/le_byteshift.h b/include/linux/unaligned/le_byteshift.h +index 59777e9..be376fb 100644 +--- a/include/linux/unaligned/le_byteshift.h ++++ b/include/linux/unaligned/le_byteshift.h +@@ -1,7 +1,7 @@ + #ifndef _LINUX_UNALIGNED_LE_BYTESHIFT_H + #define _LINUX_UNALIGNED_LE_BYTESHIFT_H + +-#include ++#include + + static inline u16 __get_unaligned_le16(const u8 *p) + { +-- +1.6.5.1 + diff --git a/target/linux/generic-2.6/patches-2.6.31/050-lzo_compressed_kernels.patch b/target/linux/generic-2.6/patches-2.6.31/050-lzo_compressed_kernels.patch new file mode 100644 index 0000000000..fad1b87466 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/050-lzo_compressed_kernels.patch @@ -0,0 +1,321 @@ +diff --git a/include/linux/decompress/unlzo.h b/include/linux/decompress/unlzo.h +new file mode 100644 +index 0000000..9872297 +--- /dev/null ++++ b/include/linux/decompress/unlzo.h +@@ -0,0 +1,10 @@ ++#ifndef DECOMPRESS_UNLZO_H ++#define DECOMPRESS_UNLZO_H ++ ++int unlzo(unsigned char *inbuf, int len, ++ int(*fill)(void*, unsigned int), ++ int(*flush)(void*, unsigned int), ++ unsigned char *output, ++ int *pos, ++ void(*error)(char *x)); ++#endif +diff --git a/init/Kconfig b/init/Kconfig +index f515864..eb65318 100644 +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -115,10 +115,13 @@ config HAVE_KERNEL_BZIP2 + config HAVE_KERNEL_LZMA + bool + ++config HAVE_KERNEL_LZO ++ bool ++ + choice + prompt "Kernel compression mode" + default KERNEL_GZIP +- depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA ++ depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_LZO + help + The linux kernel is a kind of self-extracting executable. + Several compression algorithms are available, which differ +@@ -141,9 +144,8 @@ config KERNEL_GZIP + bool "Gzip" + depends on HAVE_KERNEL_GZIP + help +- The old and tried gzip compression. Its compression ratio is +- the poorest among the 3 choices; however its speed (both +- compression and decompression) is the fastest. ++ The old and tried gzip compression. It provides a good balance ++ between compression ratio and decompression speed. + + config KERNEL_BZIP2 + bool "Bzip2" +@@ -164,6 +166,14 @@ config KERNEL_LZMA + two. Compression is slowest. The kernel size is about 33% + smaller with LZMA in comparison to gzip. + ++config KERNEL_LZO ++ bool "LZO" ++ depends on HAVE_KERNEL_LZO ++ help ++ Its compression ratio is the poorest among the 4. The kernel ++ size is about about 10% bigger than gzip; however its speed ++ (both compression and decompression) is the fastest. ++ + endchoice + + config SWAP +diff --git a/lib/decompress_unlzo.c b/lib/decompress_unlzo.c +new file mode 100644 +index 0000000..2bb736f +--- /dev/null ++++ b/lib/decompress_unlzo.c +@@ -0,0 +1,208 @@ ++/* ++ * LZO decompressor for the Linux kernel. Code borrowed from the lzo ++ * implementation by Markus Franz Xaver Johannes Oberhumer. ++ * ++ * Linux kernel adaptation: ++ * Copyright (C) 2009 ++ * Albin Tonnerre, Free Electrons ++ * ++ * Original code: ++ * Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer ++ * All Rights Reserved. ++ * ++ * lzop and the LZO library are free software; you can redistribute them ++ * and/or modify them under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, 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; see the file COPYING. ++ * If not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Markus F.X.J. Oberhumer ++ * ++ * http://www.oberhumer.com/opensource/lzop/ ++ */ ++ ++#ifdef STATIC ++#include "lzo/lzo1x_decompress.c" ++#else ++#include ++#include ++#endif ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const unsigned char lzop_magic[] = ++ { 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a }; ++ ++#define LZO_BLOCK_SIZE (256*1024l) ++#define HEADER_HAS_FILTER 0x00000800L ++ ++STATIC inline int INIT parse_header(u8 *input, u8 *skip) ++{ ++ int l; ++ u8 *parse = input; ++ u8 level = 0; ++ u16 version; ++ ++ /* read magic: 9 first bits */ ++ for (l = 0; l < 9; l++) { ++ if (*parse++ != lzop_magic[l]) ++ return 0; ++ } ++ /* get version (2bytes), skip library version (2), ++ * 'need to be extracted' version (2) and ++ * method (1) */ ++ version = get_unaligned_be16(parse); ++ parse += 7; ++ if (version >= 0x0940) ++ level = *parse++; ++ if (get_unaligned_be32(parse) & HEADER_HAS_FILTER) ++ parse += 8; /* flags + filter info */ ++ else ++ parse += 4; /* flags */ ++ ++ /* skip mode and mtime_low */ ++ parse += 8; ++ if (version >= 0x0940) ++ parse += 4; /* skip mtime_high */ ++ ++ l = *parse++; ++ /* don't care about the file name, and skip checksum */ ++ parse += l + 4; ++ ++ *skip = parse - input; ++ return 1; ++} ++ ++STATIC inline int INIT unlzo(u8 *input, int in_len, ++ int (*fill) (void *, unsigned int), ++ int (*flush) (void *, unsigned int), ++ u8 *output, int *posp, ++ void (*error_fn) (char *x)) ++{ ++ u8 skip = 0, r = 0; ++ u32 src_len, dst_len; ++ size_t tmp; ++ u8 *in_buf, *in_buf_save, *out_buf; ++ int obytes_processed = 0; ++ ++ set_error_fn(error_fn); ++ ++ if (output) ++ out_buf = output; ++ else if (!flush) { ++ error("NULL output pointer and no flush function provided"); ++ goto exit; ++ } else { ++ out_buf = malloc(LZO_BLOCK_SIZE); ++ if (!out_buf) { ++ error("Could not allocate output buffer"); ++ goto exit; ++ } ++ } ++ ++ if (input && fill) { ++ error("Both input pointer and fill function provided, don't know what to do"); ++ goto exit_1; ++ } else if (input) ++ in_buf = input; ++ else if (!fill || !posp) { ++ error("NULL input pointer and missing position pointer or fill function"); ++ goto exit_1; ++ } else { ++ in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE)); ++ if (!in_buf) { ++ error("Could not allocate input buffer"); ++ goto exit_1; ++ } ++ } ++ in_buf_save = in_buf; ++ ++ if (posp) ++ *posp = 0; ++ ++ if (fill) ++ fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE)); ++ ++ if (!parse_header(input, &skip)) { ++ error("invalid header"); ++ goto exit_2; ++ } ++ in_buf += skip; ++ ++ if (posp) ++ *posp = skip; ++ ++ for (;;) { ++ /* read uncompressed block size */ ++ dst_len = get_unaligned_be32(in_buf); ++ in_buf += 4; ++ ++ /* exit if last block */ ++ if (dst_len == 0) { ++ if (posp) ++ *posp += 4; ++ break; ++ } ++ ++ if (dst_len > LZO_BLOCK_SIZE) { ++ error("dest len longer than block size"); ++ goto exit_2; ++ } ++ ++ /* read compressed block size, and skip block checksum info */ ++ src_len = get_unaligned_be32(in_buf); ++ in_buf += 8; ++ ++ if (src_len <= 0 || src_len > dst_len) { ++ error("file corrupted"); ++ goto exit_2; ++ } ++ ++ /* decompress */ ++ tmp = dst_len; ++ r = lzo1x_decompress_safe((u8 *) in_buf, src_len, out_buf, &tmp); ++ ++ if (r != LZO_E_OK || dst_len != tmp) { ++ error("Compressed data violation"); ++ goto exit_2; ++ } ++ ++ obytes_processed += dst_len; ++ if (flush) ++ flush(out_buf, dst_len); ++ if (output) ++ out_buf += dst_len; ++ if (posp) ++ *posp += src_len + 12; ++ if (fill) { ++ in_buf = in_buf_save; ++ fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE)); ++ } else ++ in_buf += src_len; ++ } ++ ++exit_2: ++ if (!input) ++ free(in_buf); ++exit_1: ++ if (!output) ++ free(out_buf); ++exit: ++ return obytes_processed; ++} ++ ++#define decompress unlzo +diff --git a/lib/lzo/lzo1x_decompress.c b/lib/lzo/lzo1x_decompress.c +index 5dc6b29..f2fd098 100644 +--- a/lib/lzo/lzo1x_decompress.c ++++ b/lib/lzo/lzo1x_decompress.c +@@ -11,11 +11,13 @@ + * Richard Purdie + */ + ++#ifndef STATIC + #include + #include +-#include +-#include ++#endif ++ + #include ++#include + #include "lzodefs.h" + + #define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x)) +@@ -244,9 +246,10 @@ lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; + } +- ++#ifndef STATIC + EXPORT_SYMBOL_GPL(lzo1x_decompress_safe); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZO1X Decompressor"); + ++#endif +diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib +index ffdafb2..39c3483 100644 +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -230,3 +230,8 @@ quiet_cmd_lzma = LZMA $@ + cmd_lzma = (cat $(filter-out FORCE,$^) | \ + lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) ++ ++quiet_cmd_lzo = LZO $@ ++cmd_lzo = (cat $(filter-out FORCE,$^) | \ ++ lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ ++ (rm -f $@ ; false) diff --git a/target/linux/generic-2.6/patches-2.6.31/051-lzo_compressed_kernel_for_arm.patch b/target/linux/generic-2.6/patches-2.6.31/051-lzo_compressed_kernel_for_arm.patch new file mode 100644 index 0000000000..f155c0a1b5 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/051-lzo_compressed_kernel_for_arm.patch @@ -0,0 +1,298 @@ +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index 1c4119c..350921d 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -18,6 +18,8 @@ config ARM + select HAVE_KRETPROBES if (HAVE_KPROBES) + select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) + select HAVE_GENERIC_DMA_COHERENT ++ select HAVE_KERNEL_GZIP ++ select HAVE_KERNEL_LZO + help + The ARM series is a line of low-power-consumption RISC chip designs + licensed by ARM Ltd and targeted at embedded applications and +diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile +index ce39dc5..5b4629b 100644 +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -63,8 +63,12 @@ endif + + SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ + +-targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ +- head.o misc.o $(OBJS) ++suffix_$(CONFIG_KERNEL_GZIP) = gzip ++suffix_$(CONFIG_KERNEL_LZO) = lzo ++ ++targets := vmlinux vmlinux.lds \ ++ piggy.$(suffix_y) piggy.$(suffix_y).o \ ++ font.o font.c head.o misc.o $(OBJS) + + ifeq ($(CONFIG_FUNCTION_TRACER),y) + ORIG_CFLAGS := $(KBUILD_CFLAGS) +@@ -87,22 +91,31 @@ endif + ifneq ($(PARAMS_PHYS),) + LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS) + endif +-LDFLAGS_vmlinux += -p --no-undefined -X \ +- $(shell $(CC) $(KBUILD_CFLAGS) --print-libgcc-file-name) -T ++# ? ++LDFLAGS_vmlinux += -p ++# Report unresolved symbol references ++LDFLAGS_vmlinux += --no-undefined ++# Delete all temporary local symbols ++LDFLAGS_vmlinux += -X ++# Next argument is a linker script ++LDFLAGS_vmlinux += -T ++ ++# For __aeabi_uidivmod ++lib1funcs = $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.o + + # Don't allow any static data in misc.o, which + # would otherwise mess up our GOT table + CFLAGS_misc.o := -Dstatic= + +-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \ +- $(addprefix $(obj)/, $(OBJS)) FORCE ++$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ ++ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE + $(call if_changed,ld) + @: + +-$(obj)/piggy.gz: $(obj)/../Image FORCE +- $(call if_changed,gzip) ++$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE ++ $(call if_changed,$(suffix_y)) + +-$(obj)/piggy.o: $(obj)/piggy.gz FORCE ++$(obj)/piggy.$(suffix_y).o: $(obj)/piggy.$(suffix_y) FORCE + + CFLAGS_font.o := -Dstatic= + +diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c +index 17153b5..7e0fe4d 100644 +--- a/arch/arm/boot/compressed/misc.c ++++ b/arch/arm/boot/compressed/misc.c +@@ -18,10 +18,15 @@ + + unsigned int __machine_arch_type; + ++#define _LINUX_STRING_H_ ++ + #include /* for inline */ + #include /* for size_t */ + #include /* for NULL */ + #include ++#include ++ ++#include + + #ifdef STANDALONE_DEBUG + #define putstr printf +@@ -188,34 +193,8 @@ static inline __ptr_t memcpy(__ptr_t __dest, __const __ptr_t __src, + /* + * gzip delarations + */ +-#define OF(args) args + #define STATIC static + +-typedef unsigned char uch; +-typedef unsigned short ush; +-typedef unsigned long ulg; +- +-#define WSIZE 0x8000 /* Window size must be at least 32k, */ +- /* and a power of two */ +- +-static uch *inbuf; /* input buffer */ +-static uch window[WSIZE]; /* Sliding window buffer */ +- +-static unsigned insize; /* valid bytes in inbuf */ +-static unsigned inptr; /* index of next byte to be processed in inbuf */ +-static unsigned outcnt; /* bytes in output buffer */ +- +-/* gzip flag byte */ +-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +-#define COMMENT 0x10 /* bit 4 set: file comment present */ +-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +-#define RESERVED 0xC0 /* bit 6,7: reserved */ +- +-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) +- + /* Diagnostic functions */ + #ifdef DEBUG + # define Assert(cond,msg) {if(!(cond)) error(msg);} +@@ -233,24 +212,20 @@ static unsigned outcnt; /* bytes in output buffer */ + # define Tracecv(c,x) + #endif + +-static int fill_inbuf(void); +-static void flush_window(void); + static void error(char *m); + + extern char input_data[]; + extern char input_data_end[]; + +-static uch *output_data; +-static ulg output_ptr; +-static ulg bytes_out; ++static unsigned char *output_data; ++static unsigned long output_ptr; + + static void error(char *m); + + static void putstr(const char *); + +-extern int end; +-static ulg free_mem_ptr; +-static ulg free_mem_end_ptr; ++static unsigned long free_mem_ptr; ++static unsigned long free_mem_end_ptr; + + #ifdef STANDALONE_DEBUG + #define NO_INFLATE_MALLOC +@@ -258,46 +233,13 @@ static ulg free_mem_end_ptr; + + #define ARCH_HAS_DECOMP_WDOG + +-#include "../../../../lib/inflate.c" +- +-/* =========================================================================== +- * Fill the input buffer. This is called only when the buffer is empty +- * and at least one byte is really needed. +- */ +-int fill_inbuf(void) +-{ +- if (insize != 0) +- error("ran out of input data"); +- +- inbuf = input_data; +- insize = &input_data_end[0] - &input_data[0]; +- +- inptr = 1; +- return inbuf[0]; +-} ++#ifdef CONFIG_KERNEL_GZIP ++#include "../../../../lib/decompress_inflate.c" ++#endif + +-/* =========================================================================== +- * Write the output window window[0..outcnt-1] and update crc and bytes_out. +- * (Used for the decompressed data only.) +- */ +-void flush_window(void) +-{ +- ulg c = crc; +- unsigned n; +- uch *in, *out, ch; +- +- in = window; +- out = &output_data[output_ptr]; +- for (n = 0; n < outcnt; n++) { +- ch = *out++ = *in++; +- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); +- } +- crc = c; +- bytes_out += (ulg)outcnt; +- output_ptr += (ulg)outcnt; +- outcnt = 0; +- putstr("."); +-} ++#ifdef CONFIG_KERNEL_LZO ++#include "../../../../lib/decompress_unlzo.c" ++#endif + + #ifndef arch_error + #define arch_error(x) +@@ -314,22 +256,33 @@ static void error(char *x) + while(1); /* Halt */ + } + ++asmlinkage void __div0(void) ++{ ++ error("Attempting division by 0!"); ++} ++ + #ifndef STANDALONE_DEBUG + +-ulg +-decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, +- int arch_id) ++unsigned long ++decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, ++ unsigned long free_mem_ptr_end_p, ++ int arch_id) + { +- output_data = (uch *)output_start; /* Points to kernel start */ ++ unsigned char *tmp; ++ ++ output_data = (unsigned char *)output_start; + free_mem_ptr = free_mem_ptr_p; + free_mem_end_ptr = free_mem_ptr_end_p; + __machine_arch_type = arch_id; + + arch_decomp_setup(); + +- makecrc(); ++ tmp = (unsigned char *) (((unsigned long)input_data_end) - 4); ++ output_ptr = get_unaligned_le32(tmp); ++ + putstr("Uncompressing Linux..."); +- gunzip(); ++ decompress(input_data, input_data_end - input_data, ++ NULL, NULL, output_data, NULL, error); + putstr(" done, booting the kernel.\n"); + return output_ptr; + } +@@ -341,11 +294,10 @@ int main() + { + output_data = output_buffer; + +- makecrc(); + putstr("Uncompressing Linux..."); +- gunzip(); ++ decompress(input_data, input_data_end - input_data, ++ NULL, NULL, output_data, NULL, error); + putstr("done.\n"); + return 0; + } + #endif +- +diff --git a/arch/arm/boot/compressed/piggy.S b/arch/arm/boot/compressed/piggy.S +deleted file mode 100644 +index 54c9518..0000000 +--- a/arch/arm/boot/compressed/piggy.S ++++ /dev/null +@@ -1,6 +0,0 @@ +- .section .piggydata,#alloc +- .globl input_data +-input_data: +- .incbin "arch/arm/boot/compressed/piggy.gz" +- .globl input_data_end +-input_data_end: +diff --git a/arch/arm/boot/compressed/piggy.gzip.S b/arch/arm/boot/compressed/piggy.gzip.S +new file mode 100644 +index 0000000..a68adf9 +--- /dev/null ++++ b/arch/arm/boot/compressed/piggy.gzip.S +@@ -0,0 +1,6 @@ ++ .section .piggydata,#alloc ++ .globl input_data ++input_data: ++ .incbin "arch/arm/boot/compressed/piggy.gzip" ++ .globl input_data_end ++input_data_end: +diff --git a/arch/arm/boot/compressed/piggy.lzo.S b/arch/arm/boot/compressed/piggy.lzo.S +new file mode 100644 +index 0000000..a425ad9 +--- /dev/null ++++ b/arch/arm/boot/compressed/piggy.lzo.S +@@ -0,0 +1,6 @@ ++ .section .piggydata,#alloc ++ .globl input_data ++input_data: ++ .incbin "arch/arm/boot/compressed/piggy.lzo" ++ .globl input_data_end ++input_data_end: diff --git a/target/linux/generic-2.6/patches-2.6.31/052-lzo_compressed_kernel_for_x86.patch b/target/linux/generic-2.6/patches-2.6.31/052-lzo_compressed_kernel_for_x86.patch new file mode 100644 index 0000000000..bfefe8bfde --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/052-lzo_compressed_kernel_for_x86.patch @@ -0,0 +1,54 @@ +diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig +index 72ace95..89f7771 100644 +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -49,6 +49,7 @@ config X86 + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_LZMA ++ select HAVE_KERNEL_LZO + select HAVE_ARCH_KMEMCHECK + + config OUTPUT_FORMAT +diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile +index f8ed065..0e835d0 100644 +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -4,7 +4,7 @@ + # create a compressed vmlinux image from the original vmlinux + # + +-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o ++targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o piggy.o + + KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 + KBUILD_CFLAGS += -fno-strict-aliasing -fPIC +@@ -48,10 +48,13 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.all-y) FORCE + $(call if_changed,bzip2) + $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE + $(call if_changed,lzma) ++$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE ++ $(call if_changed,lzo) + + suffix-$(CONFIG_KERNEL_GZIP) := gz + suffix-$(CONFIG_KERNEL_BZIP2) := bz2 + suffix-$(CONFIG_KERNEL_LZMA) := lzma ++suffix-$(CONFIG_KERNEL_LZO) := lzo + + quiet_cmd_mkpiggy = MKPIGGY $@ + cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false ) +diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c +index 842b2a3..3b22fe8 100644 +--- a/arch/x86/boot/compressed/misc.c ++++ b/arch/x86/boot/compressed/misc.c +@@ -162,6 +162,10 @@ static int lines, cols; + #include "../../../../lib/decompress_unlzma.c" + #endif + ++#ifdef CONFIG_KERNEL_LZO ++#include "../../../../lib/decompress_unlzo.c" ++#endif ++ + static void scroll(void) + { + int i; diff --git a/target/linux/generic-2.6/patches-2.6.31/053-lzo_compression_for_initramfs.patch b/target/linux/generic-2.6/patches-2.6.31/053-lzo_compression_for_initramfs.patch new file mode 100644 index 0000000000..f0d8ff39f9 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/053-lzo_compression_for_initramfs.patch @@ -0,0 +1,114 @@ +diff --git a/lib/Kconfig b/lib/Kconfig +index bb1326d..8639349 100644 +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -117,6 +117,10 @@ config DECOMPRESS_BZIP2 + config DECOMPRESS_LZMA + tristate + ++config DECOMPRESS_LZO ++ select LZO_DECOMPRESS ++ tristate ++ + # + # Generic allocator support is selected if needed + # +diff --git a/lib/Makefile b/lib/Makefile +index 2e78277..cfa4041 100644 +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -69,6 +69,7 @@ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ + lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o + lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o + lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o ++lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o + + obj-$(CONFIG_TEXTSEARCH) += textsearch.o + obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o +diff --git a/lib/decompress.c b/lib/decompress.c +index d2842f5..a760681 100644 +--- a/lib/decompress.c ++++ b/lib/decompress.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -22,6 +23,9 @@ + #ifndef CONFIG_DECOMPRESS_LZMA + # define unlzma NULL + #endif ++#ifndef CONFIG_DECOMPRESS_LZO ++# define unlzo NULL ++#endif + + static const struct compress_format { + unsigned char magic[2]; +@@ -32,6 +36,7 @@ static const struct compress_format { + { {037, 0236}, "gzip", gunzip }, + { {0x42, 0x5a}, "bzip2", bunzip2 }, + { {0x5d, 0x00}, "lzma", unlzma }, ++ { {0x89, 0x4c}, "lzo", unlzo }, + { {0, 0}, NULL, NULL } + }; + +diff --git a/usr/Kconfig b/usr/Kconfig +index 1c3039f..e2721f5 100644 +--- a/usr/Kconfig ++++ b/usr/Kconfig +@@ -72,6 +72,15 @@ config RD_LZMA + Support loading of a LZMA encoded initial ramdisk or cpio buffer + If unsure, say N. + ++config RD_LZO ++ bool "Support initial ramdisks compressed using LZO" if EMBEDDED ++ default !EMBEDDED ++ depends on BLK_DEV_INITRD ++ select DECOMPRESS_LZO ++ help ++ Support loading of a LZO encoded initial ramdisk or cpio buffer ++ If unsure, say N. ++ + choice + prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!="" + help +@@ -108,16 +117,15 @@ config INITRAMFS_COMPRESSION_GZIP + bool "Gzip" + depends on RD_GZIP + help +- The old and tried gzip compression. Its compression ratio is +- the poorest among the 3 choices; however its speed (both +- compression and decompression) is the fastest. ++ The old and tried gzip compression. It provides a good balance ++ between compression ratio and decompression speed. + + config INITRAMFS_COMPRESSION_BZIP2 + bool "Bzip2" + depends on RD_BZIP2 + help + Its compression ratio and speed is intermediate. +- Decompression speed is slowest among the three. The initramfs ++ Decompression speed is slowest among the four. The initramfs + size is about 10% smaller with bzip2, in comparison to gzip. + Bzip2 uses a large amount of memory. For modern kernels you + will need at least 8MB RAM or more for booting. +@@ -128,7 +136,15 @@ config INITRAMFS_COMPRESSION_LZMA + help + The most recent compression algorithm. + Its ratio is best, decompression speed is between the other +- two. Compression is slowest. The initramfs size is about 33% ++ three. Compression is slowest. The initramfs size is about 33% + smaller with LZMA in comparison to gzip. + ++config INITRAMFS_COMPRESSION_LZO ++ bool "LZO" ++ depends on RD_LZO ++ help ++ Its compression ratio is the poorest among the four. The kernel ++ size is about about 10% bigger than gzip; however its speed ++ (both compression and decompression) is the fastest. ++ + endchoice diff --git a/target/linux/generic-2.6/patches-2.6.31/055-lzma_arm_kernel.patch b/target/linux/generic-2.6/patches-2.6.31/055-lzma_arm_kernel.patch new file mode 100644 index 0000000000..1f39628929 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.31/055-lzma_arm_kernel.patch @@ -0,0 +1,69 @@ +From d0f226a0f104c7d1da1d215b8013359273e39e18 Mon Sep 17 00:00:00 2001 +From: Albin Tonnerre +Date: Fri, 16 Oct 2009 16:17:22 +0200 +Subject: [PATCH] Add LZMA decompression on ARM + + +Signed-off-by: Albin Tonnerre +--- + arch/arm/Kconfig | 1 + + arch/arm/boot/compressed/Makefile | 1 + + arch/arm/boot/compressed/misc.c | 4 ++++ + arch/arm/boot/compressed/piggy.lzma.S | 6 ++++++ + 4 files changed, 12 insertions(+), 0 deletions(-) + create mode 100644 arch/arm/boot/compressed/piggy.lzma.S + +diff --git a/arch/arm/Kconfig b/arch/arm/Kconfig +index ea71c0c..f5bf779 100644 +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -20,6 +20,7 @@ config ARM + select HAVE_GENERIC_DMA_COHERENT + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_LZO ++ select HAVE_KERNEL_LZMA + help + The ARM series is a line of low-power-consumption RISC chip designs + licensed by ARM Ltd and targeted at embedded applications and +diff --git a/arch/arm/boot/compressed/Makefile b/arch/arm/boot/compressed/Makefile +index 5b4629b..dcfcb74 100644 +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -65,6 +65,7 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ + + suffix_$(CONFIG_KERNEL_GZIP) = gzip + suffix_$(CONFIG_KERNEL_LZO) = lzo ++suffix_$(CONFIG_KERNEL_LZMA) = lzma + + targets := vmlinux vmlinux.lds \ + piggy.$(suffix_y) piggy.$(suffix_y).o \ +diff --git a/arch/arm/boot/compressed/misc.c b/arch/arm/boot/compressed/misc.c +index 7e0fe4d..4e35a10 100644 +--- a/arch/arm/boot/compressed/misc.c ++++ b/arch/arm/boot/compressed/misc.c +@@ -237,6 +237,10 @@ static unsigned long free_mem_end_ptr; + #include "../../../../lib/decompress_inflate.c" + #endif + ++#ifdef CONFIG_KERNEL_LZMA ++#include "../../../../lib/decompress_unlzma.c" ++#endif ++ + #ifdef CONFIG_KERNEL_LZO + #include "../../../../lib/decompress_unlzo.c" + #endif +diff --git a/arch/arm/boot/compressed/piggy.lzma.S b/arch/arm/boot/compressed/piggy.lzma.S +new file mode 100644 +index 0000000..d7e69cf +--- /dev/null ++++ b/arch/arm/boot/compressed/piggy.lzma.S +@@ -0,0 +1,6 @@ ++ .section .piggydata,#alloc ++ .globl input_data ++input_data: ++ .incbin "arch/arm/boot/compressed/piggy.lzma" ++ .globl input_data_end ++input_data_end: +-- +1.6.5 + diff --git a/target/linux/generic-2.6/patches-2.6.31/960-arm_lzma_loader.patch b/target/linux/generic-2.6/patches-2.6.31/960-arm_lzma_loader.patch deleted file mode 100644 index 5f4f28757b..0000000000 --- a/target/linux/generic-2.6/patches-2.6.31/960-arm_lzma_loader.patch +++ /dev/null @@ -1,710 +0,0 @@ ---- a/arch/arm/boot/compressed/Makefile -+++ b/arch/arm/boot/compressed/Makefile -@@ -63,7 +63,7 @@ endif - - SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ - --targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ -+targets := vmlinux vmlinux.lds piggy.lzma piggy.o font.o font.c \ - head.o misc.o $(OBJS) - - ifeq ($(CONFIG_FUNCTION_TRACER),y) -@@ -99,10 +99,10 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj - $(call if_changed,ld) - @: - --$(obj)/piggy.gz: $(obj)/../Image FORCE -- $(call if_changed,gzip) -+$(obj)/piggy.lzma: $(obj)/../Image FORCE -+ $(call if_changed,lzma) - --$(obj)/piggy.o: $(obj)/piggy.gz FORCE -+$(obj)/piggy.o: $(obj)/piggy.lzma FORCE - - CFLAGS_font.o := -Dstatic= - ---- a/arch/arm/boot/compressed/misc.c -+++ b/arch/arm/boot/compressed/misc.c -@@ -185,36 +185,10 @@ static inline __ptr_t memcpy(__ptr_t __d - return __dest; - } - --/* -- * gzip delarations -- */ --#define OF(args) args --#define STATIC static -- --typedef unsigned char uch; --typedef unsigned short ush; --typedef unsigned long ulg; -- --#define WSIZE 0x8000 /* Window size must be at least 32k, */ -+#define WSIZE 0x20000 /* Window size must be at least 128k, */ - /* and a power of two */ - --static uch *inbuf; /* input buffer */ --static uch window[WSIZE]; /* Sliding window buffer */ -- --static unsigned insize; /* valid bytes in inbuf */ --static unsigned inptr; /* index of next byte to be processed in inbuf */ --static unsigned outcnt; /* bytes in output buffer */ -- --/* gzip flag byte */ --#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ --#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ --#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ --#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ --#define COMMENT 0x10 /* bit 4 set: file comment present */ --#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ --#define RESERVED 0xC0 /* bit 6,7: reserved */ -- --#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -+static u8 window[WSIZE]; /* Sliding window buffer */ - - /* Diagnostic functions */ - #ifdef DEBUG -@@ -233,24 +207,21 @@ static unsigned outcnt; /* bytes in out - # define Tracecv(c,x) - #endif - --static int fill_inbuf(void); --static void flush_window(void); - static void error(char *m); - - extern char input_data[]; - extern char input_data_end[]; - --static uch *output_data; --static ulg output_ptr; --static ulg bytes_out; -+static unsigned long output_ptr; -+static unsigned long bytes_out; - - static void error(char *m); - - static void putstr(const char *); - - extern int end; --static ulg free_mem_ptr; --static ulg free_mem_end_ptr; -+static unsigned long free_mem_ptr; -+static unsigned long free_mem_end_ptr; - - #ifdef STANDALONE_DEBUG - #define NO_INFLATE_MALLOC -@@ -258,50 +229,10 @@ static ulg free_mem_end_ptr; - - #define ARCH_HAS_DECOMP_WDOG - --#include "../../../../lib/inflate.c" -- --/* =========================================================================== -- * Fill the input buffer. This is called only when the buffer is empty -- * and at least one byte is really needed. -- */ --int fill_inbuf(void) --{ -- if (insize != 0) -- error("ran out of input data"); -- -- inbuf = input_data; -- insize = &input_data_end[0] - &input_data[0]; -- -- inptr = 1; -- return inbuf[0]; --} -- --/* =========================================================================== -- * Write the output window window[0..outcnt-1] and update crc and bytes_out. -- * (Used for the decompressed data only.) -- */ --void flush_window(void) --{ -- ulg c = crc; -- unsigned n; -- uch *in, *out, ch; -- -- in = window; -- out = &output_data[output_ptr]; -- for (n = 0; n < outcnt; n++) { -- ch = *out++ = *in++; -- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -- } -- crc = c; -- bytes_out += (ulg)outcnt; -- output_ptr += (ulg)outcnt; -- outcnt = 0; -- putstr("."); --} -- - #ifndef arch_error - #define arch_error(x) - #endif -+#include "unlzma.c" - - static void error(char *x) - { -@@ -316,20 +247,16 @@ static void error(char *x) - - #ifndef STANDALONE_DEBUG - --ulg --decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, -+unsigned long -+decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, - int arch_id) - { -- output_data = (uch *)output_start; /* Points to kernel start */ -- free_mem_ptr = free_mem_ptr_p; -- free_mem_end_ptr = free_mem_ptr_end_p; - __machine_arch_type = arch_id; - - arch_decomp_setup(); - -- makecrc(); - putstr("Uncompressing Linux..."); -- gunzip(); -+ output_ptr += unlzma((u8 *) output_start, input_data, window); - putstr(" done, booting the kernel.\n"); - return output_ptr; - } -@@ -339,11 +266,8 @@ char output_buffer[1500*1024]; - - int main() - { -- output_data = output_buffer; -- -- makecrc(); - putstr("Uncompressing Linux..."); -- gunzip(); -+ unlzma((u8 *) output_buffer, input_data, window); - putstr("done.\n"); - return 0; - } ---- a/arch/arm/boot/compressed/piggy.S -+++ b/arch/arm/boot/compressed/piggy.S -@@ -1,6 +1,6 @@ - .section .piggydata,#alloc - .globl input_data - input_data: -- .incbin "arch/arm/boot/compressed/piggy.gz" -+ .incbin "arch/arm/boot/compressed/piggy.lzma" - .globl input_data_end - input_data_end: ---- /dev/null -+++ b/arch/arm/boot/compressed/unlzma.c -@@ -0,0 +1,429 @@ -+/* -+ * Copyright (c) 2009 Felix Fietkau -+ * -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * uncompress.c -+ */ -+ -+#include -+#include -+#include "unlzma.h" -+ -+struct unlzma_ctx { -+ const u8 *next_in; -+ u8 *next_out; -+ u8 *outbuf; -+ -+ /* reader state */ -+ u32 code; -+ u32 range; -+ u32 bound; -+ -+ /* writer state */ -+ u8 previous_byte; -+ ssize_t pos; -+ -+ /* cstate */ -+ int state; -+ u32 rep0, rep1, rep2, rep3; -+ -+ void *workspace; -+} ctx; -+ -+static int inbs = 0; -+static inline u8 -+rc_read(void) -+{ -+#if 0 -+ if (unlikely(++inbs > 16 * 1024)) { -+ putstr("."); -+ inbs = 0; -+ } -+#endif -+ return *(ctx.next_in++); -+} -+ -+ -+static inline void -+rc_get_code(void) -+{ -+ ctx.code = (ctx.code << 8) | rc_read(); -+} -+ -+static inline void -+rc_normalize(void) -+{ -+ if (ctx.range < (1 << RC_TOP_BITS)) { -+ ctx.range <<= 8; -+ rc_get_code(); -+ } -+} -+ -+static inline int -+rc_is_bit_0(u16 *p) -+{ -+ rc_normalize(); -+ ctx.bound = *p * (ctx.range >> RC_MODEL_TOTAL_BITS); -+ return ctx.code < ctx.bound; -+} -+ -+static inline void -+rc_update_bit_0(u16 *p) -+{ -+ ctx.range = ctx.bound; -+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; -+} -+ -+static inline void -+rc_update_bit_1(u16 *p) -+{ -+ ctx.range -= ctx.bound; -+ ctx.code -= ctx.bound; -+ *p -= *p >> RC_MOVE_BITS; -+} -+ -+static inline bool -+rc_get_bit(u16 *p, int *symbol) -+{ -+ if (rc_is_bit_0(p)) { -+ rc_update_bit_0(p); -+ *symbol *= 2; -+ return 0; -+ } else { -+ rc_update_bit_1(p); -+ *symbol = *symbol * 2 + 1; -+ return 1; -+ } -+} -+ -+static inline int -+rc_direct_bit(void) -+{ -+ rc_normalize(); -+ ctx.range >>= 1; -+ if (ctx.code >= ctx.range) { -+ ctx.code -= ctx.range; -+ return 1; -+ } -+ return 0; -+} -+ -+static inline void -+rc_bit_tree_decode(u16 *p, int num_levels, int *symbol) -+{ -+ int i = num_levels; -+ -+ *symbol = 1; -+ while (i--) -+ rc_get_bit(p + *symbol, symbol); -+ *symbol -= 1 << num_levels; -+} -+ -+static inline u8 -+peek_old_byte(u32 offs) -+{ -+ u32 pos = ctx.pos - offs; -+ return ctx.outbuf[pos]; -+} -+ -+static inline void -+write_byte(u8 byte) -+{ -+ ctx.previous_byte = byte; -+ *(ctx.next_out++) = byte; -+ ctx.pos++; -+} -+ -+ -+static inline void -+copy_byte(u32 offs) -+{ -+ write_byte(peek_old_byte(offs)); -+} -+ -+static inline void -+copy_bytes(u32 rep0, int len) -+{ -+ do { -+ copy_byte(rep0); -+ len--; -+ } while (len != 0); -+} -+ -+static inline void -+process_bit0(u16 *p, int pos_state, u16 *prob, -+ int lc, u32 literal_pos_mask) -+{ -+ int mi = 1; -+ rc_update_bit_0(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.rep0); -+ do { -+ u16 bit; -+ u16 *prob_lit; -+ -+ match_byte <<= 1; -+ bit = match_byte & 0x100; -+ prob_lit = prob + 0x100 + bit + mi; -+ if (rc_get_bit(prob_lit, &mi) != !!bit) -+ break; -+ } while (mi < 0x100); -+ } -+ while (mi < 0x100) { -+ u16 *prob_lit = prob + mi; -+ rc_get_bit(prob_lit, &mi); -+ } -+ write_byte(mi); -+ if (ctx.state < 4) -+ ctx.state = 0; -+ else if (ctx.state < 10) -+ ctx.state -= 3; -+ else -+ ctx.state -= 6; -+} -+ -+static inline void -+process_bit1(u16 *p, int pos_state, u16 *prob) -+{ -+ int offset; -+ u16 *prob_len; -+ int num_bits; -+ int len; -+ -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(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(prob); -+ prob = p + LZMA_IS_REP_G0 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ prob = (p + LZMA_IS_REP_0_LONG -+ + (ctx.state << -+ LZMA_NUM_POS_BITS_MAX) + -+ pos_state); -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ -+ ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? -+ 9 : 11; -+ copy_byte(ctx.rep0); -+ return; -+ } else { -+ rc_update_bit_1(prob); -+ } -+ } else { -+ u32 distance; -+ -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP_G1 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ distance = ctx.rep1; -+ } else { -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP_G2 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ distance = ctx.rep2; -+ } else { -+ rc_update_bit_1(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(prob_len)) { -+ rc_update_bit_0(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(prob_len); -+ prob_len = prob + LZMA_LEN_CHOICE_2; -+ if (rc_is_bit_0(prob_len)) { -+ rc_update_bit_0(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(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(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(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(); -+ 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(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.rep0, len); -+} -+ -+ -+static int -+do_unlzma(void) -+{ -+ 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.pos = 0; -+ ctx.state = 0; -+ ctx.rep0 = ctx.rep1 = ctx.rep2 = ctx.rep3 = 1; -+ -+ ctx.previous_byte = 0; -+ ctx.code = 0; -+ ctx.range = 0xFFFFFFFF; -+ -+ 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; -+ -+ 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(); -+ -+ 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(prob)) -+ process_bit0(p, pos_state, prob, -+ lc, literal_pos_mask); -+ else { -+ process_bit1(p, pos_state, prob); -+ if (ctx.rep0 == 0) -+ break; -+ } -+ } -+ -+ return ctx.pos; -+} -+ -+ -+static int unlzma(unsigned char *dest, const unsigned char *src, unsigned char *workspace) -+{ -+ memset(&ctx, 0, sizeof(ctx)); -+ ctx.outbuf = dest; -+ ctx.next_in = src; -+ ctx.next_out = dest; -+ ctx.workspace = workspace; -+ -+ return do_unlzma(); -+} -+ -+ ---- /dev/null -+++ b/arch/arm/boot/compressed/unlzma.h -@@ -0,0 +1,81 @@ -+/* LZMA uncompresion module for pcomp -+ * Copyright (C) 2009 Felix Fietkau -+ * -+ * Based on: -+ * Initial Linux kernel adaptation -+ * Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ * Based on small lzma deflate implementation/Small range coder -+ * implementation for lzma. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+#ifndef __UNLZMA_H -+#define __UNLZMA_H -+ -+struct lzma_header { -+ __u8 pos; -+ __le32 dict_size; -+ __le64 uncompr_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 diff --git a/target/linux/generic-2.6/patches-2.6.32/050-lzo_compressed_kernels.patch b/target/linux/generic-2.6/patches-2.6.32/050-lzo_compressed_kernels.patch new file mode 100644 index 0000000000..733d1756f6 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.32/050-lzo_compressed_kernels.patch @@ -0,0 +1,309 @@ +--- /dev/null ++++ b/include/linux/decompress/unlzo.h +@@ -0,0 +1,10 @@ ++#ifndef DECOMPRESS_UNLZO_H ++#define DECOMPRESS_UNLZO_H ++ ++int unlzo(unsigned char *inbuf, int len, ++ int(*fill)(void*, unsigned int), ++ int(*flush)(void*, unsigned int), ++ unsigned char *output, ++ int *pos, ++ void(*error)(char *x)); ++#endif +--- a/init/Kconfig ++++ b/init/Kconfig +@@ -115,10 +115,13 @@ config HAVE_KERNEL_BZIP2 + config HAVE_KERNEL_LZMA + bool + ++config HAVE_KERNEL_LZO ++ bool ++ + choice + prompt "Kernel compression mode" + default KERNEL_GZIP +- depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA ++ depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_LZO + help + The linux kernel is a kind of self-extracting executable. + Several compression algorithms are available, which differ +@@ -141,9 +144,8 @@ config KERNEL_GZIP + bool "Gzip" + depends on HAVE_KERNEL_GZIP + help +- The old and tried gzip compression. Its compression ratio is +- the poorest among the 3 choices; however its speed (both +- compression and decompression) is the fastest. ++ The old and tried gzip compression. It provides a good balance ++ between compression ratio and decompression speed. + + config KERNEL_BZIP2 + bool "Bzip2" +@@ -164,6 +166,14 @@ config KERNEL_LZMA + two. Compression is slowest. The kernel size is about 33% + smaller with LZMA in comparison to gzip. + ++config KERNEL_LZO ++ bool "LZO" ++ depends on HAVE_KERNEL_LZO ++ help ++ Its compression ratio is the poorest among the 4. The kernel ++ size is about about 10% bigger than gzip; however its speed ++ (both compression and decompression) is the fastest. ++ + endchoice + + config SWAP +--- /dev/null ++++ b/lib/decompress_unlzo.c +@@ -0,0 +1,208 @@ ++/* ++ * LZO decompressor for the Linux kernel. Code borrowed from the lzo ++ * implementation by Markus Franz Xaver Johannes Oberhumer. ++ * ++ * Linux kernel adaptation: ++ * Copyright (C) 2009 ++ * Albin Tonnerre, Free Electrons ++ * ++ * Original code: ++ * Copyright (C) 1996-2005 Markus Franz Xaver Johannes Oberhumer ++ * All Rights Reserved. ++ * ++ * lzop and the LZO library are free software; you can redistribute them ++ * and/or modify them under the terms of the GNU General Public License as ++ * published by the Free Software Foundation; either version 2 of ++ * the License, 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; see the file COPYING. ++ * If not, write to the Free Software Foundation, Inc., ++ * 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. ++ * ++ * Markus F.X.J. Oberhumer ++ * ++ * http://www.oberhumer.com/opensource/lzop/ ++ */ ++ ++#ifdef STATIC ++#include "lzo/lzo1x_decompress.c" ++#else ++#include ++#include ++#endif ++ ++#include ++#include ++#include ++ ++#include ++#include ++ ++static const unsigned char lzop_magic[] = ++ { 0x89, 0x4c, 0x5a, 0x4f, 0x00, 0x0d, 0x0a, 0x1a, 0x0a }; ++ ++#define LZO_BLOCK_SIZE (256*1024l) ++#define HEADER_HAS_FILTER 0x00000800L ++ ++STATIC inline int INIT parse_header(u8 *input, u8 *skip) ++{ ++ int l; ++ u8 *parse = input; ++ u8 level = 0; ++ u16 version; ++ ++ /* read magic: 9 first bits */ ++ for (l = 0; l < 9; l++) { ++ if (*parse++ != lzop_magic[l]) ++ return 0; ++ } ++ /* get version (2bytes), skip library version (2), ++ * 'need to be extracted' version (2) and ++ * method (1) */ ++ version = get_unaligned_be16(parse); ++ parse += 7; ++ if (version >= 0x0940) ++ level = *parse++; ++ if (get_unaligned_be32(parse) & HEADER_HAS_FILTER) ++ parse += 8; /* flags + filter info */ ++ else ++ parse += 4; /* flags */ ++ ++ /* skip mode and mtime_low */ ++ parse += 8; ++ if (version >= 0x0940) ++ parse += 4; /* skip mtime_high */ ++ ++ l = *parse++; ++ /* don't care about the file name, and skip checksum */ ++ parse += l + 4; ++ ++ *skip = parse - input; ++ return 1; ++} ++ ++STATIC inline int INIT unlzo(u8 *input, int in_len, ++ int (*fill) (void *, unsigned int), ++ int (*flush) (void *, unsigned int), ++ u8 *output, int *posp, ++ void (*error_fn) (char *x)) ++{ ++ u8 skip = 0, r = 0; ++ u32 src_len, dst_len; ++ size_t tmp; ++ u8 *in_buf, *in_buf_save, *out_buf; ++ int obytes_processed = 0; ++ ++ set_error_fn(error_fn); ++ ++ if (output) ++ out_buf = output; ++ else if (!flush) { ++ error("NULL output pointer and no flush function provided"); ++ goto exit; ++ } else { ++ out_buf = malloc(LZO_BLOCK_SIZE); ++ if (!out_buf) { ++ error("Could not allocate output buffer"); ++ goto exit; ++ } ++ } ++ ++ if (input && fill) { ++ error("Both input pointer and fill function provided, don't know what to do"); ++ goto exit_1; ++ } else if (input) ++ in_buf = input; ++ else if (!fill || !posp) { ++ error("NULL input pointer and missing position pointer or fill function"); ++ goto exit_1; ++ } else { ++ in_buf = malloc(lzo1x_worst_compress(LZO_BLOCK_SIZE)); ++ if (!in_buf) { ++ error("Could not allocate input buffer"); ++ goto exit_1; ++ } ++ } ++ in_buf_save = in_buf; ++ ++ if (posp) ++ *posp = 0; ++ ++ if (fill) ++ fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE)); ++ ++ if (!parse_header(input, &skip)) { ++ error("invalid header"); ++ goto exit_2; ++ } ++ in_buf += skip; ++ ++ if (posp) ++ *posp = skip; ++ ++ for (;;) { ++ /* read uncompressed block size */ ++ dst_len = get_unaligned_be32(in_buf); ++ in_buf += 4; ++ ++ /* exit if last block */ ++ if (dst_len == 0) { ++ if (posp) ++ *posp += 4; ++ break; ++ } ++ ++ if (dst_len > LZO_BLOCK_SIZE) { ++ error("dest len longer than block size"); ++ goto exit_2; ++ } ++ ++ /* read compressed block size, and skip block checksum info */ ++ src_len = get_unaligned_be32(in_buf); ++ in_buf += 8; ++ ++ if (src_len <= 0 || src_len > dst_len) { ++ error("file corrupted"); ++ goto exit_2; ++ } ++ ++ /* decompress */ ++ tmp = dst_len; ++ r = lzo1x_decompress_safe((u8 *) in_buf, src_len, out_buf, &tmp); ++ ++ if (r != LZO_E_OK || dst_len != tmp) { ++ error("Compressed data violation"); ++ goto exit_2; ++ } ++ ++ obytes_processed += dst_len; ++ if (flush) ++ flush(out_buf, dst_len); ++ if (output) ++ out_buf += dst_len; ++ if (posp) ++ *posp += src_len + 12; ++ if (fill) { ++ in_buf = in_buf_save; ++ fill(in_buf, lzo1x_worst_compress(LZO_BLOCK_SIZE)); ++ } else ++ in_buf += src_len; ++ } ++ ++exit_2: ++ if (!input) ++ free(in_buf); ++exit_1: ++ if (!output) ++ free(out_buf); ++exit: ++ return obytes_processed; ++} ++ ++#define decompress unlzo +--- a/lib/lzo/lzo1x_decompress.c ++++ b/lib/lzo/lzo1x_decompress.c +@@ -11,11 +11,13 @@ + * Richard Purdie + */ + ++#ifndef STATIC + #include + #include +-#include +-#include ++#endif ++ + #include ++#include + #include "lzodefs.h" + + #define HAVE_IP(x, ip_end, ip) ((size_t)(ip_end - ip) < (x)) +@@ -244,9 +246,10 @@ lookbehind_overrun: + *out_len = op - out; + return LZO_E_LOOKBEHIND_OVERRUN; + } +- ++#ifndef STATIC + EXPORT_SYMBOL_GPL(lzo1x_decompress_safe); + + MODULE_LICENSE("GPL"); + MODULE_DESCRIPTION("LZO1X Decompressor"); + ++#endif +--- a/scripts/Makefile.lib ++++ b/scripts/Makefile.lib +@@ -230,3 +230,8 @@ quiet_cmd_lzma = LZMA $@ + cmd_lzma = (cat $(filter-out FORCE,$^) | \ + lzma -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ + (rm -f $@ ; false) ++ ++quiet_cmd_lzo = LZO $@ ++cmd_lzo = (cat $(filter-out FORCE,$^) | \ ++ lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \ ++ (rm -f $@ ; false) diff --git a/target/linux/generic-2.6/patches-2.6.32/051-lzo_compressed_kernel_for_arm.patch b/target/linux/generic-2.6/patches-2.6.32/051-lzo_compressed_kernel_for_arm.patch new file mode 100644 index 0000000000..49512bb41d --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.32/051-lzo_compressed_kernel_for_arm.patch @@ -0,0 +1,283 @@ +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -18,6 +18,8 @@ config ARM + select HAVE_KRETPROBES if (HAVE_KPROBES) + select HAVE_FUNCTION_TRACER if (!XIP_KERNEL) + select HAVE_GENERIC_DMA_COHERENT ++ select HAVE_KERNEL_GZIP ++ select HAVE_KERNEL_LZO + help + The ARM series is a line of low-power-consumption RISC chip designs + licensed by ARM Ltd and targeted at embedded applications and +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -63,8 +63,12 @@ endif + + SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ + +-targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ +- head.o misc.o $(OBJS) ++suffix_$(CONFIG_KERNEL_GZIP) = gzip ++suffix_$(CONFIG_KERNEL_LZO) = lzo ++ ++targets := vmlinux vmlinux.lds \ ++ piggy.$(suffix_y) piggy.$(suffix_y).o \ ++ font.o font.c head.o misc.o $(OBJS) + + ifeq ($(CONFIG_FUNCTION_TRACER),y) + ORIG_CFLAGS := $(KBUILD_CFLAGS) +@@ -87,22 +91,31 @@ endif + ifneq ($(PARAMS_PHYS),) + LDFLAGS_vmlinux += --defsym params_phys=$(PARAMS_PHYS) + endif +-LDFLAGS_vmlinux += -p --no-undefined -X \ +- $(shell $(CC) $(KBUILD_CFLAGS) --print-libgcc-file-name) -T ++# ? ++LDFLAGS_vmlinux += -p ++# Report unresolved symbol references ++LDFLAGS_vmlinux += --no-undefined ++# Delete all temporary local symbols ++LDFLAGS_vmlinux += -X ++# Next argument is a linker script ++LDFLAGS_vmlinux += -T ++ ++# For __aeabi_uidivmod ++lib1funcs = $(srctree)/arch/$(SRCARCH)/lib/lib1funcs.o + + # Don't allow any static data in misc.o, which + # would otherwise mess up our GOT table + CFLAGS_misc.o := -Dstatic= + +-$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.o \ +- $(addprefix $(obj)/, $(OBJS)) FORCE ++$(obj)/vmlinux: $(obj)/vmlinux.lds $(obj)/$(HEAD) $(obj)/piggy.$(suffix_y).o \ ++ $(addprefix $(obj)/, $(OBJS)) $(lib1funcs) FORCE + $(call if_changed,ld) + @: + +-$(obj)/piggy.gz: $(obj)/../Image FORCE +- $(call if_changed,gzip) ++$(obj)/piggy.$(suffix_y): $(obj)/../Image FORCE ++ $(call if_changed,$(suffix_y)) + +-$(obj)/piggy.o: $(obj)/piggy.gz FORCE ++$(obj)/piggy.$(suffix_y).o: $(obj)/piggy.$(suffix_y) FORCE + + CFLAGS_font.o := -Dstatic= + +--- a/arch/arm/boot/compressed/misc.c ++++ b/arch/arm/boot/compressed/misc.c +@@ -18,10 +18,15 @@ + + unsigned int __machine_arch_type; + ++#define _LINUX_STRING_H_ ++ + #include /* for inline */ + #include /* for size_t */ + #include /* for NULL */ + #include ++#include ++ ++#include + + #ifdef STANDALONE_DEBUG + #define putstr printf +@@ -188,34 +193,8 @@ static inline __ptr_t memcpy(__ptr_t __d + /* + * gzip delarations + */ +-#define OF(args) args + #define STATIC static + +-typedef unsigned char uch; +-typedef unsigned short ush; +-typedef unsigned long ulg; +- +-#define WSIZE 0x8000 /* Window size must be at least 32k, */ +- /* and a power of two */ +- +-static uch *inbuf; /* input buffer */ +-static uch window[WSIZE]; /* Sliding window buffer */ +- +-static unsigned insize; /* valid bytes in inbuf */ +-static unsigned inptr; /* index of next byte to be processed in inbuf */ +-static unsigned outcnt; /* bytes in output buffer */ +- +-/* gzip flag byte */ +-#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ +-#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ +-#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ +-#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ +-#define COMMENT 0x10 /* bit 4 set: file comment present */ +-#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ +-#define RESERVED 0xC0 /* bit 6,7: reserved */ +- +-#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) +- + /* Diagnostic functions */ + #ifdef DEBUG + # define Assert(cond,msg) {if(!(cond)) error(msg);} +@@ -233,24 +212,20 @@ static unsigned outcnt; /* bytes in out + # define Tracecv(c,x) + #endif + +-static int fill_inbuf(void); +-static void flush_window(void); + static void error(char *m); + + extern char input_data[]; + extern char input_data_end[]; + +-static uch *output_data; +-static ulg output_ptr; +-static ulg bytes_out; ++static unsigned char *output_data; ++static unsigned long output_ptr; + + static void error(char *m); + + static void putstr(const char *); + +-extern int end; +-static ulg free_mem_ptr; +-static ulg free_mem_end_ptr; ++static unsigned long free_mem_ptr; ++static unsigned long free_mem_end_ptr; + + #ifdef STANDALONE_DEBUG + #define NO_INFLATE_MALLOC +@@ -258,46 +233,13 @@ static ulg free_mem_end_ptr; + + #define ARCH_HAS_DECOMP_WDOG + +-#include "../../../../lib/inflate.c" +- +-/* =========================================================================== +- * Fill the input buffer. This is called only when the buffer is empty +- * and at least one byte is really needed. +- */ +-int fill_inbuf(void) +-{ +- if (insize != 0) +- error("ran out of input data"); +- +- inbuf = input_data; +- insize = &input_data_end[0] - &input_data[0]; +- +- inptr = 1; +- return inbuf[0]; +-} ++#ifdef CONFIG_KERNEL_GZIP ++#include "../../../../lib/decompress_inflate.c" ++#endif + +-/* =========================================================================== +- * Write the output window window[0..outcnt-1] and update crc and bytes_out. +- * (Used for the decompressed data only.) +- */ +-void flush_window(void) +-{ +- ulg c = crc; +- unsigned n; +- uch *in, *out, ch; +- +- in = window; +- out = &output_data[output_ptr]; +- for (n = 0; n < outcnt; n++) { +- ch = *out++ = *in++; +- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); +- } +- crc = c; +- bytes_out += (ulg)outcnt; +- output_ptr += (ulg)outcnt; +- outcnt = 0; +- putstr("."); +-} ++#ifdef CONFIG_KERNEL_LZO ++#include "../../../../lib/decompress_unlzo.c" ++#endif + + #ifndef arch_error + #define arch_error(x) +@@ -314,22 +256,33 @@ static void error(char *x) + while(1); /* Halt */ + } + ++asmlinkage void __div0(void) ++{ ++ error("Attempting division by 0!"); ++} ++ + #ifndef STANDALONE_DEBUG + +-ulg +-decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, +- int arch_id) ++unsigned long ++decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, ++ unsigned long free_mem_ptr_end_p, ++ int arch_id) + { +- output_data = (uch *)output_start; /* Points to kernel start */ ++ unsigned char *tmp; ++ ++ output_data = (unsigned char *)output_start; + free_mem_ptr = free_mem_ptr_p; + free_mem_end_ptr = free_mem_ptr_end_p; + __machine_arch_type = arch_id; + + arch_decomp_setup(); + +- makecrc(); ++ tmp = (unsigned char *) (((unsigned long)input_data_end) - 4); ++ output_ptr = get_unaligned_le32(tmp); ++ + putstr("Uncompressing Linux..."); +- gunzip(); ++ decompress(input_data, input_data_end - input_data, ++ NULL, NULL, output_data, NULL, error); + putstr(" done, booting the kernel.\n"); + return output_ptr; + } +@@ -341,11 +294,10 @@ int main() + { + output_data = output_buffer; + +- makecrc(); + putstr("Uncompressing Linux..."); +- gunzip(); ++ decompress(input_data, input_data_end - input_data, ++ NULL, NULL, output_data, NULL, error); + putstr("done.\n"); + return 0; + } + #endif +- +--- a/arch/arm/boot/compressed/piggy.S ++++ /dev/null +@@ -1,6 +0,0 @@ +- .section .piggydata,#alloc +- .globl input_data +-input_data: +- .incbin "arch/arm/boot/compressed/piggy.gz" +- .globl input_data_end +-input_data_end: +--- /dev/null ++++ b/arch/arm/boot/compressed/piggy.gzip.S +@@ -0,0 +1,6 @@ ++ .section .piggydata,#alloc ++ .globl input_data ++input_data: ++ .incbin "arch/arm/boot/compressed/piggy.gzip" ++ .globl input_data_end ++input_data_end: +--- /dev/null ++++ b/arch/arm/boot/compressed/piggy.lzo.S +@@ -0,0 +1,6 @@ ++ .section .piggydata,#alloc ++ .globl input_data ++input_data: ++ .incbin "arch/arm/boot/compressed/piggy.lzo" ++ .globl input_data_end ++input_data_end: diff --git a/target/linux/generic-2.6/patches-2.6.32/052-lzo_compressed_kernel_for_x86.patch b/target/linux/generic-2.6/patches-2.6.32/052-lzo_compressed_kernel_for_x86.patch new file mode 100644 index 0000000000..ea7d2400ba --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.32/052-lzo_compressed_kernel_for_x86.patch @@ -0,0 +1,48 @@ +--- a/arch/x86/Kconfig ++++ b/arch/x86/Kconfig +@@ -49,6 +49,7 @@ config X86 + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_BZIP2 + select HAVE_KERNEL_LZMA ++ select HAVE_KERNEL_LZO + select HAVE_ARCH_KMEMCHECK + + config OUTPUT_FORMAT +--- a/arch/x86/boot/compressed/Makefile ++++ b/arch/x86/boot/compressed/Makefile +@@ -4,7 +4,7 @@ + # create a compressed vmlinux image from the original vmlinux + # + +-targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma head_$(BITS).o misc.o piggy.o ++targets := vmlinux.lds vmlinux vmlinux.bin vmlinux.bin.gz vmlinux.bin.bz2 vmlinux.bin.lzma vmlinux.bin.lzo head_$(BITS).o misc.o piggy.o + + KBUILD_CFLAGS := -m$(BITS) -D__KERNEL__ $(LINUX_INCLUDE) -O2 + KBUILD_CFLAGS += -fno-strict-aliasing -fPIC +@@ -48,10 +48,13 @@ $(obj)/vmlinux.bin.bz2: $(vmlinux.bin.al + $(call if_changed,bzip2) + $(obj)/vmlinux.bin.lzma: $(vmlinux.bin.all-y) FORCE + $(call if_changed,lzma) ++$(obj)/vmlinux.bin.lzo: $(vmlinux.bin.all-y) FORCE ++ $(call if_changed,lzo) + + suffix-$(CONFIG_KERNEL_GZIP) := gz + suffix-$(CONFIG_KERNEL_BZIP2) := bz2 + suffix-$(CONFIG_KERNEL_LZMA) := lzma ++suffix-$(CONFIG_KERNEL_LZO) := lzo + + quiet_cmd_mkpiggy = MKPIGGY $@ + cmd_mkpiggy = $(obj)/mkpiggy $< > $@ || ( rm -f $@ ; false ) +--- a/arch/x86/boot/compressed/misc.c ++++ b/arch/x86/boot/compressed/misc.c +@@ -162,6 +162,10 @@ static int lines, cols; + #include "../../../../lib/decompress_unlzma.c" + #endif + ++#ifdef CONFIG_KERNEL_LZO ++#include "../../../../lib/decompress_unlzo.c" ++#endif ++ + static void scroll(void) + { + int i; diff --git a/target/linux/generic-2.6/patches-2.6.32/053-lzo_compression_for_initramfs.patch b/target/linux/generic-2.6/patches-2.6.32/053-lzo_compression_for_initramfs.patch new file mode 100644 index 0000000000..3445b4ae98 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.32/053-lzo_compression_for_initramfs.patch @@ -0,0 +1,106 @@ +--- a/lib/Kconfig ++++ b/lib/Kconfig +@@ -120,6 +120,10 @@ config DECOMPRESS_LZMA + config DECOMPRESS_LZMA_NEEDED + boolean + ++config DECOMPRESS_LZO ++ select LZO_DECOMPRESS ++ tristate ++ + # + # Generic allocator support is selected if needed + # +--- a/lib/Makefile ++++ b/lib/Makefile +@@ -69,6 +69,7 @@ obj-$(CONFIG_LZO_DECOMPRESS) += lzo/ + lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o + lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o + lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o ++lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o + + obj-$(CONFIG_TEXTSEARCH) += textsearch.o + obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o +--- a/lib/decompress.c ++++ b/lib/decompress.c +@@ -9,6 +9,7 @@ + #include + #include + #include ++#include + + #include + #include +@@ -22,6 +23,9 @@ + #ifndef CONFIG_DECOMPRESS_LZMA + # define unlzma NULL + #endif ++#ifndef CONFIG_DECOMPRESS_LZO ++# define unlzo NULL ++#endif + + static const struct compress_format { + unsigned char magic[2]; +@@ -32,6 +36,7 @@ static const struct compress_format { + { {037, 0236}, "gzip", gunzip }, + { {0x42, 0x5a}, "bzip2", bunzip2 }, + { {0x5d, 0x00}, "lzma", unlzma }, ++ { {0x89, 0x4c}, "lzo", unlzo }, + { {0, 0}, NULL, NULL } + }; + +--- a/usr/Kconfig ++++ b/usr/Kconfig +@@ -72,6 +72,15 @@ config RD_LZMA + Support loading of a LZMA encoded initial ramdisk or cpio buffer + If unsure, say N. + ++config RD_LZO ++ bool "Support initial ramdisks compressed using LZO" if EMBEDDED ++ default !EMBEDDED ++ depends on BLK_DEV_INITRD ++ select DECOMPRESS_LZO ++ help ++ Support loading of a LZO encoded initial ramdisk or cpio buffer ++ If unsure, say N. ++ + choice + prompt "Built-in initramfs compression mode" if INITRAMFS_SOURCE!="" + help +@@ -108,16 +117,15 @@ config INITRAMFS_COMPRESSION_GZIP + bool "Gzip" + depends on RD_GZIP + help +- The old and tried gzip compression. Its compression ratio is +- the poorest among the 3 choices; however its speed (both +- compression and decompression) is the fastest. ++ The old and tried gzip compression. It provides a good balance ++ between compression ratio and decompression speed. + + config INITRAMFS_COMPRESSION_BZIP2 + bool "Bzip2" + depends on RD_BZIP2 + help + Its compression ratio and speed is intermediate. +- Decompression speed is slowest among the three. The initramfs ++ Decompression speed is slowest among the four. The initramfs + size is about 10% smaller with bzip2, in comparison to gzip. + Bzip2 uses a large amount of memory. For modern kernels you + will need at least 8MB RAM or more for booting. +@@ -128,7 +136,15 @@ config INITRAMFS_COMPRESSION_LZMA + help + The most recent compression algorithm. + Its ratio is best, decompression speed is between the other +- two. Compression is slowest. The initramfs size is about 33% ++ three. Compression is slowest. The initramfs size is about 33% + smaller with LZMA in comparison to gzip. + ++config INITRAMFS_COMPRESSION_LZO ++ bool "LZO" ++ depends on RD_LZO ++ help ++ Its compression ratio is the poorest among the four. The kernel ++ size is about about 10% bigger than gzip; however its speed ++ (both compression and decompression) is the fastest. ++ + endchoice diff --git a/target/linux/generic-2.6/patches-2.6.32/055-lzma_arm_kernel.patch b/target/linux/generic-2.6/patches-2.6.32/055-lzma_arm_kernel.patch new file mode 100644 index 0000000000..a0111bd554 --- /dev/null +++ b/target/linux/generic-2.6/patches-2.6.32/055-lzma_arm_kernel.patch @@ -0,0 +1,57 @@ +From d0f226a0f104c7d1da1d215b8013359273e39e18 Mon Sep 17 00:00:00 2001 +From: Albin Tonnerre +Date: Fri, 16 Oct 2009 16:17:22 +0200 +Subject: [PATCH] Add LZMA decompression on ARM + + +Signed-off-by: Albin Tonnerre +--- + arch/arm/Kconfig | 1 + + arch/arm/boot/compressed/Makefile | 1 + + arch/arm/boot/compressed/misc.c | 4 ++++ + arch/arm/boot/compressed/piggy.lzma.S | 6 ++++++ + 4 files changed, 12 insertions(+), 0 deletions(-) + create mode 100644 arch/arm/boot/compressed/piggy.lzma.S + +--- a/arch/arm/Kconfig ++++ b/arch/arm/Kconfig +@@ -20,6 +20,7 @@ config ARM + select HAVE_GENERIC_DMA_COHERENT + select HAVE_KERNEL_GZIP + select HAVE_KERNEL_LZO ++ select HAVE_KERNEL_LZMA + help + The ARM series is a line of low-power-consumption RISC chip designs + licensed by ARM Ltd and targeted at embedded applications and +--- a/arch/arm/boot/compressed/Makefile ++++ b/arch/arm/boot/compressed/Makefile +@@ -65,6 +65,7 @@ SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/ + + suffix_$(CONFIG_KERNEL_GZIP) = gzip + suffix_$(CONFIG_KERNEL_LZO) = lzo ++suffix_$(CONFIG_KERNEL_LZMA) = lzma + + targets := vmlinux vmlinux.lds \ + piggy.$(suffix_y) piggy.$(suffix_y).o \ +--- a/arch/arm/boot/compressed/misc.c ++++ b/arch/arm/boot/compressed/misc.c +@@ -237,6 +237,10 @@ static unsigned long free_mem_end_ptr; + #include "../../../../lib/decompress_inflate.c" + #endif + ++#ifdef CONFIG_KERNEL_LZMA ++#include "../../../../lib/decompress_unlzma.c" ++#endif ++ + #ifdef CONFIG_KERNEL_LZO + #include "../../../../lib/decompress_unlzo.c" + #endif +--- /dev/null ++++ b/arch/arm/boot/compressed/piggy.lzma.S +@@ -0,0 +1,6 @@ ++ .section .piggydata,#alloc ++ .globl input_data ++input_data: ++ .incbin "arch/arm/boot/compressed/piggy.lzma" ++ .globl input_data_end ++input_data_end: diff --git a/target/linux/generic-2.6/patches-2.6.32/960-arm_lzma_loader.patch b/target/linux/generic-2.6/patches-2.6.32/960-arm_lzma_loader.patch deleted file mode 100644 index 5f4f28757b..0000000000 --- a/target/linux/generic-2.6/patches-2.6.32/960-arm_lzma_loader.patch +++ /dev/null @@ -1,710 +0,0 @@ ---- a/arch/arm/boot/compressed/Makefile -+++ b/arch/arm/boot/compressed/Makefile -@@ -63,7 +63,7 @@ endif - - SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ - --targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ -+targets := vmlinux vmlinux.lds piggy.lzma piggy.o font.o font.c \ - head.o misc.o $(OBJS) - - ifeq ($(CONFIG_FUNCTION_TRACER),y) -@@ -99,10 +99,10 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj - $(call if_changed,ld) - @: - --$(obj)/piggy.gz: $(obj)/../Image FORCE -- $(call if_changed,gzip) -+$(obj)/piggy.lzma: $(obj)/../Image FORCE -+ $(call if_changed,lzma) - --$(obj)/piggy.o: $(obj)/piggy.gz FORCE -+$(obj)/piggy.o: $(obj)/piggy.lzma FORCE - - CFLAGS_font.o := -Dstatic= - ---- a/arch/arm/boot/compressed/misc.c -+++ b/arch/arm/boot/compressed/misc.c -@@ -185,36 +185,10 @@ static inline __ptr_t memcpy(__ptr_t __d - return __dest; - } - --/* -- * gzip delarations -- */ --#define OF(args) args --#define STATIC static -- --typedef unsigned char uch; --typedef unsigned short ush; --typedef unsigned long ulg; -- --#define WSIZE 0x8000 /* Window size must be at least 32k, */ -+#define WSIZE 0x20000 /* Window size must be at least 128k, */ - /* and a power of two */ - --static uch *inbuf; /* input buffer */ --static uch window[WSIZE]; /* Sliding window buffer */ -- --static unsigned insize; /* valid bytes in inbuf */ --static unsigned inptr; /* index of next byte to be processed in inbuf */ --static unsigned outcnt; /* bytes in output buffer */ -- --/* gzip flag byte */ --#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ --#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ --#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ --#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ --#define COMMENT 0x10 /* bit 4 set: file comment present */ --#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ --#define RESERVED 0xC0 /* bit 6,7: reserved */ -- --#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) -+static u8 window[WSIZE]; /* Sliding window buffer */ - - /* Diagnostic functions */ - #ifdef DEBUG -@@ -233,24 +207,21 @@ static unsigned outcnt; /* bytes in out - # define Tracecv(c,x) - #endif - --static int fill_inbuf(void); --static void flush_window(void); - static void error(char *m); - - extern char input_data[]; - extern char input_data_end[]; - --static uch *output_data; --static ulg output_ptr; --static ulg bytes_out; -+static unsigned long output_ptr; -+static unsigned long bytes_out; - - static void error(char *m); - - static void putstr(const char *); - - extern int end; --static ulg free_mem_ptr; --static ulg free_mem_end_ptr; -+static unsigned long free_mem_ptr; -+static unsigned long free_mem_end_ptr; - - #ifdef STANDALONE_DEBUG - #define NO_INFLATE_MALLOC -@@ -258,50 +229,10 @@ static ulg free_mem_end_ptr; - - #define ARCH_HAS_DECOMP_WDOG - --#include "../../../../lib/inflate.c" -- --/* =========================================================================== -- * Fill the input buffer. This is called only when the buffer is empty -- * and at least one byte is really needed. -- */ --int fill_inbuf(void) --{ -- if (insize != 0) -- error("ran out of input data"); -- -- inbuf = input_data; -- insize = &input_data_end[0] - &input_data[0]; -- -- inptr = 1; -- return inbuf[0]; --} -- --/* =========================================================================== -- * Write the output window window[0..outcnt-1] and update crc and bytes_out. -- * (Used for the decompressed data only.) -- */ --void flush_window(void) --{ -- ulg c = crc; -- unsigned n; -- uch *in, *out, ch; -- -- in = window; -- out = &output_data[output_ptr]; -- for (n = 0; n < outcnt; n++) { -- ch = *out++ = *in++; -- c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); -- } -- crc = c; -- bytes_out += (ulg)outcnt; -- output_ptr += (ulg)outcnt; -- outcnt = 0; -- putstr("."); --} -- - #ifndef arch_error - #define arch_error(x) - #endif -+#include "unlzma.c" - - static void error(char *x) - { -@@ -316,20 +247,16 @@ static void error(char *x) - - #ifndef STANDALONE_DEBUG - --ulg --decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, -+unsigned long -+decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, - int arch_id) - { -- output_data = (uch *)output_start; /* Points to kernel start */ -- free_mem_ptr = free_mem_ptr_p; -- free_mem_end_ptr = free_mem_ptr_end_p; - __machine_arch_type = arch_id; - - arch_decomp_setup(); - -- makecrc(); - putstr("Uncompressing Linux..."); -- gunzip(); -+ output_ptr += unlzma((u8 *) output_start, input_data, window); - putstr(" done, booting the kernel.\n"); - return output_ptr; - } -@@ -339,11 +266,8 @@ char output_buffer[1500*1024]; - - int main() - { -- output_data = output_buffer; -- -- makecrc(); - putstr("Uncompressing Linux..."); -- gunzip(); -+ unlzma((u8 *) output_buffer, input_data, window); - putstr("done.\n"); - return 0; - } ---- a/arch/arm/boot/compressed/piggy.S -+++ b/arch/arm/boot/compressed/piggy.S -@@ -1,6 +1,6 @@ - .section .piggydata,#alloc - .globl input_data - input_data: -- .incbin "arch/arm/boot/compressed/piggy.gz" -+ .incbin "arch/arm/boot/compressed/piggy.lzma" - .globl input_data_end - input_data_end: ---- /dev/null -+++ b/arch/arm/boot/compressed/unlzma.c -@@ -0,0 +1,429 @@ -+/* -+ * Copyright (c) 2009 Felix Fietkau -+ * -+ * 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, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. -+ * -+ * uncompress.c -+ */ -+ -+#include -+#include -+#include "unlzma.h" -+ -+struct unlzma_ctx { -+ const u8 *next_in; -+ u8 *next_out; -+ u8 *outbuf; -+ -+ /* reader state */ -+ u32 code; -+ u32 range; -+ u32 bound; -+ -+ /* writer state */ -+ u8 previous_byte; -+ ssize_t pos; -+ -+ /* cstate */ -+ int state; -+ u32 rep0, rep1, rep2, rep3; -+ -+ void *workspace; -+} ctx; -+ -+static int inbs = 0; -+static inline u8 -+rc_read(void) -+{ -+#if 0 -+ if (unlikely(++inbs > 16 * 1024)) { -+ putstr("."); -+ inbs = 0; -+ } -+#endif -+ return *(ctx.next_in++); -+} -+ -+ -+static inline void -+rc_get_code(void) -+{ -+ ctx.code = (ctx.code << 8) | rc_read(); -+} -+ -+static inline void -+rc_normalize(void) -+{ -+ if (ctx.range < (1 << RC_TOP_BITS)) { -+ ctx.range <<= 8; -+ rc_get_code(); -+ } -+} -+ -+static inline int -+rc_is_bit_0(u16 *p) -+{ -+ rc_normalize(); -+ ctx.bound = *p * (ctx.range >> RC_MODEL_TOTAL_BITS); -+ return ctx.code < ctx.bound; -+} -+ -+static inline void -+rc_update_bit_0(u16 *p) -+{ -+ ctx.range = ctx.bound; -+ *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; -+} -+ -+static inline void -+rc_update_bit_1(u16 *p) -+{ -+ ctx.range -= ctx.bound; -+ ctx.code -= ctx.bound; -+ *p -= *p >> RC_MOVE_BITS; -+} -+ -+static inline bool -+rc_get_bit(u16 *p, int *symbol) -+{ -+ if (rc_is_bit_0(p)) { -+ rc_update_bit_0(p); -+ *symbol *= 2; -+ return 0; -+ } else { -+ rc_update_bit_1(p); -+ *symbol = *symbol * 2 + 1; -+ return 1; -+ } -+} -+ -+static inline int -+rc_direct_bit(void) -+{ -+ rc_normalize(); -+ ctx.range >>= 1; -+ if (ctx.code >= ctx.range) { -+ ctx.code -= ctx.range; -+ return 1; -+ } -+ return 0; -+} -+ -+static inline void -+rc_bit_tree_decode(u16 *p, int num_levels, int *symbol) -+{ -+ int i = num_levels; -+ -+ *symbol = 1; -+ while (i--) -+ rc_get_bit(p + *symbol, symbol); -+ *symbol -= 1 << num_levels; -+} -+ -+static inline u8 -+peek_old_byte(u32 offs) -+{ -+ u32 pos = ctx.pos - offs; -+ return ctx.outbuf[pos]; -+} -+ -+static inline void -+write_byte(u8 byte) -+{ -+ ctx.previous_byte = byte; -+ *(ctx.next_out++) = byte; -+ ctx.pos++; -+} -+ -+ -+static inline void -+copy_byte(u32 offs) -+{ -+ write_byte(peek_old_byte(offs)); -+} -+ -+static inline void -+copy_bytes(u32 rep0, int len) -+{ -+ do { -+ copy_byte(rep0); -+ len--; -+ } while (len != 0); -+} -+ -+static inline void -+process_bit0(u16 *p, int pos_state, u16 *prob, -+ int lc, u32 literal_pos_mask) -+{ -+ int mi = 1; -+ rc_update_bit_0(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.rep0); -+ do { -+ u16 bit; -+ u16 *prob_lit; -+ -+ match_byte <<= 1; -+ bit = match_byte & 0x100; -+ prob_lit = prob + 0x100 + bit + mi; -+ if (rc_get_bit(prob_lit, &mi) != !!bit) -+ break; -+ } while (mi < 0x100); -+ } -+ while (mi < 0x100) { -+ u16 *prob_lit = prob + mi; -+ rc_get_bit(prob_lit, &mi); -+ } -+ write_byte(mi); -+ if (ctx.state < 4) -+ ctx.state = 0; -+ else if (ctx.state < 10) -+ ctx.state -= 3; -+ else -+ ctx.state -= 6; -+} -+ -+static inline void -+process_bit1(u16 *p, int pos_state, u16 *prob) -+{ -+ int offset; -+ u16 *prob_len; -+ int num_bits; -+ int len; -+ -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(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(prob); -+ prob = p + LZMA_IS_REP_G0 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ prob = (p + LZMA_IS_REP_0_LONG -+ + (ctx.state << -+ LZMA_NUM_POS_BITS_MAX) + -+ pos_state); -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ -+ ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? -+ 9 : 11; -+ copy_byte(ctx.rep0); -+ return; -+ } else { -+ rc_update_bit_1(prob); -+ } -+ } else { -+ u32 distance; -+ -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP_G1 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ distance = ctx.rep1; -+ } else { -+ rc_update_bit_1(prob); -+ prob = p + LZMA_IS_REP_G2 + ctx.state; -+ if (rc_is_bit_0(prob)) { -+ rc_update_bit_0(prob); -+ distance = ctx.rep2; -+ } else { -+ rc_update_bit_1(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(prob_len)) { -+ rc_update_bit_0(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(prob_len); -+ prob_len = prob + LZMA_LEN_CHOICE_2; -+ if (rc_is_bit_0(prob_len)) { -+ rc_update_bit_0(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(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(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(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(); -+ 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(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.rep0, len); -+} -+ -+ -+static int -+do_unlzma(void) -+{ -+ 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.pos = 0; -+ ctx.state = 0; -+ ctx.rep0 = ctx.rep1 = ctx.rep2 = ctx.rep3 = 1; -+ -+ ctx.previous_byte = 0; -+ ctx.code = 0; -+ ctx.range = 0xFFFFFFFF; -+ -+ 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; -+ -+ 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(); -+ -+ 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(prob)) -+ process_bit0(p, pos_state, prob, -+ lc, literal_pos_mask); -+ else { -+ process_bit1(p, pos_state, prob); -+ if (ctx.rep0 == 0) -+ break; -+ } -+ } -+ -+ return ctx.pos; -+} -+ -+ -+static int unlzma(unsigned char *dest, const unsigned char *src, unsigned char *workspace) -+{ -+ memset(&ctx, 0, sizeof(ctx)); -+ ctx.outbuf = dest; -+ ctx.next_in = src; -+ ctx.next_out = dest; -+ ctx.workspace = workspace; -+ -+ return do_unlzma(); -+} -+ -+ ---- /dev/null -+++ b/arch/arm/boot/compressed/unlzma.h -@@ -0,0 +1,81 @@ -+/* LZMA uncompresion module for pcomp -+ * Copyright (C) 2009 Felix Fietkau -+ * -+ * Based on: -+ * Initial Linux kernel adaptation -+ * Copyright (C) 2006 Alain < alain@knaff.lu > -+ * -+ * Based on small lzma deflate implementation/Small range coder -+ * implementation for lzma. -+ * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > -+ * -+ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) -+ * Copyright (C) 1999-2005 Igor Pavlov -+ * -+ * This program is free software; you can redistribute it and/or modify it -+ * under the terms of the GNU General Public License version 2 as published -+ * by the Free Software Foundation. -+ */ -+#ifndef __UNLZMA_H -+#define __UNLZMA_H -+ -+struct lzma_header { -+ __u8 pos; -+ __le32 dict_size; -+ __le64 uncompr_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