aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2011-01-12 20:01:23 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2011-01-13 11:03:25 -0500
commit3ebe12439ba7fc62e1d6ecb569b7287771716ca1 (patch)
tree65945a63ad1474489d80c8ca1fb1c1c8091fb7a2
parent24fa0402a9b6a537e87e38341e78b7da86486846 (diff)
decompressors: add boot-time XZ support
This implements the API defined in <linux/decompress/generic.h> which is used for kernel, initramfs, and initrd decompression. This patch together with the first patch is enough for XZ-compressed initramfs and initrd; XZ-compressed kernel will need arch-specific changes. The buffering requirements described in decompress_unxz.c are stricter than with gzip, so the relevant changes should be done to the arch-specific code when adding support for XZ-compressed kernel. Similarly, the heap size in arch-specific pre-boot code may need to be increased (30 KiB is enough). The XZ decompressor needs memmove(), memeq() (memcmp() == 0), and memzero() (memset(ptr, 0, size)), which aren't available in all arch-specific pre-boot environments. I'm including simple versions in decompress_unxz.c, but a cleaner solution would naturally be nicer. Signed-off-by: Lasse Collin <lasse.collin@tukaani.org> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Alain Knaff <alain@knaff.lu> Cc: Albin Tonnerre <albin.tonnerre@free-electrons.com> Cc: Phillip Lougher <phillip@lougher.demon.co.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--include/linux/decompress/unxz.h19
-rw-r--r--init/Kconfig20
-rw-r--r--lib/Kconfig4
-rw-r--r--lib/Makefile1
-rw-r--r--lib/decompress.c5
-rw-r--r--lib/decompress_unxz.c397
-rw-r--r--scripts/gen_initramfs_list.sh2
-rw-r--r--usr/Kconfig18
-rw-r--r--usr/Makefile5
9 files changed, 469 insertions, 2 deletions
diff --git a/include/linux/decompress/unxz.h b/include/linux/decompress/unxz.h
new file mode 100644
index 000000000000..41728fc6c8a1
--- /dev/null
+++ b/include/linux/decompress/unxz.h
@@ -0,0 +1,19 @@
1/*
2 * Wrapper for decompressing XZ-compressed kernel, initramfs, and initrd
3 *
4 * Author: Lasse Collin <lasse.collin@tukaani.org>
5 *
6 * This file has been put into the public domain.
7 * You can do whatever you want with this file.
8 */
9
10#ifndef DECOMPRESS_UNXZ_H
11#define DECOMPRESS_UNXZ_H
12
13int unxz(unsigned char *in, int in_size,
14 int (*fill)(void *dest, unsigned int size),
15 int (*flush)(void *src, unsigned int size),
16 unsigned char *out, int *in_used,
17 void (*error)(char *x));
18
19#endif
diff --git a/init/Kconfig b/init/Kconfig
index 8dfd094e6875..ea176e8edbdd 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -130,13 +130,16 @@ config HAVE_KERNEL_BZIP2
130config HAVE_KERNEL_LZMA 130config HAVE_KERNEL_LZMA
131 bool 131 bool
132 132
133config HAVE_KERNEL_XZ
134 bool
135
133config HAVE_KERNEL_LZO 136config HAVE_KERNEL_LZO
134 bool 137 bool
135 138
136choice 139choice
137 prompt "Kernel compression mode" 140 prompt "Kernel compression mode"
138 default KERNEL_GZIP 141 default KERNEL_GZIP
139 depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_LZO 142 depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO
140 help 143 help
141 The linux kernel is a kind of self-extracting executable. 144 The linux kernel is a kind of self-extracting executable.
142 Several compression algorithms are available, which differ 145 Several compression algorithms are available, which differ
@@ -181,6 +184,21 @@ config KERNEL_LZMA
181 two. Compression is slowest. The kernel size is about 33% 184 two. Compression is slowest. The kernel size is about 33%
182 smaller with LZMA in comparison to gzip. 185 smaller with LZMA in comparison to gzip.
183 186
187config KERNEL_XZ
188 bool "XZ"
189 depends on HAVE_KERNEL_XZ
190 help
191 XZ uses the LZMA2 algorithm and instruction set specific
192 BCJ filters which can improve compression ratio of executable
193 code. The size of the kernel is about 30% smaller with XZ in
194 comparison to gzip. On architectures for which there is a BCJ
195 filter (i386, x86_64, ARM, IA-64, PowerPC, and SPARC), XZ
196 will create a few percent smaller kernel than plain LZMA.
197
198 The speed is about the same as with LZMA: The decompression
199 speed of XZ is better than that of bzip2 but worse than gzip
200 and LZO. Compression is slow.
201
184config KERNEL_LZO 202config KERNEL_LZO
185 bool "LZO" 203 bool "LZO"
186 depends on HAVE_KERNEL_LZO 204 depends on HAVE_KERNEL_LZO
diff --git a/lib/Kconfig b/lib/Kconfig
index 2b8f8540d670..0ee67e08ad3e 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -122,6 +122,10 @@ config DECOMPRESS_BZIP2
122config DECOMPRESS_LZMA 122config DECOMPRESS_LZMA
123 tristate 123 tristate
124 124
125config DECOMPRESS_XZ
126 select XZ_DEC
127 tristate
128
125config DECOMPRESS_LZO 129config DECOMPRESS_LZO
126 select LZO_DECOMPRESS 130 select LZO_DECOMPRESS
127 tristate 131 tristate
diff --git a/lib/Makefile b/lib/Makefile
index 4df2d0297721..cbb774f7d41d 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -75,6 +75,7 @@ obj-$(CONFIG_RAID6_PQ) += raid6/
75lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o 75lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
76lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o 76lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
77lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o 77lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
78lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o
78lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o 79lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
79 80
80obj-$(CONFIG_TEXTSEARCH) += textsearch.o 81obj-$(CONFIG_TEXTSEARCH) += textsearch.o
diff --git a/lib/decompress.c b/lib/decompress.c
index a7606815541f..3d766b7f60ab 100644
--- a/lib/decompress.c
+++ b/lib/decompress.c
@@ -8,6 +8,7 @@
8 8
9#include <linux/decompress/bunzip2.h> 9#include <linux/decompress/bunzip2.h>
10#include <linux/decompress/unlzma.h> 10#include <linux/decompress/unlzma.h>
11#include <linux/decompress/unxz.h>
11#include <linux/decompress/inflate.h> 12#include <linux/decompress/inflate.h>
12#include <linux/decompress/unlzo.h> 13#include <linux/decompress/unlzo.h>
13 14
@@ -23,6 +24,9 @@
23#ifndef CONFIG_DECOMPRESS_LZMA 24#ifndef CONFIG_DECOMPRESS_LZMA
24# define unlzma NULL 25# define unlzma NULL
25#endif 26#endif
27#ifndef CONFIG_DECOMPRESS_XZ
28# define unxz NULL
29#endif
26#ifndef CONFIG_DECOMPRESS_LZO 30#ifndef CONFIG_DECOMPRESS_LZO
27# define unlzo NULL 31# define unlzo NULL
28#endif 32#endif
@@ -36,6 +40,7 @@ static const struct compress_format {
36 { {037, 0236}, "gzip", gunzip }, 40 { {037, 0236}, "gzip", gunzip },
37 { {0x42, 0x5a}, "bzip2", bunzip2 }, 41 { {0x42, 0x5a}, "bzip2", bunzip2 },
38 { {0x5d, 0x00}, "lzma", unlzma }, 42 { {0x5d, 0x00}, "lzma", unlzma },
43 { {0xfd, 0x37}, "xz", unxz },
39 { {0x89, 0x4c}, "lzo", unlzo }, 44 { {0x89, 0x4c}, "lzo", unlzo },
40 { {0, 0}, NULL, NULL } 45 { {0, 0}, NULL, NULL }
41}; 46};
diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c
new file mode 100644
index 000000000000..cecd23df2b9a
--- /dev/null
+++ b/lib/decompress_unxz.c
@@ -0,0 +1,397 @@
1/*
2 * Wrapper for decompressing XZ-compressed kernel, initramfs, and initrd
3 *
4 * Author: Lasse Collin <lasse.collin@tukaani.org>
5 *
6 * This file has been put into the public domain.
7 * You can do whatever you want with this file.
8 */
9
10/*
11 * Important notes about in-place decompression
12 *
13 * At least on x86, the kernel is decompressed in place: the compressed data
14 * is placed to the end of the output buffer, and the decompressor overwrites
15 * most of the compressed data. There must be enough safety margin to
16 * guarantee that the write position is always behind the read position.
17 *
18 * The safety margin for XZ with LZMA2 or BCJ+LZMA2 is calculated below.
19 * Note that the margin with XZ is bigger than with Deflate (gzip)!
20 *
21 * The worst case for in-place decompression is that the beginning of
22 * the file is compressed extremely well, and the rest of the file is
23 * uncompressible. Thus, we must look for worst-case expansion when the
24 * compressor is encoding uncompressible data.
25 *
26 * The structure of the .xz file in case of a compresed kernel is as follows.
27 * Sizes (as bytes) of the fields are in parenthesis.
28 *
29 * Stream Header (12)
30 * Block Header:
31 * Block Header (8-12)
32 * Compressed Data (N)
33 * Block Padding (0-3)
34 * CRC32 (4)
35 * Index (8-20)
36 * Stream Footer (12)
37 *
38 * Normally there is exactly one Block, but let's assume that there are
39 * 2-4 Blocks just in case. Because Stream Header and also Block Header
40 * of the first Block don't make the decompressor produce any uncompressed
41 * data, we can ignore them from our calculations. Block Headers of possible
42 * additional Blocks have to be taken into account still. With these
43 * assumptions, it is safe to assume that the total header overhead is
44 * less than 128 bytes.
45 *
46 * Compressed Data contains LZMA2 or BCJ+LZMA2 encoded data. Since BCJ
47 * doesn't change the size of the data, it is enough to calculate the
48 * safety margin for LZMA2.
49 *
50 * LZMA2 stores the data in chunks. Each chunk has a header whose size is
51 * a maximum of 6 bytes, but to get round 2^n numbers, let's assume that
52 * the maximum chunk header size is 8 bytes. After the chunk header, there
53 * may be up to 64 KiB of actual payload in the chunk. Often the payload is
54 * quite a bit smaller though; to be safe, let's assume that an average
55 * chunk has only 32 KiB of payload.
56 *
57 * The maximum uncompressed size of the payload is 2 MiB. The minimum
58 * uncompressed size of the payload is in practice never less than the
59 * payload size itself. The LZMA2 format would allow uncompressed size
60 * to be less than the payload size, but no sane compressor creates such
61 * files. LZMA2 supports storing uncompressible data in uncompressed form,
62 * so there's never a need to create payloads whose uncompressed size is
63 * smaller than the compressed size.
64 *
65 * The assumption, that the uncompressed size of the payload is never
66 * smaller than the payload itself, is valid only when talking about