| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | /*
 | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  |  *  LZO1X Decompressor from LZO | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  |  *  Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  |  * | 
					
						
							|  |  |  |  *  The full LZO package can be found at: | 
					
						
							|  |  |  |  *  http://www.oberhumer.com/opensource/lzo/
 | 
					
						
							|  |  |  |  * | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  |  *  Changed for Linux kernel use by: | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  |  *  Nitin Gupta <nitingupta910@gmail.com> | 
					
						
							|  |  |  |  *  Richard Purdie <rpurdie@openedhand.com> | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												lib: add support for LZO-compressed kernels
This patch series adds generic support for creating and extracting
LZO-compressed kernel images, as well as support for using such images on
the x86 and ARM architectures, and support for creating and using
LZO-compressed initrd and initramfs images.
Russell King said:
: Testing on a Cortex A9 model:
: - lzo decompressor is 65% of the time gzip takes to decompress a kernel
: - lzo kernel is 9% larger than a gzip kernel
:
: which I'm happy to say confirms your figures when comparing the two.
:
: However, when comparing your new gzip code to the old gzip code:
: - new is 99% of the size of the old code
: - new takes 42% of the time to decompress than the old code
:
: What this means is that for a proper comparison, the results get even better:
: - lzo is 7.5% larger than the old gzip'd kernel image
: - lzo takes 28% of the time that the old gzip code took
:
: So the expense seems definitely worth the effort.  The only reason I
: can think of ever using gzip would be if you needed the additional
: compression (eg, because you have limited flash to store the image.)
:
: I would argue that the default for ARM should therefore be LZO.
This patch:
The lzo compressor is worse than gzip at compression, but faster at
extraction.  Here are some figures for an ARM board I'm working on:
Uncompressed size: 3.24Mo
gzip  1.61Mo 0.72s
lzo   1.75Mo 0.48s
So for a compression ratio that is still relatively close to gzip, it's
much faster to extract, at least in that case.
This part contains:
 - Makefile routine to support lzo compression
 - Fixes to the existing lzo compressor so that it can be used in
   compressed kernels
 - wrapper around the existing lzo1x_decompress, as it only extracts one
   block at a time, while we need to extract a whole file here
 - config dialog for kernel compression
[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: cleanup]
Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
Tested-by: Wu Zhangjin <wuzhangjin@gmail.com>
Acked-by: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Russell King <rmk@arm.linux.org.uk>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2010-01-08 14:42:42 -08:00
										 |  |  | #ifndef STATIC
 | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | #include <linux/module.h>
 | 
					
						
							|  |  |  | #include <linux/kernel.h>
 | 
					
						
							| 
									
										
											  
											
												lib: add support for LZO-compressed kernels
This patch series adds generic support for creating and extracting
LZO-compressed kernel images, as well as support for using such images on
the x86 and ARM architectures, and support for creating and using
LZO-compressed initrd and initramfs images.
Russell King said:
: Testing on a Cortex A9 model:
: - lzo decompressor is 65% of the time gzip takes to decompress a kernel
: - lzo kernel is 9% larger than a gzip kernel
:
: which I'm happy to say confirms your figures when comparing the two.
:
: However, when comparing your new gzip code to the old gzip code:
: - new is 99% of the size of the old code
: - new takes 42% of the time to decompress than the old code
:
: What this means is that for a proper comparison, the results get even better:
: - lzo is 7.5% larger than the old gzip'd kernel image
: - lzo takes 28% of the time that the old gzip code took
:
: So the expense seems definitely worth the effort.  The only reason I
: can think of ever using gzip would be if you needed the additional
: compression (eg, because you have limited flash to store the image.)
:
: I would argue that the default for ARM should therefore be LZO.
This patch:
The lzo compressor is worse than gzip at compression, but faster at
extraction.  Here are some figures for an ARM board I'm working on:
Uncompressed size: 3.24Mo
gzip  1.61Mo 0.72s
lzo   1.75Mo 0.48s
So for a compression ratio that is still relatively close to gzip, it's
much faster to extract, at least in that case.
This part contains:
 - Makefile routine to support lzo compression
 - Fixes to the existing lzo compressor so that it can be used in
   compressed kernels
 - wrapper around the existing lzo1x_decompress, as it only extracts one
   block at a time, while we need to extract a whole file here
 - config dialog for kernel compression
[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: cleanup]
Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
Tested-by: Wu Zhangjin <wuzhangjin@gmail.com>
Acked-by: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Russell King <rmk@arm.linux.org.uk>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2010-01-08 14:42:42 -08:00
										 |  |  | #endif
 | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | #include <asm/unaligned.h>
 | 
					
						
							| 
									
										
											  
											
												lib: add support for LZO-compressed kernels
This patch series adds generic support for creating and extracting
LZO-compressed kernel images, as well as support for using such images on
the x86 and ARM architectures, and support for creating and using
LZO-compressed initrd and initramfs images.
Russell King said:
: Testing on a Cortex A9 model:
: - lzo decompressor is 65% of the time gzip takes to decompress a kernel
: - lzo kernel is 9% larger than a gzip kernel
:
: which I'm happy to say confirms your figures when comparing the two.
:
: However, when comparing your new gzip code to the old gzip code:
: - new is 99% of the size of the old code
: - new takes 42% of the time to decompress than the old code
:
: What this means is that for a proper comparison, the results get even better:
: - lzo is 7.5% larger than the old gzip'd kernel image
: - lzo takes 28% of the time that the old gzip code took
:
: So the expense seems definitely worth the effort.  The only reason I
: can think of ever using gzip would be if you needed the additional
: compression (eg, because you have limited flash to store the image.)
:
: I would argue that the default for ARM should therefore be LZO.
This patch:
The lzo compressor is worse than gzip at compression, but faster at
extraction.  Here are some figures for an ARM board I'm working on:
Uncompressed size: 3.24Mo
gzip  1.61Mo 0.72s
lzo   1.75Mo 0.48s
So for a compression ratio that is still relatively close to gzip, it's
much faster to extract, at least in that case.
This part contains:
 - Makefile routine to support lzo compression
 - Fixes to the existing lzo compressor so that it can be used in
   compressed kernels
 - wrapper around the existing lzo1x_decompress, as it only extracts one
   block at a time, while we need to extract a whole file here
 - config dialog for kernel compression
[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: cleanup]
Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
Tested-by: Wu Zhangjin <wuzhangjin@gmail.com>
Acked-by: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Russell King <rmk@arm.linux.org.uk>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2010-01-08 14:42:42 -08:00
										 |  |  | #include <linux/lzo.h>
 | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | #include "lzodefs.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | #define HAVE_IP(x)      ((size_t)(ip_end - ip) >= (size_t)(x))
 | 
					
						
							|  |  |  | #define HAVE_OP(x)      ((size_t)(op_end - op) >= (size_t)(x))
 | 
					
						
							|  |  |  | #define NEED_IP(x)      if (!HAVE_IP(x)) goto input_overrun
 | 
					
						
							|  |  |  | #define NEED_OP(x)      if (!HAVE_OP(x)) goto output_overrun
 | 
					
						
							|  |  |  | #define TEST_LB(m_pos)  if ((m_pos) < out) goto lookbehind_overrun
 | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:37 +02:00
										 |  |  | /* This MAX_255_COUNT is the maximum number of times we can add 255 to a base
 | 
					
						
							|  |  |  |  * count without overflowing an integer. The multiply will overflow when | 
					
						
							|  |  |  |  * multiplying 255 by more than MAXINT/255. The sum will overflow earlier | 
					
						
							|  |  |  |  * depending on the base count. Since the base count is taken from a u8 | 
					
						
							|  |  |  |  * and a few bits, it is safe to assume that it will always be lower than | 
					
						
							|  |  |  |  * or equal to 2*255, thus we can always prevent any overflow by accepting | 
					
						
							|  |  |  |  * two less 255 steps. See Documentation/lzo.txt for more information. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | #define MAX_255_COUNT      ((((size_t)~0) / 255) - 2)
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | int lzo1x_decompress_safe(const unsigned char *in, size_t in_len, | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 			  unsigned char *out, size_t *out_len) | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 	unsigned char *op; | 
					
						
							|  |  |  | 	const unsigned char *ip; | 
					
						
							|  |  |  | 	size_t t, next; | 
					
						
							|  |  |  | 	size_t state = 0; | 
					
						
							|  |  |  | 	const unsigned char *m_pos; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 	const unsigned char * const ip_end = in + in_len; | 
					
						
							|  |  |  | 	unsigned char * const op_end = out + *out_len; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 	op = out; | 
					
						
							|  |  |  | 	ip = in; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 	if (unlikely(in_len < 3)) | 
					
						
							|  |  |  | 		goto input_overrun; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 	if (*ip > 17) { | 
					
						
							|  |  |  | 		t = *ip++ - 17; | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 		if (t < 4) { | 
					
						
							|  |  |  | 			next = t; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 			goto match_next; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 		goto copy_literal_run; | 
					
						
							|  |  |  | 	} | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 	for (;;) { | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 		t = *ip++; | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 		if (t < 16) { | 
					
						
							|  |  |  | 			if (likely(state == 0)) { | 
					
						
							|  |  |  | 				if (unlikely(t == 0)) { | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:37 +02:00
										 |  |  | 					size_t offset; | 
					
						
							|  |  |  | 					const unsigned char *ip_last = ip; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 					while (unlikely(*ip == 0)) { | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 						ip++; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 						NEED_IP(1); | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 					} | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:37 +02:00
										 |  |  | 					offset = ip - ip_last; | 
					
						
							|  |  |  | 					if (unlikely(offset > MAX_255_COUNT)) | 
					
						
							|  |  |  | 						return LZO_E_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 					offset = (offset << 8) - offset; | 
					
						
							|  |  |  | 					t += offset + 15 + *ip++; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				t += 3; | 
					
						
							|  |  |  | copy_literal_run: | 
					
						
							|  |  |  | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
 | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 				if (likely(HAVE_IP(t + 15) && HAVE_OP(t + 15))) { | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 					const unsigned char *ie = ip + t; | 
					
						
							|  |  |  | 					unsigned char *oe = op + t; | 
					
						
							|  |  |  | 					do { | 
					
						
							|  |  |  | 						COPY8(op, ip); | 
					
						
							|  |  |  | 						op += 8; | 
					
						
							|  |  |  | 						ip += 8; | 
					
						
							|  |  |  | 						COPY8(op, ip); | 
					
						
							|  |  |  | 						op += 8; | 
					
						
							|  |  |  | 						ip += 8; | 
					
						
							|  |  |  | 					} while (ip < ie); | 
					
						
							|  |  |  | 					ip = ie; | 
					
						
							|  |  |  | 					op = oe; | 
					
						
							|  |  |  | 				} else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 				{ | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 					NEED_OP(t); | 
					
						
							|  |  |  | 					NEED_IP(t + 3); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 					do { | 
					
						
							|  |  |  | 						*op++ = *ip++; | 
					
						
							|  |  |  | 					} while (--t > 0); | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				state = 4; | 
					
						
							|  |  |  | 				continue; | 
					
						
							|  |  |  | 			} else if (state != 4) { | 
					
						
							|  |  |  | 				next = t & 3; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 				m_pos = op - 1; | 
					
						
							|  |  |  | 				m_pos -= t >> 2; | 
					
						
							|  |  |  | 				m_pos -= *ip++ << 2; | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				TEST_LB(m_pos); | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 				NEED_OP(2); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				op[0] = m_pos[0]; | 
					
						
							|  |  |  | 				op[1] = m_pos[1]; | 
					
						
							|  |  |  | 				op += 2; | 
					
						
							|  |  |  | 				goto match_next; | 
					
						
							|  |  |  | 			} else { | 
					
						
							|  |  |  | 				next = t & 3; | 
					
						
							|  |  |  | 				m_pos = op - (1 + M2_MAX_OFFSET); | 
					
						
							|  |  |  | 				m_pos -= t >> 2; | 
					
						
							|  |  |  | 				m_pos -= *ip++ << 2; | 
					
						
							|  |  |  | 				t = 3; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 		} else if (t >= 64) { | 
					
						
							|  |  |  | 			next = t & 3; | 
					
						
							|  |  |  | 			m_pos = op - 1; | 
					
						
							|  |  |  | 			m_pos -= (t >> 2) & 7; | 
					
						
							|  |  |  | 			m_pos -= *ip++ << 3; | 
					
						
							|  |  |  | 			t = (t >> 5) - 1 + (3 - 1); | 
					
						
							|  |  |  | 		} else if (t >= 32) { | 
					
						
							|  |  |  | 			t = (t & 31) + (3 - 1); | 
					
						
							|  |  |  | 			if (unlikely(t == 2)) { | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:37 +02:00
										 |  |  | 				size_t offset; | 
					
						
							|  |  |  | 				const unsigned char *ip_last = ip; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				while (unlikely(*ip == 0)) { | 
					
						
							|  |  |  | 					ip++; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 					NEED_IP(1); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:37 +02:00
										 |  |  | 				offset = ip - ip_last; | 
					
						
							|  |  |  | 				if (unlikely(offset > MAX_255_COUNT)) | 
					
						
							|  |  |  | 					return LZO_E_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				offset = (offset << 8) - offset; | 
					
						
							|  |  |  | 				t += offset + 31 + *ip++; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 				NEED_IP(2); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			m_pos = op - 1; | 
					
						
							|  |  |  | 			next = get_unaligned_le16(ip); | 
					
						
							|  |  |  | 			ip += 2; | 
					
						
							|  |  |  | 			m_pos -= next >> 2; | 
					
						
							|  |  |  | 			next &= 3; | 
					
						
							|  |  |  | 		} else { | 
					
						
							|  |  |  | 			m_pos = op; | 
					
						
							|  |  |  | 			m_pos -= (t & 8) << 11; | 
					
						
							|  |  |  | 			t = (t & 7) + (3 - 1); | 
					
						
							|  |  |  | 			if (unlikely(t == 2)) { | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:37 +02:00
										 |  |  | 				size_t offset; | 
					
						
							|  |  |  | 				const unsigned char *ip_last = ip; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				while (unlikely(*ip == 0)) { | 
					
						
							|  |  |  | 					ip++; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 					NEED_IP(1); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				} | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:37 +02:00
										 |  |  | 				offset = ip - ip_last; | 
					
						
							|  |  |  | 				if (unlikely(offset > MAX_255_COUNT)) | 
					
						
							|  |  |  | 					return LZO_E_ERROR; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 				offset = (offset << 8) - offset; | 
					
						
							|  |  |  | 				t += offset + 7 + *ip++; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 				NEED_IP(2); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 			} | 
					
						
							|  |  |  | 			next = get_unaligned_le16(ip); | 
					
						
							|  |  |  | 			ip += 2; | 
					
						
							|  |  |  | 			m_pos -= next >> 2; | 
					
						
							|  |  |  | 			next &= 3; | 
					
						
							|  |  |  | 			if (m_pos == op) | 
					
						
							|  |  |  | 				goto eof_found; | 
					
						
							|  |  |  | 			m_pos -= 0x4000; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		TEST_LB(m_pos); | 
					
						
							|  |  |  | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
 | 
					
						
							|  |  |  | 		if (op - m_pos >= 8) { | 
					
						
							|  |  |  | 			unsigned char *oe = op + t; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 			if (likely(HAVE_OP(t + 15))) { | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 				do { | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 					COPY8(op, m_pos); | 
					
						
							|  |  |  | 					op += 8; | 
					
						
							|  |  |  | 					m_pos += 8; | 
					
						
							|  |  |  | 					COPY8(op, m_pos); | 
					
						
							|  |  |  | 					op += 8; | 
					
						
							|  |  |  | 					m_pos += 8; | 
					
						
							|  |  |  | 				} while (op < oe); | 
					
						
							|  |  |  | 				op = oe; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 				if (HAVE_IP(6)) { | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 					state = next; | 
					
						
							|  |  |  | 					COPY4(op, ip); | 
					
						
							|  |  |  | 					op += next; | 
					
						
							|  |  |  | 					ip += next; | 
					
						
							|  |  |  | 					continue; | 
					
						
							|  |  |  | 				} | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 			} else { | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 				NEED_OP(t); | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 				do { | 
					
						
							|  |  |  | 					*op++ = *m_pos++; | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				} while (op < oe); | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 		} else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			unsigned char *oe = op + t; | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 			NEED_OP(t); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 			op[0] = m_pos[0]; | 
					
						
							|  |  |  | 			op[1] = m_pos[1]; | 
					
						
							|  |  |  | 			op += 2; | 
					
						
							|  |  |  | 			m_pos += 2; | 
					
						
							|  |  |  | 			do { | 
					
						
							|  |  |  | 				*op++ = *m_pos++; | 
					
						
							|  |  |  | 			} while (op < oe); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | match_next: | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 		state = next; | 
					
						
							|  |  |  | 		t = next; | 
					
						
							|  |  |  | #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS)
 | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 		if (likely(HAVE_IP(6) && HAVE_OP(4))) { | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 			COPY4(op, ip); | 
					
						
							|  |  |  | 			op += t; | 
					
						
							|  |  |  | 			ip += t; | 
					
						
							|  |  |  | 		} else | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2014-09-27 12:31:36 +02:00
										 |  |  | 			NEED_IP(t + 3); | 
					
						
							|  |  |  | 			NEED_OP(t); | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 			while (t > 0) { | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 				*op++ = *ip++; | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 				t--; | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 			} | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 		} | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | eof_found: | 
					
						
							|  |  |  | 	*out_len = op - out; | 
					
						
							| 
									
										
										
										
											2012-08-13 17:25:44 +02:00
										 |  |  | 	return (t != 3       ? LZO_E_ERROR : | 
					
						
							|  |  |  | 		ip == ip_end ? LZO_E_OK : | 
					
						
							|  |  |  | 		ip <  ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | input_overrun: | 
					
						
							|  |  |  | 	*out_len = op - out; | 
					
						
							|  |  |  | 	return LZO_E_INPUT_OVERRUN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | output_overrun: | 
					
						
							|  |  |  | 	*out_len = op - out; | 
					
						
							|  |  |  | 	return LZO_E_OUTPUT_OVERRUN; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | lookbehind_overrun: | 
					
						
							|  |  |  | 	*out_len = op - out; | 
					
						
							|  |  |  | 	return LZO_E_LOOKBEHIND_OVERRUN; | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
											  
											
												lib: add support for LZO-compressed kernels
This patch series adds generic support for creating and extracting
LZO-compressed kernel images, as well as support for using such images on
the x86 and ARM architectures, and support for creating and using
LZO-compressed initrd and initramfs images.
Russell King said:
: Testing on a Cortex A9 model:
: - lzo decompressor is 65% of the time gzip takes to decompress a kernel
: - lzo kernel is 9% larger than a gzip kernel
:
: which I'm happy to say confirms your figures when comparing the two.
:
: However, when comparing your new gzip code to the old gzip code:
: - new is 99% of the size of the old code
: - new takes 42% of the time to decompress than the old code
:
: What this means is that for a proper comparison, the results get even better:
: - lzo is 7.5% larger than the old gzip'd kernel image
: - lzo takes 28% of the time that the old gzip code took
:
: So the expense seems definitely worth the effort.  The only reason I
: can think of ever using gzip would be if you needed the additional
: compression (eg, because you have limited flash to store the image.)
:
: I would argue that the default for ARM should therefore be LZO.
This patch:
The lzo compressor is worse than gzip at compression, but faster at
extraction.  Here are some figures for an ARM board I'm working on:
Uncompressed size: 3.24Mo
gzip  1.61Mo 0.72s
lzo   1.75Mo 0.48s
So for a compression ratio that is still relatively close to gzip, it's
much faster to extract, at least in that case.
This part contains:
 - Makefile routine to support lzo compression
 - Fixes to the existing lzo compressor so that it can be used in
   compressed kernels
 - wrapper around the existing lzo1x_decompress, as it only extracts one
   block at a time, while we need to extract a whole file here
 - config dialog for kernel compression
[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: cleanup]
Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
Tested-by: Wu Zhangjin <wuzhangjin@gmail.com>
Acked-by: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Russell King <rmk@arm.linux.org.uk>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2010-01-08 14:42:42 -08:00
										 |  |  | #ifndef STATIC
 | 
					
						
							| 
									
										
										
										
											2007-07-10 17:22:24 -07:00
										 |  |  | EXPORT_SYMBOL_GPL(lzo1x_decompress_safe); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | MODULE_LICENSE("GPL"); | 
					
						
							|  |  |  | MODULE_DESCRIPTION("LZO1X Decompressor"); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
											  
											
												lib: add support for LZO-compressed kernels
This patch series adds generic support for creating and extracting
LZO-compressed kernel images, as well as support for using such images on
the x86 and ARM architectures, and support for creating and using
LZO-compressed initrd and initramfs images.
Russell King said:
: Testing on a Cortex A9 model:
: - lzo decompressor is 65% of the time gzip takes to decompress a kernel
: - lzo kernel is 9% larger than a gzip kernel
:
: which I'm happy to say confirms your figures when comparing the two.
:
: However, when comparing your new gzip code to the old gzip code:
: - new is 99% of the size of the old code
: - new takes 42% of the time to decompress than the old code
:
: What this means is that for a proper comparison, the results get even better:
: - lzo is 7.5% larger than the old gzip'd kernel image
: - lzo takes 28% of the time that the old gzip code took
:
: So the expense seems definitely worth the effort.  The only reason I
: can think of ever using gzip would be if you needed the additional
: compression (eg, because you have limited flash to store the image.)
:
: I would argue that the default for ARM should therefore be LZO.
This patch:
The lzo compressor is worse than gzip at compression, but faster at
extraction.  Here are some figures for an ARM board I'm working on:
Uncompressed size: 3.24Mo
gzip  1.61Mo 0.72s
lzo   1.75Mo 0.48s
So for a compression ratio that is still relatively close to gzip, it's
much faster to extract, at least in that case.
This part contains:
 - Makefile routine to support lzo compression
 - Fixes to the existing lzo compressor so that it can be used in
   compressed kernels
 - wrapper around the existing lzo1x_decompress, as it only extracts one
   block at a time, while we need to extract a whole file here
 - config dialog for kernel compression
[akpm@linux-foundation.org: coding-style fixes]
[akpm@linux-foundation.org: cleanup]
Signed-off-by: Albin Tonnerre <albin.tonnerre@free-electrons.com>
Tested-by: Wu Zhangjin <wuzhangjin@gmail.com>
Acked-by: "H. Peter Anvin" <hpa@zytor.com>
Cc: Ingo Molnar <mingo@elte.hu>
Cc: Thomas Gleixner <tglx@linutronix.de>
Tested-by: Russell King <rmk@arm.linux.org.uk>
Acked-by: Russell King <rmk@arm.linux.org.uk>
Cc: Ralf Baechle <ralf@linux-mips.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
											
										 
											2010-01-08 14:42:42 -08:00
										 |  |  | #endif
 |