packages: xen/xen.spec, xen/xen-xz.patch (NEW) - xz compression support fro...

arekm arekm at pld-linux.org
Sun Nov 27 12:32:23 CET 2011


Author: arekm                        Date: Sun Nov 27 11:32:23 2011 GMT
Module: packages                      Tag: HEAD
---- Log message:
- xz compression support from upstream prepared by archlinux

---- Files affected:
packages/xen:
   xen.spec (1.90 -> 1.91) , xen-xz.patch (NONE -> 1.1)  (NEW)

---- Diffs:

================================================================
Index: packages/xen/xen.spec
diff -u packages/xen/xen.spec:1.90 packages/xen/xen.spec:1.91
--- packages/xen/xen.spec:1.90	Sun Nov 27 11:30:35 2011
+++ packages/xen/xen.spec	Sun Nov 27 12:32:18 2011
@@ -12,7 +12,7 @@
 Summary(pl.UTF-8):	Xen - monitor maszyny wirtualnej
 Name:		xen
 Version:	4.1.2
-Release:	0.2
+Release:	0.3
 License:	GPL
 Group:		Applications/System
 Source0:	http://bits.xensource.com/oss-xen/release/%{version}/%{name}-%{version}.tar.gz
@@ -36,6 +36,7 @@
 Patch1:		%{name}-symbols.patch
 Patch2:		%{name}-curses.patch
 Patch3:		%{name}-gcc.patch
+Patch4:		%{name}-xz.patch
 URL:		http://www.cl.cam.ac.uk/Research/SRG/netos/xen/index.html
 BuildRequires:	SDL-devel
 %{?with_hvm:BuildRequires:	bcc}
@@ -190,6 +191,7 @@
 %patch1 -p1
 %patch2 -p1
 #%%patch3 -p1
