wok-current diff linux-libre/stuff/002-squashfs-decompressors-add-boot-time-xz-support.patch @ rev 24594
updated getmail (5.14 -> 5.16)
author | Hans-G?nter Theisgen |
---|---|
date | Tue Mar 01 15:05:47 2022 +0100 (2022-03-01) |
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 Tue Mar 01 15:05:47 2022 +0100 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 +