wok diff linux-libre/stuff/002-squashfs-decompressors-add-boot-time-xz-support.patch @ rev 25683

Add entry menu to use pm-suspend more friendly
author Stanislas Leduc <shann@slitaz.org>
date Sat Apr 06 11:51:33 2024 +0200 (7 months ago)
parents
children
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/linux-libre/stuff/002-squashfs-decompressors-add-boot-time-xz-support.patch	Sat Apr 06 11:51:33 2024 +0200
     1.3 @@ -0,0 +1,638 @@
     1.4 +From: Lasse Collin <lasse.collin@tukaani.org>
     1.5 +Date: Thu, 2 Dec 2010 19:14:37 +0000 (+0200)
     1.6 +Subject: Decompressors: Add boot-time XZ support
     1.7 +X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fpkl%2Fsquashfs-xz.git;a=commitdiff_plain;h=c64bc9a229b46db75d7761601dd8ca25385a7780
     1.8 +
     1.9 +Decompressors: Add boot-time XZ support
    1.10 +
    1.11 +This implements the API defined in <linux/decompress/generic.h>
    1.12 +which is used for kernel, initramfs, and initrd decompression.
    1.13 +This patch together with the first patch is enough for
    1.14 +XZ-compressed initramfs and initrd; XZ-compressed kernel will
    1.15 +need arch-specific changes.
    1.16 +
    1.17 +In contrast to other initramfs compression methods, support for
    1.18 +XZ-compressed initramfs is not enabled by default in usr/Kconfig.
    1.19 +This is primarily due to the Kconfig options of the xz_dec
    1.20 +module. It can be good to require that xz_dec is enabled
    1.21 +separately so the user can select only the BCJ filters he needs
    1.22 +when EMBEDDED=y.
    1.23 +
    1.24 +The buffering requirements described in decompress_unxz.c are
    1.25 +stricter than with gzip, so the relevant changes should be done
    1.26 +to the arch-specific code when adding support for XZ-compressed
    1.27 +kernel. Similarly, the heap size in arch-specific pre-boot code
    1.28 +may need to be increased (30 KiB is enough).
    1.29 +
    1.30 +The XZ decompressor needs memmove(), memeq() (memcmp() == 0),
    1.31 +and memzero() (memset(ptr, 0, size)), which aren't available in
    1.32 +all arch-specific pre-boot environments. I'm including simple
    1.33 +versions in decompress_unxz.c, but a cleaner solution would
    1.34 +naturally be nicer.
    1.35 +
    1.36 +Signed-off-by: Lasse Collin <lasse.collin@tukaani.org>
    1.37 +---
    1.38 +
    1.39 +diff --git a/include/linux/decompress/unxz.h b/include/linux/decompress/unxz.h
    1.40 +new file mode 100644
    1.41 +index 0000000..41728fc
    1.42 +--- /dev/null
    1.43 ++++ b/include/linux/decompress/unxz.h
    1.44 +@@ -0,0 +1,19 @@
    1.45 ++/*
    1.46 ++ * Wrapper for decompressing XZ-compressed kernel, initramfs, and initrd
    1.47 ++ *
    1.48 ++ * Author: Lasse Collin <lasse.collin@tukaani.org>
    1.49 ++ *
    1.50 ++ * This file has been put into the public domain.
    1.51 ++ * You can do whatever you want with this file.
    1.52 ++ */
    1.53 ++
    1.54 ++#ifndef DECOMPRESS_UNXZ_H
    1.55 ++#define DECOMPRESS_UNXZ_H
    1.56 ++
    1.57 ++int unxz(unsigned char *in, int in_size,
    1.58 ++	 int (*fill)(void *dest, unsigned int size),
    1.59 ++	 int (*flush)(void *src, unsigned int size),
    1.60 ++	 unsigned char *out, int *in_used,
    1.61 ++	 void (*error)(char *x));
    1.62 ++
    1.63 ++#endif
    1.64 +diff --git a/init/Kconfig b/init/Kconfig
    1.65 +index 2de5b1c..d9fbb0f 100644
    1.66 +--- a/init/Kconfig
    1.67 ++++ b/init/Kconfig
    1.68 +@@ -123,13 +123,16 @@ config HAVE_KERNEL_BZIP2
    1.69 + config HAVE_KERNEL_LZMA
    1.70 + 	bool
    1.71 + 
    1.72 ++config HAVE_KERNEL_XZ
    1.73 ++	bool
    1.74 ++
    1.75 + config HAVE_KERNEL_LZO
    1.76 + 	bool
    1.77 + 
    1.78 + choice
    1.79 + 	prompt "Kernel compression mode"
    1.80 + 	default KERNEL_GZIP
    1.81 +-	depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_LZO
    1.82 ++	depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO
    1.83 + 	help
    1.84 + 	  The linux kernel is a kind of self-extracting executable.
    1.85 + 	  Several compression algorithms are available, which differ
    1.86 +@@ -174,6 +177,21 @@ config KERNEL_LZMA
    1.87 + 	  two. Compression is slowest.	The kernel size is about 33%
    1.88 + 	  smaller with LZMA in comparison to gzip.
    1.89 + 
    1.90 ++config KERNEL_XZ
    1.91 ++	bool "XZ"
    1.92 ++	depends on HAVE_KERNEL_XZ
    1.93 ++	help
    1.94 ++	  XZ uses the LZMA2 algorithm and instruction set specific
    1.95 ++	  BCJ filters which can improve compression ratio of executable
    1.96 ++	  code. The size of the kernel is about 30% smaller with XZ in
    1.97 ++	  comparison to gzip. On architectures for which there is a BCJ
    1.98 ++	  filter (i386, x86_64, ARM, IA-64, PowerPC, and SPARC), XZ
    1.99 ++	  will create a few percent smaller kernel than plain LZMA.
   1.100 ++
   1.101 ++	  The speed is about the same as with LZMA: The decompression
   1.102 ++	  speed of XZ is better than that of bzip2 but worse than gzip
   1.103 ++	  and LZO. Compression is slow.
   1.104 ++
   1.105 + config KERNEL_LZO
   1.106 + 	bool "LZO"
   1.107 + 	depends on HAVE_KERNEL_LZO
   1.108 +diff --git a/lib/Kconfig b/lib/Kconfig
   1.109 +index 6090314..45960e1 100644
   1.110 +--- a/lib/Kconfig
   1.111 ++++ b/lib/Kconfig
   1.112 +@@ -122,6 +122,9 @@ config DECOMPRESS_BZIP2
   1.113 + config DECOMPRESS_LZMA
   1.114 + 	tristate
   1.115 + 
   1.116 ++config DECOMPRESS_XZ
   1.117 ++	tristate
   1.118 ++
   1.119 + config DECOMPRESS_LZO
   1.120 + 	select LZO_DECOMPRESS
   1.121 + 	tristate
   1.122 +diff --git a/lib/Makefile b/lib/Makefile
   1.123 +index f2f98dd..06e3d8a 100644
   1.124 +--- a/lib/Makefile
   1.125 ++++ b/lib/Makefile
   1.126 +@@ -75,6 +75,7 @@ obj-$(CONFIG_RAID6_PQ) += raid6/
   1.127 + lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
   1.128 + lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
   1.129 + lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
   1.130 ++lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o
   1.131 + lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
   1.132 + 
   1.133 + obj-$(CONFIG_TEXTSEARCH) += textsearch.o
   1.134 +diff --git a/lib/decompress.c b/lib/decompress.c
   1.135 +index a760681..3d766b7 100644
   1.136 +--- a/lib/decompress.c
   1.137 ++++ b/lib/decompress.c
   1.138 +@@ -8,6 +8,7 @@
   1.139 + 
   1.140 + #include <linux/decompress/bunzip2.h>
   1.141 + #include <linux/decompress/unlzma.h>
   1.142 ++#include <linux/decompress/unxz.h>
   1.143 + #include <linux/decompress/inflate.h>
   1.144 + #include <linux/decompress/unlzo.h>
   1.145 + 
   1.146 +@@ -23,6 +24,9 @@
   1.147 + #ifndef CONFIG_DECOMPRESS_LZMA
   1.148 + # define unlzma NULL
   1.149 + #endif
   1.150 ++#ifndef CONFIG_DECOMPRESS_XZ
   1.151 ++# define unxz NULL
   1.152 ++#endif
   1.153 + #ifndef CONFIG_DECOMPRESS_LZO
   1.154 + # define unlzo NULL
   1.155 + #endif
   1.156 +@@ -36,6 +40,7 @@ static const struct compress_format {
   1.157 + 	{ {037, 0236}, "gzip", gunzip },
   1.158 + 	{ {0x42, 0x5a}, "bzip2", bunzip2 },
   1.159 + 	{ {0x5d, 0x00}, "lzma", unlzma },
   1.160 ++	{ {0xfd, 0x37}, "xz", unxz },
   1.161 + 	{ {0x89, 0x4c}, "lzo", unlzo },
   1.162 + 	{ {0, 0}, NULL, NULL }
   1.163 + };
   1.164 +diff --git a/lib/decompress_unxz.c b/lib/decompress_unxz.c
   1.165 +new file mode 100644
   1.166 +index 0000000..cecd23d
   1.167 +--- /dev/null
   1.168 ++++ b/lib/decompress_unxz.c
   1.169 +@@ -0,0 +1,397 @@
   1.170 ++/*
   1.171 ++ * Wrapper for decompressing XZ-compressed kernel, initramfs, and initrd
   1.172 ++ *
   1.173 ++ * Author: Lasse Collin <lasse.collin@tukaani.org>
   1.174 ++ *
   1.175 ++ * This file has been put into the public domain.
   1.176 ++ * You can do whatever you want with this file.
   1.177 ++ */
   1.178 ++
   1.179 ++/*
   1.180 ++ * Important notes about in-place decompression
   1.181 ++ *
   1.182 ++ * At least on x86, the kernel is decompressed in place: the compressed data
   1.183 ++ * is placed to the end of the output buffer, and the decompressor overwrites
   1.184 ++ * most of the compressed data. There must be enough safety margin to
   1.185 ++ * guarantee that the write position is always behind the read position.
   1.186 ++ *
   1.187 ++ * The safety margin for XZ with LZMA2 or BCJ+LZMA2 is calculated below.
   1.188 ++ * Note that the margin with XZ is bigger than with Deflate (gzip)!
   1.189 ++ *
   1.190 ++ * The worst case for in-place decompression is that the beginning of
   1.191 ++ * the file is compressed extremely well, and the rest of the file is
   1.192 ++ * uncompressible. Thus, we must look for worst-case expansion when the
   1.193 ++ * compressor is encoding uncompressible data.
   1.194 ++ *
   1.195 ++ * The structure of the .xz file in case of a compresed kernel is as follows.
   1.196 ++ * Sizes (as bytes) of the fields are in parenthesis.
   1.197 ++ *
   1.198 ++ *    Stream Header (12)
   1.199 ++ *    Block Header:
   1.200 ++ *      Block Header (8-12)
   1.201 ++ *      Compressed Data (N)
   1.202 ++ *      Block Padding (0-3)
   1.203 ++ *      CRC32 (4)
   1.204 ++ *    Index (8-20)
   1.205 ++ *    Stream Footer (12)
   1.206 ++ *
   1.207 ++ * Normally there is exactly one Block, but let's assume that there are
   1.208 ++ * 2-4 Blocks just in case. Because Stream Header and also Block Header
   1.209 ++ * of the first Block don't make the decompressor produce any uncompressed
   1.210 ++ * data, we can ignore them from our calculations. Block Headers of possible
   1.211 ++ * additional Blocks have to be taken into account still. With these
   1.212 ++ * assumptions, it is safe to assume that the total header overhead is
   1.213 ++ * less than 128 bytes.
   1.214 ++ *
   1.215 ++ * Compressed Data contains LZMA2 or BCJ+LZMA2 encoded data. Since BCJ
   1.216 ++ * doesn't change the size of the data, it is enough to calculate the
   1.217 ++ * safety margin for LZMA2.
   1.218 ++ *
   1.219 ++ * LZMA2 stores the data in chunks. Each chunk has a header whose size is
   1.220 ++ * a maximum of 6 bytes, but to get round 2^n numbers, let's assume that
   1.221 ++ * the maximum chunk header size is 8 bytes. After the chunk header, there
   1.222 ++ * may be up to 64 KiB of actual payload in the chunk. Often the payload is
   1.223 ++ * quite a bit smaller though; to be safe, let's assume that an average
   1.224 ++ * chunk has only 32 KiB of payload.
   1.225 ++ *
   1.226 ++ * The maximum uncompressed size of the payload is 2 MiB. The minimum
   1.227 ++ * uncompressed size of the payload is in practice never less than the
   1.228 ++ * payload size itself. The LZMA2 format would allow uncompressed size
   1.229 ++ * to be less than the payload size, but no sane compressor creates such
   1.230 ++ * files. LZMA2 supports storing uncompressible data in uncompressed form,
   1.231 ++ * so there's never a need to create payloads whose uncompressed size is
   1.232 ++ * smaller than the compressed size.
   1.233 ++ *
   1.234 ++ * The assumption, that the uncompressed size of the payload is never
   1.235 ++ * smaller than the payload itself, is valid only when talking about
   1.236 ++ * the payload as a whole. It is possible that the payload has parts where
   1.237 ++ * the decompressor consumes more input than it produces output. Calculating
   1.238 ++ * the worst case for this would be tricky. Instead of trying to do that,
   1.239 ++ * let's simply make sure that the decompressor never overwrites any bytes
   1.240 ++ * of the payload which it is currently reading.
   1.241 ++ *
   1.242 ++ * Now we have enough information to calculate the safety margin. We need
   1.243 ++ *   - 128 bytes for the .xz file format headers;
   1.244 ++ *   - 8 bytes per every 32 KiB of uncompressed size (one LZMA2 chunk header
   1.245 ++ *     per chunk, each chunk having average payload size of 32 KiB); and
   1.246 ++ *   - 64 KiB (biggest possible LZMA2 chunk payload size) to make sure that
   1.247 ++ *     the decompressor never overwrites anything from the LZMA2 chunk
   1.248 ++ *     payload it is currently reading.
   1.249 ++ *
   1.250 ++ * We get the following formula:
   1.251 ++ *
   1.252 ++ *    safety_margin = 128 + uncompressed_size * 8 / 32768 + 65536
   1.253 ++ *                  = 128 + (uncompressed_size >> 12) + 65536
   1.254 ++ *
   1.255 ++ * For comparision, according to arch/x86/boot/compressed/misc.c, the
   1.256 ++ * equivalent formula for Deflate is this:
   1.257 ++ *
   1.258 ++ *    safety_margin = 18 + (uncompressed_size >> 12) + 32768
   1.259 ++ *
   1.260 ++ * Thus, when updating Deflate-only in-place kernel decompressor to
   1.261 ++ * support XZ, the fixed overhead has to be increased from 18+32768 bytes
   1.262 ++ * to 128+65536 bytes.
   1.263 ++ */
   1.264 ++
   1.265 ++/*
   1.266 ++ * STATIC is defined to "static" if we are being built for kernel
   1.267 ++ * decompression (pre-boot code). <linux/decompress/mm.h> will define
   1.268 ++ * STATIC to empty if it wasn't already defined. Since we will need to
   1.269 ++ * know later if we are being used for kernel decompression, we define
   1.270 ++ * XZ_PREBOOT here.
   1.271 ++ */
   1.272 ++#ifdef STATIC
   1.273 ++#	define XZ_PREBOOT
   1.274 ++#endif
   1.275 ++#ifdef __KERNEL__
   1.276 ++#	include <linux/decompress/mm.h>
   1.277 ++#endif
   1.278 ++#define XZ_EXTERN STATIC
   1.279 ++
   1.280 ++#ifndef XZ_PREBOOT
   1.281 ++#	include <linux/slab.h>
   1.282 ++#	include <linux/xz.h>
   1.283 ++#else
   1.284 ++/*
   1.285 ++ * Use the internal CRC32 code instead of kernel's CRC32 module, which
   1.286 ++ * is not available in early phase of booting.
   1.287 ++ */
   1.288 ++#define XZ_INTERNAL_CRC32 1
   1.289 ++
   1.290 ++/*
   1.291 ++ * For boot time use, we enable only the BCJ filter of the current
   1.292 ++ * architecture or none if no BCJ filter is available for the architecture.
   1.293 ++ */
   1.294 ++#ifdef CONFIG_X86
   1.295 ++#	define XZ_DEC_X86
   1.296 ++#endif
   1.297 ++#ifdef CONFIG_PPC
   1.298 ++#	define XZ_DEC_POWERPC
   1.299 ++#endif
   1.300 ++#ifdef CONFIG_ARM
   1.301 ++#	define XZ_DEC_ARM
   1.302 ++#endif
   1.303 ++#ifdef CONFIG_IA64
   1.304 ++#	define XZ_DEC_IA64
   1.305 ++#endif
   1.306 ++#ifdef CONFIG_SPARC
   1.307 ++#	define XZ_DEC_SPARC
   1.308 ++#endif
   1.309 ++
   1.310 ++/*
   1.311 ++ * This will get the basic headers so that memeq() and others
   1.312 ++ * can be defined.
   1.313 ++ */
   1.314 ++#include "xz/xz_private.h"
   1.315 ++
   1.316 ++/*
   1.317 ++ * Replace the normal allocation functions with the versions from
   1.318 ++ * <linux/decompress/mm.h>. vfree() needs to support vfree(NULL)
   1.319 ++ * when XZ_DYNALLOC is used, but the pre-boot free() doesn't support it.
   1.320 ++ * Workaround it here because the other decompressors don't need it.
   1.321 ++ */
   1.322 ++#undef kmalloc
   1.323 ++#undef kfree
   1.324 ++#undef vmalloc
   1.325 ++#undef vfree
   1.326 ++#define kmalloc(size, flags) malloc(size)
   1.327 ++#define kfree(ptr) free(ptr)
   1.328 ++#define vmalloc(size) malloc(size)
   1.329 ++#define vfree(ptr) do { if (ptr != NULL) free(ptr); } while (0)
   1.330 ++
   1.331 ++/*
   1.332 ++ * FIXME: Not all basic memory functions are provided in architecture-specific
   1.333 ++ * files (yet). We define our own versions here for now, but this should be
   1.334 ++ * only a temporary solution.
   1.335 ++ *
   1.336 ++ * memeq and memzero are not used much and any remotely sane implementation
   1.337 ++ * is fast enough. memcpy/memmove speed matters in multi-call mode, but
   1.338 ++ * the kernel image is decompressed in single-call mode, in which only
   1.339 ++ * memcpy speed can matter and only if there is a lot of uncompressible data
   1.340 ++ * (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the
   1.341 ++ * functions below should just be kept small; it's probably not worth
   1.342 ++ * optimizing for speed.
   1.343 ++ */
   1.344 ++
   1.345 ++#ifndef memeq
   1.346 ++static bool memeq(const void *a, const void *b, size_t size)
   1.347 ++{
   1.348 ++	const uint8_t *x = a;
   1.349 ++	const uint8_t *y = b;
   1.350 ++	size_t i;
   1.351 ++
   1.352 ++	for (i = 0; i < size; ++i)
   1.353 ++		if (x[i] != y[i])
   1.354 ++			return false;
   1.355 ++
   1.356 ++	return true;
   1.357 ++}
   1.358 ++#endif
   1.359 ++
   1.360 ++#ifndef memzero
   1.361 ++static void memzero(void *buf, size_t size)
   1.362 ++{
   1.363 ++	uint8_t *b = buf;
   1.364 ++	uint8_t *e = b + size;
   1.365 ++
   1.366 ++	while (b != e)
   1.367 ++		*b++ = '\0';
   1.368 ++}
   1.369 ++#endif
   1.370 ++
   1.371 ++#ifndef memmove
   1.372 ++/* Not static to avoid a conflict with the prototype in the Linux headers. */
   1.373 ++void *memmove(void *dest, const void *src, size_t size)
   1.374 ++{
   1.375 ++	uint8_t *d = dest;
   1.376 ++	const uint8_t *s = src;
   1.377 ++	size_t i;
   1.378 ++
   1.379 ++	if (d < s) {
   1.380 ++		for (i = 0; i < size; ++i)
   1.381 ++			d[i] = s[i];
   1.382 ++	} else if (d > s) {
   1.383 ++		i = size;
   1.384 ++		while (i-- > 0)
   1.385 ++			d[i] = s[i];
   1.386 ++	}
   1.387 ++
   1.388 ++	return dest;
   1.389 ++}
   1.390 ++#endif
   1.391 ++
   1.392 ++/*
   1.393 ++ * Since we need memmove anyway, would use it as memcpy too.
   1.394 ++ * Commented out for now to avoid breaking things.
   1.395 ++ */
   1.396 ++/*
   1.397 ++#ifndef memcpy
   1.398 ++#	define memcpy memmove
   1.399 ++#endif
   1.400 ++*/
   1.401 ++
   1.402 ++#include "xz/xz_crc32.c"
   1.403 ++#include "xz/xz_dec_stream.c"
   1.404 ++#include "xz/xz_dec_lzma2.c"
   1.405 ++#include "xz/xz_dec_bcj.c"
   1.406 ++
   1.407 ++#endif /* XZ_PREBOOT */
   1.408 ++
   1.409 ++/* Size of the input and output buffers in multi-call mode */
   1.410 ++#define XZ_IOBUF_SIZE 4096
   1.411 ++
   1.412 ++/*
   1.413 ++ * This function implements the API defined in <linux/decompress/generic.h>.
   1.414 ++ *
   1.415 ++ * This wrapper will automatically choose single-call or multi-call mode
   1.416 ++ * of the native XZ decoder API. The single-call mode can be used only when
   1.417 ++ * both input and output buffers are available as a single chunk, i.e. when
   1.418 ++ * fill() and flush() won't be used.
   1.419 ++ */
   1.420 ++STATIC int INIT unxz(unsigned char *in, int in_size,
   1.421 ++		     int (*fill)(void *dest, unsigned int size),
   1.422 ++		     int (*flush)(void *src, unsigned int size),
   1.423 ++		     unsigned char *out, int *in_used,
   1.424 ++		     void (*error)(char *x))
   1.425 ++{
   1.426 ++	struct xz_buf b;
   1.427 ++	struct xz_dec *s;
   1.428 ++	enum xz_ret ret;
   1.429 ++	bool must_free_in = false;
   1.430 ++
   1.431 ++#if XZ_INTERNAL_CRC32
   1.432 ++	xz_crc32_init();
   1.433 ++#endif
   1.434 ++
   1.435 ++	if (in_used != NULL)
   1.436 ++		*in_used = 0;
   1.437 ++
   1.438 ++	if (fill == NULL && flush == NULL)
   1.439 ++		s = xz_dec_init(XZ_SINGLE, 0);
   1.440 ++	else
   1.441 ++		s = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
   1.442 ++
   1.443 ++	if (s == NULL)
   1.444 ++		goto error_alloc_state;
   1.445 ++
   1.446 ++	if (flush == NULL) {
   1.447 ++		b.out = out;
   1.448 ++		b.out_size = (size_t)-1;
   1.449 ++	} else {
   1.450 ++		b.out_size = XZ_IOBUF_SIZE;
   1.451 ++		b.out = malloc(XZ_IOBUF_SIZE);
   1.452 ++		if (b.out == NULL)
   1.453 ++			goto error_alloc_out;
   1.454 ++	}
   1.455 ++
   1.456 ++	if (in == NULL) {
   1.457 ++		must_free_in = true;
   1.458 ++		in = malloc(XZ_IOBUF_SIZE);
   1.459 ++		if (in == NULL)
   1.460 ++			goto error_alloc_in;
   1.461 ++	}
   1.462 ++
   1.463 ++	b.in = in;
   1.464 ++	b.in_pos = 0;
   1.465 ++	b.in_size = in_size;
   1.466 ++	b.out_pos = 0;
   1.467 ++
   1.468 ++	if (fill == NULL && flush == NULL) {
   1.469 ++		ret = xz_dec_run(s, &b);
   1.470 ++	} else {
   1.471 ++		do {
   1.472 ++			if (b.in_pos == b.in_size && fill != NULL) {
   1.473 ++				if (in_used != NULL)
   1.474 ++					*in_used += b.in_pos;
   1.475 ++
   1.476 ++				b.in_pos = 0;
   1.477 ++
   1.478 ++				in_size = fill(in, XZ_IOBUF_SIZE);
   1.479 ++				if (in_size < 0) {
   1.480 ++					/*
   1.481 ++					 * This isn't an optimal error code
   1.482 ++					 * but it probably isn't worth making
   1.483 ++					 * a new one either.
   1.484 ++					 */
   1.485 ++					ret = XZ_BUF_ERROR;
   1.486 ++					break;
   1.487 ++				}
   1.488 ++
   1.489 ++				b.in_size = in_size;
   1.490 ++			}
   1.491 ++
   1.492 ++			ret = xz_dec_run(s, &b);
   1.493 ++
   1.494 ++			if (flush != NULL && (b.out_pos == b.out_size
   1.495 ++					|| (ret != XZ_OK && b.out_pos > 0))) {
   1.496 ++				/*
   1.497 ++				 * Setting ret here may hide an error
   1.498 ++				 * returned by xz_dec_run(), but probably
   1.499 ++				 * it's not too bad.
   1.500 ++				 */
   1.501 ++				if (flush(b.out, b.out_pos) != (int)b.out_pos)
   1.502 ++					ret = XZ_BUF_ERROR;
   1.503 ++
   1.504 ++				b.out_pos = 0;
   1.505 ++			}
   1.506 ++		} while (ret == XZ_OK);
   1.507 ++
   1.508 ++		if (must_free_in)
   1.509 ++			free(in);
   1.510 ++
   1.511 ++		if (flush != NULL)
   1.512 ++			free(b.out);
   1.513 ++	}
   1.514 ++
   1.515 ++	if (in_used != NULL)
   1.516 ++		*in_used += b.in_pos;
   1.517 ++
   1.518 ++	xz_dec_end(s);
   1.519 ++
   1.520 ++	switch (ret) {
   1.521 ++	case XZ_STREAM_END:
   1.522 ++		return 0;
   1.523 ++
   1.524 ++	case XZ_MEM_ERROR:
   1.525 ++		/* This can occur only in multi-call mode. */
   1.526 ++		error("XZ decompressor ran out of memory");
   1.527 ++		break;
   1.528 ++
   1.529 ++	case XZ_FORMAT_ERROR:
   1.530 ++		error("Input is not in the XZ format (wrong magic bytes)");
   1.531 ++		break;
   1.532 ++
   1.533 ++	case XZ_OPTIONS_ERROR:
   1.534 ++		error("Input was encoded with settings that are not "
   1.535 ++				"supported by this XZ decoder");
   1.536 ++		break;
   1.537 ++
   1.538 ++	case XZ_DATA_ERROR:
   1.539 ++	case XZ_BUF_ERROR:
   1.540 ++		error("XZ-compressed data is corrupt");
   1.541 ++		break;
   1.542 ++
   1.543 ++	default:
   1.544 ++		error("Bug in the XZ decompressor");
   1.545 ++		break;
   1.546 ++	}
   1.547 ++
   1.548 ++	return -1;
   1.549 ++
   1.550 ++error_alloc_in:
   1.551 ++	if (flush != NULL)
   1.552 ++		free(b.out);
   1.553 ++
   1.554 ++error_alloc_out:
   1.555 ++	xz_dec_end(s);
   1.556 ++
   1.557 ++error_alloc_state:
   1.558 ++	error("XZ decompressor ran out of memory");
   1.559 ++	return -1;
   1.560 ++}
   1.561 ++
   1.562 ++/*
   1.563 ++ * This macro is used by architecture-specific files to decompress
   1.564 ++ * the kernel image.
   1.565 ++ */
   1.566 ++#define decompress unxz
   1.567 +diff --git a/scripts/gen_initramfs_list.sh b/scripts/gen_initramfs_list.sh
   1.568 +index 5958fff..55caecd 100644
   1.569 +--- a/scripts/gen_initramfs_list.sh
   1.570 ++++ b/scripts/gen_initramfs_list.sh
   1.571 +@@ -243,6 +243,8 @@ case "$arg" in
   1.572 + 		echo "$output_file" | grep -q "\.gz$" && compr="gzip -9 -f"
   1.573 + 		echo "$output_file" | grep -q "\.bz2$" && compr="bzip2 -9 -f"
   1.574 + 		echo "$output_file" | grep -q "\.lzma$" && compr="lzma -9 -f"
   1.575 ++		echo "$output_file" | grep -q "\.xz$" && \
   1.576 ++				compr="xz --check=crc32 --lzma2=dict=1MiB"
   1.577 + 		echo "$output_file" | grep -q "\.lzo$" && compr="lzop -9 -f"
   1.578 + 		echo "$output_file" | grep -q "\.cpio$" && compr="cat"
   1.579 + 		shift
   1.580 +diff --git a/usr/Kconfig b/usr/Kconfig
   1.581 +index e2721f5..9f51a29 100644
   1.582 +--- a/usr/Kconfig
   1.583 ++++ b/usr/Kconfig
   1.584 +@@ -72,6 +72,18 @@ config RD_LZMA
   1.585 + 	  Support loading of a LZMA encoded initial ramdisk or cpio buffer
   1.586 + 	  If unsure, say N.
   1.587 + 
   1.588 ++config RD_XZ
   1.589 ++	bool "Support initial ramdisks compressed using XZ"
   1.590 ++	depends on BLK_DEV_INITRD && XZ_DEC=y
   1.591 ++	select DECOMPRESS_XZ
   1.592 ++	help
   1.593 ++	  Support loading of a XZ encoded initial ramdisk or cpio buffer.
   1.594 ++
   1.595 ++	  If this option is inactive, say Y to "XZ decompression support"
   1.596 ++	  under "Library routines" first.
   1.597 ++
   1.598 ++	  If unsure, say N.
   1.599 ++
   1.600 + config RD_LZO
   1.601 + 	bool "Support initial ramdisks compressed using LZO" if EMBEDDED
   1.602 + 	default !EMBEDDED
   1.603 +@@ -139,6 +151,15 @@ config INITRAMFS_COMPRESSION_LZMA
   1.604 + 	  three. Compression is slowest. The initramfs size is about 33%
   1.605 + 	  smaller with LZMA in comparison to gzip.
   1.606 + 
   1.607 ++config INITRAMFS_COMPRESSION_XZ
   1.608 ++	bool "XZ"
   1.609 ++	depends on RD_XZ
   1.610 ++	help
   1.611 ++	  XZ uses the LZMA2 algorithm. The initramfs size is about 30%
   1.612 ++	  smaller with XZ in comparison to gzip. Decompression speed
   1.613 ++	  is better than that of bzip2 but worse than gzip and LZO.
   1.614 ++	  Compression is slow.
   1.615 ++
   1.616 + config INITRAMFS_COMPRESSION_LZO
   1.617 + 	bool "LZO"
   1.618 + 	depends on RD_LZO
   1.619 +diff --git a/usr/Makefile b/usr/Makefile
   1.620 +index 6b4b6da..5845a13 100644
   1.621 +--- a/usr/Makefile
   1.622 ++++ b/usr/Makefile
   1.623 +@@ -15,6 +15,9 @@ suffix_$(CONFIG_INITRAMFS_COMPRESSION_BZIP2)  = .bz2
   1.624 + # Lzma
   1.625 + suffix_$(CONFIG_INITRAMFS_COMPRESSION_LZMA)   = .lzma
   1.626 + 
   1.627 ++# XZ
   1.628 ++suffix_$(CONFIG_INITRAMFS_COMPRESSION_XZ)     = .xz
   1.629 ++
   1.630 + # Lzo
   1.631 + suffix_$(CONFIG_INITRAMFS_COMPRESSION_LZO)   = .lzo
   1.632 + 
   1.633 +@@ -48,7 +51,7 @@ endif
   1.634 + quiet_cmd_initfs = GEN     $@
   1.635 +       cmd_initfs = $(initramfs) -o $@ $(ramfs-args) $(ramfs-input)
   1.636 + 
   1.637 +-targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 initramfs_data.cpio.lzma initramfs_data.cpio.lzo initramfs_data.cpio
   1.638 ++targets := initramfs_data.cpio.gz initramfs_data.cpio.bz2 initramfs_data.cpio.lzma initramfs_data.cpio.xz initramfs_data.cpio.lzo initramfs_data.cpio
   1.639 + # do not try to update files included in initramfs
   1.640 + $(deps_initramfs): ;
   1.641 +