+%patch4 -p1
 
 %{__rm} -v tools/check/*.orig
 
@@ -367,6 +369,9 @@
 All persons listed below can be reached at <cvs_login>@pld-linux.org
 
 $Log$
+Revision 1.91  2011/11/27 11:32:18  arekm
+- xz compression support from upstream prepared by archlinux
+
 Revision 1.90  2011/11/27 10:30:35  glen
 - download stubdown sources to distfiles
 

================================================================
Index: packages/xen/xen-xz.patch
diff -u /dev/null packages/xen/xen-xz.patch:1.1
--- /dev/null	Sun Nov 27 12:32:23 2011
+++ packages/xen/xen-xz.patch	Sun Nov 27 12:32:18 2011
@@ -0,0 +1,3528 @@
+diff --git a/xen/common/Makefile b/xen/common/Makefile
+--- a/xen/common/Makefile
++++ b/xen/common/Makefile
+@@ -43,7 +43,7 @@
+ obj-y += rbtree.o
+ obj-y += lzo.o
+ 
+-obj-$(CONFIG_X86) += decompress.o bunzip2.o unlzma.o unlzo.o
++obj-$(CONFIG_X86) += decompress.o bunzip2.o unxz.o unlzma.o unlzo.o
+ 
+ obj-$(perfc)       += perfc.o
+ obj-$(crash_debug) += gdbstub.o
+diff --git a/xen/common/decompress.c b/xen/common/decompress.c
+--- a/xen/common/decompress.c
++++ b/xen/common/decompress.c
+@@ -20,6 +20,9 @@
+     if ( len >= 3 && !memcmp(inbuf, "\x42\x5a\x68", 3) )
+         return bunzip2(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ 
++    if ( len >= 6 && !memcmp(inbuf, "\3757zXZ", 6) )
++        return unxz(inbuf, len, NULL, NULL, outbuf, NULL, error);
++
+     if ( len >= 2 && !memcmp(inbuf, "\135\000", 2) )
+         return unlzma(inbuf, len, NULL, NULL, outbuf, NULL, error);
+ 
+diff --git a/xen/common/decompress.h b/xen/common/decompress.h
+--- a/xen/common/decompress.h
++++ b/xen/common/decompress.h
+@@ -8,6 +8,7 @@
+ 
+ #define STATIC
+ #define INIT __init
++#define INITDATA __initdata
+ 
+ static void(*__initdata error)(const char *);
+ #define set_error_fn(x) error = x;
+diff --git a/xen/common/unxz.c b/xen/common/unxz.c
+new file mode 100644
+--- /dev/null
++++ b/xen/common/unxz.c
+@@ -0,0 +1,306 @@
++/*
++ * Wrapper for decompressing XZ-compressed kernel, initramfs, and initrd
++ *
++ * Author: Lasse Collin <lasse.collin at tukaani.org>
++ *
++ * This file has been put into the public domain.
++ * You can do whatever you want with this file.
++ */
++
++/*
++ * Important notes about in-place decompression
++ *
++ * At least on x86, the kernel is decompressed in place: the compressed data
++ * is placed to the end of the output buffer, and the decompressor overwrites
++ * most of the compressed data. There must be enough safety margin to
++ * guarantee that the write position is always behind the read position.
++ *
++ * The safety margin for XZ with LZMA2 or BCJ+LZMA2 is calculated below.
++ * Note that the margin with XZ is bigger than with Deflate (gzip)!
++ *
++ * The worst case for in-place decompression is that the beginning of
++ * the file is compressed extremely well, and the rest of the file is
++ * uncompressible. Thus, we must look for worst-case expansion when the
++ * compressor is encoding uncompressible data.
++ *
++ * The structure of the .xz file in case of a compresed kernel is as follows.
++ * Sizes (as bytes) of the fields are in parenthesis.
++ *
++ *    Stream Header (12)
++ *    Block Header:
++ *      Block Header (8-12)
++ *      Compressed Data (N)
++ *      Block Padding (0-3)
++ *      CRC32 (4)
++ *    Index (8-20)
++ *    Stream Footer (12)
++ *
++ * Normally there is exactly one Block, but let's assume that there are
++ * 2-4 Blocks just in case. Because Stream Header and also Block Header
++ * of the first Block don't make the decompressor produce any uncompressed
++ * data, we can ignore them from our calculations. Block Headers of possible
++ * additional Blocks have to be taken into account still. With these
++ * assumptions, it is safe to assume that the total header overhead is
++ * less than 128 bytes.
++ *
++ * Compressed Data contains LZMA2 or BCJ+LZMA2 encoded data. Since BCJ
++ * doesn't change the size of the data, it is enough to calculate the
++ * safety margin for LZMA2.
++ *
++ * LZMA2 stores the data in chunks. Each chunk has a header whose size is
++ * a maximum of 6 bytes, but to get round 2^n numbers, let's assume that
++ * the maximum chunk header size is 8 bytes. After the chunk header, there
++ * may be up to 64 KiB of actual payload in the chunk. Often the payload is
++ * quite a bit smaller though; to be safe, let's assume that an average
++ * chunk has only 32 KiB of payload.
++ *
++ * The maximum uncompressed size of the payload is 2 MiB. The minimum
++ * uncompressed size of the payload is in practice never less than the
++ * payload size itself. The LZMA2 format would allow uncompressed size
++ * to be less than the payload size, but no sane compressor creates such
++ * files. LZMA2 supports storing uncompressible data in uncompressed form,
++ * so there's never a need to create payloads whose uncompressed size is
++ * smaller than the compressed size.
++ *
++ * The assumption, that the uncompressed size of the payload is never
++ * smaller than the payload itself, is valid only when talking about
++ * the payload as a whole. It is possible that the payload has parts where
++ * the decompressor consumes more input than it produces output. Calculating
++ * the worst case for this would be tricky. Instead of trying to do that,
++ * let's simply make sure that the decompressor never overwrites any bytes
++ * of the payload which it is currently reading.
++ *
++ * Now we have enough information to calculate the safety margin. We need
++ *   - 128 bytes for the .xz file format headers;
++ *   - 8 bytes per every 32 KiB of uncompressed size (one LZMA2 chunk header
++ *     per chunk, each chunk having average payload size of 32 KiB); and
++ *   - 64 KiB (biggest possible LZMA2 chunk payload size) to make sure that
++ *     the decompressor never overwrites anything from the LZMA2 chunk
++ *     payload it is currently reading.
++ *
++ * We get the following formula:
++ *
++ *    safety_margin = 128 + uncompressed_size * 8 / 32768 + 65536
++ *                  = 128 + (uncompressed_size >> 12) + 65536
++ *
++ * For comparision, according to arch/x86/boot/compressed/misc.c, the
++ * equivalent formula for Deflate is this:
++ *
++ *    safety_margin = 18 + (uncompressed_size >> 12) + 32768
++ *
++ * Thus, when updating Deflate-only in-place kernel decompressor to
++ * support XZ, the fixed overhead has to be increased from 18+32768 bytes
++ * to 128+65536 bytes.
++ */
++
++#include "decompress.h"
++
++#define XZ_EXTERN STATIC
++
++/*
++ * For boot time use, we enable only the BCJ filter of the current
++ * architecture or none if no BCJ filter is available for the architecture.
++ */
++#ifdef CONFIG_X86
++#	define XZ_DEC_X86
++#endif
++#ifdef CONFIG_PPC
++#	define XZ_DEC_POWERPC
++#endif
++#ifdef CONFIG_ARM
++#	define XZ_DEC_ARM
++#endif
++#ifdef CONFIG_IA64
++#	define XZ_DEC_IA64
++#endif
++#ifdef CONFIG_SPARC
++#	define XZ_DEC_SPARC
++#endif
++
++/*
++ * This will get the basic headers so that memeq() and others
++ * can be defined.
++ */
++#include "xz/private.h"
++
++/*
++ * memeq and memzero are not used much and any remotely sane implementation
++ * is fast enough. memcpy/memmove speed matters in multi-call mode, but
++ * the kernel image is decompressed in single-call mode, in which only
++ * memcpy speed can matter and only if there is a lot of uncompressible data
++ * (LZMA2 stores uncompressible chunks in uncompressed form). Thus, the
++ * functions below should just be kept small; it's probably not worth
++ * optimizing for speed.
++ */
++
++#ifndef memeq
++#define memeq(p1, p2, sz) (memcmp(p1, p2, sz) == 0)
++#endif
++
++#ifndef memzero
++#define memzero(p, sz) memset(p, 0, sz)
++#endif
++
++#include "xz/crc32.c"
++#include "xz/dec_stream.c"
++#include "xz/dec_lzma2.c"
++#include "xz/dec_bcj.c"
++
++/* Size of the input and output buffers in multi-call mode */
++#define XZ_IOBUF_SIZE 4096
++
++/*
++ * This function implements the API defined in <linux/decompress/generic.h>.
++ *
++ * This wrapper will automatically choose single-call or multi-call mode
++ * of the native XZ decoder API. The single-call mode can be used only when
++ * both input and output buffers are available as a single chunk, i.e. when
++ * fill() and flush() won't be used.
++ */
++STATIC int INIT unxz(unsigned char *in, unsigned int in_size,
++		     int (*fill)(void *dest, unsigned int size),
++		     int (*flush)(void *src, unsigned int size),
++		     unsigned char *out, unsigned int *in_used,
++		     void (*error_fn)(const char *x))
++{
++	struct xz_buf b;
++	struct xz_dec *s;
++	enum xz_ret ret;
++	bool_t must_free_in = false;
++
++	set_error_fn(error_fn);
++
++	xz_crc32_init();
++
++	if (in_used != NULL)
++		*in_used = 0;
++
++	if (fill == NULL && flush == NULL)
++		s = xz_dec_init(XZ_SINGLE, 0);
++	else
++		s = xz_dec_init(XZ_DYNALLOC, (uint32_t)-1);
++
++	if (s == NULL)
++		goto error_alloc_state;
++
++	if (flush == NULL) {
++		b.out = out;
++		b.out_size = (size_t)-1;
++	} else {
++		b.out_size = XZ_IOBUF_SIZE;
++		b.out = malloc(XZ_IOBUF_SIZE);
++		if (b.out == NULL)
++			goto error_alloc_out;
++	}
++
++	if (in == NULL) {
++		must_free_in = true;
++		in = malloc(XZ_IOBUF_SIZE);
++		if (in == NULL)
++			goto error_alloc_in;
++	}
++
++	b.in = in;
++	b.in_pos = 0;
++	b.in_size = in_size;
++	b.out_pos = 0;
++
++	if (fill == NULL && flush == NULL) {
++		ret = xz_dec_run(s, &b);
++	} else {
++		do {
++			if (b.in_pos == b.in_size && fill != NULL) {
++				if (in_used != NULL)
++					*in_used += b.in_pos;
++
++				b.in_pos = 0;
++
++				in_size = fill(in, XZ_IOBUF_SIZE);
++				if (in_size < 0) {
++					/*
++					 * This isn't an optimal error code
++					 * but it probably isn't worth making
++					 * a new one either.
++					 */
++					ret = XZ_BUF_ERROR;
++					break;
++				}
++
++				b.in_size = in_size;
++			}
++
++			ret = xz_dec_run(s, &b);
++
++			if (flush != NULL && (b.out_pos == b.out_size
++					|| (ret != XZ_OK && b.out_pos > 0))) {
++				/*
++				 * Setting ret here may hide an error
++				 * returned by xz_dec_run(), but probably
++				 * it's not too bad.
++				 */
++				if (flush(b.out, b.out_pos) != (int)b.out_pos)
++					ret = XZ_BUF_ERROR;
++
++				b.out_pos = 0;
++			}
++		} while (ret == XZ_OK);
++
++		if (must_free_in)
++			free(in);
++
++		if (flush != NULL)
++			free(b.out);
++	}
++
++	if (in_used != NULL)
++		*in_used += b.in_pos;
++
++	xz_dec_end(s);
++
++	switch (ret) {
++	case XZ_STREAM_END:
++		return 0;
++
++	case XZ_MEM_ERROR:
++		/* This can occur only in multi-call mode. */
++		error("XZ decompressor ran out of memory");
++		break;
++
++	case XZ_FORMAT_ERROR:
++		error("Input is not in the XZ format (wrong magic bytes)");
++		break;
++
++	case XZ_OPTIONS_ERROR:
++		error("Input was encoded with settings that are not "
++				"supported by this XZ decoder");
++		break;
++
++	case XZ_DATA_ERROR:
++	case XZ_BUF_ERROR:
++		error("XZ-compressed data is corrupt");
++		break;
++
++	default:
++		error("Bug in the XZ decompressor");
++		break;
++	}
++
++	return -1;
++
++error_alloc_in:
++	if (flush != NULL)
++		free(b.out);
++
++error_alloc_out:
++	xz_dec_end(s);
++
++error_alloc_state:
++	error("XZ decompressor ran out of memory");
++	return -1;
++}
++
++/*
++ * This macro is used by architecture-specific files to decompress
++ * the kernel image.
++ */
++#define decompress unxz
+diff --git a/xen/common/xz/crc32.c b/xen/common/xz/crc32.c
+new file mode 100644
+--- /dev/null
++++ b/xen/common/xz/crc32.c
+@@ -0,0 +1,51 @@
++/*
++ * CRC32 using the polynomial from IEEE-802.3
++ *
++ * Authors: Lasse Collin <lasse.collin at tukaani.org>
++ *          Igor Pavlov <http://7-zip.org/>
++ *
++ * This file has been put into the public domain.
++ * You can do whatever you want with this file.
++ */
++
++/*
++ * This is not the fastest implementation, but it is pretty compact.
++ * The fastest versions of xz_crc32() on modern CPUs without hardware
++ * accelerated CRC instruction are 3-5 times as fast as this version,
++ * but they are bigger and use more memory for the lookup table.
++ */
++
++#include "private.h"
++
++XZ_EXTERN uint32_t INITDATA xz_crc32_table[256];
++
++XZ_EXTERN void INIT xz_crc32_init(void)
++{
++	const uint32_t poly = 0xEDB88320;
++
++	uint32_t i;
++	uint32_t j;
++	uint32_t r;
++
++	for (i = 0; i < 256; ++i) {
++		r = i;
++		for (j = 0; j < 8; ++j)
++			r = (r >> 1) ^ (poly & ~((r & 1) - 1));
++
++		xz_crc32_table[i] = r;
++	}
++
++	return;
++}
++
++XZ_EXTERN uint32_t INIT xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
++{
++	crc = ~crc;
++
++	while (size != 0) {
++		crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
++		--size;
++	}
++
++	return ~crc;
++}
+diff --git a/xen/common/xz/dec_bcj.c b/xen/common/xz/dec_bcj.c
+new file mode 100644
+--- /dev/null
++++ b/xen/common/xz/dec_bcj.c
+@@ -0,0 +1,562 @@
++/*
++ * Branch/Call/Jump (BCJ) filter decoders
++ *
++ * Authors: Lasse Collin <lasse.collin at tukaani.org>
++ *          Igor Pavlov <http://7-zip.org/>
++ *
++ * This file has been put into the public domain.
++ * You can do whatever you want with this file.
++ */
++
++#include "private.h"
++
++/*
++ * The rest of the file is inside this ifdef. It makes things a little more
++ * convenient when building without support for any BCJ filters.
++ */
++#ifdef XZ_DEC_BCJ
++
++struct xz_dec_bcj {
++	/* Type of the BCJ filter being used */
++	enum {
++		BCJ_X86 = 4,        /* x86 or x86-64 */
++		BCJ_POWERPC = 5,    /* Big endian only */
++		BCJ_IA64 = 6,       /* Big or little endian */
++		BCJ_ARM = 7,        /* Little endian only */
++		BCJ_ARMTHUMB = 8,   /* Little endian only */
++		BCJ_SPARC = 9       /* Big or little endian */
++	} type;
++
++	/*
++	 * Return value of the next filter in the chain. We need to preserve
++	 * this information across calls, because we must not call the next
++	 * filter anymore once it has returned XZ_STREAM_END.
++	 */
++	enum xz_ret ret;
++
++	/* True if we are operating in single-call mode. */
++	bool_t single_call;
++
++	/*
++	 * Absolute position relative to the beginning of the uncompressed
++	 * data (in a single .xz Block). We care only about the lowest 32
++	 * bits so this doesn't need to be uint64_t even with big files.
++	 */
++	uint32_t pos;
++
++	/* x86 filter state */
++	uint32_t x86_prev_mask;
++
++	/* Temporary space to hold the variables from struct xz_buf */
++	uint8_t *out;
++	size_t out_pos;
++	size_t out_size;
++
++	struct {
++		/* Amount of already filtered data in the beginning of buf */
++		size_t filtered;
++
++		/* Total amount of data currently stored in buf  */
++		size_t size;
++
++		/*
++		 * Buffer to hold a mix of filtered and unfiltered data. This
++		 * needs to be big enough to hold Alignment + 2 * Look-ahead:
++		 *
++		 * Type         Alignment   Look-ahead
++		 * x86              1           4
++		 * PowerPC          4           0
++		 * IA-64           16           0
++		 * ARM              4           0
++		 * ARM-Thumb        2           2
++		 * SPARC            4           0
++		 */
++		uint8_t buf[16];
++	} temp;
++};
++
++#ifdef XZ_DEC_X86
++/*
++ * This is used to test the most significant byte of a memory address
++ * in an x86 instruction.
++ */
++static inline int INIT bcj_x86_test_msbyte(uint8_t b)
++{
++	return b == 0x00 || b == 0xFF;
++}
++
++static size_t INIT bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
++{
++	static /*const*/ bool_t INITDATA mask_to_allowed_status[8]
++		= { true, true, true, false, true, false, false, false };
++
++	static /*const*/ uint8_t INITDATA mask_to_bit_num[8]
++		= { 0, 1, 2, 2, 3, 3, 3, 3 };
++
++	size_t i;
++	size_t prev_pos = (size_t)-1;
++	uint32_t prev_mask = s->x86_prev_mask;
++	uint32_t src;
++	uint32_t dest;
++	uint32_t j;
++	uint8_t b;
++
++	if (size <= 4)
++		return 0;
++
++	size -= 4;
++	for (i = 0; i < size; ++i) {
++		if ((buf[i] & 0xFE) != 0xE8)
++			continue;
++
++		prev_pos = i - prev_pos;
++		if (prev_pos > 3) {
++			prev_mask = 0;
++		} else {
++			prev_mask = (prev_mask << (prev_pos - 1)) & 7;
++			if (prev_mask != 0) {
++				b = buf[i + 4 - mask_to_bit_num[prev_mask]];
++				if (!mask_to_allowed_status[prev_mask]
++						|| bcj_x86_test_msbyte(b)) {
++					prev_pos = i;
++					prev_mask = (prev_mask << 1) | 1;
++					continue;
++				}
++			}
++		}
++
++		prev_pos = i;
++
++		if (bcj_x86_test_msbyte(buf[i + 4])) {
++			src = get_unaligned_le32(buf + i + 1);
++			while (true) {
++				dest = src - (s->pos + (uint32_t)i + 5);
++				if (prev_mask == 0)
++					break;
++
++				j = mask_to_bit_num[prev_mask] * 8;
++				b = (uint8_t)(dest >> (24 - j));
++				if (!bcj_x86_test_msbyte(b))
++					break;
++
++				src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
++			}
<<Diff was trimmed, longer than 597 lines>>

---- CVS-web:
    http://cvs.pld-linux.org/cgi-bin/cvsweb.cgi/packages/xen/xen.spec?r1=1.90&r2=1.91&f=u



More information about the pld-cvs-commit mailing list