wok-current annotate linux-libre/stuff/001-squashfs-decompressors-add-xz-decompressor-module.patch @ rev 13150

get-flash-plugin: be busybox/sed compatible
author Pascal Bellard <pascal.bellard@slitaz.org>
date Wed Jul 11 11:13:01 2012 +0200 (2012-07-11)
parents
children
rev   line source
gokhlayeh@9258 1 From: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 2 Date: Thu, 2 Dec 2010 19:14:19 +0000 (+0200)
gokhlayeh@9258 3 Subject: Decompressors: Add XZ decompressor module
gokhlayeh@9258 4 X-Git-Url: http://git.kernel.org/?p=linux%2Fkernel%2Fgit%2Fpkl%2Fsquashfs-xz.git;a=commitdiff_plain;h=3dbc3fe7878e53b43064a12d4ab31ca4c18ce85f
gokhlayeh@9258 5
gokhlayeh@9258 6 Decompressors: Add XZ decompressor module
gokhlayeh@9258 7
gokhlayeh@9258 8 In userspace, the .lzma format has become mostly a legacy
gokhlayeh@9258 9 file format that got superseded by the .xz format. Similarly,
gokhlayeh@9258 10 LZMA Utils was superseded by XZ Utils.
gokhlayeh@9258 11
gokhlayeh@9258 12 These patches add support for XZ decompression into
gokhlayeh@9258 13 the kernel. Most of the code is as is from XZ Embedded
gokhlayeh@9258 14 <http://tukaani.org/xz/embedded.html>. It was written for
gokhlayeh@9258 15 the Linux kernel but is usable in other projects too.
gokhlayeh@9258 16
gokhlayeh@9258 17 Advantages of XZ over the current LZMA code in the kernel:
gokhlayeh@9258 18 - Nice API that can be used by other kernel modules; it's
gokhlayeh@9258 19 not limited to kernel, initramfs, and initrd decompression.
gokhlayeh@9258 20 - Integrity check support (CRC32)
gokhlayeh@9258 21 - BCJ filters improve compression of executable code on
gokhlayeh@9258 22 certain architectures. These together with LZMA2 can
gokhlayeh@9258 23 produce a few percent smaller kernel or Squashfs images
gokhlayeh@9258 24 than plain LZMA without making the decompression slower.
gokhlayeh@9258 25
gokhlayeh@9258 26 This patch: Add the main decompression code (xz_dec), testing
gokhlayeh@9258 27 module (xz_dec_test), wrapper script (xz_wrap.sh) for the xz
gokhlayeh@9258 28 command line tool, and documentation. The xz_dec module is
gokhlayeh@9258 29 enough to have a usable XZ decompressor e.g. for Squashfs.
gokhlayeh@9258 30
gokhlayeh@9258 31 Signed-off-by: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 32 ---
gokhlayeh@9258 33
gokhlayeh@9258 34 diff --git a/Documentation/xz.txt b/Documentation/xz.txt
gokhlayeh@9258 35 new file mode 100644
gokhlayeh@9258 36 index 0000000..68329ac
gokhlayeh@9258 37 --- /dev/null
gokhlayeh@9258 38 +++ b/Documentation/xz.txt
gokhlayeh@9258 39 @@ -0,0 +1,122 @@
gokhlayeh@9258 40 +
gokhlayeh@9258 41 +XZ data compression in Linux
gokhlayeh@9258 42 +============================
gokhlayeh@9258 43 +
gokhlayeh@9258 44 +Introduction
gokhlayeh@9258 45 +
gokhlayeh@9258 46 + XZ is a general purpose data compression format with high compression
gokhlayeh@9258 47 + ratio and relatively fast decompression. The primary compression
gokhlayeh@9258 48 + algorithm (filter) is LZMA2. Additional filters can be used to improve
gokhlayeh@9258 49 + compression ratio even further. E.g. Branch/Call/Jump (BCJ) filters
gokhlayeh@9258 50 + improve compression ratio of executable data.
gokhlayeh@9258 51 +
gokhlayeh@9258 52 + The XZ decompressor in Linux is called XZ Embedded. It supports
gokhlayeh@9258 53 + the LZMA2 filter and optionally also BCJ filters. CRC32 is supported
gokhlayeh@9258 54 + for integrity checking. The home page of XZ Embedded is at
gokhlayeh@9258 55 + <http://tukaani.org/xz/embedded.html>, where you can find the
gokhlayeh@9258 56 + latest version and also information about using the code outside
gokhlayeh@9258 57 + the Linux kernel.
gokhlayeh@9258 58 +
gokhlayeh@9258 59 + For userspace, XZ Utils provide a zlib-like compression library
gokhlayeh@9258 60 + and a gzip-like command line tool. XZ Utils can be downloaded from
gokhlayeh@9258 61 + <http://tukaani.org/xz/>.
gokhlayeh@9258 62 +
gokhlayeh@9258 63 +XZ related components in the kernel
gokhlayeh@9258 64 +
gokhlayeh@9258 65 + The xz_dec module provides XZ decompressor with single-call (buffer
gokhlayeh@9258 66 + to buffer) and multi-call (stateful) APIs. The usage of the xz_dec
gokhlayeh@9258 67 + module is documented in include/linux/xz.h.
gokhlayeh@9258 68 +
gokhlayeh@9258 69 + The xz_dec_test module is for testing xz_dec. xz_dec_test is not
gokhlayeh@9258 70 + useful unless you are hacking the XZ decompressor. xz_dec_test
gokhlayeh@9258 71 + allocates a char device major dynamically to which one can write
gokhlayeh@9258 72 + .xz files from userspace. The decompressed output is thrown away.
gokhlayeh@9258 73 + Keep an eye on dmesg to see diagnostics printed by xz_dec_test.
gokhlayeh@9258 74 + See the xz_dec_test source code for the details.
gokhlayeh@9258 75 +
gokhlayeh@9258 76 + For decompressing the kernel image, initramfs, and initrd, there
gokhlayeh@9258 77 + is a wrapper function in lib/decompress_unxz.c. Its API is the
gokhlayeh@9258 78 + same as in other decompress_*.c files, which is defined in
gokhlayeh@9258 79 + include/linux/decompress/generic.h.
gokhlayeh@9258 80 +
gokhlayeh@9258 81 + scripts/xz_wrap.sh is a wrapper for the xz command line tool found
gokhlayeh@9258 82 + from XZ Utils. The wrapper sets compression options to values suitable
gokhlayeh@9258 83 + for compressing the kernel image.
gokhlayeh@9258 84 +
gokhlayeh@9258 85 + For kernel makefiles, two commands are provided for use with
gokhlayeh@9258 86 + $(call if_needed). The kernel image should be compressed with
gokhlayeh@9258 87 + $(call if_needed,xzkern) which will use a BCJ filter and a big LZMA2
gokhlayeh@9258 88 + dictionary. It will also append a four-byte trailer containing the
gokhlayeh@9258 89 + uncompressed size of the file, which is needed by the boot code.
gokhlayeh@9258 90 + Other things should be compressed with $(call if_needed,xzmisc)
gokhlayeh@9258 91 + which will use no BCJ filter and 1 MiB LZMA2 dictionary.
gokhlayeh@9258 92 +
gokhlayeh@9258 93 +Notes on compression options
gokhlayeh@9258 94 +
gokhlayeh@9258 95 + Since the XZ Embedded supports only streams with no integrity check or
gokhlayeh@9258 96 + CRC32, make sure that you don't use some other integrity check type
gokhlayeh@9258 97 + when encoding files that are supposed to be decoded by the kernel. With
gokhlayeh@9258 98 + liblzma, you need to use either LZMA_CHECK_NONE or LZMA_CHECK_CRC32
gokhlayeh@9258 99 + when encoding. With the xz command line tool, use --check=none or
gokhlayeh@9258 100 + --check=crc32.
gokhlayeh@9258 101 +
gokhlayeh@9258 102 + Using CRC32 is strongly recommended unless there is some other layer
gokhlayeh@9258 103 + which will verify the integrity of the uncompressed data anyway.
gokhlayeh@9258 104 + Double checking the integrity would probably be waste of CPU cycles.
gokhlayeh@9258 105 + Note that the headers will always have a CRC32 which will be validated
gokhlayeh@9258 106 + by the decoder; you can only change the integrity check type (or
gokhlayeh@9258 107 + disable it) for the actual uncompressed data.
gokhlayeh@9258 108 +
gokhlayeh@9258 109 + In userspace, LZMA2 is typically used with dictionary sizes of several
gokhlayeh@9258 110 + megabytes. The decoder needs to have the dictionary in RAM, thus big
gokhlayeh@9258 111 + dictionaries cannot be used for files that are intended to be decoded
gokhlayeh@9258 112 + by the kernel. 1 MiB is probably the maximum reasonable dictionary
gokhlayeh@9258 113 + size for in-kernel use (maybe more is OK for initramfs). The presets
gokhlayeh@9258 114 + in XZ Utils may not be optimal when creating files for the kernel,
gokhlayeh@9258 115 + so don't hesitate to use custom settings. Example:
gokhlayeh@9258 116 +
gokhlayeh@9258 117 + xz --check=crc32 --lzma2=dict=512KiB inputfile
gokhlayeh@9258 118 +
gokhlayeh@9258 119 + An exception to above dictionary size limitation is when the decoder
gokhlayeh@9258 120 + is used in single-call mode. Decompressing the kernel itself is an
gokhlayeh@9258 121 + example of this situation. In single-call mode, the memory usage
gokhlayeh@9258 122 + doesn't depend on the dictionary size, and it is perfectly fine to
gokhlayeh@9258 123 + use a big dictionary: for maximum compression, the dictionary should
gokhlayeh@9258 124 + be at least as big as the uncompressed data itself.
gokhlayeh@9258 125 +
gokhlayeh@9258 126 +Future plans
gokhlayeh@9258 127 +
gokhlayeh@9258 128 + Creating a limited XZ encoder may be considered if people think it is
gokhlayeh@9258 129 + useful. LZMA2 is slower to compress than e.g. Deflate or LZO even at
gokhlayeh@9258 130 + the fastest settings, so it isn't clear if LZMA2 encoder is wanted
gokhlayeh@9258 131 + into the kernel.
gokhlayeh@9258 132 +
gokhlayeh@9258 133 + Support for limited random-access reading is planned for the
gokhlayeh@9258 134 + decompression code. I don't know if it could have any use in the
gokhlayeh@9258 135 + kernel, but I know that it would be useful in some embedded projects
gokhlayeh@9258 136 + outside the Linux kernel.
gokhlayeh@9258 137 +
gokhlayeh@9258 138 +Conformance to the .xz file format specification
gokhlayeh@9258 139 +
gokhlayeh@9258 140 + There are a couple of corner cases where things have been simplified
gokhlayeh@9258 141 + at expense of detecting errors as early as possible. These should not
gokhlayeh@9258 142 + matter in practice all, since they don't cause security issues. But
gokhlayeh@9258 143 + it is good to know this if testing the code e.g. with the test files
gokhlayeh@9258 144 + from XZ Utils.
gokhlayeh@9258 145 +
gokhlayeh@9258 146 +Reporting bugs
gokhlayeh@9258 147 +
gokhlayeh@9258 148 + Before reporting a bug, please check that it's not fixed already
gokhlayeh@9258 149 + at upstream. See <http://tukaani.org/xz/embedded.html> to get the
gokhlayeh@9258 150 + latest code.
gokhlayeh@9258 151 +
gokhlayeh@9258 152 + Report bugs to <lasse.collin@tukaani.org> or visit #tukaani on
gokhlayeh@9258 153 + Freenode and talk to Larhzu. I don't actively read LKML or other
gokhlayeh@9258 154 + kernel-related mailing lists, so if there's something I should know,
gokhlayeh@9258 155 + you should email to me personally or use IRC.
gokhlayeh@9258 156 +
gokhlayeh@9258 157 + Don't bother Igor Pavlov with questions about the XZ implementation
gokhlayeh@9258 158 + in the kernel or about XZ Utils. While these two implementations
gokhlayeh@9258 159 + include essential code that is directly based on Igor Pavlov's code,
gokhlayeh@9258 160 + these implementations aren't maintained nor supported by him.
gokhlayeh@9258 161 +
gokhlayeh@9258 162 diff --git a/include/linux/xz.h b/include/linux/xz.h
gokhlayeh@9258 163 new file mode 100644
gokhlayeh@9258 164 index 0000000..64cffa6
gokhlayeh@9258 165 --- /dev/null
gokhlayeh@9258 166 +++ b/include/linux/xz.h
gokhlayeh@9258 167 @@ -0,0 +1,264 @@
gokhlayeh@9258 168 +/*
gokhlayeh@9258 169 + * XZ decompressor
gokhlayeh@9258 170 + *
gokhlayeh@9258 171 + * Authors: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 172 + * Igor Pavlov <http://7-zip.org/>
gokhlayeh@9258 173 + *
gokhlayeh@9258 174 + * This file has been put into the public domain.
gokhlayeh@9258 175 + * You can do whatever you want with this file.
gokhlayeh@9258 176 + */
gokhlayeh@9258 177 +
gokhlayeh@9258 178 +#ifndef XZ_H
gokhlayeh@9258 179 +#define XZ_H
gokhlayeh@9258 180 +
gokhlayeh@9258 181 +#ifdef __KERNEL__
gokhlayeh@9258 182 +# include <linux/stddef.h>
gokhlayeh@9258 183 +# include <linux/types.h>
gokhlayeh@9258 184 +#else
gokhlayeh@9258 185 +# include <stddef.h>
gokhlayeh@9258 186 +# include <stdint.h>
gokhlayeh@9258 187 +#endif
gokhlayeh@9258 188 +
gokhlayeh@9258 189 +/* In Linux, this is used to make extern functions static when needed. */
gokhlayeh@9258 190 +#ifndef XZ_EXTERN
gokhlayeh@9258 191 +# define XZ_EXTERN extern
gokhlayeh@9258 192 +#endif
gokhlayeh@9258 193 +
gokhlayeh@9258 194 +/**
gokhlayeh@9258 195 + * enum xz_mode - Operation mode
gokhlayeh@9258 196 + *
gokhlayeh@9258 197 + * @XZ_SINGLE: Single-call mode. This uses less RAM than
gokhlayeh@9258 198 + * than multi-call modes, because the LZMA2
gokhlayeh@9258 199 + * dictionary doesn't need to be allocated as
gokhlayeh@9258 200 + * part of the decoder state. All required data
gokhlayeh@9258 201 + * structures are allocated at initialization,
gokhlayeh@9258 202 + * so xz_dec_run() cannot return XZ_MEM_ERROR.
gokhlayeh@9258 203 + * @XZ_PREALLOC: Multi-call mode with preallocated LZMA2
gokhlayeh@9258 204 + * dictionary buffer. All data structures are
gokhlayeh@9258 205 + * allocated at initialization, so xz_dec_run()
gokhlayeh@9258 206 + * cannot return XZ_MEM_ERROR.
gokhlayeh@9258 207 + * @XZ_DYNALLOC: Multi-call mode. The LZMA2 dictionary is
gokhlayeh@9258 208 + * allocated once the required size has been
gokhlayeh@9258 209 + * parsed from the stream headers. If the
gokhlayeh@9258 210 + * allocation fails, xz_dec_run() will return
gokhlayeh@9258 211 + * XZ_MEM_ERROR.
gokhlayeh@9258 212 + *
gokhlayeh@9258 213 + * It is possible to enable support only for a subset of the above
gokhlayeh@9258 214 + * modes at compile time by defining XZ_DEC_SINGLE, XZ_DEC_PREALLOC,
gokhlayeh@9258 215 + * or XZ_DEC_DYNALLOC. The xz_dec kernel module is always compiled
gokhlayeh@9258 216 + * with support for all operation modes, but the preboot code may
gokhlayeh@9258 217 + * be built with fewer features to minimize code size.
gokhlayeh@9258 218 + */
gokhlayeh@9258 219 +enum xz_mode {
gokhlayeh@9258 220 + XZ_SINGLE,
gokhlayeh@9258 221 + XZ_PREALLOC,
gokhlayeh@9258 222 + XZ_DYNALLOC
gokhlayeh@9258 223 +};
gokhlayeh@9258 224 +
gokhlayeh@9258 225 +/**
gokhlayeh@9258 226 + * enum xz_ret - Return codes
gokhlayeh@9258 227 + * @XZ_OK: Everything is OK so far. More input or more
gokhlayeh@9258 228 + * output space is required to continue. This
gokhlayeh@9258 229 + * return code is possible only in multi-call mode
gokhlayeh@9258 230 + * (XZ_PREALLOC or XZ_DYNALLOC).
gokhlayeh@9258 231 + * @XZ_STREAM_END: Operation finished successfully.
gokhlayeh@9258 232 + * @XZ_UNSUPPORTED_CHECK: Integrity check type is not supported. Decoding
gokhlayeh@9258 233 + * is still possible in multi-call mode by simply
gokhlayeh@9258 234 + * calling xz_dec_run() again.
gokhlayeh@9258 235 + * Note that this return value is used only if
gokhlayeh@9258 236 + * XZ_DEC_ANY_CHECK was defined at build time,
gokhlayeh@9258 237 + * which is not used in the kernel. Unsupported
gokhlayeh@9258 238 + * check types return XZ_OPTIONS_ERROR if
gokhlayeh@9258 239 + * XZ_DEC_ANY_CHECK was not defined at build time.
gokhlayeh@9258 240 + * @XZ_MEM_ERROR: Allocating memory failed. This return code is
gokhlayeh@9258 241 + * possible only if the decoder was initialized
gokhlayeh@9258 242 + * with XZ_DYNALLOC. The amount of memory that was
gokhlayeh@9258 243 + * tried to be allocated was no more than the
gokhlayeh@9258 244 + * dict_max argument given to xz_dec_init().
gokhlayeh@9258 245 + * @XZ_MEMLIMIT_ERROR: A bigger LZMA2 dictionary would be needed than
gokhlayeh@9258 246 + * allowed by the dict_max argument given to
gokhlayeh@9258 247 + * xz_dec_init(). This return value is possible
gokhlayeh@9258 248 + * only in multi-call mode (XZ_PREALLOC or
gokhlayeh@9258 249 + * XZ_DYNALLOC); the single-call mode (XZ_SINGLE)
gokhlayeh@9258 250 + * ignores the dict_max argument.
gokhlayeh@9258 251 + * @XZ_FORMAT_ERROR: File format was not recognized (wrong magic
gokhlayeh@9258 252 + * bytes).
gokhlayeh@9258 253 + * @XZ_OPTIONS_ERROR: This implementation doesn't support the requested
gokhlayeh@9258 254 + * compression options. In the decoder this means
gokhlayeh@9258 255 + * that the header CRC32 matches, but the header
gokhlayeh@9258 256 + * itself specifies something that we don't support.
gokhlayeh@9258 257 + * @XZ_DATA_ERROR: Compressed data is corrupt.
gokhlayeh@9258 258 + * @XZ_BUF_ERROR: Cannot make any progress. Details are slightly
gokhlayeh@9258 259 + * different between multi-call and single-call
gokhlayeh@9258 260 + * mode; more information below.
gokhlayeh@9258 261 + *
gokhlayeh@9258 262 + * In multi-call mode, XZ_BUF_ERROR is returned when two consecutive calls
gokhlayeh@9258 263 + * to XZ code cannot consume any input and cannot produce any new output.
gokhlayeh@9258 264 + * This happens when there is no new input available, or the output buffer
gokhlayeh@9258 265 + * is full while at least one output byte is still pending. Assuming your
gokhlayeh@9258 266 + * code is not buggy, you can get this error only when decoding a compressed
gokhlayeh@9258 267 + * stream that is truncated or otherwise corrupt.
gokhlayeh@9258 268 + *
gokhlayeh@9258 269 + * In single-call mode, XZ_BUF_ERROR is returned only when the output buffer
gokhlayeh@9258 270 + * is too small or the compressed input is corrupt in a way that makes the
gokhlayeh@9258 271 + * decoder produce more output than the caller expected. When it is
gokhlayeh@9258 272 + * (relatively) clear that the compressed input is truncated, XZ_DATA_ERROR
gokhlayeh@9258 273 + * is used instead of XZ_BUF_ERROR.
gokhlayeh@9258 274 + */
gokhlayeh@9258 275 +enum xz_ret {
gokhlayeh@9258 276 + XZ_OK,
gokhlayeh@9258 277 + XZ_STREAM_END,
gokhlayeh@9258 278 + XZ_UNSUPPORTED_CHECK,
gokhlayeh@9258 279 + XZ_MEM_ERROR,
gokhlayeh@9258 280 + XZ_MEMLIMIT_ERROR,
gokhlayeh@9258 281 + XZ_FORMAT_ERROR,
gokhlayeh@9258 282 + XZ_OPTIONS_ERROR,
gokhlayeh@9258 283 + XZ_DATA_ERROR,
gokhlayeh@9258 284 + XZ_BUF_ERROR
gokhlayeh@9258 285 +};
gokhlayeh@9258 286 +
gokhlayeh@9258 287 +/**
gokhlayeh@9258 288 + * struct xz_buf - Passing input and output buffers to XZ code
gokhlayeh@9258 289 + * @in: Beginning of the input buffer. This may be NULL if and only
gokhlayeh@9258 290 + * if in_pos is equal to in_size.
gokhlayeh@9258 291 + * @in_pos: Current position in the input buffer. This must not exceed
gokhlayeh@9258 292 + * in_size.
gokhlayeh@9258 293 + * @in_size: Size of the input buffer
gokhlayeh@9258 294 + * @out: Beginning of the output buffer. This may be NULL if and only
gokhlayeh@9258 295 + * if out_pos is equal to out_size.
gokhlayeh@9258 296 + * @out_pos: Current position in the output buffer. This must not exceed
gokhlayeh@9258 297 + * out_size.
gokhlayeh@9258 298 + * @out_size: Size of the output buffer
gokhlayeh@9258 299 + *
gokhlayeh@9258 300 + * Only the contents of the output buffer from out[out_pos] onward, and
gokhlayeh@9258 301 + * the variables in_pos and out_pos are modified by the XZ code.
gokhlayeh@9258 302 + */
gokhlayeh@9258 303 +struct xz_buf {
gokhlayeh@9258 304 + const uint8_t *in;
gokhlayeh@9258 305 + size_t in_pos;
gokhlayeh@9258 306 + size_t in_size;
gokhlayeh@9258 307 +
gokhlayeh@9258 308 + uint8_t *out;
gokhlayeh@9258 309 + size_t out_pos;
gokhlayeh@9258 310 + size_t out_size;
gokhlayeh@9258 311 +};
gokhlayeh@9258 312 +
gokhlayeh@9258 313 +/**
gokhlayeh@9258 314 + * struct xz_dec - Opaque type to hold the XZ decoder state
gokhlayeh@9258 315 + */
gokhlayeh@9258 316 +struct xz_dec;
gokhlayeh@9258 317 +
gokhlayeh@9258 318 +/**
gokhlayeh@9258 319 + * xz_dec_init() - Allocate and initialize a XZ decoder state
gokhlayeh@9258 320 + * @mode: Operation mode
gokhlayeh@9258 321 + * @dict_max: Maximum size of the LZMA2 dictionary (history buffer) for
gokhlayeh@9258 322 + * multi-call decoding. This is ignored in single-call mode
gokhlayeh@9258 323 + * (mode == XZ_SINGLE). LZMA2 dictionary is always 2^n bytes
gokhlayeh@9258 324 + * or 2^n + 2^(n-1) bytes (the latter sizes are less common
gokhlayeh@9258 325 + * in practice), so other values for dict_max don't make sense.
gokhlayeh@9258 326 + * In the kernel, dictionary sizes of 64 KiB, 128 KiB, 256 KiB,
gokhlayeh@9258 327 + * 512 KiB, and 1 MiB are probably the only reasonable values,
gokhlayeh@9258 328 + * except for kernel and initramfs images where a bigger
gokhlayeh@9258 329 + * dictionary can be fine and useful.
gokhlayeh@9258 330 + *
gokhlayeh@9258 331 + * Single-call mode (XZ_SINGLE): xz_dec_run() decodes the whole stream at
gokhlayeh@9258 332 + * once. The caller must provide enough output space or the decoding will
gokhlayeh@9258 333 + * fail. The output space is used as the dictionary buffer, which is why
gokhlayeh@9258 334 + * there is no need to allocate the dictionary as part of the decoder's
gokhlayeh@9258 335 + * internal state.
gokhlayeh@9258 336 + *
gokhlayeh@9258 337 + * Because the output buffer is used as the workspace, streams encoded using
gokhlayeh@9258 338 + * a big dictionary are not a problem in single-call mode. It is enough that
gokhlayeh@9258 339 + * the output buffer is big enough to hold the actual uncompressed data; it
gokhlayeh@9258 340 + * can be smaller than the dictionary size stored in the stream headers.
gokhlayeh@9258 341 + *
gokhlayeh@9258 342 + * Multi-call mode with preallocated dictionary (XZ_PREALLOC): dict_max bytes
gokhlayeh@9258 343 + * of memory is preallocated for the LZMA2 dictionary. This way there is no
gokhlayeh@9258 344 + * risk that xz_dec_run() could run out of memory, since xz_dec_run() will
gokhlayeh@9258 345 + * never allocate any memory. Instead, if the preallocated dictionary is too
gokhlayeh@9258 346 + * small for decoding the given input stream, xz_dec_run() will return
gokhlayeh@9258 347 + * XZ_MEMLIMIT_ERROR. Thus, it is important to know what kind of data will be
gokhlayeh@9258 348 + * decoded to avoid allocating excessive amount of memory for the dictionary.
gokhlayeh@9258 349 + *
gokhlayeh@9258 350 + * Multi-call mode with dynamically allocated dictionary (XZ_DYNALLOC):
gokhlayeh@9258 351 + * dict_max specifies the maximum allowed dictionary size that xz_dec_run()
gokhlayeh@9258 352 + * may allocate once it has parsed the dictionary size from the stream
gokhlayeh@9258 353 + * headers. This way excessive allocations can be avoided while still
gokhlayeh@9258 354 + * limiting the maximum memory usage to a sane value to prevent running the
gokhlayeh@9258 355 + * system out of memory when decompressing streams from untrusted sources.
gokhlayeh@9258 356 + *
gokhlayeh@9258 357 + * On success, xz_dec_init() returns a pointer to struct xz_dec, which is
gokhlayeh@9258 358 + * ready to be used with xz_dec_run(). If memory allocation fails,
gokhlayeh@9258 359 + * xz_dec_init() returns NULL.
gokhlayeh@9258 360 + */
gokhlayeh@9258 361 +XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max);
gokhlayeh@9258 362 +
gokhlayeh@9258 363 +/**
gokhlayeh@9258 364 + * xz_dec_run() - Run the XZ decoder
gokhlayeh@9258 365 + * @s: Decoder state allocated using xz_dec_init()
gokhlayeh@9258 366 + * @b: Input and output buffers
gokhlayeh@9258 367 + *
gokhlayeh@9258 368 + * The possible return values depend on build options and operation mode.
gokhlayeh@9258 369 + * See enum xz_ret for details.
gokhlayeh@9258 370 + *
gokhlayeh@9258 371 + * Note that if an error occurs in single-call mode (return value is not
gokhlayeh@9258 372 + * XZ_STREAM_END), b->in_pos and b->out_pos are not modified and the
gokhlayeh@9258 373 + * contents of the output buffer from b->out[b->out_pos] onward are
gokhlayeh@9258 374 + * undefined. This is true even after XZ_BUF_ERROR, because with some filter
gokhlayeh@9258 375 + * chains, there may be a second pass over the output buffer, and this pass
gokhlayeh@9258 376 + * cannot be properly done if the output buffer is truncated. Thus, you
gokhlayeh@9258 377 + * cannot give the single-call decoder a too small buffer and then expect to
gokhlayeh@9258 378 + * get that amount valid data from the beginning of the stream. You must use
gokhlayeh@9258 379 + * the multi-call decoder if you don't want to uncompress the whole stream.
gokhlayeh@9258 380 + */
gokhlayeh@9258 381 +XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b);
gokhlayeh@9258 382 +
gokhlayeh@9258 383 +/**
gokhlayeh@9258 384 + * xz_dec_reset() - Reset an already allocated decoder state
gokhlayeh@9258 385 + * @s: Decoder state allocated using xz_dec_init()
gokhlayeh@9258 386 + *
gokhlayeh@9258 387 + * This function can be used to reset the multi-call decoder state without
gokhlayeh@9258 388 + * freeing and reallocating memory with xz_dec_end() and xz_dec_init().
gokhlayeh@9258 389 + *
gokhlayeh@9258 390 + * In single-call mode, xz_dec_reset() is always called in the beginning of
gokhlayeh@9258 391 + * xz_dec_run(). Thus, explicit call to xz_dec_reset() is useful only in
gokhlayeh@9258 392 + * multi-call mode.
gokhlayeh@9258 393 + */
gokhlayeh@9258 394 +XZ_EXTERN void xz_dec_reset(struct xz_dec *s);
gokhlayeh@9258 395 +
gokhlayeh@9258 396 +/**
gokhlayeh@9258 397 + * xz_dec_end() - Free the memory allocated for the decoder state
gokhlayeh@9258 398 + * @s: Decoder state allocated using xz_dec_init(). If s is NULL,
gokhlayeh@9258 399 + * this function does nothing.
gokhlayeh@9258 400 + */
gokhlayeh@9258 401 +XZ_EXTERN void xz_dec_end(struct xz_dec *s);
gokhlayeh@9258 402 +
gokhlayeh@9258 403 +/*
gokhlayeh@9258 404 + * Standalone build (userspace build or in-kernel build for boot time use)
gokhlayeh@9258 405 + * needs a CRC32 implementation. For normal in-kernel use, kernel's own
gokhlayeh@9258 406 + * CRC32 module is used instead, and users of this module don't need to
gokhlayeh@9258 407 + * care about the functions below.
gokhlayeh@9258 408 + */
gokhlayeh@9258 409 +#ifndef XZ_INTERNAL_CRC32
gokhlayeh@9258 410 +# ifdef __KERNEL__
gokhlayeh@9258 411 +# define XZ_INTERNAL_CRC32 0
gokhlayeh@9258 412 +# else
gokhlayeh@9258 413 +# define XZ_INTERNAL_CRC32 1
gokhlayeh@9258 414 +# endif
gokhlayeh@9258 415 +#endif
gokhlayeh@9258 416 +
gokhlayeh@9258 417 +#if XZ_INTERNAL_CRC32
gokhlayeh@9258 418 +/*
gokhlayeh@9258 419 + * This must be called before any other xz_* function to initialize
gokhlayeh@9258 420 + * the CRC32 lookup table.
gokhlayeh@9258 421 + */
gokhlayeh@9258 422 +XZ_EXTERN void xz_crc32_init(void);
gokhlayeh@9258 423 +
gokhlayeh@9258 424 +/*
gokhlayeh@9258 425 + * Update CRC32 value using the polynomial from IEEE-802.3. To start a new
gokhlayeh@9258 426 + * calculation, the third argument must be zero. To continue the calculation,
gokhlayeh@9258 427 + * the previously returned value is passed as the third argument.
gokhlayeh@9258 428 + */
gokhlayeh@9258 429 +XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc);
gokhlayeh@9258 430 +#endif
gokhlayeh@9258 431 +#endif
gokhlayeh@9258 432 diff --git a/lib/Kconfig b/lib/Kconfig
gokhlayeh@9258 433 index fa9bf2c..6090314 100644
gokhlayeh@9258 434 --- a/lib/Kconfig
gokhlayeh@9258 435 +++ b/lib/Kconfig
gokhlayeh@9258 436 @@ -106,6 +106,8 @@ config LZO_COMPRESS
gokhlayeh@9258 437 config LZO_DECOMPRESS
gokhlayeh@9258 438 tristate
gokhlayeh@9258 439
gokhlayeh@9258 440 +source "lib/xz/Kconfig"
gokhlayeh@9258 441 +
gokhlayeh@9258 442 #
gokhlayeh@9258 443 # These all provide a common interface (hence the apparent duplication with
gokhlayeh@9258 444 # ZLIB_INFLATE; DECOMPRESS_GZIP is just a wrapper.)
gokhlayeh@9258 445 diff --git a/lib/Makefile b/lib/Makefile
gokhlayeh@9258 446 index e6a3763..f2f98dd 100644
gokhlayeh@9258 447 --- a/lib/Makefile
gokhlayeh@9258 448 +++ b/lib/Makefile
gokhlayeh@9258 449 @@ -69,6 +69,7 @@ obj-$(CONFIG_ZLIB_DEFLATE) += zlib_deflate/
gokhlayeh@9258 450 obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
gokhlayeh@9258 451 obj-$(CONFIG_LZO_COMPRESS) += lzo/
gokhlayeh@9258 452 obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
gokhlayeh@9258 453 +obj-$(CONFIG_XZ_DEC) += xz/
gokhlayeh@9258 454 obj-$(CONFIG_RAID6_PQ) += raid6/
gokhlayeh@9258 455
gokhlayeh@9258 456 lib-$(CONFIG_DECOMPRESS_GZIP) += decompress_inflate.o
gokhlayeh@9258 457 diff --git a/lib/xz/Kconfig b/lib/xz/Kconfig
gokhlayeh@9258 458 new file mode 100644
gokhlayeh@9258 459 index 0000000..e3b6e18
gokhlayeh@9258 460 --- /dev/null
gokhlayeh@9258 461 +++ b/lib/xz/Kconfig
gokhlayeh@9258 462 @@ -0,0 +1,59 @@
gokhlayeh@9258 463 +config XZ_DEC
gokhlayeh@9258 464 + tristate "XZ decompression support"
gokhlayeh@9258 465 + select CRC32
gokhlayeh@9258 466 + help
gokhlayeh@9258 467 + LZMA2 compression algorithm and BCJ filters are supported using
gokhlayeh@9258 468 + the .xz file format as the container. For integrity checking,
gokhlayeh@9258 469 + CRC32 is supported. See Documentation/xz.txt for more information.
gokhlayeh@9258 470 +
gokhlayeh@9258 471 +config XZ_DEC_X86
gokhlayeh@9258 472 + bool "x86 BCJ filter decoder" if EMBEDDED
gokhlayeh@9258 473 + default y
gokhlayeh@9258 474 + depends on XZ_DEC
gokhlayeh@9258 475 + select XZ_DEC_BCJ
gokhlayeh@9258 476 +
gokhlayeh@9258 477 +config XZ_DEC_POWERPC
gokhlayeh@9258 478 + bool "PowerPC BCJ filter decoder" if EMBEDDED
gokhlayeh@9258 479 + default y
gokhlayeh@9258 480 + depends on XZ_DEC
gokhlayeh@9258 481 + select XZ_DEC_BCJ
gokhlayeh@9258 482 +
gokhlayeh@9258 483 +config XZ_DEC_IA64
gokhlayeh@9258 484 + bool "IA-64 BCJ filter decoder" if EMBEDDED
gokhlayeh@9258 485 + default y
gokhlayeh@9258 486 + depends on XZ_DEC
gokhlayeh@9258 487 + select XZ_DEC_BCJ
gokhlayeh@9258 488 +
gokhlayeh@9258 489 +config XZ_DEC_ARM
gokhlayeh@9258 490 + bool "ARM BCJ filter decoder" if EMBEDDED
gokhlayeh@9258 491 + default y
gokhlayeh@9258 492 + depends on XZ_DEC
gokhlayeh@9258 493 + select XZ_DEC_BCJ
gokhlayeh@9258 494 +
gokhlayeh@9258 495 +config XZ_DEC_ARMTHUMB
gokhlayeh@9258 496 + bool "ARM-Thumb BCJ filter decoder" if EMBEDDED
gokhlayeh@9258 497 + default y
gokhlayeh@9258 498 + depends on XZ_DEC
gokhlayeh@9258 499 + select XZ_DEC_BCJ
gokhlayeh@9258 500 +
gokhlayeh@9258 501 +config XZ_DEC_SPARC
gokhlayeh@9258 502 + bool "SPARC BCJ filter decoder" if EMBEDDED
gokhlayeh@9258 503 + default y
gokhlayeh@9258 504 + depends on XZ_DEC
gokhlayeh@9258 505 + select XZ_DEC_BCJ
gokhlayeh@9258 506 +
gokhlayeh@9258 507 +config XZ_DEC_BCJ
gokhlayeh@9258 508 + bool
gokhlayeh@9258 509 + default n
gokhlayeh@9258 510 +
gokhlayeh@9258 511 +config XZ_DEC_TEST
gokhlayeh@9258 512 + tristate "XZ decompressor tester"
gokhlayeh@9258 513 + default n
gokhlayeh@9258 514 + depends on XZ_DEC
gokhlayeh@9258 515 + help
gokhlayeh@9258 516 + This allows passing .xz files to the in-kernel XZ decoder via
gokhlayeh@9258 517 + a character special file. It calculates CRC32 of the decompressed
gokhlayeh@9258 518 + data and writes diagnostics to the system log.
gokhlayeh@9258 519 +
gokhlayeh@9258 520 + Unless you are developing the XZ decoder, you don't need this
gokhlayeh@9258 521 + and should say N.
gokhlayeh@9258 522 diff --git a/lib/xz/Makefile b/lib/xz/Makefile
gokhlayeh@9258 523 new file mode 100644
gokhlayeh@9258 524 index 0000000..a7fa769
gokhlayeh@9258 525 --- /dev/null
gokhlayeh@9258 526 +++ b/lib/xz/Makefile
gokhlayeh@9258 527 @@ -0,0 +1,5 @@
gokhlayeh@9258 528 +obj-$(CONFIG_XZ_DEC) += xz_dec.o
gokhlayeh@9258 529 +xz_dec-y := xz_dec_syms.o xz_dec_stream.o xz_dec_lzma2.o
gokhlayeh@9258 530 +xz_dec-$(CONFIG_XZ_DEC_BCJ) += xz_dec_bcj.o
gokhlayeh@9258 531 +
gokhlayeh@9258 532 +obj-$(CONFIG_XZ_DEC_TEST) += xz_dec_test.o
gokhlayeh@9258 533 diff --git a/lib/xz/xz_crc32.c b/lib/xz/xz_crc32.c
gokhlayeh@9258 534 new file mode 100644
gokhlayeh@9258 535 index 0000000..34532d1
gokhlayeh@9258 536 --- /dev/null
gokhlayeh@9258 537 +++ b/lib/xz/xz_crc32.c
gokhlayeh@9258 538 @@ -0,0 +1,59 @@
gokhlayeh@9258 539 +/*
gokhlayeh@9258 540 + * CRC32 using the polynomial from IEEE-802.3
gokhlayeh@9258 541 + *
gokhlayeh@9258 542 + * Authors: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 543 + * Igor Pavlov <http://7-zip.org/>
gokhlayeh@9258 544 + *
gokhlayeh@9258 545 + * This file has been put into the public domain.
gokhlayeh@9258 546 + * You can do whatever you want with this file.
gokhlayeh@9258 547 + */
gokhlayeh@9258 548 +
gokhlayeh@9258 549 +/*
gokhlayeh@9258 550 + * This is not the fastest implementation, but it is pretty compact.
gokhlayeh@9258 551 + * The fastest versions of xz_crc32() on modern CPUs without hardware
gokhlayeh@9258 552 + * accelerated CRC instruction are 3-5 times as fast as this version,
gokhlayeh@9258 553 + * but they are bigger and use more memory for the lookup table.
gokhlayeh@9258 554 + */
gokhlayeh@9258 555 +
gokhlayeh@9258 556 +#include "xz_private.h"
gokhlayeh@9258 557 +
gokhlayeh@9258 558 +/*
gokhlayeh@9258 559 + * STATIC_RW_DATA is used in the pre-boot environment on some architectures.
gokhlayeh@9258 560 + * See <linux/decompress/mm.h> for details.
gokhlayeh@9258 561 + */
gokhlayeh@9258 562 +#ifndef STATIC_RW_DATA
gokhlayeh@9258 563 +# define STATIC_RW_DATA static
gokhlayeh@9258 564 +#endif
gokhlayeh@9258 565 +
gokhlayeh@9258 566 +STATIC_RW_DATA uint32_t xz_crc32_table[256];
gokhlayeh@9258 567 +
gokhlayeh@9258 568 +XZ_EXTERN void xz_crc32_init(void)
gokhlayeh@9258 569 +{
gokhlayeh@9258 570 + const uint32_t poly = 0xEDB88320;
gokhlayeh@9258 571 +
gokhlayeh@9258 572 + uint32_t i;
gokhlayeh@9258 573 + uint32_t j;
gokhlayeh@9258 574 + uint32_t r;
gokhlayeh@9258 575 +
gokhlayeh@9258 576 + for (i = 0; i < 256; ++i) {
gokhlayeh@9258 577 + r = i;
gokhlayeh@9258 578 + for (j = 0; j < 8; ++j)
gokhlayeh@9258 579 + r = (r >> 1) ^ (poly & ~((r & 1) - 1));
gokhlayeh@9258 580 +
gokhlayeh@9258 581 + xz_crc32_table[i] = r;
gokhlayeh@9258 582 + }
gokhlayeh@9258 583 +
gokhlayeh@9258 584 + return;
gokhlayeh@9258 585 +}
gokhlayeh@9258 586 +
gokhlayeh@9258 587 +XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc)
gokhlayeh@9258 588 +{
gokhlayeh@9258 589 + crc = ~crc;
gokhlayeh@9258 590 +
gokhlayeh@9258 591 + while (size != 0) {
gokhlayeh@9258 592 + crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8);
gokhlayeh@9258 593 + --size;
gokhlayeh@9258 594 + }
gokhlayeh@9258 595 +
gokhlayeh@9258 596 + return ~crc;
gokhlayeh@9258 597 +}
gokhlayeh@9258 598 diff --git a/lib/xz/xz_dec_bcj.c b/lib/xz/xz_dec_bcj.c
gokhlayeh@9258 599 new file mode 100644
gokhlayeh@9258 600 index 0000000..e51e255
gokhlayeh@9258 601 --- /dev/null
gokhlayeh@9258 602 +++ b/lib/xz/xz_dec_bcj.c
gokhlayeh@9258 603 @@ -0,0 +1,561 @@
gokhlayeh@9258 604 +/*
gokhlayeh@9258 605 + * Branch/Call/Jump (BCJ) filter decoders
gokhlayeh@9258 606 + *
gokhlayeh@9258 607 + * Authors: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 608 + * Igor Pavlov <http://7-zip.org/>
gokhlayeh@9258 609 + *
gokhlayeh@9258 610 + * This file has been put into the public domain.
gokhlayeh@9258 611 + * You can do whatever you want with this file.
gokhlayeh@9258 612 + */
gokhlayeh@9258 613 +
gokhlayeh@9258 614 +#include "xz_private.h"
gokhlayeh@9258 615 +
gokhlayeh@9258 616 +/*
gokhlayeh@9258 617 + * The rest of the file is inside this ifdef. It makes things a little more
gokhlayeh@9258 618 + * convenient when building without support for any BCJ filters.
gokhlayeh@9258 619 + */
gokhlayeh@9258 620 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 621 +
gokhlayeh@9258 622 +struct xz_dec_bcj {
gokhlayeh@9258 623 + /* Type of the BCJ filter being used */
gokhlayeh@9258 624 + enum {
gokhlayeh@9258 625 + BCJ_X86 = 4, /* x86 or x86-64 */
gokhlayeh@9258 626 + BCJ_POWERPC = 5, /* Big endian only */
gokhlayeh@9258 627 + BCJ_IA64 = 6, /* Big or little endian */
gokhlayeh@9258 628 + BCJ_ARM = 7, /* Little endian only */
gokhlayeh@9258 629 + BCJ_ARMTHUMB = 8, /* Little endian only */
gokhlayeh@9258 630 + BCJ_SPARC = 9 /* Big or little endian */
gokhlayeh@9258 631 + } type;
gokhlayeh@9258 632 +
gokhlayeh@9258 633 + /*
gokhlayeh@9258 634 + * Return value of the next filter in the chain. We need to preserve
gokhlayeh@9258 635 + * this information across calls, because we must not call the next
gokhlayeh@9258 636 + * filter anymore once it has returned XZ_STREAM_END.
gokhlayeh@9258 637 + */
gokhlayeh@9258 638 + enum xz_ret ret;
gokhlayeh@9258 639 +
gokhlayeh@9258 640 + /* True if we are operating in single-call mode. */
gokhlayeh@9258 641 + bool single_call;
gokhlayeh@9258 642 +
gokhlayeh@9258 643 + /*
gokhlayeh@9258 644 + * Absolute position relative to the beginning of the uncompressed
gokhlayeh@9258 645 + * data (in a single .xz Block). We care only about the lowest 32
gokhlayeh@9258 646 + * bits so this doesn't need to be uint64_t even with big files.
gokhlayeh@9258 647 + */
gokhlayeh@9258 648 + uint32_t pos;
gokhlayeh@9258 649 +
gokhlayeh@9258 650 + /* x86 filter state */
gokhlayeh@9258 651 + uint32_t x86_prev_mask;
gokhlayeh@9258 652 +
gokhlayeh@9258 653 + /* Temporary space to hold the variables from struct xz_buf */
gokhlayeh@9258 654 + uint8_t *out;
gokhlayeh@9258 655 + size_t out_pos;
gokhlayeh@9258 656 + size_t out_size;
gokhlayeh@9258 657 +
gokhlayeh@9258 658 + struct {
gokhlayeh@9258 659 + /* Amount of already filtered data in the beginning of buf */
gokhlayeh@9258 660 + size_t filtered;
gokhlayeh@9258 661 +
gokhlayeh@9258 662 + /* Total amount of data currently stored in buf */
gokhlayeh@9258 663 + size_t size;
gokhlayeh@9258 664 +
gokhlayeh@9258 665 + /*
gokhlayeh@9258 666 + * Buffer to hold a mix of filtered and unfiltered data. This
gokhlayeh@9258 667 + * needs to be big enough to hold Alignment + 2 * Look-ahead:
gokhlayeh@9258 668 + *
gokhlayeh@9258 669 + * Type Alignment Look-ahead
gokhlayeh@9258 670 + * x86 1 4
gokhlayeh@9258 671 + * PowerPC 4 0
gokhlayeh@9258 672 + * IA-64 16 0
gokhlayeh@9258 673 + * ARM 4 0
gokhlayeh@9258 674 + * ARM-Thumb 2 2
gokhlayeh@9258 675 + * SPARC 4 0
gokhlayeh@9258 676 + */
gokhlayeh@9258 677 + uint8_t buf[16];
gokhlayeh@9258 678 + } temp;
gokhlayeh@9258 679 +};
gokhlayeh@9258 680 +
gokhlayeh@9258 681 +#ifdef XZ_DEC_X86
gokhlayeh@9258 682 +/*
gokhlayeh@9258 683 + * This is used to test the most significant byte of a memory address
gokhlayeh@9258 684 + * in an x86 instruction.
gokhlayeh@9258 685 + */
gokhlayeh@9258 686 +static inline int bcj_x86_test_msbyte(uint8_t b)
gokhlayeh@9258 687 +{
gokhlayeh@9258 688 + return b == 0x00 || b == 0xFF;
gokhlayeh@9258 689 +}
gokhlayeh@9258 690 +
gokhlayeh@9258 691 +static size_t bcj_x86(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
gokhlayeh@9258 692 +{
gokhlayeh@9258 693 + static const bool mask_to_allowed_status[8]
gokhlayeh@9258 694 + = { true, true, true, false, true, false, false, false };
gokhlayeh@9258 695 +
gokhlayeh@9258 696 + static const uint8_t mask_to_bit_num[8] = { 0, 1, 2, 2, 3, 3, 3, 3 };
gokhlayeh@9258 697 +
gokhlayeh@9258 698 + size_t i;
gokhlayeh@9258 699 + size_t prev_pos = (size_t)-1;
gokhlayeh@9258 700 + uint32_t prev_mask = s->x86_prev_mask;
gokhlayeh@9258 701 + uint32_t src;
gokhlayeh@9258 702 + uint32_t dest;
gokhlayeh@9258 703 + uint32_t j;
gokhlayeh@9258 704 + uint8_t b;
gokhlayeh@9258 705 +
gokhlayeh@9258 706 + if (size <= 4)
gokhlayeh@9258 707 + return 0;
gokhlayeh@9258 708 +
gokhlayeh@9258 709 + size -= 4;
gokhlayeh@9258 710 + for (i = 0; i < size; ++i) {
gokhlayeh@9258 711 + if ((buf[i] & 0xFE) != 0xE8)
gokhlayeh@9258 712 + continue;
gokhlayeh@9258 713 +
gokhlayeh@9258 714 + prev_pos = i - prev_pos;
gokhlayeh@9258 715 + if (prev_pos > 3) {
gokhlayeh@9258 716 + prev_mask = 0;
gokhlayeh@9258 717 + } else {
gokhlayeh@9258 718 + prev_mask = (prev_mask << (prev_pos - 1)) & 7;
gokhlayeh@9258 719 + if (prev_mask != 0) {
gokhlayeh@9258 720 + b = buf[i + 4 - mask_to_bit_num[prev_mask]];
gokhlayeh@9258 721 + if (!mask_to_allowed_status[prev_mask]
gokhlayeh@9258 722 + || bcj_x86_test_msbyte(b)) {
gokhlayeh@9258 723 + prev_pos = i;
gokhlayeh@9258 724 + prev_mask = (prev_mask << 1) | 1;
gokhlayeh@9258 725 + continue;
gokhlayeh@9258 726 + }
gokhlayeh@9258 727 + }
gokhlayeh@9258 728 + }
gokhlayeh@9258 729 +
gokhlayeh@9258 730 + prev_pos = i;
gokhlayeh@9258 731 +
gokhlayeh@9258 732 + if (bcj_x86_test_msbyte(buf[i + 4])) {
gokhlayeh@9258 733 + src = get_unaligned_le32(buf + i + 1);
gokhlayeh@9258 734 + while (true) {
gokhlayeh@9258 735 + dest = src - (s->pos + (uint32_t)i + 5);
gokhlayeh@9258 736 + if (prev_mask == 0)
gokhlayeh@9258 737 + break;
gokhlayeh@9258 738 +
gokhlayeh@9258 739 + j = mask_to_bit_num[prev_mask] * 8;
gokhlayeh@9258 740 + b = (uint8_t)(dest >> (24 - j));
gokhlayeh@9258 741 + if (!bcj_x86_test_msbyte(b))
gokhlayeh@9258 742 + break;
gokhlayeh@9258 743 +
gokhlayeh@9258 744 + src = dest ^ (((uint32_t)1 << (32 - j)) - 1);
gokhlayeh@9258 745 + }
gokhlayeh@9258 746 +
gokhlayeh@9258 747 + dest &= 0x01FFFFFF;
gokhlayeh@9258 748 + dest |= (uint32_t)0 - (dest & 0x01000000);
gokhlayeh@9258 749 + put_unaligned_le32(dest, buf + i + 1);
gokhlayeh@9258 750 + i += 4;
gokhlayeh@9258 751 + } else {
gokhlayeh@9258 752 + prev_mask = (prev_mask << 1) | 1;
gokhlayeh@9258 753 + }
gokhlayeh@9258 754 + }
gokhlayeh@9258 755 +
gokhlayeh@9258 756 + prev_pos = i - prev_pos;
gokhlayeh@9258 757 + s->x86_prev_mask = prev_pos > 3 ? 0 : prev_mask << (prev_pos - 1);
gokhlayeh@9258 758 + return i;
gokhlayeh@9258 759 +}
gokhlayeh@9258 760 +#endif
gokhlayeh@9258 761 +
gokhlayeh@9258 762 +#ifdef XZ_DEC_POWERPC
gokhlayeh@9258 763 +static size_t bcj_powerpc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
gokhlayeh@9258 764 +{
gokhlayeh@9258 765 + size_t i;
gokhlayeh@9258 766 + uint32_t instr;
gokhlayeh@9258 767 +
gokhlayeh@9258 768 + for (i = 0; i + 4 <= size; i += 4) {
gokhlayeh@9258 769 + instr = get_unaligned_be32(buf + i);
gokhlayeh@9258 770 + if ((instr & 0xFC000003) == 0x48000001) {
gokhlayeh@9258 771 + instr &= 0x03FFFFFC;
gokhlayeh@9258 772 + instr -= s->pos + (uint32_t)i;
gokhlayeh@9258 773 + instr &= 0x03FFFFFC;
gokhlayeh@9258 774 + instr |= 0x48000001;
gokhlayeh@9258 775 + put_unaligned_be32(instr, buf + i);
gokhlayeh@9258 776 + }
gokhlayeh@9258 777 + }
gokhlayeh@9258 778 +
gokhlayeh@9258 779 + return i;
gokhlayeh@9258 780 +}
gokhlayeh@9258 781 +#endif
gokhlayeh@9258 782 +
gokhlayeh@9258 783 +#ifdef XZ_DEC_IA64
gokhlayeh@9258 784 +static size_t bcj_ia64(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
gokhlayeh@9258 785 +{
gokhlayeh@9258 786 + static const uint8_t branch_table[32] = {
gokhlayeh@9258 787 + 0, 0, 0, 0, 0, 0, 0, 0,
gokhlayeh@9258 788 + 0, 0, 0, 0, 0, 0, 0, 0,
gokhlayeh@9258 789 + 4, 4, 6, 6, 0, 0, 7, 7,
gokhlayeh@9258 790 + 4, 4, 0, 0, 4, 4, 0, 0
gokhlayeh@9258 791 + };
gokhlayeh@9258 792 +
gokhlayeh@9258 793 + /*
gokhlayeh@9258 794 + * The local variables take a little bit stack space, but it's less
gokhlayeh@9258 795 + * than what LZMA2 decoder takes, so it doesn't make sense to reduce
gokhlayeh@9258 796 + * stack usage here without doing that for the LZMA2 decoder too.
gokhlayeh@9258 797 + */
gokhlayeh@9258 798 +
gokhlayeh@9258 799 + /* Loop counters */
gokhlayeh@9258 800 + size_t i;
gokhlayeh@9258 801 + size_t j;
gokhlayeh@9258 802 +
gokhlayeh@9258 803 + /* Instruction slot (0, 1, or 2) in the 128-bit instruction word */
gokhlayeh@9258 804 + uint32_t slot;
gokhlayeh@9258 805 +
gokhlayeh@9258 806 + /* Bitwise offset of the instruction indicated by slot */
gokhlayeh@9258 807 + uint32_t bit_pos;
gokhlayeh@9258 808 +
gokhlayeh@9258 809 + /* bit_pos split into byte and bit parts */
gokhlayeh@9258 810 + uint32_t byte_pos;
gokhlayeh@9258 811 + uint32_t bit_res;
gokhlayeh@9258 812 +
gokhlayeh@9258 813 + /* Address part of an instruction */
gokhlayeh@9258 814 + uint32_t addr;
gokhlayeh@9258 815 +
gokhlayeh@9258 816 + /* Mask used to detect which instructions to convert */
gokhlayeh@9258 817 + uint32_t mask;
gokhlayeh@9258 818 +
gokhlayeh@9258 819 + /* 41-bit instruction stored somewhere in the lowest 48 bits */
gokhlayeh@9258 820 + uint64_t instr;
gokhlayeh@9258 821 +
gokhlayeh@9258 822 + /* Instruction normalized with bit_res for easier manipulation */
gokhlayeh@9258 823 + uint64_t norm;
gokhlayeh@9258 824 +
gokhlayeh@9258 825 + for (i = 0; i + 16 <= size; i += 16) {
gokhlayeh@9258 826 + mask = branch_table[buf[i] & 0x1F];
gokhlayeh@9258 827 + for (slot = 0, bit_pos = 5; slot < 3; ++slot, bit_pos += 41) {
gokhlayeh@9258 828 + if (((mask >> slot) & 1) == 0)
gokhlayeh@9258 829 + continue;
gokhlayeh@9258 830 +
gokhlayeh@9258 831 + byte_pos = bit_pos >> 3;
gokhlayeh@9258 832 + bit_res = bit_pos & 7;
gokhlayeh@9258 833 + instr = 0;
gokhlayeh@9258 834 + for (j = 0; j < 6; ++j)
gokhlayeh@9258 835 + instr |= (uint64_t)(buf[i + j + byte_pos])
gokhlayeh@9258 836 + << (8 * j);
gokhlayeh@9258 837 +
gokhlayeh@9258 838 + norm = instr >> bit_res;
gokhlayeh@9258 839 +
gokhlayeh@9258 840 + if (((norm >> 37) & 0x0F) == 0x05
gokhlayeh@9258 841 + && ((norm >> 9) & 0x07) == 0) {
gokhlayeh@9258 842 + addr = (norm >> 13) & 0x0FFFFF;
gokhlayeh@9258 843 + addr |= ((uint32_t)(norm >> 36) & 1) << 20;
gokhlayeh@9258 844 + addr <<= 4;
gokhlayeh@9258 845 + addr -= s->pos + (uint32_t)i;
gokhlayeh@9258 846 + addr >>= 4;
gokhlayeh@9258 847 +
gokhlayeh@9258 848 + norm &= ~((uint64_t)0x8FFFFF << 13);
gokhlayeh@9258 849 + norm |= (uint64_t)(addr & 0x0FFFFF) << 13;
gokhlayeh@9258 850 + norm |= (uint64_t)(addr & 0x100000)
gokhlayeh@9258 851 + << (36 - 20);
gokhlayeh@9258 852 +
gokhlayeh@9258 853 + instr &= (1 << bit_res) - 1;
gokhlayeh@9258 854 + instr |= norm << bit_res;
gokhlayeh@9258 855 +
gokhlayeh@9258 856 + for (j = 0; j < 6; j++)
gokhlayeh@9258 857 + buf[i + j + byte_pos]
gokhlayeh@9258 858 + = (uint8_t)(instr >> (8 * j));
gokhlayeh@9258 859 + }
gokhlayeh@9258 860 + }
gokhlayeh@9258 861 + }
gokhlayeh@9258 862 +
gokhlayeh@9258 863 + return i;
gokhlayeh@9258 864 +}
gokhlayeh@9258 865 +#endif
gokhlayeh@9258 866 +
gokhlayeh@9258 867 +#ifdef XZ_DEC_ARM
gokhlayeh@9258 868 +static size_t bcj_arm(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
gokhlayeh@9258 869 +{
gokhlayeh@9258 870 + size_t i;
gokhlayeh@9258 871 + uint32_t addr;
gokhlayeh@9258 872 +
gokhlayeh@9258 873 + for (i = 0; i + 4 <= size; i += 4) {
gokhlayeh@9258 874 + if (buf[i + 3] == 0xEB) {
gokhlayeh@9258 875 + addr = (uint32_t)buf[i] | ((uint32_t)buf[i + 1] << 8)
gokhlayeh@9258 876 + | ((uint32_t)buf[i + 2] << 16);
gokhlayeh@9258 877 + addr <<= 2;
gokhlayeh@9258 878 + addr -= s->pos + (uint32_t)i + 8;
gokhlayeh@9258 879 + addr >>= 2;
gokhlayeh@9258 880 + buf[i] = (uint8_t)addr;
gokhlayeh@9258 881 + buf[i + 1] = (uint8_t)(addr >> 8);
gokhlayeh@9258 882 + buf[i + 2] = (uint8_t)(addr >> 16);
gokhlayeh@9258 883 + }
gokhlayeh@9258 884 + }
gokhlayeh@9258 885 +
gokhlayeh@9258 886 + return i;
gokhlayeh@9258 887 +}
gokhlayeh@9258 888 +#endif
gokhlayeh@9258 889 +
gokhlayeh@9258 890 +#ifdef XZ_DEC_ARMTHUMB
gokhlayeh@9258 891 +static size_t bcj_armthumb(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
gokhlayeh@9258 892 +{
gokhlayeh@9258 893 + size_t i;
gokhlayeh@9258 894 + uint32_t addr;
gokhlayeh@9258 895 +
gokhlayeh@9258 896 + for (i = 0; i + 4 <= size; i += 2) {
gokhlayeh@9258 897 + if ((buf[i + 1] & 0xF8) == 0xF0
gokhlayeh@9258 898 + && (buf[i + 3] & 0xF8) == 0xF8) {
gokhlayeh@9258 899 + addr = (((uint32_t)buf[i + 1] & 0x07) << 19)
gokhlayeh@9258 900 + | ((uint32_t)buf[i] << 11)
gokhlayeh@9258 901 + | (((uint32_t)buf[i + 3] & 0x07) << 8)
gokhlayeh@9258 902 + | (uint32_t)buf[i + 2];
gokhlayeh@9258 903 + addr <<= 1;
gokhlayeh@9258 904 + addr -= s->pos + (uint32_t)i + 4;
gokhlayeh@9258 905 + addr >>= 1;
gokhlayeh@9258 906 + buf[i + 1] = (uint8_t)(0xF0 | ((addr >> 19) & 0x07));
gokhlayeh@9258 907 + buf[i] = (uint8_t)(addr >> 11);
gokhlayeh@9258 908 + buf[i + 3] = (uint8_t)(0xF8 | ((addr >> 8) & 0x07));
gokhlayeh@9258 909 + buf[i + 2] = (uint8_t)addr;
gokhlayeh@9258 910 + i += 2;
gokhlayeh@9258 911 + }
gokhlayeh@9258 912 + }
gokhlayeh@9258 913 +
gokhlayeh@9258 914 + return i;
gokhlayeh@9258 915 +}
gokhlayeh@9258 916 +#endif
gokhlayeh@9258 917 +
gokhlayeh@9258 918 +#ifdef XZ_DEC_SPARC
gokhlayeh@9258 919 +static size_t bcj_sparc(struct xz_dec_bcj *s, uint8_t *buf, size_t size)
gokhlayeh@9258 920 +{
gokhlayeh@9258 921 + size_t i;
gokhlayeh@9258 922 + uint32_t instr;
gokhlayeh@9258 923 +
gokhlayeh@9258 924 + for (i = 0; i + 4 <= size; i += 4) {
gokhlayeh@9258 925 + instr = get_unaligned_be32(buf + i);
gokhlayeh@9258 926 + if ((instr >> 22) == 0x100 || (instr >> 22) == 0x1FF) {
gokhlayeh@9258 927 + instr <<= 2;
gokhlayeh@9258 928 + instr -= s->pos + (uint32_t)i;
gokhlayeh@9258 929 + instr >>= 2;
gokhlayeh@9258 930 + instr = ((uint32_t)0x40000000 - (instr & 0x400000))
gokhlayeh@9258 931 + | 0x40000000 | (instr & 0x3FFFFF);
gokhlayeh@9258 932 + put_unaligned_be32(instr, buf + i);
gokhlayeh@9258 933 + }
gokhlayeh@9258 934 + }
gokhlayeh@9258 935 +
gokhlayeh@9258 936 + return i;
gokhlayeh@9258 937 +}
gokhlayeh@9258 938 +#endif
gokhlayeh@9258 939 +
gokhlayeh@9258 940 +/*
gokhlayeh@9258 941 + * Apply the selected BCJ filter. Update *pos and s->pos to match the amount
gokhlayeh@9258 942 + * of data that got filtered.
gokhlayeh@9258 943 + *
gokhlayeh@9258 944 + * NOTE: This is implemented as a switch statement to avoid using function
gokhlayeh@9258 945 + * pointers, which could be problematic in the kernel boot code, which must
gokhlayeh@9258 946 + * avoid pointers to static data (at least on x86).
gokhlayeh@9258 947 + */
gokhlayeh@9258 948 +static void bcj_apply(struct xz_dec_bcj *s,
gokhlayeh@9258 949 + uint8_t *buf, size_t *pos, size_t size)
gokhlayeh@9258 950 +{
gokhlayeh@9258 951 + size_t filtered;
gokhlayeh@9258 952 +
gokhlayeh@9258 953 + buf += *pos;
gokhlayeh@9258 954 + size -= *pos;
gokhlayeh@9258 955 +
gokhlayeh@9258 956 + switch (s->type) {
gokhlayeh@9258 957 +#ifdef XZ_DEC_X86
gokhlayeh@9258 958 + case BCJ_X86:
gokhlayeh@9258 959 + filtered = bcj_x86(s, buf, size);
gokhlayeh@9258 960 + break;
gokhlayeh@9258 961 +#endif
gokhlayeh@9258 962 +#ifdef XZ_DEC_POWERPC
gokhlayeh@9258 963 + case BCJ_POWERPC:
gokhlayeh@9258 964 + filtered = bcj_powerpc(s, buf, size);
gokhlayeh@9258 965 + break;
gokhlayeh@9258 966 +#endif
gokhlayeh@9258 967 +#ifdef XZ_DEC_IA64
gokhlayeh@9258 968 + case BCJ_IA64:
gokhlayeh@9258 969 + filtered = bcj_ia64(s, buf, size);
gokhlayeh@9258 970 + break;
gokhlayeh@9258 971 +#endif
gokhlayeh@9258 972 +#ifdef XZ_DEC_ARM
gokhlayeh@9258 973 + case BCJ_ARM:
gokhlayeh@9258 974 + filtered = bcj_arm(s, buf, size);
gokhlayeh@9258 975 + break;
gokhlayeh@9258 976 +#endif
gokhlayeh@9258 977 +#ifdef XZ_DEC_ARMTHUMB
gokhlayeh@9258 978 + case BCJ_ARMTHUMB:
gokhlayeh@9258 979 + filtered = bcj_armthumb(s, buf, size);
gokhlayeh@9258 980 + break;
gokhlayeh@9258 981 +#endif
gokhlayeh@9258 982 +#ifdef XZ_DEC_SPARC
gokhlayeh@9258 983 + case BCJ_SPARC:
gokhlayeh@9258 984 + filtered = bcj_sparc(s, buf, size);
gokhlayeh@9258 985 + break;
gokhlayeh@9258 986 +#endif
gokhlayeh@9258 987 + default:
gokhlayeh@9258 988 + /* Never reached but silence compiler warnings. */
gokhlayeh@9258 989 + filtered = 0;
gokhlayeh@9258 990 + break;
gokhlayeh@9258 991 + }
gokhlayeh@9258 992 +
gokhlayeh@9258 993 + *pos += filtered;
gokhlayeh@9258 994 + s->pos += filtered;
gokhlayeh@9258 995 +}
gokhlayeh@9258 996 +
gokhlayeh@9258 997 +/*
gokhlayeh@9258 998 + * Flush pending filtered data from temp to the output buffer.
gokhlayeh@9258 999 + * Move the remaining mixture of possibly filtered and unfiltered
gokhlayeh@9258 1000 + * data to the beginning of temp.
gokhlayeh@9258 1001 + */
gokhlayeh@9258 1002 +static void bcj_flush(struct xz_dec_bcj *s, struct xz_buf *b)
gokhlayeh@9258 1003 +{
gokhlayeh@9258 1004 + size_t copy_size;
gokhlayeh@9258 1005 +
gokhlayeh@9258 1006 + copy_size = min_t(size_t, s->temp.filtered, b->out_size - b->out_pos);
gokhlayeh@9258 1007 + memcpy(b->out + b->out_pos, s->temp.buf, copy_size);
gokhlayeh@9258 1008 + b->out_pos += copy_size;
gokhlayeh@9258 1009 +
gokhlayeh@9258 1010 + s->temp.filtered -= copy_size;
gokhlayeh@9258 1011 + s->temp.size -= copy_size;
gokhlayeh@9258 1012 + memmove(s->temp.buf, s->temp.buf + copy_size, s->temp.size);
gokhlayeh@9258 1013 +}
gokhlayeh@9258 1014 +
gokhlayeh@9258 1015 +/*
gokhlayeh@9258 1016 + * The BCJ filter functions are primitive in sense that they process the
gokhlayeh@9258 1017 + * data in chunks of 1-16 bytes. To hide this issue, this function does
gokhlayeh@9258 1018 + * some buffering.
gokhlayeh@9258 1019 + */
gokhlayeh@9258 1020 +XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
gokhlayeh@9258 1021 + struct xz_dec_lzma2 *lzma2,
gokhlayeh@9258 1022 + struct xz_buf *b)
gokhlayeh@9258 1023 +{
gokhlayeh@9258 1024 + size_t out_start;
gokhlayeh@9258 1025 +
gokhlayeh@9258 1026 + /*
gokhlayeh@9258 1027 + * Flush pending already filtered data to the output buffer. Return
gokhlayeh@9258 1028 + * immediatelly if we couldn't flush everything, or if the next
gokhlayeh@9258 1029 + * filter in the chain had already returned XZ_STREAM_END.
gokhlayeh@9258 1030 + */
gokhlayeh@9258 1031 + if (s->temp.filtered > 0) {
gokhlayeh@9258 1032 + bcj_flush(s, b);
gokhlayeh@9258 1033 + if (s->temp.filtered > 0)
gokhlayeh@9258 1034 + return XZ_OK;
gokhlayeh@9258 1035 +
gokhlayeh@9258 1036 + if (s->ret == XZ_STREAM_END)
gokhlayeh@9258 1037 + return XZ_STREAM_END;
gokhlayeh@9258 1038 + }
gokhlayeh@9258 1039 +
gokhlayeh@9258 1040 + /*
gokhlayeh@9258 1041 + * If we have more output space than what is currently pending in
gokhlayeh@9258 1042 + * temp, copy the unfiltered data from temp to the output buffer
gokhlayeh@9258 1043 + * and try to fill the output buffer by decoding more data from the
gokhlayeh@9258 1044 + * next filter in the chain. Apply the BCJ filter on the new data
gokhlayeh@9258 1045 + * in the output buffer. If everything cannot be filtered, copy it
gokhlayeh@9258 1046 + * to temp and rewind the output buffer position accordingly.
gokhlayeh@9258 1047 + */
gokhlayeh@9258 1048 + if (s->temp.size < b->out_size - b->out_pos) {
gokhlayeh@9258 1049 + out_start = b->out_pos;
gokhlayeh@9258 1050 + memcpy(b->out + b->out_pos, s->temp.buf, s->temp.size);
gokhlayeh@9258 1051 + b->out_pos += s->temp.size;
gokhlayeh@9258 1052 +
gokhlayeh@9258 1053 + s->ret = xz_dec_lzma2_run(lzma2, b);
gokhlayeh@9258 1054 + if (s->ret != XZ_STREAM_END
gokhlayeh@9258 1055 + && (s->ret != XZ_OK || s->single_call))
gokhlayeh@9258 1056 + return s->ret;
gokhlayeh@9258 1057 +
gokhlayeh@9258 1058 + bcj_apply(s, b->out, &out_start, b->out_pos);
gokhlayeh@9258 1059 +
gokhlayeh@9258 1060 + /*
gokhlayeh@9258 1061 + * As an exception, if the next filter returned XZ_STREAM_END,
gokhlayeh@9258 1062 + * we can do that too, since the last few bytes that remain
gokhlayeh@9258 1063 + * unfiltered are meant to remain unfiltered.
gokhlayeh@9258 1064 + */
gokhlayeh@9258 1065 + if (s->ret == XZ_STREAM_END)
gokhlayeh@9258 1066 + return XZ_STREAM_END;
gokhlayeh@9258 1067 +
gokhlayeh@9258 1068 + s->temp.size = b->out_pos - out_start;
gokhlayeh@9258 1069 + b->out_pos -= s->temp.size;
gokhlayeh@9258 1070 + memcpy(s->temp.buf, b->out + b->out_pos, s->temp.size);
gokhlayeh@9258 1071 + }
gokhlayeh@9258 1072 +
gokhlayeh@9258 1073 + /*
gokhlayeh@9258 1074 + * If we have unfiltered data in temp, try to fill by decoding more
gokhlayeh@9258 1075 + * data from the next filter. Apply the BCJ filter on temp. Then we
gokhlayeh@9258 1076 + * hopefully can fill the actual output buffer by copying filtered
gokhlayeh@9258 1077 + * data from temp. A mix of filtered and unfiltered data may be left
gokhlayeh@9258 1078 + * in temp; it will be taken care on the next call to this function.
gokhlayeh@9258 1079 + */
gokhlayeh@9258 1080 + if (s->temp.size > 0) {
gokhlayeh@9258 1081 + /* Make b->out{,_pos,_size} temporarily point to s->temp. */
gokhlayeh@9258 1082 + s->out = b->out;
gokhlayeh@9258 1083 + s->out_pos = b->out_pos;
gokhlayeh@9258 1084 + s->out_size = b->out_size;
gokhlayeh@9258 1085 + b->out = s->temp.buf;
gokhlayeh@9258 1086 + b->out_pos = s->temp.size;
gokhlayeh@9258 1087 + b->out_size = sizeof(s->temp.buf);
gokhlayeh@9258 1088 +
gokhlayeh@9258 1089 + s->ret = xz_dec_lzma2_run(lzma2, b);
gokhlayeh@9258 1090 +
gokhlayeh@9258 1091 + s->temp.size = b->out_pos;
gokhlayeh@9258 1092 + b->out = s->out;
gokhlayeh@9258 1093 + b->out_pos = s->out_pos;
gokhlayeh@9258 1094 + b->out_size = s->out_size;
gokhlayeh@9258 1095 +
gokhlayeh@9258 1096 + if (s->ret != XZ_OK && s->ret != XZ_STREAM_END)
gokhlayeh@9258 1097 + return s->ret;
gokhlayeh@9258 1098 +
gokhlayeh@9258 1099 + bcj_apply(s, s->temp.buf, &s->temp.filtered, s->temp.size);
gokhlayeh@9258 1100 +
gokhlayeh@9258 1101 + /*
gokhlayeh@9258 1102 + * If the next filter returned XZ_STREAM_END, we mark that
gokhlayeh@9258 1103 + * everything is filtered, since the last unfiltered bytes
gokhlayeh@9258 1104 + * of the stream are meant to be left as is.
gokhlayeh@9258 1105 + */
gokhlayeh@9258 1106 + if (s->ret == XZ_STREAM_END)
gokhlayeh@9258 1107 + s->temp.filtered = s->temp.size;
gokhlayeh@9258 1108 +
gokhlayeh@9258 1109 + bcj_flush(s, b);
gokhlayeh@9258 1110 + if (s->temp.filtered > 0)
gokhlayeh@9258 1111 + return XZ_OK;
gokhlayeh@9258 1112 + }
gokhlayeh@9258 1113 +
gokhlayeh@9258 1114 + return s->ret;
gokhlayeh@9258 1115 +}
gokhlayeh@9258 1116 +
gokhlayeh@9258 1117 +XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call)
gokhlayeh@9258 1118 +{
gokhlayeh@9258 1119 + struct xz_dec_bcj *s = kmalloc(sizeof(*s), GFP_KERNEL);
gokhlayeh@9258 1120 + if (s != NULL)
gokhlayeh@9258 1121 + s->single_call = single_call;
gokhlayeh@9258 1122 +
gokhlayeh@9258 1123 + return s;
gokhlayeh@9258 1124 +}
gokhlayeh@9258 1125 +
gokhlayeh@9258 1126 +XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id)
gokhlayeh@9258 1127 +{
gokhlayeh@9258 1128 + switch (id) {
gokhlayeh@9258 1129 +#ifdef XZ_DEC_X86
gokhlayeh@9258 1130 + case BCJ_X86:
gokhlayeh@9258 1131 +#endif
gokhlayeh@9258 1132 +#ifdef XZ_DEC_POWERPC
gokhlayeh@9258 1133 + case BCJ_POWERPC:
gokhlayeh@9258 1134 +#endif
gokhlayeh@9258 1135 +#ifdef XZ_DEC_IA64
gokhlayeh@9258 1136 + case BCJ_IA64:
gokhlayeh@9258 1137 +#endif
gokhlayeh@9258 1138 +#ifdef XZ_DEC_ARM
gokhlayeh@9258 1139 + case BCJ_ARM:
gokhlayeh@9258 1140 +#endif
gokhlayeh@9258 1141 +#ifdef XZ_DEC_ARMTHUMB
gokhlayeh@9258 1142 + case BCJ_ARMTHUMB:
gokhlayeh@9258 1143 +#endif
gokhlayeh@9258 1144 +#ifdef XZ_DEC_SPARC
gokhlayeh@9258 1145 + case BCJ_SPARC:
gokhlayeh@9258 1146 +#endif
gokhlayeh@9258 1147 + break;
gokhlayeh@9258 1148 +
gokhlayeh@9258 1149 + default:
gokhlayeh@9258 1150 + /* Unsupported Filter ID */
gokhlayeh@9258 1151 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 1152 + }
gokhlayeh@9258 1153 +
gokhlayeh@9258 1154 + s->type = id;
gokhlayeh@9258 1155 + s->ret = XZ_OK;
gokhlayeh@9258 1156 + s->pos = 0;
gokhlayeh@9258 1157 + s->x86_prev_mask = 0;
gokhlayeh@9258 1158 + s->temp.filtered = 0;
gokhlayeh@9258 1159 + s->temp.size = 0;
gokhlayeh@9258 1160 +
gokhlayeh@9258 1161 + return XZ_OK;
gokhlayeh@9258 1162 +}
gokhlayeh@9258 1163 +
gokhlayeh@9258 1164 +#endif
gokhlayeh@9258 1165 diff --git a/lib/xz/xz_dec_lzma2.c b/lib/xz/xz_dec_lzma2.c
gokhlayeh@9258 1166 new file mode 100644
gokhlayeh@9258 1167 index 0000000..ea5fa4f
gokhlayeh@9258 1168 --- /dev/null
gokhlayeh@9258 1169 +++ b/lib/xz/xz_dec_lzma2.c
gokhlayeh@9258 1170 @@ -0,0 +1,1171 @@
gokhlayeh@9258 1171 +/*
gokhlayeh@9258 1172 + * LZMA2 decoder
gokhlayeh@9258 1173 + *
gokhlayeh@9258 1174 + * Authors: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 1175 + * Igor Pavlov <http://7-zip.org/>
gokhlayeh@9258 1176 + *
gokhlayeh@9258 1177 + * This file has been put into the public domain.
gokhlayeh@9258 1178 + * You can do whatever you want with this file.
gokhlayeh@9258 1179 + */
gokhlayeh@9258 1180 +
gokhlayeh@9258 1181 +#include "xz_private.h"
gokhlayeh@9258 1182 +#include "xz_lzma2.h"
gokhlayeh@9258 1183 +
gokhlayeh@9258 1184 +/*
gokhlayeh@9258 1185 + * Range decoder initialization eats the first five bytes of each LZMA chunk.
gokhlayeh@9258 1186 + */
gokhlayeh@9258 1187 +#define RC_INIT_BYTES 5
gokhlayeh@9258 1188 +
gokhlayeh@9258 1189 +/*
gokhlayeh@9258 1190 + * Minimum number of usable input buffer to safely decode one LZMA symbol.
gokhlayeh@9258 1191 + * The worst case is that we decode 22 bits using probabilities and 26
gokhlayeh@9258 1192 + * direct bits. This may decode at maximum of 20 bytes of input. However,
gokhlayeh@9258 1193 + * lzma_main() does an extra normalization before returning, thus we
gokhlayeh@9258 1194 + * need to put 21 here.
gokhlayeh@9258 1195 + */
gokhlayeh@9258 1196 +#define LZMA_IN_REQUIRED 21
gokhlayeh@9258 1197 +
gokhlayeh@9258 1198 +/*
gokhlayeh@9258 1199 + * Dictionary (history buffer)
gokhlayeh@9258 1200 + *
gokhlayeh@9258 1201 + * These are always true:
gokhlayeh@9258 1202 + * start <= pos <= full <= end
gokhlayeh@9258 1203 + * pos <= limit <= end
gokhlayeh@9258 1204 + *
gokhlayeh@9258 1205 + * In multi-call mode, also these are true:
gokhlayeh@9258 1206 + * end == size
gokhlayeh@9258 1207 + * size <= size_max
gokhlayeh@9258 1208 + * allocated <= size
gokhlayeh@9258 1209 + *
gokhlayeh@9258 1210 + * Most of these variables are size_t to support single-call mode,
gokhlayeh@9258 1211 + * in which the dictionary variables address the actual output
gokhlayeh@9258 1212 + * buffer directly.
gokhlayeh@9258 1213 + */
gokhlayeh@9258 1214 +struct dictionary {
gokhlayeh@9258 1215 + /* Beginning of the history buffer */
gokhlayeh@9258 1216 + uint8_t *buf;
gokhlayeh@9258 1217 +
gokhlayeh@9258 1218 + /* Old position in buf (before decoding more data) */
gokhlayeh@9258 1219 + size_t start;
gokhlayeh@9258 1220 +
gokhlayeh@9258 1221 + /* Position in buf */
gokhlayeh@9258 1222 + size_t pos;
gokhlayeh@9258 1223 +
gokhlayeh@9258 1224 + /*
gokhlayeh@9258 1225 + * How full dictionary is. This is used to detect corrupt input that
gokhlayeh@9258 1226 + * would read beyond the beginning of the uncompressed stream.
gokhlayeh@9258 1227 + */
gokhlayeh@9258 1228 + size_t full;
gokhlayeh@9258 1229 +
gokhlayeh@9258 1230 + /* Write limit; we don't write to buf[limit] or later bytes. */
gokhlayeh@9258 1231 + size_t limit;
gokhlayeh@9258 1232 +
gokhlayeh@9258 1233 + /*
gokhlayeh@9258 1234 + * End of the dictionary buffer. In multi-call mode, this is
gokhlayeh@9258 1235 + * the same as the dictionary size. In single-call mode, this
gokhlayeh@9258 1236 + * indicates the size of the output buffer.
gokhlayeh@9258 1237 + */
gokhlayeh@9258 1238 + size_t end;
gokhlayeh@9258 1239 +
gokhlayeh@9258 1240 + /*
gokhlayeh@9258 1241 + * Size of the dictionary as specified in Block Header. This is used
gokhlayeh@9258 1242 + * together with "full" to detect corrupt input that would make us
gokhlayeh@9258 1243 + * read beyond the beginning of the uncompressed stream.
gokhlayeh@9258 1244 + */
gokhlayeh@9258 1245 + uint32_t size;
gokhlayeh@9258 1246 +
gokhlayeh@9258 1247 + /*
gokhlayeh@9258 1248 + * Maximum allowed dictionary size in multi-call mode.
gokhlayeh@9258 1249 + * This is ignored in single-call mode.
gokhlayeh@9258 1250 + */
gokhlayeh@9258 1251 + uint32_t size_max;
gokhlayeh@9258 1252 +
gokhlayeh@9258 1253 + /*
gokhlayeh@9258 1254 + * Amount of memory currently allocated for the dictionary.
gokhlayeh@9258 1255 + * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC,
gokhlayeh@9258 1256 + * size_max is always the same as the allocated size.)
gokhlayeh@9258 1257 + */
gokhlayeh@9258 1258 + uint32_t allocated;
gokhlayeh@9258 1259 +
gokhlayeh@9258 1260 + /* Operation mode */
gokhlayeh@9258 1261 + enum xz_mode mode;
gokhlayeh@9258 1262 +};
gokhlayeh@9258 1263 +
gokhlayeh@9258 1264 +/* Range decoder */
gokhlayeh@9258 1265 +struct rc_dec {
gokhlayeh@9258 1266 + uint32_t range;
gokhlayeh@9258 1267 + uint32_t code;
gokhlayeh@9258 1268 +
gokhlayeh@9258 1269 + /*
gokhlayeh@9258 1270 + * Number of initializing bytes remaining to be read
gokhlayeh@9258 1271 + * by rc_read_init().
gokhlayeh@9258 1272 + */
gokhlayeh@9258 1273 + uint32_t init_bytes_left;
gokhlayeh@9258 1274 +
gokhlayeh@9258 1275 + /*
gokhlayeh@9258 1276 + * Buffer from which we read our input. It can be either
gokhlayeh@9258 1277 + * temp.buf or the caller-provided input buffer.
gokhlayeh@9258 1278 + */
gokhlayeh@9258 1279 + const uint8_t *in;
gokhlayeh@9258 1280 + size_t in_pos;
gokhlayeh@9258 1281 + size_t in_limit;
gokhlayeh@9258 1282 +};
gokhlayeh@9258 1283 +
gokhlayeh@9258 1284 +/* Probabilities for a length decoder. */
gokhlayeh@9258 1285 +struct lzma_len_dec {
gokhlayeh@9258 1286 + /* Probability of match length being at least 10 */
gokhlayeh@9258 1287 + uint16_t choice;
gokhlayeh@9258 1288 +
gokhlayeh@9258 1289 + /* Probability of match length being at least 18 */
gokhlayeh@9258 1290 + uint16_t choice2;
gokhlayeh@9258 1291 +
gokhlayeh@9258 1292 + /* Probabilities for match lengths 2-9 */
gokhlayeh@9258 1293 + uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS];
gokhlayeh@9258 1294 +
gokhlayeh@9258 1295 + /* Probabilities for match lengths 10-17 */
gokhlayeh@9258 1296 + uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS];
gokhlayeh@9258 1297 +
gokhlayeh@9258 1298 + /* Probabilities for match lengths 18-273 */
gokhlayeh@9258 1299 + uint16_t high[LEN_HIGH_SYMBOLS];
gokhlayeh@9258 1300 +};
gokhlayeh@9258 1301 +
gokhlayeh@9258 1302 +struct lzma_dec {
gokhlayeh@9258 1303 + /* Distances of latest four matches */
gokhlayeh@9258 1304 + uint32_t rep0;
gokhlayeh@9258 1305 + uint32_t rep1;
gokhlayeh@9258 1306 + uint32_t rep2;
gokhlayeh@9258 1307 + uint32_t rep3;
gokhlayeh@9258 1308 +
gokhlayeh@9258 1309 + /* Types of the most recently seen LZMA symbols */
gokhlayeh@9258 1310 + enum lzma_state state;
gokhlayeh@9258 1311 +
gokhlayeh@9258 1312 + /*
gokhlayeh@9258 1313 + * Length of a match. This is updated so that dict_repeat can
gokhlayeh@9258 1314 + * be called again to finish repeating the whole match.
gokhlayeh@9258 1315 + */
gokhlayeh@9258 1316 + uint32_t len;
gokhlayeh@9258 1317 +
gokhlayeh@9258 1318 + /*
gokhlayeh@9258 1319 + * LZMA properties or related bit masks (number of literal
gokhlayeh@9258 1320 + * context bits, a mask dervied from the number of literal
gokhlayeh@9258 1321 + * position bits, and a mask dervied from the number
gokhlayeh@9258 1322 + * position bits)
gokhlayeh@9258 1323 + */
gokhlayeh@9258 1324 + uint32_t lc;
gokhlayeh@9258 1325 + uint32_t literal_pos_mask; /* (1 << lp) - 1 */
gokhlayeh@9258 1326 + uint32_t pos_mask; /* (1 << pb) - 1 */
gokhlayeh@9258 1327 +
gokhlayeh@9258 1328 + /* If 1, it's a match. Otherwise it's a single 8-bit literal. */
gokhlayeh@9258 1329 + uint16_t is_match[STATES][POS_STATES_MAX];
gokhlayeh@9258 1330 +
gokhlayeh@9258 1331 + /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */
gokhlayeh@9258 1332 + uint16_t is_rep[STATES];
gokhlayeh@9258 1333 +
gokhlayeh@9258 1334 + /*
gokhlayeh@9258 1335 + * If 0, distance of a repeated match is rep0.
gokhlayeh@9258 1336 + * Otherwise check is_rep1.
gokhlayeh@9258 1337 + */
gokhlayeh@9258 1338 + uint16_t is_rep0[STATES];
gokhlayeh@9258 1339 +
gokhlayeh@9258 1340 + /*
gokhlayeh@9258 1341 + * If 0, distance of a repeated match is rep1.
gokhlayeh@9258 1342 + * Otherwise check is_rep2.
gokhlayeh@9258 1343 + */
gokhlayeh@9258 1344 + uint16_t is_rep1[STATES];
gokhlayeh@9258 1345 +
gokhlayeh@9258 1346 + /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */
gokhlayeh@9258 1347 + uint16_t is_rep2[STATES];
gokhlayeh@9258 1348 +
gokhlayeh@9258 1349 + /*
gokhlayeh@9258 1350 + * If 1, the repeated match has length of one byte. Otherwise
gokhlayeh@9258 1351 + * the length is decoded from rep_len_decoder.
gokhlayeh@9258 1352 + */
gokhlayeh@9258 1353 + uint16_t is_rep0_long[STATES][POS_STATES_MAX];
gokhlayeh@9258 1354 +
gokhlayeh@9258 1355 + /*
gokhlayeh@9258 1356 + * Probability tree for the highest two bits of the match
gokhlayeh@9258 1357 + * distance. There is a separate probability tree for match
gokhlayeh@9258 1358 + * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273].
gokhlayeh@9258 1359 + */
gokhlayeh@9258 1360 + uint16_t dist_slot[DIST_STATES][DIST_SLOTS];
gokhlayeh@9258 1361 +
gokhlayeh@9258 1362 + /*
gokhlayeh@9258 1363 + * Probility trees for additional bits for match distance
gokhlayeh@9258 1364 + * when the distance is in the range [4, 127].
gokhlayeh@9258 1365 + */
gokhlayeh@9258 1366 + uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END];
gokhlayeh@9258 1367 +
gokhlayeh@9258 1368 + /*
gokhlayeh@9258 1369 + * Probability tree for the lowest four bits of a match
gokhlayeh@9258 1370 + * distance that is equal to or greater than 128.
gokhlayeh@9258 1371 + */
gokhlayeh@9258 1372 + uint16_t dist_align[ALIGN_SIZE];
gokhlayeh@9258 1373 +
gokhlayeh@9258 1374 + /* Length of a normal match */
gokhlayeh@9258 1375 + struct lzma_len_dec match_len_dec;
gokhlayeh@9258 1376 +
gokhlayeh@9258 1377 + /* Length of a repeated match */
gokhlayeh@9258 1378 + struct lzma_len_dec rep_len_dec;
gokhlayeh@9258 1379 +
gokhlayeh@9258 1380 + /* Probabilities of literals */
gokhlayeh@9258 1381 + uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE];
gokhlayeh@9258 1382 +};
gokhlayeh@9258 1383 +
gokhlayeh@9258 1384 +struct lzma2_dec {
gokhlayeh@9258 1385 + /* Position in xz_dec_lzma2_run(). */
gokhlayeh@9258 1386 + enum lzma2_seq {
gokhlayeh@9258 1387 + SEQ_CONTROL,
gokhlayeh@9258 1388 + SEQ_UNCOMPRESSED_1,
gokhlayeh@9258 1389 + SEQ_UNCOMPRESSED_2,
gokhlayeh@9258 1390 + SEQ_COMPRESSED_0,
gokhlayeh@9258 1391 + SEQ_COMPRESSED_1,
gokhlayeh@9258 1392 + SEQ_PROPERTIES,
gokhlayeh@9258 1393 + SEQ_LZMA_PREPARE,
gokhlayeh@9258 1394 + SEQ_LZMA_RUN,
gokhlayeh@9258 1395 + SEQ_COPY
gokhlayeh@9258 1396 + } sequence;
gokhlayeh@9258 1397 +
gokhlayeh@9258 1398 + /* Next position after decoding the compressed size of the chunk. */
gokhlayeh@9258 1399 + enum lzma2_seq next_sequence;
gokhlayeh@9258 1400 +
gokhlayeh@9258 1401 + /* Uncompressed size of LZMA chunk (2 MiB at maximum) */
gokhlayeh@9258 1402 + uint32_t uncompressed;
gokhlayeh@9258 1403 +
gokhlayeh@9258 1404 + /*
gokhlayeh@9258 1405 + * Compressed size of LZMA chunk or compressed/uncompressed
gokhlayeh@9258 1406 + * size of uncompressed chunk (64 KiB at maximum)
gokhlayeh@9258 1407 + */
gokhlayeh@9258 1408 + uint32_t compressed;
gokhlayeh@9258 1409 +
gokhlayeh@9258 1410 + /*
gokhlayeh@9258 1411 + * True if dictionary reset is needed. This is false before
gokhlayeh@9258 1412 + * the first chunk (LZMA or uncompressed).
gokhlayeh@9258 1413 + */
gokhlayeh@9258 1414 + bool need_dict_reset;
gokhlayeh@9258 1415 +
gokhlayeh@9258 1416 + /*
gokhlayeh@9258 1417 + * True if new LZMA properties are needed. This is false
gokhlayeh@9258 1418 + * before the first LZMA chunk.
gokhlayeh@9258 1419 + */
gokhlayeh@9258 1420 + bool need_props;
gokhlayeh@9258 1421 +};
gokhlayeh@9258 1422 +
gokhlayeh@9258 1423 +struct xz_dec_lzma2 {
gokhlayeh@9258 1424 + /*
gokhlayeh@9258 1425 + * The order below is important on x86 to reduce code size and
gokhlayeh@9258 1426 + * it shouldn't hurt on other platforms. Everything up to and
gokhlayeh@9258 1427 + * including lzma.pos_mask are in the first 128 bytes on x86-32,
gokhlayeh@9258 1428 + * which allows using smaller instructions to access those
gokhlayeh@9258 1429 + * variables. On x86-64, fewer variables fit into the first 128
gokhlayeh@9258 1430 + * bytes, but this is still the best order without sacrificing
gokhlayeh@9258 1431 + * the readability by splitting the structures.
gokhlayeh@9258 1432 + */
gokhlayeh@9258 1433 + struct rc_dec rc;
gokhlayeh@9258 1434 + struct dictionary dict;
gokhlayeh@9258 1435 + struct lzma2_dec lzma2;
gokhlayeh@9258 1436 + struct lzma_dec lzma;
gokhlayeh@9258 1437 +
gokhlayeh@9258 1438 + /*
gokhlayeh@9258 1439 + * Temporary buffer which holds small number of input bytes between
gokhlayeh@9258 1440 + * decoder calls. See lzma2_lzma() for details.
gokhlayeh@9258 1441 + */
gokhlayeh@9258 1442 + struct {
gokhlayeh@9258 1443 + uint32_t size;
gokhlayeh@9258 1444 + uint8_t buf[3 * LZMA_IN_REQUIRED];
gokhlayeh@9258 1445 + } temp;
gokhlayeh@9258 1446 +};
gokhlayeh@9258 1447 +
gokhlayeh@9258 1448 +/**************
gokhlayeh@9258 1449 + * Dictionary *
gokhlayeh@9258 1450 + **************/
gokhlayeh@9258 1451 +
gokhlayeh@9258 1452 +/*
gokhlayeh@9258 1453 + * Reset the dictionary state. When in single-call mode, set up the beginning
gokhlayeh@9258 1454 + * of the dictionary to point to the actual output buffer.
gokhlayeh@9258 1455 + */
gokhlayeh@9258 1456 +static void dict_reset(struct dictionary *dict, struct xz_buf *b)
gokhlayeh@9258 1457 +{
gokhlayeh@9258 1458 + if (DEC_IS_SINGLE(dict->mode)) {
gokhlayeh@9258 1459 + dict->buf = b->out + b->out_pos;
gokhlayeh@9258 1460 + dict->end = b->out_size - b->out_pos;
gokhlayeh@9258 1461 + }
gokhlayeh@9258 1462 +
gokhlayeh@9258 1463 + dict->start = 0;
gokhlayeh@9258 1464 + dict->pos = 0;
gokhlayeh@9258 1465 + dict->limit = 0;
gokhlayeh@9258 1466 + dict->full = 0;
gokhlayeh@9258 1467 +}
gokhlayeh@9258 1468 +
gokhlayeh@9258 1469 +/* Set dictionary write limit */
gokhlayeh@9258 1470 +static void dict_limit(struct dictionary *dict, size_t out_max)
gokhlayeh@9258 1471 +{
gokhlayeh@9258 1472 + if (dict->end - dict->pos <= out_max)
gokhlayeh@9258 1473 + dict->limit = dict->end;
gokhlayeh@9258 1474 + else
gokhlayeh@9258 1475 + dict->limit = dict->pos + out_max;
gokhlayeh@9258 1476 +}
gokhlayeh@9258 1477 +
gokhlayeh@9258 1478 +/* Return true if at least one byte can be written into the dictionary. */
gokhlayeh@9258 1479 +static inline bool dict_has_space(const struct dictionary *dict)
gokhlayeh@9258 1480 +{
gokhlayeh@9258 1481 + return dict->pos < dict->limit;
gokhlayeh@9258 1482 +}
gokhlayeh@9258 1483 +
gokhlayeh@9258 1484 +/*
gokhlayeh@9258 1485 + * Get a byte from the dictionary at the given distance. The distance is
gokhlayeh@9258 1486 + * assumed to valid, or as a special case, zero when the dictionary is
gokhlayeh@9258 1487 + * still empty. This special case is needed for single-call decoding to
gokhlayeh@9258 1488 + * avoid writing a '\0' to the end of the destination buffer.
gokhlayeh@9258 1489 + */
gokhlayeh@9258 1490 +static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist)
gokhlayeh@9258 1491 +{
gokhlayeh@9258 1492 + size_t offset = dict->pos - dist - 1;
gokhlayeh@9258 1493 +
gokhlayeh@9258 1494 + if (dist >= dict->pos)
gokhlayeh@9258 1495 + offset += dict->end;
gokhlayeh@9258 1496 +
gokhlayeh@9258 1497 + return dict->full > 0 ? dict->buf[offset] : 0;
gokhlayeh@9258 1498 +}
gokhlayeh@9258 1499 +
gokhlayeh@9258 1500 +/*
gokhlayeh@9258 1501 + * Put one byte into the dictionary. It is assumed that there is space for it.
gokhlayeh@9258 1502 + */
gokhlayeh@9258 1503 +static inline void dict_put(struct dictionary *dict, uint8_t byte)
gokhlayeh@9258 1504 +{
gokhlayeh@9258 1505 + dict->buf[dict->pos++] = byte;
gokhlayeh@9258 1506 +
gokhlayeh@9258 1507 + if (dict->full < dict->pos)
gokhlayeh@9258 1508 + dict->full = dict->pos;
gokhlayeh@9258 1509 +}
gokhlayeh@9258 1510 +
gokhlayeh@9258 1511 +/*
gokhlayeh@9258 1512 + * Repeat given number of bytes from the given distance. If the distance is
gokhlayeh@9258 1513 + * invalid, false is returned. On success, true is returned and *len is
gokhlayeh@9258 1514 + * updated to indicate how many bytes were left to be repeated.
gokhlayeh@9258 1515 + */
gokhlayeh@9258 1516 +static bool dict_repeat(struct dictionary *dict, uint32_t *len, uint32_t dist)
gokhlayeh@9258 1517 +{
gokhlayeh@9258 1518 + size_t back;
gokhlayeh@9258 1519 + uint32_t left;
gokhlayeh@9258 1520 +
gokhlayeh@9258 1521 + if (dist >= dict->full || dist >= dict->size)
gokhlayeh@9258 1522 + return false;
gokhlayeh@9258 1523 +
gokhlayeh@9258 1524 + left = min_t(size_t, dict->limit - dict->pos, *len);
gokhlayeh@9258 1525 + *len -= left;
gokhlayeh@9258 1526 +
gokhlayeh@9258 1527 + back = dict->pos - dist - 1;
gokhlayeh@9258 1528 + if (dist >= dict->pos)
gokhlayeh@9258 1529 + back += dict->end;
gokhlayeh@9258 1530 +
gokhlayeh@9258 1531 + do {
gokhlayeh@9258 1532 + dict->buf[dict->pos++] = dict->buf[back++];
gokhlayeh@9258 1533 + if (back == dict->end)
gokhlayeh@9258 1534 + back = 0;
gokhlayeh@9258 1535 + } while (--left > 0);
gokhlayeh@9258 1536 +
gokhlayeh@9258 1537 + if (dict->full < dict->pos)
gokhlayeh@9258 1538 + dict->full = dict->pos;
gokhlayeh@9258 1539 +
gokhlayeh@9258 1540 + return true;
gokhlayeh@9258 1541 +}
gokhlayeh@9258 1542 +
gokhlayeh@9258 1543 +/* Copy uncompressed data as is from input to dictionary and output buffers. */
gokhlayeh@9258 1544 +static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b,
gokhlayeh@9258 1545 + uint32_t *left)
gokhlayeh@9258 1546 +{
gokhlayeh@9258 1547 + size_t copy_size;
gokhlayeh@9258 1548 +
gokhlayeh@9258 1549 + while (*left > 0 && b->in_pos < b->in_size
gokhlayeh@9258 1550 + && b->out_pos < b->out_size) {
gokhlayeh@9258 1551 + copy_size = min(b->in_size - b->in_pos,
gokhlayeh@9258 1552 + b->out_size - b->out_pos);
gokhlayeh@9258 1553 + if (copy_size > dict->end - dict->pos)
gokhlayeh@9258 1554 + copy_size = dict->end - dict->pos;
gokhlayeh@9258 1555 + if (copy_size > *left)
gokhlayeh@9258 1556 + copy_size = *left;
gokhlayeh@9258 1557 +
gokhlayeh@9258 1558 + *left -= copy_size;
gokhlayeh@9258 1559 +
gokhlayeh@9258 1560 + memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size);
gokhlayeh@9258 1561 + dict->pos += copy_size;
gokhlayeh@9258 1562 +
gokhlayeh@9258 1563 + if (dict->full < dict->pos)
gokhlayeh@9258 1564 + dict->full = dict->pos;
gokhlayeh@9258 1565 +
gokhlayeh@9258 1566 + if (DEC_IS_MULTI(dict->mode)) {
gokhlayeh@9258 1567 + if (dict->pos == dict->end)
gokhlayeh@9258 1568 + dict->pos = 0;
gokhlayeh@9258 1569 +
gokhlayeh@9258 1570 + memcpy(b->out + b->out_pos, b->in + b->in_pos,
gokhlayeh@9258 1571 + copy_size);
gokhlayeh@9258 1572 + }
gokhlayeh@9258 1573 +
gokhlayeh@9258 1574 + dict->start = dict->pos;
gokhlayeh@9258 1575 +
gokhlayeh@9258 1576 + b->out_pos += copy_size;
gokhlayeh@9258 1577 + b->in_pos += copy_size;
gokhlayeh@9258 1578 + }
gokhlayeh@9258 1579 +}
gokhlayeh@9258 1580 +
gokhlayeh@9258 1581 +/*
gokhlayeh@9258 1582 + * Flush pending data from dictionary to b->out. It is assumed that there is
gokhlayeh@9258 1583 + * enough space in b->out. This is guaranteed because caller uses dict_limit()
gokhlayeh@9258 1584 + * before decoding data into the dictionary.
gokhlayeh@9258 1585 + */
gokhlayeh@9258 1586 +static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b)
gokhlayeh@9258 1587 +{
gokhlayeh@9258 1588 + size_t copy_size = dict->pos - dict->start;
gokhlayeh@9258 1589 +
gokhlayeh@9258 1590 + if (DEC_IS_MULTI(dict->mode)) {
gokhlayeh@9258 1591 + if (dict->pos == dict->end)
gokhlayeh@9258 1592 + dict->pos = 0;
gokhlayeh@9258 1593 +
gokhlayeh@9258 1594 + memcpy(b->out + b->out_pos, dict->buf + dict->start,
gokhlayeh@9258 1595 + copy_size);
gokhlayeh@9258 1596 + }
gokhlayeh@9258 1597 +
gokhlayeh@9258 1598 + dict->start = dict->pos;
gokhlayeh@9258 1599 + b->out_pos += copy_size;
gokhlayeh@9258 1600 + return copy_size;
gokhlayeh@9258 1601 +}
gokhlayeh@9258 1602 +
gokhlayeh@9258 1603 +/*****************
gokhlayeh@9258 1604 + * Range decoder *
gokhlayeh@9258 1605 + *****************/
gokhlayeh@9258 1606 +
gokhlayeh@9258 1607 +/* Reset the range decoder. */
gokhlayeh@9258 1608 +static void rc_reset(struct rc_dec *rc)
gokhlayeh@9258 1609 +{
gokhlayeh@9258 1610 + rc->range = (uint32_t)-1;
gokhlayeh@9258 1611 + rc->code = 0;
gokhlayeh@9258 1612 + rc->init_bytes_left = RC_INIT_BYTES;
gokhlayeh@9258 1613 +}
gokhlayeh@9258 1614 +
gokhlayeh@9258 1615 +/*
gokhlayeh@9258 1616 + * Read the first five initial bytes into rc->code if they haven't been
gokhlayeh@9258 1617 + * read already. (Yes, the first byte gets completely ignored.)
gokhlayeh@9258 1618 + */
gokhlayeh@9258 1619 +static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b)
gokhlayeh@9258 1620 +{
gokhlayeh@9258 1621 + while (rc->init_bytes_left > 0) {
gokhlayeh@9258 1622 + if (b->in_pos == b->in_size)
gokhlayeh@9258 1623 + return false;
gokhlayeh@9258 1624 +
gokhlayeh@9258 1625 + rc->code = (rc->code << 8) + b->in[b->in_pos++];
gokhlayeh@9258 1626 + --rc->init_bytes_left;
gokhlayeh@9258 1627 + }
gokhlayeh@9258 1628 +
gokhlayeh@9258 1629 + return true;
gokhlayeh@9258 1630 +}
gokhlayeh@9258 1631 +
gokhlayeh@9258 1632 +/* Return true if there may not be enough input for the next decoding loop. */
gokhlayeh@9258 1633 +static inline bool rc_limit_exceeded(const struct rc_dec *rc)
gokhlayeh@9258 1634 +{
gokhlayeh@9258 1635 + return rc->in_pos > rc->in_limit;
gokhlayeh@9258 1636 +}
gokhlayeh@9258 1637 +
gokhlayeh@9258 1638 +/*
gokhlayeh@9258 1639 + * Return true if it is possible (from point of view of range decoder) that
gokhlayeh@9258 1640 + * we have reached the end of the LZMA chunk.
gokhlayeh@9258 1641 + */
gokhlayeh@9258 1642 +static inline bool rc_is_finished(const struct rc_dec *rc)
gokhlayeh@9258 1643 +{
gokhlayeh@9258 1644 + return rc->code == 0;
gokhlayeh@9258 1645 +}
gokhlayeh@9258 1646 +
gokhlayeh@9258 1647 +/* Read the next input byte if needed. */
gokhlayeh@9258 1648 +static __always_inline void rc_normalize(struct rc_dec *rc)
gokhlayeh@9258 1649 +{
gokhlayeh@9258 1650 + if (rc->range < RC_TOP_VALUE) {
gokhlayeh@9258 1651 + rc->range <<= RC_SHIFT_BITS;
gokhlayeh@9258 1652 + rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++];
gokhlayeh@9258 1653 + }
gokhlayeh@9258 1654 +}
gokhlayeh@9258 1655 +
gokhlayeh@9258 1656 +/*
gokhlayeh@9258 1657 + * Decode one bit. In some versions, this function has been splitted in three
gokhlayeh@9258 1658 + * functions so that the compiler is supposed to be able to more easily avoid
gokhlayeh@9258 1659 + * an extra branch. In this particular version of the LZMA decoder, this
gokhlayeh@9258 1660 + * doesn't seem to be a good idea (tested with GCC 3.3.6, 3.4.6, and 4.3.3
gokhlayeh@9258 1661 + * on x86). Using a non-splitted version results in nicer looking code too.
gokhlayeh@9258 1662 + *
gokhlayeh@9258 1663 + * NOTE: This must return an int. Do not make it return a bool or the speed
gokhlayeh@9258 1664 + * of the code generated by GCC 3.x decreases 10-15 %. (GCC 4.3 doesn't care,
gokhlayeh@9258 1665 + * and it generates 10-20 % faster code than GCC 3.x from this file anyway.)
gokhlayeh@9258 1666 + */
gokhlayeh@9258 1667 +static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob)
gokhlayeh@9258 1668 +{
gokhlayeh@9258 1669 + uint32_t bound;
gokhlayeh@9258 1670 + int bit;
gokhlayeh@9258 1671 +
gokhlayeh@9258 1672 + rc_normalize(rc);
gokhlayeh@9258 1673 + bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob;
gokhlayeh@9258 1674 + if (rc->code < bound) {
gokhlayeh@9258 1675 + rc->range = bound;
gokhlayeh@9258 1676 + *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS;
gokhlayeh@9258 1677 + bit = 0;
gokhlayeh@9258 1678 + } else {
gokhlayeh@9258 1679 + rc->range -= bound;
gokhlayeh@9258 1680 + rc->code -= bound;
gokhlayeh@9258 1681 + *prob -= *prob >> RC_MOVE_BITS;
gokhlayeh@9258 1682 + bit = 1;
gokhlayeh@9258 1683 + }
gokhlayeh@9258 1684 +
gokhlayeh@9258 1685 + return bit;
gokhlayeh@9258 1686 +}
gokhlayeh@9258 1687 +
gokhlayeh@9258 1688 +/* Decode a bittree starting from the most significant bit. */
gokhlayeh@9258 1689 +static __always_inline uint32_t rc_bittree(struct rc_dec *rc,
gokhlayeh@9258 1690 + uint16_t *probs, uint32_t limit)
gokhlayeh@9258 1691 +{
gokhlayeh@9258 1692 + uint32_t symbol = 1;
gokhlayeh@9258 1693 +
gokhlayeh@9258 1694 + do {
gokhlayeh@9258 1695 + if (rc_bit(rc, &probs[symbol]))
gokhlayeh@9258 1696 + symbol = (symbol << 1) + 1;
gokhlayeh@9258 1697 + else
gokhlayeh@9258 1698 + symbol <<= 1;
gokhlayeh@9258 1699 + } while (symbol < limit);
gokhlayeh@9258 1700 +
gokhlayeh@9258 1701 + return symbol;
gokhlayeh@9258 1702 +}
gokhlayeh@9258 1703 +
gokhlayeh@9258 1704 +/* Decode a bittree starting from the least significant bit. */
gokhlayeh@9258 1705 +static __always_inline void rc_bittree_reverse(struct rc_dec *rc,
gokhlayeh@9258 1706 + uint16_t *probs,
gokhlayeh@9258 1707 + uint32_t *dest, uint32_t limit)
gokhlayeh@9258 1708 +{
gokhlayeh@9258 1709 + uint32_t symbol = 1;
gokhlayeh@9258 1710 + uint32_t i = 0;
gokhlayeh@9258 1711 +
gokhlayeh@9258 1712 + do {
gokhlayeh@9258 1713 + if (rc_bit(rc, &probs[symbol])) {
gokhlayeh@9258 1714 + symbol = (symbol << 1) + 1;
gokhlayeh@9258 1715 + *dest += 1 << i;
gokhlayeh@9258 1716 + } else {
gokhlayeh@9258 1717 + symbol <<= 1;
gokhlayeh@9258 1718 + }
gokhlayeh@9258 1719 + } while (++i < limit);
gokhlayeh@9258 1720 +}
gokhlayeh@9258 1721 +
gokhlayeh@9258 1722 +/* Decode direct bits (fixed fifty-fifty probability) */
gokhlayeh@9258 1723 +static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit)
gokhlayeh@9258 1724 +{
gokhlayeh@9258 1725 + uint32_t mask;
gokhlayeh@9258 1726 +
gokhlayeh@9258 1727 + do {
gokhlayeh@9258 1728 + rc_normalize(rc);
gokhlayeh@9258 1729 + rc->range >>= 1;
gokhlayeh@9258 1730 + rc->code -= rc->range;
gokhlayeh@9258 1731 + mask = (uint32_t)0 - (rc->code >> 31);
gokhlayeh@9258 1732 + rc->code += rc->range & mask;
gokhlayeh@9258 1733 + *dest = (*dest << 1) + (mask + 1);
gokhlayeh@9258 1734 + } while (--limit > 0);
gokhlayeh@9258 1735 +}
gokhlayeh@9258 1736 +
gokhlayeh@9258 1737 +/********
gokhlayeh@9258 1738 + * LZMA *
gokhlayeh@9258 1739 + ********/
gokhlayeh@9258 1740 +
gokhlayeh@9258 1741 +/* Get pointer to literal coder probability array. */
gokhlayeh@9258 1742 +static uint16_t *lzma_literal_probs(struct xz_dec_lzma2 *s)
gokhlayeh@9258 1743 +{
gokhlayeh@9258 1744 + uint32_t prev_byte = dict_get(&s->dict, 0);
gokhlayeh@9258 1745 + uint32_t low = prev_byte >> (8 - s->lzma.lc);
gokhlayeh@9258 1746 + uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc;
gokhlayeh@9258 1747 + return s->lzma.literal[low + high];
gokhlayeh@9258 1748 +}
gokhlayeh@9258 1749 +
gokhlayeh@9258 1750 +/* Decode a literal (one 8-bit byte) */
gokhlayeh@9258 1751 +static void lzma_literal(struct xz_dec_lzma2 *s)
gokhlayeh@9258 1752 +{
gokhlayeh@9258 1753 + uint16_t *probs;
gokhlayeh@9258 1754 + uint32_t symbol;
gokhlayeh@9258 1755 + uint32_t match_byte;
gokhlayeh@9258 1756 + uint32_t match_bit;
gokhlayeh@9258 1757 + uint32_t offset;
gokhlayeh@9258 1758 + uint32_t i;
gokhlayeh@9258 1759 +
gokhlayeh@9258 1760 + probs = lzma_literal_probs(s);
gokhlayeh@9258 1761 +
gokhlayeh@9258 1762 + if (lzma_state_is_literal(s->lzma.state)) {
gokhlayeh@9258 1763 + symbol = rc_bittree(&s->rc, probs, 0x100);
gokhlayeh@9258 1764 + } else {
gokhlayeh@9258 1765 + symbol = 1;
gokhlayeh@9258 1766 + match_byte = dict_get(&s->dict, s->lzma.rep0) << 1;
gokhlayeh@9258 1767 + offset = 0x100;
gokhlayeh@9258 1768 +
gokhlayeh@9258 1769 + do {
gokhlayeh@9258 1770 + match_bit = match_byte & offset;
gokhlayeh@9258 1771 + match_byte <<= 1;
gokhlayeh@9258 1772 + i = offset + match_bit + symbol;
gokhlayeh@9258 1773 +
gokhlayeh@9258 1774 + if (rc_bit(&s->rc, &probs[i])) {
gokhlayeh@9258 1775 + symbol = (symbol << 1) + 1;
gokhlayeh@9258 1776 + offset &= match_bit;
gokhlayeh@9258 1777 + } else {
gokhlayeh@9258 1778 + symbol <<= 1;
gokhlayeh@9258 1779 + offset &= ~match_bit;
gokhlayeh@9258 1780 + }
gokhlayeh@9258 1781 + } while (symbol < 0x100);
gokhlayeh@9258 1782 + }
gokhlayeh@9258 1783 +
gokhlayeh@9258 1784 + dict_put(&s->dict, (uint8_t)symbol);
gokhlayeh@9258 1785 + lzma_state_literal(&s->lzma.state);
gokhlayeh@9258 1786 +}
gokhlayeh@9258 1787 +
gokhlayeh@9258 1788 +/* Decode the length of the match into s->lzma.len. */
gokhlayeh@9258 1789 +static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l,
gokhlayeh@9258 1790 + uint32_t pos_state)
gokhlayeh@9258 1791 +{
gokhlayeh@9258 1792 + uint16_t *probs;
gokhlayeh@9258 1793 + uint32_t limit;
gokhlayeh@9258 1794 +
gokhlayeh@9258 1795 + if (!rc_bit(&s->rc, &l->choice)) {
gokhlayeh@9258 1796 + probs = l->low[pos_state];
gokhlayeh@9258 1797 + limit = LEN_LOW_SYMBOLS;
gokhlayeh@9258 1798 + s->lzma.len = MATCH_LEN_MIN;
gokhlayeh@9258 1799 + } else {
gokhlayeh@9258 1800 + if (!rc_bit(&s->rc, &l->choice2)) {
gokhlayeh@9258 1801 + probs = l->mid[pos_state];
gokhlayeh@9258 1802 + limit = LEN_MID_SYMBOLS;
gokhlayeh@9258 1803 + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS;
gokhlayeh@9258 1804 + } else {
gokhlayeh@9258 1805 + probs = l->high;
gokhlayeh@9258 1806 + limit = LEN_HIGH_SYMBOLS;
gokhlayeh@9258 1807 + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS
gokhlayeh@9258 1808 + + LEN_MID_SYMBOLS;
gokhlayeh@9258 1809 + }
gokhlayeh@9258 1810 + }
gokhlayeh@9258 1811 +
gokhlayeh@9258 1812 + s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit;
gokhlayeh@9258 1813 +}
gokhlayeh@9258 1814 +
gokhlayeh@9258 1815 +/* Decode a match. The distance will be stored in s->lzma.rep0. */
gokhlayeh@9258 1816 +static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state)
gokhlayeh@9258 1817 +{
gokhlayeh@9258 1818 + uint16_t *probs;
gokhlayeh@9258 1819 + uint32_t dist_slot;
gokhlayeh@9258 1820 + uint32_t limit;
gokhlayeh@9258 1821 +
gokhlayeh@9258 1822 + lzma_state_match(&s->lzma.state);
gokhlayeh@9258 1823 +
gokhlayeh@9258 1824 + s->lzma.rep3 = s->lzma.rep2;
gokhlayeh@9258 1825 + s->lzma.rep2 = s->lzma.rep1;
gokhlayeh@9258 1826 + s->lzma.rep1 = s->lzma.rep0;
gokhlayeh@9258 1827 +
gokhlayeh@9258 1828 + lzma_len(s, &s->lzma.match_len_dec, pos_state);
gokhlayeh@9258 1829 +
gokhlayeh@9258 1830 + probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)];
gokhlayeh@9258 1831 + dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS;
gokhlayeh@9258 1832 +
gokhlayeh@9258 1833 + if (dist_slot < DIST_MODEL_START) {
gokhlayeh@9258 1834 + s->lzma.rep0 = dist_slot;
gokhlayeh@9258 1835 + } else {
gokhlayeh@9258 1836 + limit = (dist_slot >> 1) - 1;
gokhlayeh@9258 1837 + s->lzma.rep0 = 2 + (dist_slot & 1);
gokhlayeh@9258 1838 +
gokhlayeh@9258 1839 + if (dist_slot < DIST_MODEL_END) {
gokhlayeh@9258 1840 + s->lzma.rep0 <<= limit;
gokhlayeh@9258 1841 + probs = s->lzma.dist_special + s->lzma.rep0
gokhlayeh@9258 1842 + - dist_slot - 1;
gokhlayeh@9258 1843 + rc_bittree_reverse(&s->rc, probs,
gokhlayeh@9258 1844 + &s->lzma.rep0, limit);
gokhlayeh@9258 1845 + } else {
gokhlayeh@9258 1846 + rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS);
gokhlayeh@9258 1847 + s->lzma.rep0 <<= ALIGN_BITS;
gokhlayeh@9258 1848 + rc_bittree_reverse(&s->rc, s->lzma.dist_align,
gokhlayeh@9258 1849 + &s->lzma.rep0, ALIGN_BITS);
gokhlayeh@9258 1850 + }
gokhlayeh@9258 1851 + }
gokhlayeh@9258 1852 +}
gokhlayeh@9258 1853 +
gokhlayeh@9258 1854 +/*
gokhlayeh@9258 1855 + * Decode a repeated match. The distance is one of the four most recently
gokhlayeh@9258 1856 + * seen matches. The distance will be stored in s->lzma.rep0.
gokhlayeh@9258 1857 + */
gokhlayeh@9258 1858 +static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state)
gokhlayeh@9258 1859 +{
gokhlayeh@9258 1860 + uint32_t tmp;
gokhlayeh@9258 1861 +
gokhlayeh@9258 1862 + if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) {
gokhlayeh@9258 1863 + if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[
gokhlayeh@9258 1864 + s->lzma.state][pos_state])) {
gokhlayeh@9258 1865 + lzma_state_short_rep(&s->lzma.state);
gokhlayeh@9258 1866 + s->lzma.len = 1;
gokhlayeh@9258 1867 + return;
gokhlayeh@9258 1868 + }
gokhlayeh@9258 1869 + } else {
gokhlayeh@9258 1870 + if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) {
gokhlayeh@9258 1871 + tmp = s->lzma.rep1;
gokhlayeh@9258 1872 + } else {
gokhlayeh@9258 1873 + if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) {
gokhlayeh@9258 1874 + tmp = s->lzma.rep2;
gokhlayeh@9258 1875 + } else {
gokhlayeh@9258 1876 + tmp = s->lzma.rep3;
gokhlayeh@9258 1877 + s->lzma.rep3 = s->lzma.rep2;
gokhlayeh@9258 1878 + }
gokhlayeh@9258 1879 +
gokhlayeh@9258 1880 + s->lzma.rep2 = s->lzma.rep1;
gokhlayeh@9258 1881 + }
gokhlayeh@9258 1882 +
gokhlayeh@9258 1883 + s->lzma.rep1 = s->lzma.rep0;
gokhlayeh@9258 1884 + s->lzma.rep0 = tmp;
gokhlayeh@9258 1885 + }
gokhlayeh@9258 1886 +
gokhlayeh@9258 1887 + lzma_state_long_rep(&s->lzma.state);
gokhlayeh@9258 1888 + lzma_len(s, &s->lzma.rep_len_dec, pos_state);
gokhlayeh@9258 1889 +}
gokhlayeh@9258 1890 +
gokhlayeh@9258 1891 +/* LZMA decoder core */
gokhlayeh@9258 1892 +static bool lzma_main(struct xz_dec_lzma2 *s)
gokhlayeh@9258 1893 +{
gokhlayeh@9258 1894 + uint32_t pos_state;
gokhlayeh@9258 1895 +
gokhlayeh@9258 1896 + /*
gokhlayeh@9258 1897 + * If the dictionary was reached during the previous call, try to
gokhlayeh@9258 1898 + * finish the possibly pending repeat in the dictionary.
gokhlayeh@9258 1899 + */
gokhlayeh@9258 1900 + if (dict_has_space(&s->dict) && s->lzma.len > 0)
gokhlayeh@9258 1901 + dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0);
gokhlayeh@9258 1902 +
gokhlayeh@9258 1903 + /*
gokhlayeh@9258 1904 + * Decode more LZMA symbols. One iteration may consume up to
gokhlayeh@9258 1905 + * LZMA_IN_REQUIRED - 1 bytes.
gokhlayeh@9258 1906 + */
gokhlayeh@9258 1907 + while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) {
gokhlayeh@9258 1908 + pos_state = s->dict.pos & s->lzma.pos_mask;
gokhlayeh@9258 1909 +
gokhlayeh@9258 1910 + if (!rc_bit(&s->rc, &s->lzma.is_match[
gokhlayeh@9258 1911 + s->lzma.state][pos_state])) {
gokhlayeh@9258 1912 + lzma_literal(s);
gokhlayeh@9258 1913 + } else {
gokhlayeh@9258 1914 + if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state]))
gokhlayeh@9258 1915 + lzma_rep_match(s, pos_state);
gokhlayeh@9258 1916 + else
gokhlayeh@9258 1917 + lzma_match(s, pos_state);
gokhlayeh@9258 1918 +
gokhlayeh@9258 1919 + if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0))
gokhlayeh@9258 1920 + return false;
gokhlayeh@9258 1921 + }
gokhlayeh@9258 1922 + }
gokhlayeh@9258 1923 +
gokhlayeh@9258 1924 + /*
gokhlayeh@9258 1925 + * Having the range decoder always normalized when we are outside
gokhlayeh@9258 1926 + * this function makes it easier to correctly handle end of the chunk.
gokhlayeh@9258 1927 + */
gokhlayeh@9258 1928 + rc_normalize(&s->rc);
gokhlayeh@9258 1929 +
gokhlayeh@9258 1930 + return true;
gokhlayeh@9258 1931 +}
gokhlayeh@9258 1932 +
gokhlayeh@9258 1933 +/*
gokhlayeh@9258 1934 + * Reset the LZMA decoder and range decoder state. Dictionary is nore reset
gokhlayeh@9258 1935 + * here, because LZMA state may be reset without resetting the dictionary.
gokhlayeh@9258 1936 + */
gokhlayeh@9258 1937 +static void lzma_reset(struct xz_dec_lzma2 *s)
gokhlayeh@9258 1938 +{
gokhlayeh@9258 1939 + uint16_t *probs;
gokhlayeh@9258 1940 + size_t i;
gokhlayeh@9258 1941 +
gokhlayeh@9258 1942 + s->lzma.state = STATE_LIT_LIT;
gokhlayeh@9258 1943 + s->lzma.rep0 = 0;
gokhlayeh@9258 1944 + s->lzma.rep1 = 0;
gokhlayeh@9258 1945 + s->lzma.rep2 = 0;
gokhlayeh@9258 1946 + s->lzma.rep3 = 0;
gokhlayeh@9258 1947 +
gokhlayeh@9258 1948 + /*
gokhlayeh@9258 1949 + * All probabilities are initialized to the same value. This hack
gokhlayeh@9258 1950 + * makes the code smaller by avoiding a separate loop for each
gokhlayeh@9258 1951 + * probability array.
gokhlayeh@9258 1952 + *
gokhlayeh@9258 1953 + * This could be optimized so that only that part of literal
gokhlayeh@9258 1954 + * probabilities that are actually required. In the common case
gokhlayeh@9258 1955 + * we would write 12 KiB less.
gokhlayeh@9258 1956 + */
gokhlayeh@9258 1957 + probs = s->lzma.is_match[0];
gokhlayeh@9258 1958 + for (i = 0; i < PROBS_TOTAL; ++i)
gokhlayeh@9258 1959 + probs[i] = RC_BIT_MODEL_TOTAL / 2;
gokhlayeh@9258 1960 +
gokhlayeh@9258 1961 + rc_reset(&s->rc);
gokhlayeh@9258 1962 +}
gokhlayeh@9258 1963 +
gokhlayeh@9258 1964 +/*
gokhlayeh@9258 1965 + * Decode and validate LZMA properties (lc/lp/pb) and calculate the bit masks
gokhlayeh@9258 1966 + * from the decoded lp and pb values. On success, the LZMA decoder state is
gokhlayeh@9258 1967 + * reset and true is returned.
gokhlayeh@9258 1968 + */
gokhlayeh@9258 1969 +static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props)
gokhlayeh@9258 1970 +{
gokhlayeh@9258 1971 + if (props > (4 * 5 + 4) * 9 + 8)
gokhlayeh@9258 1972 + return false;
gokhlayeh@9258 1973 +
gokhlayeh@9258 1974 + s->lzma.pos_mask = 0;
gokhlayeh@9258 1975 + while (props >= 9 * 5) {
gokhlayeh@9258 1976 + props -= 9 * 5;
gokhlayeh@9258 1977 + ++s->lzma.pos_mask;
gokhlayeh@9258 1978 + }
gokhlayeh@9258 1979 +
gokhlayeh@9258 1980 + s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1;
gokhlayeh@9258 1981 +
gokhlayeh@9258 1982 + s->lzma.literal_pos_mask = 0;
gokhlayeh@9258 1983 + while (props >= 9) {
gokhlayeh@9258 1984 + props -= 9;
gokhlayeh@9258 1985 + ++s->lzma.literal_pos_mask;
gokhlayeh@9258 1986 + }
gokhlayeh@9258 1987 +
gokhlayeh@9258 1988 + s->lzma.lc = props;
gokhlayeh@9258 1989 +
gokhlayeh@9258 1990 + if (s->lzma.lc + s->lzma.literal_pos_mask > 4)
gokhlayeh@9258 1991 + return false;
gokhlayeh@9258 1992 +
gokhlayeh@9258 1993 + s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1;
gokhlayeh@9258 1994 +
gokhlayeh@9258 1995 + lzma_reset(s);
gokhlayeh@9258 1996 +
gokhlayeh@9258 1997 + return true;
gokhlayeh@9258 1998 +}
gokhlayeh@9258 1999 +
gokhlayeh@9258 2000 +/*********
gokhlayeh@9258 2001 + * LZMA2 *
gokhlayeh@9258 2002 + *********/
gokhlayeh@9258 2003 +
gokhlayeh@9258 2004 +/*
gokhlayeh@9258 2005 + * The LZMA decoder assumes that if the input limit (s->rc.in_limit) hasn't
gokhlayeh@9258 2006 + * been exceeded, it is safe to read up to LZMA_IN_REQUIRED bytes. This
gokhlayeh@9258 2007 + * wrapper function takes care of making the LZMA decoder's assumption safe.
gokhlayeh@9258 2008 + *
gokhlayeh@9258 2009 + * As long as there is plenty of input left to be decoded in the current LZMA
gokhlayeh@9258 2010 + * chunk, we decode directly from the caller-supplied input buffer until
gokhlayeh@9258 2011 + * there's LZMA_IN_REQUIRED bytes left. Those remaining bytes are copied into
gokhlayeh@9258 2012 + * s->temp.buf, which (hopefully) gets filled on the next call to this
gokhlayeh@9258 2013 + * function. We decode a few bytes from the temporary buffer so that we can
gokhlayeh@9258 2014 + * continue decoding from the caller-supplied input buffer again.
gokhlayeh@9258 2015 + */
gokhlayeh@9258 2016 +static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b)
gokhlayeh@9258 2017 +{
gokhlayeh@9258 2018 + size_t in_avail;
gokhlayeh@9258 2019 + uint32_t tmp;
gokhlayeh@9258 2020 +
gokhlayeh@9258 2021 + in_avail = b->in_size - b->in_pos;
gokhlayeh@9258 2022 + if (s->temp.size > 0 || s->lzma2.compressed == 0) {
gokhlayeh@9258 2023 + tmp = 2 * LZMA_IN_REQUIRED - s->temp.size;
gokhlayeh@9258 2024 + if (tmp > s->lzma2.compressed - s->temp.size)
gokhlayeh@9258 2025 + tmp = s->lzma2.compressed - s->temp.size;
gokhlayeh@9258 2026 + if (tmp > in_avail)
gokhlayeh@9258 2027 + tmp = in_avail;
gokhlayeh@9258 2028 +
gokhlayeh@9258 2029 + memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp);
gokhlayeh@9258 2030 +
gokhlayeh@9258 2031 + if (s->temp.size + tmp == s->lzma2.compressed) {
gokhlayeh@9258 2032 + memzero(s->temp.buf + s->temp.size + tmp,
gokhlayeh@9258 2033 + sizeof(s->temp.buf)
gokhlayeh@9258 2034 + - s->temp.size - tmp);
gokhlayeh@9258 2035 + s->rc.in_limit = s->temp.size + tmp;
gokhlayeh@9258 2036 + } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) {
gokhlayeh@9258 2037 + s->temp.size += tmp;
gokhlayeh@9258 2038 + b->in_pos += tmp;
gokhlayeh@9258 2039 + return true;
gokhlayeh@9258 2040 + } else {
gokhlayeh@9258 2041 + s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED;
gokhlayeh@9258 2042 + }
gokhlayeh@9258 2043 +
gokhlayeh@9258 2044 + s->rc.in = s->temp.buf;
gokhlayeh@9258 2045 + s->rc.in_pos = 0;
gokhlayeh@9258 2046 +
gokhlayeh@9258 2047 + if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp)
gokhlayeh@9258 2048 + return false;
gokhlayeh@9258 2049 +
gokhlayeh@9258 2050 + s->lzma2.compressed -= s->rc.in_pos;
gokhlayeh@9258 2051 +
gokhlayeh@9258 2052 + if (s->rc.in_pos < s->temp.size) {
gokhlayeh@9258 2053 + s->temp.size -= s->rc.in_pos;
gokhlayeh@9258 2054 + memmove(s->temp.buf, s->temp.buf + s->rc.in_pos,
gokhlayeh@9258 2055 + s->temp.size);
gokhlayeh@9258 2056 + return true;
gokhlayeh@9258 2057 + }
gokhlayeh@9258 2058 +
gokhlayeh@9258 2059 + b->in_pos += s->rc.in_pos - s->temp.size;
gokhlayeh@9258 2060 + s->temp.size = 0;
gokhlayeh@9258 2061 + }
gokhlayeh@9258 2062 +
gokhlayeh@9258 2063 + in_avail = b->in_size - b->in_pos;
gokhlayeh@9258 2064 + if (in_avail >= LZMA_IN_REQUIRED) {
gokhlayeh@9258 2065 + s->rc.in = b->in;
gokhlayeh@9258 2066 + s->rc.in_pos = b->in_pos;
gokhlayeh@9258 2067 +
gokhlayeh@9258 2068 + if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED)
gokhlayeh@9258 2069 + s->rc.in_limit = b->in_pos + s->lzma2.compressed;
gokhlayeh@9258 2070 + else
gokhlayeh@9258 2071 + s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED;
gokhlayeh@9258 2072 +
gokhlayeh@9258 2073 + if (!lzma_main(s))
gokhlayeh@9258 2074 + return false;
gokhlayeh@9258 2075 +
gokhlayeh@9258 2076 + in_avail = s->rc.in_pos - b->in_pos;
gokhlayeh@9258 2077 + if (in_avail > s->lzma2.compressed)
gokhlayeh@9258 2078 + return false;
gokhlayeh@9258 2079 +
gokhlayeh@9258 2080 + s->lzma2.compressed -= in_avail;
gokhlayeh@9258 2081 + b->in_pos = s->rc.in_pos;
gokhlayeh@9258 2082 + }
gokhlayeh@9258 2083 +
gokhlayeh@9258 2084 + in_avail = b->in_size - b->in_pos;
gokhlayeh@9258 2085 + if (in_avail < LZMA_IN_REQUIRED) {
gokhlayeh@9258 2086 + if (in_avail > s->lzma2.compressed)
gokhlayeh@9258 2087 + in_avail = s->lzma2.compressed;
gokhlayeh@9258 2088 +
gokhlayeh@9258 2089 + memcpy(s->temp.buf, b->in + b->in_pos, in_avail);
gokhlayeh@9258 2090 + s->temp.size = in_avail;
gokhlayeh@9258 2091 + b->in_pos += in_avail;
gokhlayeh@9258 2092 + }
gokhlayeh@9258 2093 +
gokhlayeh@9258 2094 + return true;
gokhlayeh@9258 2095 +}
gokhlayeh@9258 2096 +
gokhlayeh@9258 2097 +/*
gokhlayeh@9258 2098 + * Take care of the LZMA2 control layer, and forward the job of actual LZMA
gokhlayeh@9258 2099 + * decoding or copying of uncompressed chunks to other functions.
gokhlayeh@9258 2100 + */
gokhlayeh@9258 2101 +XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
gokhlayeh@9258 2102 + struct xz_buf *b)
gokhlayeh@9258 2103 +{
gokhlayeh@9258 2104 + uint32_t tmp;
gokhlayeh@9258 2105 +
gokhlayeh@9258 2106 + while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) {
gokhlayeh@9258 2107 + switch (s->lzma2.sequence) {
gokhlayeh@9258 2108 + case SEQ_CONTROL:
gokhlayeh@9258 2109 + /*
gokhlayeh@9258 2110 + * LZMA2 control byte
gokhlayeh@9258 2111 + *
gokhlayeh@9258 2112 + * Exact values:
gokhlayeh@9258 2113 + * 0x00 End marker
gokhlayeh@9258 2114 + * 0x01 Dictionary reset followed by
gokhlayeh@9258 2115 + * an uncompressed chunk
gokhlayeh@9258 2116 + * 0x02 Uncompressed chunk (no dictionary reset)
gokhlayeh@9258 2117 + *
gokhlayeh@9258 2118 + * Highest three bits (s->control & 0xE0):
gokhlayeh@9258 2119 + * 0xE0 Dictionary reset, new properties and state
gokhlayeh@9258 2120 + * reset, followed by LZMA compressed chunk
gokhlayeh@9258 2121 + * 0xC0 New properties and state reset, followed
gokhlayeh@9258 2122 + * by LZMA compressed chunk (no dictionary
gokhlayeh@9258 2123 + * reset)
gokhlayeh@9258 2124 + * 0xA0 State reset using old properties,
gokhlayeh@9258 2125 + * followed by LZMA compressed chunk (no
gokhlayeh@9258 2126 + * dictionary reset)
gokhlayeh@9258 2127 + * 0x80 LZMA chunk (no dictionary or state reset)
gokhlayeh@9258 2128 + *
gokhlayeh@9258 2129 + * For LZMA compressed chunks, the lowest five bits
gokhlayeh@9258 2130 + * (s->control & 1F) are the highest bits of the
gokhlayeh@9258 2131 + * uncompressed size (bits 16-20).
gokhlayeh@9258 2132 + *
gokhlayeh@9258 2133 + * A new LZMA2 stream must begin with a dictionary
gokhlayeh@9258 2134 + * reset. The first LZMA chunk must set new
gokhlayeh@9258 2135 + * properties and reset the LZMA state.
gokhlayeh@9258 2136 + *
gokhlayeh@9258 2137 + * Values that don't match anything described above
gokhlayeh@9258 2138 + * are invalid and we return XZ_DATA_ERROR.
gokhlayeh@9258 2139 + */
gokhlayeh@9258 2140 + tmp = b->in[b->in_pos++];
gokhlayeh@9258 2141 +
gokhlayeh@9258 2142 + if (tmp >= 0xE0 || tmp == 0x01) {
gokhlayeh@9258 2143 + s->lzma2.need_props = true;
gokhlayeh@9258 2144 + s->lzma2.need_dict_reset = false;
gokhlayeh@9258 2145 + dict_reset(&s->dict, b);
gokhlayeh@9258 2146 + } else if (s->lzma2.need_dict_reset) {
gokhlayeh@9258 2147 + return XZ_DATA_ERROR;
gokhlayeh@9258 2148 + }
gokhlayeh@9258 2149 +
gokhlayeh@9258 2150 + if (tmp >= 0x80) {
gokhlayeh@9258 2151 + s->lzma2.uncompressed = (tmp & 0x1F) << 16;
gokhlayeh@9258 2152 + s->lzma2.sequence = SEQ_UNCOMPRESSED_1;
gokhlayeh@9258 2153 +
gokhlayeh@9258 2154 + if (tmp >= 0xC0) {
gokhlayeh@9258 2155 + /*
gokhlayeh@9258 2156 + * When there are new properties,
gokhlayeh@9258 2157 + * state reset is done at
gokhlayeh@9258 2158 + * SEQ_PROPERTIES.
gokhlayeh@9258 2159 + */
gokhlayeh@9258 2160 + s->lzma2.need_props = false;
gokhlayeh@9258 2161 + s->lzma2.next_sequence
gokhlayeh@9258 2162 + = SEQ_PROPERTIES;
gokhlayeh@9258 2163 +
gokhlayeh@9258 2164 + } else if (s->lzma2.need_props) {
gokhlayeh@9258 2165 + return XZ_DATA_ERROR;
gokhlayeh@9258 2166 +
gokhlayeh@9258 2167 + } else {
gokhlayeh@9258 2168 + s->lzma2.next_sequence
gokhlayeh@9258 2169 + = SEQ_LZMA_PREPARE;
gokhlayeh@9258 2170 + if (tmp >= 0xA0)
gokhlayeh@9258 2171 + lzma_reset(s);
gokhlayeh@9258 2172 + }
gokhlayeh@9258 2173 + } else {
gokhlayeh@9258 2174 + if (tmp == 0x00)
gokhlayeh@9258 2175 + return XZ_STREAM_END;
gokhlayeh@9258 2176 +
gokhlayeh@9258 2177 + if (tmp > 0x02)
gokhlayeh@9258 2178 + return XZ_DATA_ERROR;
gokhlayeh@9258 2179 +
gokhlayeh@9258 2180 + s->lzma2.sequence = SEQ_COMPRESSED_0;
gokhlayeh@9258 2181 + s->lzma2.next_sequence = SEQ_COPY;
gokhlayeh@9258 2182 + }
gokhlayeh@9258 2183 +
gokhlayeh@9258 2184 + break;
gokhlayeh@9258 2185 +
gokhlayeh@9258 2186 + case SEQ_UNCOMPRESSED_1:
gokhlayeh@9258 2187 + s->lzma2.uncompressed
gokhlayeh@9258 2188 + += (uint32_t)b->in[b->in_pos++] << 8;
gokhlayeh@9258 2189 + s->lzma2.sequence = SEQ_UNCOMPRESSED_2;
gokhlayeh@9258 2190 + break;
gokhlayeh@9258 2191 +
gokhlayeh@9258 2192 + case SEQ_UNCOMPRESSED_2:
gokhlayeh@9258 2193 + s->lzma2.uncompressed
gokhlayeh@9258 2194 + += (uint32_t)b->in[b->in_pos++] + 1;
gokhlayeh@9258 2195 + s->lzma2.sequence = SEQ_COMPRESSED_0;
gokhlayeh@9258 2196 + break;
gokhlayeh@9258 2197 +
gokhlayeh@9258 2198 + case SEQ_COMPRESSED_0:
gokhlayeh@9258 2199 + s->lzma2.compressed
gokhlayeh@9258 2200 + = (uint32_t)b->in[b->in_pos++] << 8;
gokhlayeh@9258 2201 + s->lzma2.sequence = SEQ_COMPRESSED_1;
gokhlayeh@9258 2202 + break;
gokhlayeh@9258 2203 +
gokhlayeh@9258 2204 + case SEQ_COMPRESSED_1:
gokhlayeh@9258 2205 + s->lzma2.compressed
gokhlayeh@9258 2206 + += (uint32_t)b->in[b->in_pos++] + 1;
gokhlayeh@9258 2207 + s->lzma2.sequence = s->lzma2.next_sequence;
gokhlayeh@9258 2208 + break;
gokhlayeh@9258 2209 +
gokhlayeh@9258 2210 + case SEQ_PROPERTIES:
gokhlayeh@9258 2211 + if (!lzma_props(s, b->in[b->in_pos++]))
gokhlayeh@9258 2212 + return XZ_DATA_ERROR;
gokhlayeh@9258 2213 +
gokhlayeh@9258 2214 + s->lzma2.sequence = SEQ_LZMA_PREPARE;
gokhlayeh@9258 2215 +
gokhlayeh@9258 2216 + case SEQ_LZMA_PREPARE:
gokhlayeh@9258 2217 + if (s->lzma2.compressed < RC_INIT_BYTES)
gokhlayeh@9258 2218 + return XZ_DATA_ERROR;
gokhlayeh@9258 2219 +
gokhlayeh@9258 2220 + if (!rc_read_init(&s->rc, b))
gokhlayeh@9258 2221 + return XZ_OK;
gokhlayeh@9258 2222 +
gokhlayeh@9258 2223 + s->lzma2.compressed -= RC_INIT_BYTES;
gokhlayeh@9258 2224 + s->lzma2.sequence = SEQ_LZMA_RUN;
gokhlayeh@9258 2225 +
gokhlayeh@9258 2226 + case SEQ_LZMA_RUN:
gokhlayeh@9258 2227 + /*
gokhlayeh@9258 2228 + * Set dictionary limit to indicate how much we want
gokhlayeh@9258 2229 + * to be encoded at maximum. Decode new data into the
gokhlayeh@9258 2230 + * dictionary. Flush the new data from dictionary to
gokhlayeh@9258 2231 + * b->out. Check if we finished decoding this chunk.
gokhlayeh@9258 2232 + * In case the dictionary got full but we didn't fill
gokhlayeh@9258 2233 + * the output buffer yet, we may run this loop
gokhlayeh@9258 2234 + * multiple times without changing s->lzma2.sequence.
gokhlayeh@9258 2235 + */
gokhlayeh@9258 2236 + dict_limit(&s->dict, min_t(size_t,
gokhlayeh@9258 2237 + b->out_size - b->out_pos,
gokhlayeh@9258 2238 + s->lzma2.uncompressed));
gokhlayeh@9258 2239 + if (!lzma2_lzma(s, b))
gokhlayeh@9258 2240 + return XZ_DATA_ERROR;
gokhlayeh@9258 2241 +
gokhlayeh@9258 2242 + s->lzma2.uncompressed -= dict_flush(&s->dict, b);
gokhlayeh@9258 2243 +
gokhlayeh@9258 2244 + if (s->lzma2.uncompressed == 0) {
gokhlayeh@9258 2245 + if (s->lzma2.compressed > 0 || s->lzma.len > 0
gokhlayeh@9258 2246 + || !rc_is_finished(&s->rc))
gokhlayeh@9258 2247 + return XZ_DATA_ERROR;
gokhlayeh@9258 2248 +
gokhlayeh@9258 2249 + rc_reset(&s->rc);
gokhlayeh@9258 2250 + s->lzma2.sequence = SEQ_CONTROL;
gokhlayeh@9258 2251 +
gokhlayeh@9258 2252 + } else if (b->out_pos == b->out_size
gokhlayeh@9258 2253 + || (b->in_pos == b->in_size
gokhlayeh@9258 2254 + && s->temp.size
gokhlayeh@9258 2255 + < s->lzma2.compressed)) {
gokhlayeh@9258 2256 + return XZ_OK;
gokhlayeh@9258 2257 + }
gokhlayeh@9258 2258 +
gokhlayeh@9258 2259 + break;
gokhlayeh@9258 2260 +
gokhlayeh@9258 2261 + case SEQ_COPY:
gokhlayeh@9258 2262 + dict_uncompressed(&s->dict, b, &s->lzma2.compressed);
gokhlayeh@9258 2263 + if (s->lzma2.compressed > 0)
gokhlayeh@9258 2264 + return XZ_OK;
gokhlayeh@9258 2265 +
gokhlayeh@9258 2266 + s->lzma2.sequence = SEQ_CONTROL;
gokhlayeh@9258 2267 + break;
gokhlayeh@9258 2268 + }
gokhlayeh@9258 2269 + }
gokhlayeh@9258 2270 +
gokhlayeh@9258 2271 + return XZ_OK;
gokhlayeh@9258 2272 +}
gokhlayeh@9258 2273 +
gokhlayeh@9258 2274 +XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode,
gokhlayeh@9258 2275 + uint32_t dict_max)
gokhlayeh@9258 2276 +{
gokhlayeh@9258 2277 + struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL);
gokhlayeh@9258 2278 + if (s == NULL)
gokhlayeh@9258 2279 + return NULL;
gokhlayeh@9258 2280 +
gokhlayeh@9258 2281 + s->dict.mode = mode;
gokhlayeh@9258 2282 + s->dict.size_max = dict_max;
gokhlayeh@9258 2283 +
gokhlayeh@9258 2284 + if (DEC_IS_PREALLOC(mode)) {
gokhlayeh@9258 2285 + s->dict.buf = vmalloc(dict_max);
gokhlayeh@9258 2286 + if (s->dict.buf == NULL) {
gokhlayeh@9258 2287 + kfree(s);
gokhlayeh@9258 2288 + return NULL;
gokhlayeh@9258 2289 + }
gokhlayeh@9258 2290 + } else if (DEC_IS_DYNALLOC(mode)) {
gokhlayeh@9258 2291 + s->dict.buf = NULL;
gokhlayeh@9258 2292 + s->dict.allocated = 0;
gokhlayeh@9258 2293 + }
gokhlayeh@9258 2294 +
gokhlayeh@9258 2295 + return s;
gokhlayeh@9258 2296 +}
gokhlayeh@9258 2297 +
gokhlayeh@9258 2298 +XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props)
gokhlayeh@9258 2299 +{
gokhlayeh@9258 2300 + /* This limits dictionary size to 3 GiB to keep parsing simpler. */
gokhlayeh@9258 2301 + if (props > 39)
gokhlayeh@9258 2302 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2303 +
gokhlayeh@9258 2304 + s->dict.size = 2 + (props & 1);
gokhlayeh@9258 2305 + s->dict.size <<= (props >> 1) + 11;
gokhlayeh@9258 2306 +
gokhlayeh@9258 2307 + if (DEC_IS_MULTI(s->dict.mode)) {
gokhlayeh@9258 2308 + if (s->dict.size > s->dict.size_max)
gokhlayeh@9258 2309 + return XZ_MEMLIMIT_ERROR;
gokhlayeh@9258 2310 +
gokhlayeh@9258 2311 + s->dict.end = s->dict.size;
gokhlayeh@9258 2312 +
gokhlayeh@9258 2313 + if (DEC_IS_DYNALLOC(s->dict.mode)) {
gokhlayeh@9258 2314 + if (s->dict.allocated < s->dict.size) {
gokhlayeh@9258 2315 + vfree(s->dict.buf);
gokhlayeh@9258 2316 + s->dict.buf = vmalloc(s->dict.size);
gokhlayeh@9258 2317 + if (s->dict.buf == NULL) {
gokhlayeh@9258 2318 + s->dict.allocated = 0;
gokhlayeh@9258 2319 + return XZ_MEM_ERROR;
gokhlayeh@9258 2320 + }
gokhlayeh@9258 2321 + }
gokhlayeh@9258 2322 + }
gokhlayeh@9258 2323 + }
gokhlayeh@9258 2324 +
gokhlayeh@9258 2325 + s->lzma.len = 0;
gokhlayeh@9258 2326 +
gokhlayeh@9258 2327 + s->lzma2.sequence = SEQ_CONTROL;
gokhlayeh@9258 2328 + s->lzma2.need_dict_reset = true;
gokhlayeh@9258 2329 +
gokhlayeh@9258 2330 + s->temp.size = 0;
gokhlayeh@9258 2331 +
gokhlayeh@9258 2332 + return XZ_OK;
gokhlayeh@9258 2333 +}
gokhlayeh@9258 2334 +
gokhlayeh@9258 2335 +XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s)
gokhlayeh@9258 2336 +{
gokhlayeh@9258 2337 + if (DEC_IS_MULTI(s->dict.mode))
gokhlayeh@9258 2338 + vfree(s->dict.buf);
gokhlayeh@9258 2339 +
gokhlayeh@9258 2340 + kfree(s);
gokhlayeh@9258 2341 +}
gokhlayeh@9258 2342 diff --git a/lib/xz/xz_dec_stream.c b/lib/xz/xz_dec_stream.c
gokhlayeh@9258 2343 new file mode 100644
gokhlayeh@9258 2344 index 0000000..ac809b1
gokhlayeh@9258 2345 --- /dev/null
gokhlayeh@9258 2346 +++ b/lib/xz/xz_dec_stream.c
gokhlayeh@9258 2347 @@ -0,0 +1,821 @@
gokhlayeh@9258 2348 +/*
gokhlayeh@9258 2349 + * .xz Stream decoder
gokhlayeh@9258 2350 + *
gokhlayeh@9258 2351 + * Author: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 2352 + *
gokhlayeh@9258 2353 + * This file has been put into the public domain.
gokhlayeh@9258 2354 + * You can do whatever you want with this file.
gokhlayeh@9258 2355 + */
gokhlayeh@9258 2356 +
gokhlayeh@9258 2357 +#include "xz_private.h"
gokhlayeh@9258 2358 +#include "xz_stream.h"
gokhlayeh@9258 2359 +
gokhlayeh@9258 2360 +/* Hash used to validate the Index field */
gokhlayeh@9258 2361 +struct xz_dec_hash {
gokhlayeh@9258 2362 + vli_type unpadded;
gokhlayeh@9258 2363 + vli_type uncompressed;
gokhlayeh@9258 2364 + uint32_t crc32;
gokhlayeh@9258 2365 +};
gokhlayeh@9258 2366 +
gokhlayeh@9258 2367 +struct xz_dec {
gokhlayeh@9258 2368 + /* Position in dec_main() */
gokhlayeh@9258 2369 + enum {
gokhlayeh@9258 2370 + SEQ_STREAM_HEADER,
gokhlayeh@9258 2371 + SEQ_BLOCK_START,
gokhlayeh@9258 2372 + SEQ_BLOCK_HEADER,
gokhlayeh@9258 2373 + SEQ_BLOCK_UNCOMPRESS,
gokhlayeh@9258 2374 + SEQ_BLOCK_PADDING,
gokhlayeh@9258 2375 + SEQ_BLOCK_CHECK,
gokhlayeh@9258 2376 + SEQ_INDEX,
gokhlayeh@9258 2377 + SEQ_INDEX_PADDING,
gokhlayeh@9258 2378 + SEQ_INDEX_CRC32,
gokhlayeh@9258 2379 + SEQ_STREAM_FOOTER
gokhlayeh@9258 2380 + } sequence;
gokhlayeh@9258 2381 +
gokhlayeh@9258 2382 + /* Position in variable-length integers and Check fields */
gokhlayeh@9258 2383 + uint32_t pos;
gokhlayeh@9258 2384 +
gokhlayeh@9258 2385 + /* Variable-length integer decoded by dec_vli() */
gokhlayeh@9258 2386 + vli_type vli;
gokhlayeh@9258 2387 +
gokhlayeh@9258 2388 + /* Saved in_pos and out_pos */
gokhlayeh@9258 2389 + size_t in_start;
gokhlayeh@9258 2390 + size_t out_start;
gokhlayeh@9258 2391 +
gokhlayeh@9258 2392 + /* CRC32 value in Block or Index */
gokhlayeh@9258 2393 + uint32_t crc32;
gokhlayeh@9258 2394 +
gokhlayeh@9258 2395 + /* Type of the integrity check calculated from uncompressed data */
gokhlayeh@9258 2396 + enum xz_check check_type;
gokhlayeh@9258 2397 +
gokhlayeh@9258 2398 + /* Operation mode */
gokhlayeh@9258 2399 + enum xz_mode mode;
gokhlayeh@9258 2400 +
gokhlayeh@9258 2401 + /*
gokhlayeh@9258 2402 + * True if the next call to xz_dec_run() is allowed to return
gokhlayeh@9258 2403 + * XZ_BUF_ERROR.
gokhlayeh@9258 2404 + */
gokhlayeh@9258 2405 + bool allow_buf_error;
gokhlayeh@9258 2406 +
gokhlayeh@9258 2407 + /* Information stored in Block Header */
gokhlayeh@9258 2408 + struct {
gokhlayeh@9258 2409 + /*
gokhlayeh@9258 2410 + * Value stored in the Compressed Size field, or
gokhlayeh@9258 2411 + * VLI_UNKNOWN if Compressed Size is not present.
gokhlayeh@9258 2412 + */
gokhlayeh@9258 2413 + vli_type compressed;
gokhlayeh@9258 2414 +
gokhlayeh@9258 2415 + /*
gokhlayeh@9258 2416 + * Value stored in the Uncompressed Size field, or
gokhlayeh@9258 2417 + * VLI_UNKNOWN if Uncompressed Size is not present.
gokhlayeh@9258 2418 + */
gokhlayeh@9258 2419 + vli_type uncompressed;
gokhlayeh@9258 2420 +
gokhlayeh@9258 2421 + /* Size of the Block Header field */
gokhlayeh@9258 2422 + uint32_t size;
gokhlayeh@9258 2423 + } block_header;
gokhlayeh@9258 2424 +
gokhlayeh@9258 2425 + /* Information collected when decoding Blocks */
gokhlayeh@9258 2426 + struct {
gokhlayeh@9258 2427 + /* Observed compressed size of the current Block */
gokhlayeh@9258 2428 + vli_type compressed;
gokhlayeh@9258 2429 +
gokhlayeh@9258 2430 + /* Observed uncompressed size of the current Block */
gokhlayeh@9258 2431 + vli_type uncompressed;
gokhlayeh@9258 2432 +
gokhlayeh@9258 2433 + /* Number of Blocks decoded so far */
gokhlayeh@9258 2434 + vli_type count;
gokhlayeh@9258 2435 +
gokhlayeh@9258 2436 + /*
gokhlayeh@9258 2437 + * Hash calculated from the Block sizes. This is used to
gokhlayeh@9258 2438 + * validate the Index field.
gokhlayeh@9258 2439 + */
gokhlayeh@9258 2440 + struct xz_dec_hash hash;
gokhlayeh@9258 2441 + } block;
gokhlayeh@9258 2442 +
gokhlayeh@9258 2443 + /* Variables needed when verifying the Index field */
gokhlayeh@9258 2444 + struct {
gokhlayeh@9258 2445 + /* Position in dec_index() */
gokhlayeh@9258 2446 + enum {
gokhlayeh@9258 2447 + SEQ_INDEX_COUNT,
gokhlayeh@9258 2448 + SEQ_INDEX_UNPADDED,
gokhlayeh@9258 2449 + SEQ_INDEX_UNCOMPRESSED
gokhlayeh@9258 2450 + } sequence;
gokhlayeh@9258 2451 +
gokhlayeh@9258 2452 + /* Size of the Index in bytes */
gokhlayeh@9258 2453 + vli_type size;
gokhlayeh@9258 2454 +
gokhlayeh@9258 2455 + /* Number of Records (matches block.count in valid files) */
gokhlayeh@9258 2456 + vli_type count;
gokhlayeh@9258 2457 +
gokhlayeh@9258 2458 + /*
gokhlayeh@9258 2459 + * Hash calculated from the Records (matches block.hash in
gokhlayeh@9258 2460 + * valid files).
gokhlayeh@9258 2461 + */
gokhlayeh@9258 2462 + struct xz_dec_hash hash;
gokhlayeh@9258 2463 + } index;
gokhlayeh@9258 2464 +
gokhlayeh@9258 2465 + /*
gokhlayeh@9258 2466 + * Temporary buffer needed to hold Stream Header, Block Header,
gokhlayeh@9258 2467 + * and Stream Footer. The Block Header is the biggest (1 KiB)
gokhlayeh@9258 2468 + * so we reserve space according to that. buf[] has to be aligned
gokhlayeh@9258 2469 + * to a multiple of four bytes; the size_t variables before it
gokhlayeh@9258 2470 + * should guarantee this.
gokhlayeh@9258 2471 + */
gokhlayeh@9258 2472 + struct {
gokhlayeh@9258 2473 + size_t pos;
gokhlayeh@9258 2474 + size_t size;
gokhlayeh@9258 2475 + uint8_t buf[1024];
gokhlayeh@9258 2476 + } temp;
gokhlayeh@9258 2477 +
gokhlayeh@9258 2478 + struct xz_dec_lzma2 *lzma2;
gokhlayeh@9258 2479 +
gokhlayeh@9258 2480 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 2481 + struct xz_dec_bcj *bcj;
gokhlayeh@9258 2482 + bool bcj_active;
gokhlayeh@9258 2483 +#endif
gokhlayeh@9258 2484 +};
gokhlayeh@9258 2485 +
gokhlayeh@9258 2486 +#ifdef XZ_DEC_ANY_CHECK
gokhlayeh@9258 2487 +/* Sizes of the Check field with different Check IDs */
gokhlayeh@9258 2488 +static const uint8_t check_sizes[16] = {
gokhlayeh@9258 2489 + 0,
gokhlayeh@9258 2490 + 4, 4, 4,
gokhlayeh@9258 2491 + 8, 8, 8,
gokhlayeh@9258 2492 + 16, 16, 16,
gokhlayeh@9258 2493 + 32, 32, 32,
gokhlayeh@9258 2494 + 64, 64, 64
gokhlayeh@9258 2495 +};
gokhlayeh@9258 2496 +#endif
gokhlayeh@9258 2497 +
gokhlayeh@9258 2498 +/*
gokhlayeh@9258 2499 + * Fill s->temp by copying data starting from b->in[b->in_pos]. Caller
gokhlayeh@9258 2500 + * must have set s->temp.pos to indicate how much data we are supposed
gokhlayeh@9258 2501 + * to copy into s->temp.buf. Return true once s->temp.pos has reached
gokhlayeh@9258 2502 + * s->temp.size.
gokhlayeh@9258 2503 + */
gokhlayeh@9258 2504 +static bool fill_temp(struct xz_dec *s, struct xz_buf *b)
gokhlayeh@9258 2505 +{
gokhlayeh@9258 2506 + size_t copy_size = min_t(size_t,
gokhlayeh@9258 2507 + b->in_size - b->in_pos, s->temp.size - s->temp.pos);
gokhlayeh@9258 2508 +
gokhlayeh@9258 2509 + memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size);
gokhlayeh@9258 2510 + b->in_pos += copy_size;
gokhlayeh@9258 2511 + s->temp.pos += copy_size;
gokhlayeh@9258 2512 +
gokhlayeh@9258 2513 + if (s->temp.pos == s->temp.size) {
gokhlayeh@9258 2514 + s->temp.pos = 0;
gokhlayeh@9258 2515 + return true;
gokhlayeh@9258 2516 + }
gokhlayeh@9258 2517 +
gokhlayeh@9258 2518 + return false;
gokhlayeh@9258 2519 +}
gokhlayeh@9258 2520 +
gokhlayeh@9258 2521 +/* Decode a variable-length integer (little-endian base-128 encoding) */
gokhlayeh@9258 2522 +static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in,
gokhlayeh@9258 2523 + size_t *in_pos, size_t in_size)
gokhlayeh@9258 2524 +{
gokhlayeh@9258 2525 + uint8_t byte;
gokhlayeh@9258 2526 +
gokhlayeh@9258 2527 + if (s->pos == 0)
gokhlayeh@9258 2528 + s->vli = 0;
gokhlayeh@9258 2529 +
gokhlayeh@9258 2530 + while (*in_pos < in_size) {
gokhlayeh@9258 2531 + byte = in[*in_pos];
gokhlayeh@9258 2532 + ++*in_pos;
gokhlayeh@9258 2533 +
gokhlayeh@9258 2534 + s->vli |= (vli_type)(byte & 0x7F) << s->pos;
gokhlayeh@9258 2535 +
gokhlayeh@9258 2536 + if ((byte & 0x80) == 0) {
gokhlayeh@9258 2537 + /* Don't allow non-minimal encodings. */
gokhlayeh@9258 2538 + if (byte == 0 && s->pos != 0)
gokhlayeh@9258 2539 + return XZ_DATA_ERROR;
gokhlayeh@9258 2540 +
gokhlayeh@9258 2541 + s->pos = 0;
gokhlayeh@9258 2542 + return XZ_STREAM_END;
gokhlayeh@9258 2543 + }
gokhlayeh@9258 2544 +
gokhlayeh@9258 2545 + s->pos += 7;
gokhlayeh@9258 2546 + if (s->pos == 7 * VLI_BYTES_MAX)
gokhlayeh@9258 2547 + return XZ_DATA_ERROR;
gokhlayeh@9258 2548 + }
gokhlayeh@9258 2549 +
gokhlayeh@9258 2550 + return XZ_OK;
gokhlayeh@9258 2551 +}
gokhlayeh@9258 2552 +
gokhlayeh@9258 2553 +/*
gokhlayeh@9258 2554 + * Decode the Compressed Data field from a Block. Update and validate
gokhlayeh@9258 2555 + * the observed compressed and uncompressed sizes of the Block so that
gokhlayeh@9258 2556 + * they don't exceed the values possibly stored in the Block Header
gokhlayeh@9258 2557 + * (validation assumes that no integer overflow occurs, since vli_type
gokhlayeh@9258 2558 + * is normally uint64_t). Update the CRC32 if presence of the CRC32
gokhlayeh@9258 2559 + * field was indicated in Stream Header.
gokhlayeh@9258 2560 + *
gokhlayeh@9258 2561 + * Once the decoding is finished, validate that the observed sizes match
gokhlayeh@9258 2562 + * the sizes possibly stored in the Block Header. Update the hash and
gokhlayeh@9258 2563 + * Block count, which are later used to validate the Index field.
gokhlayeh@9258 2564 + */
gokhlayeh@9258 2565 +static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b)
gokhlayeh@9258 2566 +{
gokhlayeh@9258 2567 + enum xz_ret ret;
gokhlayeh@9258 2568 +
gokhlayeh@9258 2569 + s->in_start = b->in_pos;
gokhlayeh@9258 2570 + s->out_start = b->out_pos;
gokhlayeh@9258 2571 +
gokhlayeh@9258 2572 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 2573 + if (s->bcj_active)
gokhlayeh@9258 2574 + ret = xz_dec_bcj_run(s->bcj, s->lzma2, b);
gokhlayeh@9258 2575 + else
gokhlayeh@9258 2576 +#endif
gokhlayeh@9258 2577 + ret = xz_dec_lzma2_run(s->lzma2, b);
gokhlayeh@9258 2578 +
gokhlayeh@9258 2579 + s->block.compressed += b->in_pos - s->in_start;
gokhlayeh@9258 2580 + s->block.uncompressed += b->out_pos - s->out_start;
gokhlayeh@9258 2581 +
gokhlayeh@9258 2582 + /*
gokhlayeh@9258 2583 + * There is no need to separately check for VLI_UNKNOWN, since
gokhlayeh@9258 2584 + * the observed sizes are always smaller than VLI_UNKNOWN.
gokhlayeh@9258 2585 + */
gokhlayeh@9258 2586 + if (s->block.compressed > s->block_header.compressed
gokhlayeh@9258 2587 + || s->block.uncompressed
gokhlayeh@9258 2588 + > s->block_header.uncompressed)
gokhlayeh@9258 2589 + return XZ_DATA_ERROR;
gokhlayeh@9258 2590 +
gokhlayeh@9258 2591 + if (s->check_type == XZ_CHECK_CRC32)
gokhlayeh@9258 2592 + s->crc32 = xz_crc32(b->out + s->out_start,
gokhlayeh@9258 2593 + b->out_pos - s->out_start, s->crc32);
gokhlayeh@9258 2594 +
gokhlayeh@9258 2595 + if (ret == XZ_STREAM_END) {
gokhlayeh@9258 2596 + if (s->block_header.compressed != VLI_UNKNOWN
gokhlayeh@9258 2597 + && s->block_header.compressed
gokhlayeh@9258 2598 + != s->block.compressed)
gokhlayeh@9258 2599 + return XZ_DATA_ERROR;
gokhlayeh@9258 2600 +
gokhlayeh@9258 2601 + if (s->block_header.uncompressed != VLI_UNKNOWN
gokhlayeh@9258 2602 + && s->block_header.uncompressed
gokhlayeh@9258 2603 + != s->block.uncompressed)
gokhlayeh@9258 2604 + return XZ_DATA_ERROR;
gokhlayeh@9258 2605 +
gokhlayeh@9258 2606 + s->block.hash.unpadded += s->block_header.size
gokhlayeh@9258 2607 + + s->block.compressed;
gokhlayeh@9258 2608 +
gokhlayeh@9258 2609 +#ifdef XZ_DEC_ANY_CHECK
gokhlayeh@9258 2610 + s->block.hash.unpadded += check_sizes[s->check_type];
gokhlayeh@9258 2611 +#else
gokhlayeh@9258 2612 + if (s->check_type == XZ_CHECK_CRC32)
gokhlayeh@9258 2613 + s->block.hash.unpadded += 4;
gokhlayeh@9258 2614 +#endif
gokhlayeh@9258 2615 +
gokhlayeh@9258 2616 + s->block.hash.uncompressed += s->block.uncompressed;
gokhlayeh@9258 2617 + s->block.hash.crc32 = xz_crc32(
gokhlayeh@9258 2618 + (const uint8_t *)&s->block.hash,
gokhlayeh@9258 2619 + sizeof(s->block.hash), s->block.hash.crc32);
gokhlayeh@9258 2620 +
gokhlayeh@9258 2621 + ++s->block.count;
gokhlayeh@9258 2622 + }
gokhlayeh@9258 2623 +
gokhlayeh@9258 2624 + return ret;
gokhlayeh@9258 2625 +}
gokhlayeh@9258 2626 +
gokhlayeh@9258 2627 +/* Update the Index size and the CRC32 value. */
gokhlayeh@9258 2628 +static void index_update(struct xz_dec *s, const struct xz_buf *b)
gokhlayeh@9258 2629 +{
gokhlayeh@9258 2630 + size_t in_used = b->in_pos - s->in_start;
gokhlayeh@9258 2631 + s->index.size += in_used;
gokhlayeh@9258 2632 + s->crc32 = xz_crc32(b->in + s->in_start, in_used, s->crc32);
gokhlayeh@9258 2633 +}
gokhlayeh@9258 2634 +
gokhlayeh@9258 2635 +/*
gokhlayeh@9258 2636 + * Decode the Number of Records, Unpadded Size, and Uncompressed Size
gokhlayeh@9258 2637 + * fields from the Index field. That is, Index Padding and CRC32 are not
gokhlayeh@9258 2638 + * decoded by this function.
gokhlayeh@9258 2639 + *
gokhlayeh@9258 2640 + * This can return XZ_OK (more input needed), XZ_STREAM_END (everything
gokhlayeh@9258 2641 + * successfully decoded), or XZ_DATA_ERROR (input is corrupt).
gokhlayeh@9258 2642 + */
gokhlayeh@9258 2643 +static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b)
gokhlayeh@9258 2644 +{
gokhlayeh@9258 2645 + enum xz_ret ret;
gokhlayeh@9258 2646 +
gokhlayeh@9258 2647 + do {
gokhlayeh@9258 2648 + ret = dec_vli(s, b->in, &b->in_pos, b->in_size);
gokhlayeh@9258 2649 + if (ret != XZ_STREAM_END) {
gokhlayeh@9258 2650 + index_update(s, b);
gokhlayeh@9258 2651 + return ret;
gokhlayeh@9258 2652 + }
gokhlayeh@9258 2653 +
gokhlayeh@9258 2654 + switch (s->index.sequence) {
gokhlayeh@9258 2655 + case SEQ_INDEX_COUNT:
gokhlayeh@9258 2656 + s->index.count = s->vli;
gokhlayeh@9258 2657 +
gokhlayeh@9258 2658 + /*
gokhlayeh@9258 2659 + * Validate that the Number of Records field
gokhlayeh@9258 2660 + * indicates the same number of Records as
gokhlayeh@9258 2661 + * there were Blocks in the Stream.
gokhlayeh@9258 2662 + */
gokhlayeh@9258 2663 + if (s->index.count != s->block.count)
gokhlayeh@9258 2664 + return XZ_DATA_ERROR;
gokhlayeh@9258 2665 +
gokhlayeh@9258 2666 + s->index.sequence = SEQ_INDEX_UNPADDED;
gokhlayeh@9258 2667 + break;
gokhlayeh@9258 2668 +
gokhlayeh@9258 2669 + case SEQ_INDEX_UNPADDED:
gokhlayeh@9258 2670 + s->index.hash.unpadded += s->vli;
gokhlayeh@9258 2671 + s->index.sequence = SEQ_INDEX_UNCOMPRESSED;
gokhlayeh@9258 2672 + break;
gokhlayeh@9258 2673 +
gokhlayeh@9258 2674 + case SEQ_INDEX_UNCOMPRESSED:
gokhlayeh@9258 2675 + s->index.hash.uncompressed += s->vli;
gokhlayeh@9258 2676 + s->index.hash.crc32 = xz_crc32(
gokhlayeh@9258 2677 + (const uint8_t *)&s->index.hash,
gokhlayeh@9258 2678 + sizeof(s->index.hash),
gokhlayeh@9258 2679 + s->index.hash.crc32);
gokhlayeh@9258 2680 + --s->index.count;
gokhlayeh@9258 2681 + s->index.sequence = SEQ_INDEX_UNPADDED;
gokhlayeh@9258 2682 + break;
gokhlayeh@9258 2683 + }
gokhlayeh@9258 2684 + } while (s->index.count > 0);
gokhlayeh@9258 2685 +
gokhlayeh@9258 2686 + return XZ_STREAM_END;
gokhlayeh@9258 2687 +}
gokhlayeh@9258 2688 +
gokhlayeh@9258 2689 +/*
gokhlayeh@9258 2690 + * Validate that the next four input bytes match the value of s->crc32.
gokhlayeh@9258 2691 + * s->pos must be zero when starting to validate the first byte.
gokhlayeh@9258 2692 + */
gokhlayeh@9258 2693 +static enum xz_ret crc32_validate(struct xz_dec *s, struct xz_buf *b)
gokhlayeh@9258 2694 +{
gokhlayeh@9258 2695 + do {
gokhlayeh@9258 2696 + if (b->in_pos == b->in_size)
gokhlayeh@9258 2697 + return XZ_OK;
gokhlayeh@9258 2698 +
gokhlayeh@9258 2699 + if (((s->crc32 >> s->pos) & 0xFF) != b->in[b->in_pos++])
gokhlayeh@9258 2700 + return XZ_DATA_ERROR;
gokhlayeh@9258 2701 +
gokhlayeh@9258 2702 + s->pos += 8;
gokhlayeh@9258 2703 +
gokhlayeh@9258 2704 + } while (s->pos < 32);
gokhlayeh@9258 2705 +
gokhlayeh@9258 2706 + s->crc32 = 0;
gokhlayeh@9258 2707 + s->pos = 0;
gokhlayeh@9258 2708 +
gokhlayeh@9258 2709 + return XZ_STREAM_END;
gokhlayeh@9258 2710 +}
gokhlayeh@9258 2711 +
gokhlayeh@9258 2712 +#ifdef XZ_DEC_ANY_CHECK
gokhlayeh@9258 2713 +/*
gokhlayeh@9258 2714 + * Skip over the Check field when the Check ID is not supported.
gokhlayeh@9258 2715 + * Returns true once the whole Check field has been skipped over.
gokhlayeh@9258 2716 + */
gokhlayeh@9258 2717 +static bool check_skip(struct xz_dec *s, struct xz_buf *b)
gokhlayeh@9258 2718 +{
gokhlayeh@9258 2719 + while (s->pos < check_sizes[s->check_type]) {
gokhlayeh@9258 2720 + if (b->in_pos == b->in_size)
gokhlayeh@9258 2721 + return false;
gokhlayeh@9258 2722 +
gokhlayeh@9258 2723 + ++b->in_pos;
gokhlayeh@9258 2724 + ++s->pos;
gokhlayeh@9258 2725 + }
gokhlayeh@9258 2726 +
gokhlayeh@9258 2727 + s->pos = 0;
gokhlayeh@9258 2728 +
gokhlayeh@9258 2729 + return true;
gokhlayeh@9258 2730 +}
gokhlayeh@9258 2731 +#endif
gokhlayeh@9258 2732 +
gokhlayeh@9258 2733 +/* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */
gokhlayeh@9258 2734 +static enum xz_ret dec_stream_header(struct xz_dec *s)
gokhlayeh@9258 2735 +{
gokhlayeh@9258 2736 + if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE))
gokhlayeh@9258 2737 + return XZ_FORMAT_ERROR;
gokhlayeh@9258 2738 +
gokhlayeh@9258 2739 + if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0)
gokhlayeh@9258 2740 + != get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2))
gokhlayeh@9258 2741 + return XZ_DATA_ERROR;
gokhlayeh@9258 2742 +
gokhlayeh@9258 2743 + if (s->temp.buf[HEADER_MAGIC_SIZE] != 0)
gokhlayeh@9258 2744 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2745 +
gokhlayeh@9258 2746 + /*
gokhlayeh@9258 2747 + * Of integrity checks, we support only none (Check ID = 0) and
gokhlayeh@9258 2748 + * CRC32 (Check ID = 1). However, if XZ_DEC_ANY_CHECK is defined,
gokhlayeh@9258 2749 + * we will accept other check types too, but then the check won't
gokhlayeh@9258 2750 + * be verified and a warning (XZ_UNSUPPORTED_CHECK) will be given.
gokhlayeh@9258 2751 + */
gokhlayeh@9258 2752 + s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1];
gokhlayeh@9258 2753 +
gokhlayeh@9258 2754 +#ifdef XZ_DEC_ANY_CHECK
gokhlayeh@9258 2755 + if (s->check_type > XZ_CHECK_MAX)
gokhlayeh@9258 2756 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2757 +
gokhlayeh@9258 2758 + if (s->check_type > XZ_CHECK_CRC32)
gokhlayeh@9258 2759 + return XZ_UNSUPPORTED_CHECK;
gokhlayeh@9258 2760 +#else
gokhlayeh@9258 2761 + if (s->check_type > XZ_CHECK_CRC32)
gokhlayeh@9258 2762 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2763 +#endif
gokhlayeh@9258 2764 +
gokhlayeh@9258 2765 + return XZ_OK;
gokhlayeh@9258 2766 +}
gokhlayeh@9258 2767 +
gokhlayeh@9258 2768 +/* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */
gokhlayeh@9258 2769 +static enum xz_ret dec_stream_footer(struct xz_dec *s)
gokhlayeh@9258 2770 +{
gokhlayeh@9258 2771 + if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE))
gokhlayeh@9258 2772 + return XZ_DATA_ERROR;
gokhlayeh@9258 2773 +
gokhlayeh@9258 2774 + if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf))
gokhlayeh@9258 2775 + return XZ_DATA_ERROR;
gokhlayeh@9258 2776 +
gokhlayeh@9258 2777 + /*
gokhlayeh@9258 2778 + * Validate Backward Size. Note that we never added the size of the
gokhlayeh@9258 2779 + * Index CRC32 field to s->index.size, thus we use s->index.size / 4
gokhlayeh@9258 2780 + * instead of s->index.size / 4 - 1.
gokhlayeh@9258 2781 + */
gokhlayeh@9258 2782 + if ((s->index.size >> 2) != get_le32(s->temp.buf + 4))
gokhlayeh@9258 2783 + return XZ_DATA_ERROR;
gokhlayeh@9258 2784 +
gokhlayeh@9258 2785 + if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type)
gokhlayeh@9258 2786 + return XZ_DATA_ERROR;
gokhlayeh@9258 2787 +
gokhlayeh@9258 2788 + /*
gokhlayeh@9258 2789 + * Use XZ_STREAM_END instead of XZ_OK to be more convenient
gokhlayeh@9258 2790 + * for the caller.
gokhlayeh@9258 2791 + */
gokhlayeh@9258 2792 + return XZ_STREAM_END;
gokhlayeh@9258 2793 +}
gokhlayeh@9258 2794 +
gokhlayeh@9258 2795 +/* Decode the Block Header and initialize the filter chain. */
gokhlayeh@9258 2796 +static enum xz_ret dec_block_header(struct xz_dec *s)
gokhlayeh@9258 2797 +{
gokhlayeh@9258 2798 + enum xz_ret ret;
gokhlayeh@9258 2799 +
gokhlayeh@9258 2800 + /*
gokhlayeh@9258 2801 + * Validate the CRC32. We know that the temp buffer is at least
gokhlayeh@9258 2802 + * eight bytes so this is safe.
gokhlayeh@9258 2803 + */
gokhlayeh@9258 2804 + s->temp.size -= 4;
gokhlayeh@9258 2805 + if (xz_crc32(s->temp.buf, s->temp.size, 0)
gokhlayeh@9258 2806 + != get_le32(s->temp.buf + s->temp.size))
gokhlayeh@9258 2807 + return XZ_DATA_ERROR;
gokhlayeh@9258 2808 +
gokhlayeh@9258 2809 + s->temp.pos = 2;
gokhlayeh@9258 2810 +
gokhlayeh@9258 2811 + /*
gokhlayeh@9258 2812 + * Catch unsupported Block Flags. We support only one or two filters
gokhlayeh@9258 2813 + * in the chain, so we catch that with the same test.
gokhlayeh@9258 2814 + */
gokhlayeh@9258 2815 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 2816 + if (s->temp.buf[1] & 0x3E)
gokhlayeh@9258 2817 +#else
gokhlayeh@9258 2818 + if (s->temp.buf[1] & 0x3F)
gokhlayeh@9258 2819 +#endif
gokhlayeh@9258 2820 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2821 +
gokhlayeh@9258 2822 + /* Compressed Size */
gokhlayeh@9258 2823 + if (s->temp.buf[1] & 0x40) {
gokhlayeh@9258 2824 + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
gokhlayeh@9258 2825 + != XZ_STREAM_END)
gokhlayeh@9258 2826 + return XZ_DATA_ERROR;
gokhlayeh@9258 2827 +
gokhlayeh@9258 2828 + s->block_header.compressed = s->vli;
gokhlayeh@9258 2829 + } else {
gokhlayeh@9258 2830 + s->block_header.compressed = VLI_UNKNOWN;
gokhlayeh@9258 2831 + }
gokhlayeh@9258 2832 +
gokhlayeh@9258 2833 + /* Uncompressed Size */
gokhlayeh@9258 2834 + if (s->temp.buf[1] & 0x80) {
gokhlayeh@9258 2835 + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size)
gokhlayeh@9258 2836 + != XZ_STREAM_END)
gokhlayeh@9258 2837 + return XZ_DATA_ERROR;
gokhlayeh@9258 2838 +
gokhlayeh@9258 2839 + s->block_header.uncompressed = s->vli;
gokhlayeh@9258 2840 + } else {
gokhlayeh@9258 2841 + s->block_header.uncompressed = VLI_UNKNOWN;
gokhlayeh@9258 2842 + }
gokhlayeh@9258 2843 +
gokhlayeh@9258 2844 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 2845 + /* If there are two filters, the first one must be a BCJ filter. */
gokhlayeh@9258 2846 + s->bcj_active = s->temp.buf[1] & 0x01;
gokhlayeh@9258 2847 + if (s->bcj_active) {
gokhlayeh@9258 2848 + if (s->temp.size - s->temp.pos < 2)
gokhlayeh@9258 2849 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2850 +
gokhlayeh@9258 2851 + ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]);
gokhlayeh@9258 2852 + if (ret != XZ_OK)
gokhlayeh@9258 2853 + return ret;
gokhlayeh@9258 2854 +
gokhlayeh@9258 2855 + /*
gokhlayeh@9258 2856 + * We don't support custom start offset,
gokhlayeh@9258 2857 + * so Size of Properties must be zero.
gokhlayeh@9258 2858 + */
gokhlayeh@9258 2859 + if (s->temp.buf[s->temp.pos++] != 0x00)
gokhlayeh@9258 2860 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2861 + }
gokhlayeh@9258 2862 +#endif
gokhlayeh@9258 2863 +
gokhlayeh@9258 2864 + /* Valid Filter Flags always take at least two bytes. */
gokhlayeh@9258 2865 + if (s->temp.size - s->temp.pos < 2)
gokhlayeh@9258 2866 + return XZ_DATA_ERROR;
gokhlayeh@9258 2867 +
gokhlayeh@9258 2868 + /* Filter ID = LZMA2 */
gokhlayeh@9258 2869 + if (s->temp.buf[s->temp.pos++] != 0x21)
gokhlayeh@9258 2870 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2871 +
gokhlayeh@9258 2872 + /* Size of Properties = 1-byte Filter Properties */
gokhlayeh@9258 2873 + if (s->temp.buf[s->temp.pos++] != 0x01)
gokhlayeh@9258 2874 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2875 +
gokhlayeh@9258 2876 + /* Filter Properties contains LZMA2 dictionary size. */
gokhlayeh@9258 2877 + if (s->temp.size - s->temp.pos < 1)
gokhlayeh@9258 2878 + return XZ_DATA_ERROR;
gokhlayeh@9258 2879 +
gokhlayeh@9258 2880 + ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]);
gokhlayeh@9258 2881 + if (ret != XZ_OK)
gokhlayeh@9258 2882 + return ret;
gokhlayeh@9258 2883 +
gokhlayeh@9258 2884 + /* The rest must be Header Padding. */
gokhlayeh@9258 2885 + while (s->temp.pos < s->temp.size)
gokhlayeh@9258 2886 + if (s->temp.buf[s->temp.pos++] != 0x00)
gokhlayeh@9258 2887 + return XZ_OPTIONS_ERROR;
gokhlayeh@9258 2888 +
gokhlayeh@9258 2889 + s->temp.pos = 0;
gokhlayeh@9258 2890 + s->block.compressed = 0;
gokhlayeh@9258 2891 + s->block.uncompressed = 0;
gokhlayeh@9258 2892 +
gokhlayeh@9258 2893 + return XZ_OK;
gokhlayeh@9258 2894 +}
gokhlayeh@9258 2895 +
gokhlayeh@9258 2896 +static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b)
gokhlayeh@9258 2897 +{
gokhlayeh@9258 2898 + enum xz_ret ret;
gokhlayeh@9258 2899 +
gokhlayeh@9258 2900 + /*
gokhlayeh@9258 2901 + * Store the start position for the case when we are in the middle
gokhlayeh@9258 2902 + * of the Index field.
gokhlayeh@9258 2903 + */
gokhlayeh@9258 2904 + s->in_start = b->in_pos;
gokhlayeh@9258 2905 +
gokhlayeh@9258 2906 + while (true) {
gokhlayeh@9258 2907 + switch (s->sequence) {
gokhlayeh@9258 2908 + case SEQ_STREAM_HEADER:
gokhlayeh@9258 2909 + /*
gokhlayeh@9258 2910 + * Stream Header is copied to s->temp, and then
gokhlayeh@9258 2911 + * decoded from there. This way if the caller
gokhlayeh@9258 2912 + * gives us only little input at a time, we can
gokhlayeh@9258 2913 + * still keep the Stream Header decoding code
gokhlayeh@9258 2914 + * simple. Similar approach is used in many places
gokhlayeh@9258 2915 + * in this file.
gokhlayeh@9258 2916 + */
gokhlayeh@9258 2917 + if (!fill_temp(s, b))
gokhlayeh@9258 2918 + return XZ_OK;
gokhlayeh@9258 2919 +
gokhlayeh@9258 2920 + /*
gokhlayeh@9258 2921 + * If dec_stream_header() returns
gokhlayeh@9258 2922 + * XZ_UNSUPPORTED_CHECK, it is still possible
gokhlayeh@9258 2923 + * to continue decoding if working in multi-call
gokhlayeh@9258 2924 + * mode. Thus, update s->sequence before calling
gokhlayeh@9258 2925 + * dec_stream_header().
gokhlayeh@9258 2926 + */
gokhlayeh@9258 2927 + s->sequence = SEQ_BLOCK_START;
gokhlayeh@9258 2928 +
gokhlayeh@9258 2929 + ret = dec_stream_header(s);
gokhlayeh@9258 2930 + if (ret != XZ_OK)
gokhlayeh@9258 2931 + return ret;
gokhlayeh@9258 2932 +
gokhlayeh@9258 2933 + case SEQ_BLOCK_START:
gokhlayeh@9258 2934 + /* We need one byte of input to continue. */
gokhlayeh@9258 2935 + if (b->in_pos == b->in_size)
gokhlayeh@9258 2936 + return XZ_OK;
gokhlayeh@9258 2937 +
gokhlayeh@9258 2938 + /* See if this is the beginning of the Index field. */
gokhlayeh@9258 2939 + if (b->in[b->in_pos] == 0) {
gokhlayeh@9258 2940 + s->in_start = b->in_pos++;
gokhlayeh@9258 2941 + s->sequence = SEQ_INDEX;
gokhlayeh@9258 2942 + break;
gokhlayeh@9258 2943 + }
gokhlayeh@9258 2944 +
gokhlayeh@9258 2945 + /*
gokhlayeh@9258 2946 + * Calculate the size of the Block Header and
gokhlayeh@9258 2947 + * prepare to decode it.
gokhlayeh@9258 2948 + */
gokhlayeh@9258 2949 + s->block_header.size
gokhlayeh@9258 2950 + = ((uint32_t)b->in[b->in_pos] + 1) * 4;
gokhlayeh@9258 2951 +
gokhlayeh@9258 2952 + s->temp.size = s->block_header.size;
gokhlayeh@9258 2953 + s->temp.pos = 0;
gokhlayeh@9258 2954 + s->sequence = SEQ_BLOCK_HEADER;
gokhlayeh@9258 2955 +
gokhlayeh@9258 2956 + case SEQ_BLOCK_HEADER:
gokhlayeh@9258 2957 + if (!fill_temp(s, b))
gokhlayeh@9258 2958 + return XZ_OK;
gokhlayeh@9258 2959 +
gokhlayeh@9258 2960 + ret = dec_block_header(s);
gokhlayeh@9258 2961 + if (ret != XZ_OK)
gokhlayeh@9258 2962 + return ret;
gokhlayeh@9258 2963 +
gokhlayeh@9258 2964 + s->sequence = SEQ_BLOCK_UNCOMPRESS;
gokhlayeh@9258 2965 +
gokhlayeh@9258 2966 + case SEQ_BLOCK_UNCOMPRESS:
gokhlayeh@9258 2967 + ret = dec_block(s, b);
gokhlayeh@9258 2968 + if (ret != XZ_STREAM_END)
gokhlayeh@9258 2969 + return ret;
gokhlayeh@9258 2970 +
gokhlayeh@9258 2971 + s->sequence = SEQ_BLOCK_PADDING;
gokhlayeh@9258 2972 +
gokhlayeh@9258 2973 + case SEQ_BLOCK_PADDING:
gokhlayeh@9258 2974 + /*
gokhlayeh@9258 2975 + * Size of Compressed Data + Block Padding
gokhlayeh@9258 2976 + * must be a multiple of four. We don't need
gokhlayeh@9258 2977 + * s->block.compressed for anything else
gokhlayeh@9258 2978 + * anymore, so we use it here to test the size
gokhlayeh@9258 2979 + * of the Block Padding field.
gokhlayeh@9258 2980 + */
gokhlayeh@9258 2981 + while (s->block.compressed & 3) {
gokhlayeh@9258 2982 + if (b->in_pos == b->in_size)
gokhlayeh@9258 2983 + return XZ_OK;
gokhlayeh@9258 2984 +
gokhlayeh@9258 2985 + if (b->in[b->in_pos++] != 0)
gokhlayeh@9258 2986 + return XZ_DATA_ERROR;
gokhlayeh@9258 2987 +
gokhlayeh@9258 2988 + ++s->block.compressed;
gokhlayeh@9258 2989 + }
gokhlayeh@9258 2990 +
gokhlayeh@9258 2991 + s->sequence = SEQ_BLOCK_CHECK;
gokhlayeh@9258 2992 +
gokhlayeh@9258 2993 + case SEQ_BLOCK_CHECK:
gokhlayeh@9258 2994 + if (s->check_type == XZ_CHECK_CRC32) {
gokhlayeh@9258 2995 + ret = crc32_validate(s, b);
gokhlayeh@9258 2996 + if (ret != XZ_STREAM_END)
gokhlayeh@9258 2997 + return ret;
gokhlayeh@9258 2998 + }
gokhlayeh@9258 2999 +#ifdef XZ_DEC_ANY_CHECK
gokhlayeh@9258 3000 + else if (!check_skip(s, b)) {
gokhlayeh@9258 3001 + return XZ_OK;
gokhlayeh@9258 3002 + }
gokhlayeh@9258 3003 +#endif
gokhlayeh@9258 3004 +
gokhlayeh@9258 3005 + s->sequence = SEQ_BLOCK_START;
gokhlayeh@9258 3006 + break;
gokhlayeh@9258 3007 +
gokhlayeh@9258 3008 + case SEQ_INDEX:
gokhlayeh@9258 3009 + ret = dec_index(s, b);
gokhlayeh@9258 3010 + if (ret != XZ_STREAM_END)
gokhlayeh@9258 3011 + return ret;
gokhlayeh@9258 3012 +
gokhlayeh@9258 3013 + s->sequence = SEQ_INDEX_PADDING;
gokhlayeh@9258 3014 +
gokhlayeh@9258 3015 + case SEQ_INDEX_PADDING:
gokhlayeh@9258 3016 + while ((s->index.size + (b->in_pos - s->in_start))
gokhlayeh@9258 3017 + & 3) {
gokhlayeh@9258 3018 + if (b->in_pos == b->in_size) {
gokhlayeh@9258 3019 + index_update(s, b);
gokhlayeh@9258 3020 + return XZ_OK;
gokhlayeh@9258 3021 + }
gokhlayeh@9258 3022 +
gokhlayeh@9258 3023 + if (b->in[b->in_pos++] != 0)
gokhlayeh@9258 3024 + return XZ_DATA_ERROR;
gokhlayeh@9258 3025 + }
gokhlayeh@9258 3026 +
gokhlayeh@9258 3027 + /* Finish the CRC32 value and Index size. */
gokhlayeh@9258 3028 + index_update(s, b);
gokhlayeh@9258 3029 +
gokhlayeh@9258 3030 + /* Compare the hashes to validate the Index field. */
gokhlayeh@9258 3031 + if (!memeq(&s->block.hash, &s->index.hash,
gokhlayeh@9258 3032 + sizeof(s->block.hash)))
gokhlayeh@9258 3033 + return XZ_DATA_ERROR;
gokhlayeh@9258 3034 +
gokhlayeh@9258 3035 + s->sequence = SEQ_INDEX_CRC32;
gokhlayeh@9258 3036 +
gokhlayeh@9258 3037 + case SEQ_INDEX_CRC32:
gokhlayeh@9258 3038 + ret = crc32_validate(s, b);
gokhlayeh@9258 3039 + if (ret != XZ_STREAM_END)
gokhlayeh@9258 3040 + return ret;
gokhlayeh@9258 3041 +
gokhlayeh@9258 3042 + s->temp.size = STREAM_HEADER_SIZE;
gokhlayeh@9258 3043 + s->sequence = SEQ_STREAM_FOOTER;
gokhlayeh@9258 3044 +
gokhlayeh@9258 3045 + case SEQ_STREAM_FOOTER:
gokhlayeh@9258 3046 + if (!fill_temp(s, b))
gokhlayeh@9258 3047 + return XZ_OK;
gokhlayeh@9258 3048 +
gokhlayeh@9258 3049 + return dec_stream_footer(s);
gokhlayeh@9258 3050 + }
gokhlayeh@9258 3051 + }
gokhlayeh@9258 3052 +
gokhlayeh@9258 3053 + /* Never reached */
gokhlayeh@9258 3054 +}
gokhlayeh@9258 3055 +
gokhlayeh@9258 3056 +/*
gokhlayeh@9258 3057 + * xz_dec_run() is a wrapper for dec_main() to handle some special cases in
gokhlayeh@9258 3058 + * multi-call and single-call decoding.
gokhlayeh@9258 3059 + *
gokhlayeh@9258 3060 + * In multi-call mode, we must return XZ_BUF_ERROR when it seems clear that we
gokhlayeh@9258 3061 + * are not going to make any progress anymore. This is to prevent the caller
gokhlayeh@9258 3062 + * from calling us infinitely when the input file is truncated or otherwise
gokhlayeh@9258 3063 + * corrupt. Since zlib-style API allows that the caller fills the input buffer
gokhlayeh@9258 3064 + * only when the decoder doesn't produce any new output, we have to be careful
gokhlayeh@9258 3065 + * to avoid returning XZ_BUF_ERROR too easily: XZ_BUF_ERROR is returned only
gokhlayeh@9258 3066 + * after the second consecutive call to xz_dec_run() that makes no progress.
gokhlayeh@9258 3067 + *
gokhlayeh@9258 3068 + * In single-call mode, if we couldn't decode everything and no error
gokhlayeh@9258 3069 + * occurred, either the input is truncated or the output buffer is too small.
gokhlayeh@9258 3070 + * Since we know that the last input byte never produces any output, we know
gokhlayeh@9258 3071 + * that if all the input was consumed and decoding wasn't finished, the file
gokhlayeh@9258 3072 + * must be corrupt. Otherwise the output buffer has to be too small or the
gokhlayeh@9258 3073 + * file is corrupt in a way that decoding it produces too big output.
gokhlayeh@9258 3074 + *
gokhlayeh@9258 3075 + * If single-call decoding fails, we reset b->in_pos and b->out_pos back to
gokhlayeh@9258 3076 + * their original values. This is because with some filter chains there won't
gokhlayeh@9258 3077 + * be any valid uncompressed data in the output buffer unless the decoding
gokhlayeh@9258 3078 + * actually succeeds (that's the price to pay of using the output buffer as
gokhlayeh@9258 3079 + * the workspace).
gokhlayeh@9258 3080 + */
gokhlayeh@9258 3081 +XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b)
gokhlayeh@9258 3082 +{
gokhlayeh@9258 3083 + size_t in_start;
gokhlayeh@9258 3084 + size_t out_start;
gokhlayeh@9258 3085 + enum xz_ret ret;
gokhlayeh@9258 3086 +
gokhlayeh@9258 3087 + if (DEC_IS_SINGLE(s->mode))
gokhlayeh@9258 3088 + xz_dec_reset(s);
gokhlayeh@9258 3089 +
gokhlayeh@9258 3090 + in_start = b->in_pos;
gokhlayeh@9258 3091 + out_start = b->out_pos;
gokhlayeh@9258 3092 + ret = dec_main(s, b);
gokhlayeh@9258 3093 +
gokhlayeh@9258 3094 + if (DEC_IS_SINGLE(s->mode)) {
gokhlayeh@9258 3095 + if (ret == XZ_OK)
gokhlayeh@9258 3096 + ret = b->in_pos == b->in_size
gokhlayeh@9258 3097 + ? XZ_DATA_ERROR : XZ_BUF_ERROR;
gokhlayeh@9258 3098 +
gokhlayeh@9258 3099 + if (ret != XZ_STREAM_END) {
gokhlayeh@9258 3100 + b->in_pos = in_start;
gokhlayeh@9258 3101 + b->out_pos = out_start;
gokhlayeh@9258 3102 + }
gokhlayeh@9258 3103 +
gokhlayeh@9258 3104 + } else if (ret == XZ_OK && in_start == b->in_pos
gokhlayeh@9258 3105 + && out_start == b->out_pos) {
gokhlayeh@9258 3106 + if (s->allow_buf_error)
gokhlayeh@9258 3107 + ret = XZ_BUF_ERROR;
gokhlayeh@9258 3108 +
gokhlayeh@9258 3109 + s->allow_buf_error = true;
gokhlayeh@9258 3110 + } else {
gokhlayeh@9258 3111 + s->allow_buf_error = false;
gokhlayeh@9258 3112 + }
gokhlayeh@9258 3113 +
gokhlayeh@9258 3114 + return ret;
gokhlayeh@9258 3115 +}
gokhlayeh@9258 3116 +
gokhlayeh@9258 3117 +XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max)
gokhlayeh@9258 3118 +{
gokhlayeh@9258 3119 + struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL);
gokhlayeh@9258 3120 + if (s == NULL)
gokhlayeh@9258 3121 + return NULL;
gokhlayeh@9258 3122 +
gokhlayeh@9258 3123 + s->mode = mode;
gokhlayeh@9258 3124 +
gokhlayeh@9258 3125 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 3126 + s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode));
gokhlayeh@9258 3127 + if (s->bcj == NULL)
gokhlayeh@9258 3128 + goto error_bcj;
gokhlayeh@9258 3129 +#endif
gokhlayeh@9258 3130 +
gokhlayeh@9258 3131 + s->lzma2 = xz_dec_lzma2_create(mode, dict_max);
gokhlayeh@9258 3132 + if (s->lzma2 == NULL)
gokhlayeh@9258 3133 + goto error_lzma2;
gokhlayeh@9258 3134 +
gokhlayeh@9258 3135 + xz_dec_reset(s);
gokhlayeh@9258 3136 + return s;
gokhlayeh@9258 3137 +
gokhlayeh@9258 3138 +error_lzma2:
gokhlayeh@9258 3139 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 3140 + xz_dec_bcj_end(s->bcj);
gokhlayeh@9258 3141 +error_bcj:
gokhlayeh@9258 3142 +#endif
gokhlayeh@9258 3143 + kfree(s);
gokhlayeh@9258 3144 + return NULL;
gokhlayeh@9258 3145 +}
gokhlayeh@9258 3146 +
gokhlayeh@9258 3147 +XZ_EXTERN void xz_dec_reset(struct xz_dec *s)
gokhlayeh@9258 3148 +{
gokhlayeh@9258 3149 + s->sequence = SEQ_STREAM_HEADER;
gokhlayeh@9258 3150 + s->allow_buf_error = false;
gokhlayeh@9258 3151 + s->pos = 0;
gokhlayeh@9258 3152 + s->crc32 = 0;
gokhlayeh@9258 3153 + memzero(&s->block, sizeof(s->block));
gokhlayeh@9258 3154 + memzero(&s->index, sizeof(s->index));
gokhlayeh@9258 3155 + s->temp.pos = 0;
gokhlayeh@9258 3156 + s->temp.size = STREAM_HEADER_SIZE;
gokhlayeh@9258 3157 +}
gokhlayeh@9258 3158 +
gokhlayeh@9258 3159 +XZ_EXTERN void xz_dec_end(struct xz_dec *s)
gokhlayeh@9258 3160 +{
gokhlayeh@9258 3161 + if (s != NULL) {
gokhlayeh@9258 3162 + xz_dec_lzma2_end(s->lzma2);
gokhlayeh@9258 3163 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 3164 + xz_dec_bcj_end(s->bcj);
gokhlayeh@9258 3165 +#endif
gokhlayeh@9258 3166 + kfree(s);
gokhlayeh@9258 3167 + }
gokhlayeh@9258 3168 +}
gokhlayeh@9258 3169 diff --git a/lib/xz/xz_dec_syms.c b/lib/xz/xz_dec_syms.c
gokhlayeh@9258 3170 new file mode 100644
gokhlayeh@9258 3171 index 0000000..32eb3c0
gokhlayeh@9258 3172 --- /dev/null
gokhlayeh@9258 3173 +++ b/lib/xz/xz_dec_syms.c
gokhlayeh@9258 3174 @@ -0,0 +1,26 @@
gokhlayeh@9258 3175 +/*
gokhlayeh@9258 3176 + * XZ decoder module information
gokhlayeh@9258 3177 + *
gokhlayeh@9258 3178 + * Author: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 3179 + *
gokhlayeh@9258 3180 + * This file has been put into the public domain.
gokhlayeh@9258 3181 + * You can do whatever you want with this file.
gokhlayeh@9258 3182 + */
gokhlayeh@9258 3183 +
gokhlayeh@9258 3184 +#include <linux/module.h>
gokhlayeh@9258 3185 +#include <linux/xz.h>
gokhlayeh@9258 3186 +
gokhlayeh@9258 3187 +EXPORT_SYMBOL(xz_dec_init);
gokhlayeh@9258 3188 +EXPORT_SYMBOL(xz_dec_reset);
gokhlayeh@9258 3189 +EXPORT_SYMBOL(xz_dec_run);
gokhlayeh@9258 3190 +EXPORT_SYMBOL(xz_dec_end);
gokhlayeh@9258 3191 +
gokhlayeh@9258 3192 +MODULE_DESCRIPTION("XZ decompressor");
gokhlayeh@9258 3193 +MODULE_VERSION("1.0");
gokhlayeh@9258 3194 +MODULE_AUTHOR("Lasse Collin <lasse.collin@tukaani.org> and Igor Pavlov");
gokhlayeh@9258 3195 +
gokhlayeh@9258 3196 +/*
gokhlayeh@9258 3197 + * This code is in the public domain, but in Linux it's simplest to just
gokhlayeh@9258 3198 + * say it's GPL and consider the authors as the copyright holders.
gokhlayeh@9258 3199 + */
gokhlayeh@9258 3200 +MODULE_LICENSE("GPL");
gokhlayeh@9258 3201 diff --git a/lib/xz/xz_dec_test.c b/lib/xz/xz_dec_test.c
gokhlayeh@9258 3202 new file mode 100644
gokhlayeh@9258 3203 index 0000000..da28a19
gokhlayeh@9258 3204 --- /dev/null
gokhlayeh@9258 3205 +++ b/lib/xz/xz_dec_test.c
gokhlayeh@9258 3206 @@ -0,0 +1,220 @@
gokhlayeh@9258 3207 +/*
gokhlayeh@9258 3208 + * XZ decoder tester
gokhlayeh@9258 3209 + *
gokhlayeh@9258 3210 + * Author: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 3211 + *
gokhlayeh@9258 3212 + * This file has been put into the public domain.
gokhlayeh@9258 3213 + * You can do whatever you want with this file.
gokhlayeh@9258 3214 + */
gokhlayeh@9258 3215 +
gokhlayeh@9258 3216 +#include <linux/kernel.h>
gokhlayeh@9258 3217 +#include <linux/module.h>
gokhlayeh@9258 3218 +#include <linux/fs.h>
gokhlayeh@9258 3219 +#include <linux/uaccess.h>
gokhlayeh@9258 3220 +#include <linux/crc32.h>
gokhlayeh@9258 3221 +#include <linux/xz.h>
gokhlayeh@9258 3222 +
gokhlayeh@9258 3223 +/* Maximum supported dictionary size */
gokhlayeh@9258 3224 +#define DICT_MAX (1 << 20)
gokhlayeh@9258 3225 +
gokhlayeh@9258 3226 +/* Device name to pass to register_chrdev(). */
gokhlayeh@9258 3227 +#define DEVICE_NAME "xz_dec_test"
gokhlayeh@9258 3228 +
gokhlayeh@9258 3229 +/* Dynamically allocated device major number */
gokhlayeh@9258 3230 +static int device_major;
gokhlayeh@9258 3231 +
gokhlayeh@9258 3232 +/*
gokhlayeh@9258 3233 + * We reuse the same decoder state, and thus can decode only one
gokhlayeh@9258 3234 + * file at a time.
gokhlayeh@9258 3235 + */
gokhlayeh@9258 3236 +static bool device_is_open;
gokhlayeh@9258 3237 +
gokhlayeh@9258 3238 +/* XZ decoder state */
gokhlayeh@9258 3239 +static struct xz_dec *state;
gokhlayeh@9258 3240 +
gokhlayeh@9258 3241 +/*
gokhlayeh@9258 3242 + * Return value of xz_dec_run(). We need to avoid calling xz_dec_run() after
gokhlayeh@9258 3243 + * it has returned XZ_STREAM_END, so we make this static.
gokhlayeh@9258 3244 + */
gokhlayeh@9258 3245 +static enum xz_ret ret;
gokhlayeh@9258 3246 +
gokhlayeh@9258 3247 +/*
gokhlayeh@9258 3248 + * Input and output buffers. The input buffer is used as a temporary safe
gokhlayeh@9258 3249 + * place for the data coming from the userspace.
gokhlayeh@9258 3250 + */
gokhlayeh@9258 3251 +static uint8_t buffer_in[1024];
gokhlayeh@9258 3252 +static uint8_t buffer_out[1024];
gokhlayeh@9258 3253 +
gokhlayeh@9258 3254 +/*
gokhlayeh@9258 3255 + * Structure to pass the input and output buffers to the XZ decoder.
gokhlayeh@9258 3256 + * A few of the fields are never modified so we initialize them here.
gokhlayeh@9258 3257 + */
gokhlayeh@9258 3258 +static struct xz_buf buffers = {
gokhlayeh@9258 3259 + .in = buffer_in,
gokhlayeh@9258 3260 + .out = buffer_out,
gokhlayeh@9258 3261 + .out_size = sizeof(buffer_out)
gokhlayeh@9258 3262 +};
gokhlayeh@9258 3263 +
gokhlayeh@9258 3264 +/*
gokhlayeh@9258 3265 + * CRC32 of uncompressed data. This is used to give the user a simple way
gokhlayeh@9258 3266 + * to check that the decoder produces correct output.
gokhlayeh@9258 3267 + */
gokhlayeh@9258 3268 +static uint32_t crc;
gokhlayeh@9258 3269 +
gokhlayeh@9258 3270 +static int xz_dec_test_open(struct inode *i, struct file *f)
gokhlayeh@9258 3271 +{
gokhlayeh@9258 3272 + if (device_is_open)
gokhlayeh@9258 3273 + return -EBUSY;
gokhlayeh@9258 3274 +
gokhlayeh@9258 3275 + device_is_open = true;
gokhlayeh@9258 3276 +
gokhlayeh@9258 3277 + xz_dec_reset(state);
gokhlayeh@9258 3278 + ret = XZ_OK;
gokhlayeh@9258 3279 + crc = 0xFFFFFFFF;
gokhlayeh@9258 3280 +
gokhlayeh@9258 3281 + buffers.in_pos = 0;
gokhlayeh@9258 3282 + buffers.in_size = 0;
gokhlayeh@9258 3283 + buffers.out_pos = 0;
gokhlayeh@9258 3284 +
gokhlayeh@9258 3285 + printk(KERN_INFO DEVICE_NAME ": opened\n");
gokhlayeh@9258 3286 + return 0;
gokhlayeh@9258 3287 +}
gokhlayeh@9258 3288 +
gokhlayeh@9258 3289 +static int xz_dec_test_release(struct inode *i, struct file *f)
gokhlayeh@9258 3290 +{
gokhlayeh@9258 3291 + device_is_open = false;
gokhlayeh@9258 3292 +
gokhlayeh@9258 3293 + if (ret == XZ_OK)
gokhlayeh@9258 3294 + printk(KERN_INFO DEVICE_NAME ": input was truncated\n");
gokhlayeh@9258 3295 +
gokhlayeh@9258 3296 + printk(KERN_INFO DEVICE_NAME ": closed\n");
gokhlayeh@9258 3297 + return 0;
gokhlayeh@9258 3298 +}
gokhlayeh@9258 3299 +
gokhlayeh@9258 3300 +/*
gokhlayeh@9258 3301 + * Decode the data given to us from the userspace. CRC32 of the uncompressed
gokhlayeh@9258 3302 + * data is calculated and is printed at the end of successful decoding. The
gokhlayeh@9258 3303 + * uncompressed data isn't stored anywhere for further use.
gokhlayeh@9258 3304 + *
gokhlayeh@9258 3305 + * The .xz file must have exactly one Stream and no Stream Padding. The data
gokhlayeh@9258 3306 + * after the first Stream is considered to be garbage.
gokhlayeh@9258 3307 + */
gokhlayeh@9258 3308 +static ssize_t xz_dec_test_write(struct file *file, const char __user *buf,
gokhlayeh@9258 3309 + size_t size, loff_t *pos)
gokhlayeh@9258 3310 +{
gokhlayeh@9258 3311 + size_t remaining;
gokhlayeh@9258 3312 +
gokhlayeh@9258 3313 + if (ret != XZ_OK) {
gokhlayeh@9258 3314 + if (size > 0)
gokhlayeh@9258 3315 + printk(KERN_INFO DEVICE_NAME ": %zu bytes of "
gokhlayeh@9258 3316 + "garbage at the end of the file\n",
gokhlayeh@9258 3317 + size);
gokhlayeh@9258 3318 +
gokhlayeh@9258 3319 + return -ENOSPC;
gokhlayeh@9258 3320 + }
gokhlayeh@9258 3321 +
gokhlayeh@9258 3322 + printk(KERN_INFO DEVICE_NAME ": decoding %zu bytes of input\n",
gokhlayeh@9258 3323 + size);
gokhlayeh@9258 3324 +
gokhlayeh@9258 3325 + remaining = size;
gokhlayeh@9258 3326 + while ((remaining > 0 || buffers.out_pos == buffers.out_size)
gokhlayeh@9258 3327 + && ret == XZ_OK) {
gokhlayeh@9258 3328 + if (buffers.in_pos == buffers.in_size) {
gokhlayeh@9258 3329 + buffers.in_pos = 0;
gokhlayeh@9258 3330 + buffers.in_size = min(remaining, sizeof(buffer_in));
gokhlayeh@9258 3331 + if (copy_from_user(buffer_in, buf, buffers.in_size))
gokhlayeh@9258 3332 + return -EFAULT;
gokhlayeh@9258 3333 +
gokhlayeh@9258 3334 + buf += buffers.in_size;
gokhlayeh@9258 3335 + remaining -= buffers.in_size;
gokhlayeh@9258 3336 + }
gokhlayeh@9258 3337 +
gokhlayeh@9258 3338 + buffers.out_pos = 0;
gokhlayeh@9258 3339 + ret = xz_dec_run(state, &buffers);
gokhlayeh@9258 3340 + crc = crc32(crc, buffer_out, buffers.out_pos);
gokhlayeh@9258 3341 + }
gokhlayeh@9258 3342 +
gokhlayeh@9258 3343 + switch (ret) {
gokhlayeh@9258 3344 + case XZ_OK:
gokhlayeh@9258 3345 + printk(KERN_INFO DEVICE_NAME ": XZ_OK\n");
gokhlayeh@9258 3346 + return size;
gokhlayeh@9258 3347 +
gokhlayeh@9258 3348 + case XZ_STREAM_END:
gokhlayeh@9258 3349 + printk(KERN_INFO DEVICE_NAME ": XZ_STREAM_END, "
gokhlayeh@9258 3350 + "CRC32 = 0x%08X\n", ~crc);
gokhlayeh@9258 3351 + return size - remaining - (buffers.in_size - buffers.in_pos);
gokhlayeh@9258 3352 +
gokhlayeh@9258 3353 + case XZ_MEMLIMIT_ERROR:
gokhlayeh@9258 3354 + printk(KERN_INFO DEVICE_NAME ": XZ_MEMLIMIT_ERROR\n");
gokhlayeh@9258 3355 + break;
gokhlayeh@9258 3356 +
gokhlayeh@9258 3357 + case XZ_FORMAT_ERROR:
gokhlayeh@9258 3358 + printk(KERN_INFO DEVICE_NAME ": XZ_FORMAT_ERROR\n");
gokhlayeh@9258 3359 + break;
gokhlayeh@9258 3360 +
gokhlayeh@9258 3361 + case XZ_OPTIONS_ERROR:
gokhlayeh@9258 3362 + printk(KERN_INFO DEVICE_NAME ": XZ_OPTIONS_ERROR\n");
gokhlayeh@9258 3363 + break;
gokhlayeh@9258 3364 +
gokhlayeh@9258 3365 + case XZ_DATA_ERROR:
gokhlayeh@9258 3366 + printk(KERN_INFO DEVICE_NAME ": XZ_DATA_ERROR\n");
gokhlayeh@9258 3367 + break;
gokhlayeh@9258 3368 +
gokhlayeh@9258 3369 + case XZ_BUF_ERROR:
gokhlayeh@9258 3370 + printk(KERN_INFO DEVICE_NAME ": XZ_BUF_ERROR\n");
gokhlayeh@9258 3371 + break;
gokhlayeh@9258 3372 +
gokhlayeh@9258 3373 + default:
gokhlayeh@9258 3374 + printk(KERN_INFO DEVICE_NAME ": Bug detected!\n");
gokhlayeh@9258 3375 + break;
gokhlayeh@9258 3376 + }
gokhlayeh@9258 3377 +
gokhlayeh@9258 3378 + return -EIO;
gokhlayeh@9258 3379 +}
gokhlayeh@9258 3380 +
gokhlayeh@9258 3381 +/* Allocate the XZ decoder state and register the character device. */
gokhlayeh@9258 3382 +static int __init xz_dec_test_init(void)
gokhlayeh@9258 3383 +{
gokhlayeh@9258 3384 + static const struct file_operations fileops = {
gokhlayeh@9258 3385 + .owner = THIS_MODULE,
gokhlayeh@9258 3386 + .open = &xz_dec_test_open,
gokhlayeh@9258 3387 + .release = &xz_dec_test_release,
gokhlayeh@9258 3388 + .write = &xz_dec_test_write
gokhlayeh@9258 3389 + };
gokhlayeh@9258 3390 +
gokhlayeh@9258 3391 + state = xz_dec_init(XZ_PREALLOC, DICT_MAX);
gokhlayeh@9258 3392 + if (state == NULL)
gokhlayeh@9258 3393 + return -ENOMEM;
gokhlayeh@9258 3394 +
gokhlayeh@9258 3395 + device_major = register_chrdev(0, DEVICE_NAME, &fileops);
gokhlayeh@9258 3396 + if (device_major < 0) {
gokhlayeh@9258 3397 + xz_dec_end(state);
gokhlayeh@9258 3398 + return device_major;
gokhlayeh@9258 3399 + }
gokhlayeh@9258 3400 +
gokhlayeh@9258 3401 + printk(KERN_INFO DEVICE_NAME ": module loaded\n");
gokhlayeh@9258 3402 + printk(KERN_INFO DEVICE_NAME ": Create a device node with "
gokhlayeh@9258 3403 + "'mknod " DEVICE_NAME " c %d 0' and write .xz files "
gokhlayeh@9258 3404 + "to it.\n", device_major);
gokhlayeh@9258 3405 + return 0;
gokhlayeh@9258 3406 +}
gokhlayeh@9258 3407 +
gokhlayeh@9258 3408 +static void __exit xz_dec_test_exit(void)
gokhlayeh@9258 3409 +{
gokhlayeh@9258 3410 + unregister_chrdev(device_major, DEVICE_NAME);
gokhlayeh@9258 3411 + xz_dec_end(state);
gokhlayeh@9258 3412 + printk(KERN_INFO DEVICE_NAME ": module unloaded\n");
gokhlayeh@9258 3413 +}
gokhlayeh@9258 3414 +
gokhlayeh@9258 3415 +module_init(xz_dec_test_init);
gokhlayeh@9258 3416 +module_exit(xz_dec_test_exit);
gokhlayeh@9258 3417 +
gokhlayeh@9258 3418 +MODULE_DESCRIPTION("XZ decompressor tester");
gokhlayeh@9258 3419 +MODULE_VERSION("1.0");
gokhlayeh@9258 3420 +MODULE_AUTHOR("Lasse Collin <lasse.collin@tukaani.org>");
gokhlayeh@9258 3421 +
gokhlayeh@9258 3422 +/*
gokhlayeh@9258 3423 + * This code is in the public domain, but in Linux it's simplest to just
gokhlayeh@9258 3424 + * say it's GPL and consider the authors as the copyright holders.
gokhlayeh@9258 3425 + */
gokhlayeh@9258 3426 +MODULE_LICENSE("GPL");
gokhlayeh@9258 3427 diff --git a/lib/xz/xz_lzma2.h b/lib/xz/xz_lzma2.h
gokhlayeh@9258 3428 new file mode 100644
gokhlayeh@9258 3429 index 0000000..071d67b
gokhlayeh@9258 3430 --- /dev/null
gokhlayeh@9258 3431 +++ b/lib/xz/xz_lzma2.h
gokhlayeh@9258 3432 @@ -0,0 +1,204 @@
gokhlayeh@9258 3433 +/*
gokhlayeh@9258 3434 + * LZMA2 definitions
gokhlayeh@9258 3435 + *
gokhlayeh@9258 3436 + * Authors: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 3437 + * Igor Pavlov <http://7-zip.org/>
gokhlayeh@9258 3438 + *
gokhlayeh@9258 3439 + * This file has been put into the public domain.
gokhlayeh@9258 3440 + * You can do whatever you want with this file.
gokhlayeh@9258 3441 + */
gokhlayeh@9258 3442 +
gokhlayeh@9258 3443 +#ifndef XZ_LZMA2_H
gokhlayeh@9258 3444 +#define XZ_LZMA2_H
gokhlayeh@9258 3445 +
gokhlayeh@9258 3446 +/* Range coder constants */
gokhlayeh@9258 3447 +#define RC_SHIFT_BITS 8
gokhlayeh@9258 3448 +#define RC_TOP_BITS 24
gokhlayeh@9258 3449 +#define RC_TOP_VALUE (1 << RC_TOP_BITS)
gokhlayeh@9258 3450 +#define RC_BIT_MODEL_TOTAL_BITS 11
gokhlayeh@9258 3451 +#define RC_BIT_MODEL_TOTAL (1 << RC_BIT_MODEL_TOTAL_BITS)
gokhlayeh@9258 3452 +#define RC_MOVE_BITS 5
gokhlayeh@9258 3453 +
gokhlayeh@9258 3454 +/*
gokhlayeh@9258 3455 + * Maximum number of position states. A position state is the lowest pb
gokhlayeh@9258 3456 + * number of bits of the current uncompressed offset. In some places there
gokhlayeh@9258 3457 + * are different sets of probabilities for different position states.
gokhlayeh@9258 3458 + */
gokhlayeh@9258 3459 +#define POS_STATES_MAX (1 << 4)
gokhlayeh@9258 3460 +
gokhlayeh@9258 3461 +/*
gokhlayeh@9258 3462 + * This enum is used to track which LZMA symbols have occurred most recently
gokhlayeh@9258 3463 + * and in which order. This information is used to predict the next symbol.
gokhlayeh@9258 3464 + *
gokhlayeh@9258 3465 + * Symbols:
gokhlayeh@9258 3466 + * - Literal: One 8-bit byte
gokhlayeh@9258 3467 + * - Match: Repeat a chunk of data at some distance
gokhlayeh@9258 3468 + * - Long repeat: Multi-byte match at a recently seen distance
gokhlayeh@9258 3469 + * - Short repeat: One-byte repeat at a recently seen distance
gokhlayeh@9258 3470 + *
gokhlayeh@9258 3471 + * The symbol names are in from STATE_oldest_older_previous. REP means
gokhlayeh@9258 3472 + * either short or long repeated match, and NONLIT means any non-literal.
gokhlayeh@9258 3473 + */
gokhlayeh@9258 3474 +enum lzma_state {
gokhlayeh@9258 3475 + STATE_LIT_LIT,
gokhlayeh@9258 3476 + STATE_MATCH_LIT_LIT,
gokhlayeh@9258 3477 + STATE_REP_LIT_LIT,
gokhlayeh@9258 3478 + STATE_SHORTREP_LIT_LIT,
gokhlayeh@9258 3479 + STATE_MATCH_LIT,
gokhlayeh@9258 3480 + STATE_REP_LIT,
gokhlayeh@9258 3481 + STATE_SHORTREP_LIT,
gokhlayeh@9258 3482 + STATE_LIT_MATCH,
gokhlayeh@9258 3483 + STATE_LIT_LONGREP,
gokhlayeh@9258 3484 + STATE_LIT_SHORTREP,
gokhlayeh@9258 3485 + STATE_NONLIT_MATCH,
gokhlayeh@9258 3486 + STATE_NONLIT_REP
gokhlayeh@9258 3487 +};
gokhlayeh@9258 3488 +
gokhlayeh@9258 3489 +/* Total number of states */
gokhlayeh@9258 3490 +#define STATES 12
gokhlayeh@9258 3491 +
gokhlayeh@9258 3492 +/* The lowest 7 states indicate that the previous state was a literal. */
gokhlayeh@9258 3493 +#define LIT_STATES 7
gokhlayeh@9258 3494 +
gokhlayeh@9258 3495 +/* Indicate that the latest symbol was a literal. */
gokhlayeh@9258 3496 +static inline void lzma_state_literal(enum lzma_state *state)
gokhlayeh@9258 3497 +{
gokhlayeh@9258 3498 + if (*state <= STATE_SHORTREP_LIT_LIT)
gokhlayeh@9258 3499 + *state = STATE_LIT_LIT;
gokhlayeh@9258 3500 + else if (*state <= STATE_LIT_SHORTREP)
gokhlayeh@9258 3501 + *state -= 3;
gokhlayeh@9258 3502 + else
gokhlayeh@9258 3503 + *state -= 6;
gokhlayeh@9258 3504 +}
gokhlayeh@9258 3505 +
gokhlayeh@9258 3506 +/* Indicate that the latest symbol was a match. */
gokhlayeh@9258 3507 +static inline void lzma_state_match(enum lzma_state *state)
gokhlayeh@9258 3508 +{
gokhlayeh@9258 3509 + *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH;
gokhlayeh@9258 3510 +}
gokhlayeh@9258 3511 +
gokhlayeh@9258 3512 +/* Indicate that the latest state was a long repeated match. */
gokhlayeh@9258 3513 +static inline void lzma_state_long_rep(enum lzma_state *state)
gokhlayeh@9258 3514 +{
gokhlayeh@9258 3515 + *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP;
gokhlayeh@9258 3516 +}
gokhlayeh@9258 3517 +
gokhlayeh@9258 3518 +/* Indicate that the latest symbol was a short match. */
gokhlayeh@9258 3519 +static inline void lzma_state_short_rep(enum lzma_state *state)
gokhlayeh@9258 3520 +{
gokhlayeh@9258 3521 + *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP;
gokhlayeh@9258 3522 +}
gokhlayeh@9258 3523 +
gokhlayeh@9258 3524 +/* Test if the previous symbol was a literal. */
gokhlayeh@9258 3525 +static inline bool lzma_state_is_literal(enum lzma_state state)
gokhlayeh@9258 3526 +{
gokhlayeh@9258 3527 + return state < LIT_STATES;
gokhlayeh@9258 3528 +}
gokhlayeh@9258 3529 +
gokhlayeh@9258 3530 +/* Each literal coder is divided in three sections:
gokhlayeh@9258 3531 + * - 0x001-0x0FF: Without match byte
gokhlayeh@9258 3532 + * - 0x101-0x1FF: With match byte; match bit is 0
gokhlayeh@9258 3533 + * - 0x201-0x2FF: With match byte; match bit is 1
gokhlayeh@9258 3534 + *
gokhlayeh@9258 3535 + * Match byte is used when the previous LZMA symbol was something else than
gokhlayeh@9258 3536 + * a literal (that is, it was some kind of match).
gokhlayeh@9258 3537 + */
gokhlayeh@9258 3538 +#define LITERAL_CODER_SIZE 0x300
gokhlayeh@9258 3539 +
gokhlayeh@9258 3540 +/* Maximum number of literal coders */
gokhlayeh@9258 3541 +#define LITERAL_CODERS_MAX (1 << 4)
gokhlayeh@9258 3542 +
gokhlayeh@9258 3543 +/* Minimum length of a match is two bytes. */
gokhlayeh@9258 3544 +#define MATCH_LEN_MIN 2
gokhlayeh@9258 3545 +
gokhlayeh@9258 3546 +/* Match length is encoded with 4, 5, or 10 bits.
gokhlayeh@9258 3547 + *
gokhlayeh@9258 3548 + * Length Bits
gokhlayeh@9258 3549 + * 2-9 4 = Choice=0 + 3 bits
gokhlayeh@9258 3550 + * 10-17 5 = Choice=1 + Choice2=0 + 3 bits
gokhlayeh@9258 3551 + * 18-273 10 = Choice=1 + Choice2=1 + 8 bits
gokhlayeh@9258 3552 + */
gokhlayeh@9258 3553 +#define LEN_LOW_BITS 3
gokhlayeh@9258 3554 +#define LEN_LOW_SYMBOLS (1 << LEN_LOW_BITS)
gokhlayeh@9258 3555 +#define LEN_MID_BITS 3
gokhlayeh@9258 3556 +#define LEN_MID_SYMBOLS (1 << LEN_MID_BITS)
gokhlayeh@9258 3557 +#define LEN_HIGH_BITS 8
gokhlayeh@9258 3558 +#define LEN_HIGH_SYMBOLS (1 << LEN_HIGH_BITS)
gokhlayeh@9258 3559 +#define LEN_SYMBOLS (LEN_LOW_SYMBOLS + LEN_MID_SYMBOLS + LEN_HIGH_SYMBOLS)
gokhlayeh@9258 3560 +
gokhlayeh@9258 3561 +/*
gokhlayeh@9258 3562 + * Maximum length of a match is 273 which is a result of the encoding
gokhlayeh@9258 3563 + * described above.
gokhlayeh@9258 3564 + */
gokhlayeh@9258 3565 +#define MATCH_LEN_MAX (MATCH_LEN_MIN + LEN_SYMBOLS - 1)
gokhlayeh@9258 3566 +
gokhlayeh@9258 3567 +/*
gokhlayeh@9258 3568 + * Different sets of probabilities are used for match distances that have
gokhlayeh@9258 3569 + * very short match length: Lengths of 2, 3, and 4 bytes have a separate
gokhlayeh@9258 3570 + * set of probabilities for each length. The matches with longer length
gokhlayeh@9258 3571 + * use a shared set of probabilities.
gokhlayeh@9258 3572 + */
gokhlayeh@9258 3573 +#define DIST_STATES 4
gokhlayeh@9258 3574 +
gokhlayeh@9258 3575 +/*
gokhlayeh@9258 3576 + * Get the index of the appropriate probability array for decoding
gokhlayeh@9258 3577 + * the distance slot.
gokhlayeh@9258 3578 + */
gokhlayeh@9258 3579 +static inline uint32_t lzma_get_dist_state(uint32_t len)
gokhlayeh@9258 3580 +{
gokhlayeh@9258 3581 + return len < DIST_STATES + MATCH_LEN_MIN
gokhlayeh@9258 3582 + ? len - MATCH_LEN_MIN : DIST_STATES - 1;
gokhlayeh@9258 3583 +}
gokhlayeh@9258 3584 +
gokhlayeh@9258 3585 +/*
gokhlayeh@9258 3586 + * The highest two bits of a 32-bit match distance are encoded using six bits.
gokhlayeh@9258 3587 + * This six-bit value is called a distance slot. This way encoding a 32-bit
gokhlayeh@9258 3588 + * value takes 6-36 bits, larger values taking more bits.
gokhlayeh@9258 3589 + */
gokhlayeh@9258 3590 +#define DIST_SLOT_BITS 6
gokhlayeh@9258 3591 +#define DIST_SLOTS (1 << DIST_SLOT_BITS)
gokhlayeh@9258 3592 +
gokhlayeh@9258 3593 +/* Match distances up to 127 are fully encoded using probabilities. Since
gokhlayeh@9258 3594 + * the highest two bits (distance slot) are always encoded using six bits,
gokhlayeh@9258 3595 + * the distances 0-3 don't need any additional bits to encode, since the
gokhlayeh@9258 3596 + * distance slot itself is the same as the actual distance. DIST_MODEL_START
gokhlayeh@9258 3597 + * indicates the first distance slot where at least one additional bit is
gokhlayeh@9258 3598 + * needed.
gokhlayeh@9258 3599 + */
gokhlayeh@9258 3600 +#define DIST_MODEL_START 4
gokhlayeh@9258 3601 +
gokhlayeh@9258 3602 +/*
gokhlayeh@9258 3603 + * Match distances greater than 127 are encoded in three pieces:
gokhlayeh@9258 3604 + * - distance slot: the highest two bits
gokhlayeh@9258 3605 + * - direct bits: 2-26 bits below the highest two bits
gokhlayeh@9258 3606 + * - alignment bits: four lowest bits
gokhlayeh@9258 3607 + *
gokhlayeh@9258 3608 + * Direct bits don't use any probabilities.
gokhlayeh@9258 3609 + *
gokhlayeh@9258 3610 + * The distance slot value of 14 is for distances 128-191.
gokhlayeh@9258 3611 + */
gokhlayeh@9258 3612 +#define DIST_MODEL_END 14
gokhlayeh@9258 3613 +
gokhlayeh@9258 3614 +/* Distance slots that indicate a distance <= 127. */
gokhlayeh@9258 3615 +#define FULL_DISTANCES_BITS (DIST_MODEL_END / 2)
gokhlayeh@9258 3616 +#define FULL_DISTANCES (1 << FULL_DISTANCES_BITS)
gokhlayeh@9258 3617 +
gokhlayeh@9258 3618 +/*
gokhlayeh@9258 3619 + * For match distances greater than 127, only the highest two bits and the
gokhlayeh@9258 3620 + * lowest four bits (alignment) is encoded using probabilities.
gokhlayeh@9258 3621 + */
gokhlayeh@9258 3622 +#define ALIGN_BITS 4
gokhlayeh@9258 3623 +#define ALIGN_SIZE (1 << ALIGN_BITS)
gokhlayeh@9258 3624 +#define ALIGN_MASK (ALIGN_SIZE - 1)
gokhlayeh@9258 3625 +
gokhlayeh@9258 3626 +/* Total number of all probability variables */
gokhlayeh@9258 3627 +#define PROBS_TOTAL (1846 + LITERAL_CODERS_MAX * LITERAL_CODER_SIZE)
gokhlayeh@9258 3628 +
gokhlayeh@9258 3629 +/*
gokhlayeh@9258 3630 + * LZMA remembers the four most recent match distances. Reusing these
gokhlayeh@9258 3631 + * distances tends to take less space than re-encoding the actual
gokhlayeh@9258 3632 + * distance value.
gokhlayeh@9258 3633 + */
gokhlayeh@9258 3634 +#define REPS 4
gokhlayeh@9258 3635 +
gokhlayeh@9258 3636 +#endif
gokhlayeh@9258 3637 diff --git a/lib/xz/xz_private.h b/lib/xz/xz_private.h
gokhlayeh@9258 3638 new file mode 100644
gokhlayeh@9258 3639 index 0000000..a65633e
gokhlayeh@9258 3640 --- /dev/null
gokhlayeh@9258 3641 +++ b/lib/xz/xz_private.h
gokhlayeh@9258 3642 @@ -0,0 +1,156 @@
gokhlayeh@9258 3643 +/*
gokhlayeh@9258 3644 + * Private includes and definitions
gokhlayeh@9258 3645 + *
gokhlayeh@9258 3646 + * Author: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 3647 + *
gokhlayeh@9258 3648 + * This file has been put into the public domain.
gokhlayeh@9258 3649 + * You can do whatever you want with this file.
gokhlayeh@9258 3650 + */
gokhlayeh@9258 3651 +
gokhlayeh@9258 3652 +#ifndef XZ_PRIVATE_H
gokhlayeh@9258 3653 +#define XZ_PRIVATE_H
gokhlayeh@9258 3654 +
gokhlayeh@9258 3655 +#ifdef __KERNEL__
gokhlayeh@9258 3656 +# include <linux/xz.h>
gokhlayeh@9258 3657 +# include <asm/byteorder.h>
gokhlayeh@9258 3658 +# include <asm/unaligned.h>
gokhlayeh@9258 3659 + /* XZ_PREBOOT may be defined only via decompress_unxz.c. */
gokhlayeh@9258 3660 +# ifndef XZ_PREBOOT
gokhlayeh@9258 3661 +# include <linux/slab.h>
gokhlayeh@9258 3662 +# include <linux/vmalloc.h>
gokhlayeh@9258 3663 +# include <linux/string.h>
gokhlayeh@9258 3664 +# ifdef CONFIG_XZ_DEC_X86
gokhlayeh@9258 3665 +# define XZ_DEC_X86
gokhlayeh@9258 3666 +# endif
gokhlayeh@9258 3667 +# ifdef CONFIG_XZ_DEC_POWERPC
gokhlayeh@9258 3668 +# define XZ_DEC_POWERPC
gokhlayeh@9258 3669 +# endif
gokhlayeh@9258 3670 +# ifdef CONFIG_XZ_DEC_IA64
gokhlayeh@9258 3671 +# define XZ_DEC_IA64
gokhlayeh@9258 3672 +# endif
gokhlayeh@9258 3673 +# ifdef CONFIG_XZ_DEC_ARM
gokhlayeh@9258 3674 +# define XZ_DEC_ARM
gokhlayeh@9258 3675 +# endif
gokhlayeh@9258 3676 +# ifdef CONFIG_XZ_DEC_ARMTHUMB
gokhlayeh@9258 3677 +# define XZ_DEC_ARMTHUMB
gokhlayeh@9258 3678 +# endif
gokhlayeh@9258 3679 +# ifdef CONFIG_XZ_DEC_SPARC
gokhlayeh@9258 3680 +# define XZ_DEC_SPARC
gokhlayeh@9258 3681 +# endif
gokhlayeh@9258 3682 +# define memeq(a, b, size) (memcmp(a, b, size) == 0)
gokhlayeh@9258 3683 +# define memzero(buf, size) memset(buf, 0, size)
gokhlayeh@9258 3684 +# endif
gokhlayeh@9258 3685 +# define get_le32(p) le32_to_cpup((const uint32_t *)(p))
gokhlayeh@9258 3686 +#else
gokhlayeh@9258 3687 + /*
gokhlayeh@9258 3688 + * For userspace builds, use a separate header to define the required
gokhlayeh@9258 3689 + * macros and functions. This makes it easier to adapt the code into
gokhlayeh@9258 3690 + * different environments and avoids clutter in the Linux kernel tree.
gokhlayeh@9258 3691 + */
gokhlayeh@9258 3692 +# include "xz_config.h"
gokhlayeh@9258 3693 +#endif
gokhlayeh@9258 3694 +
gokhlayeh@9258 3695 +/* If no specific decoding mode is requested, enable support for all modes. */
gokhlayeh@9258 3696 +#if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \
gokhlayeh@9258 3697 + && !defined(XZ_DEC_DYNALLOC)
gokhlayeh@9258 3698 +# define XZ_DEC_SINGLE
gokhlayeh@9258 3699 +# define XZ_DEC_PREALLOC
gokhlayeh@9258 3700 +# define XZ_DEC_DYNALLOC
gokhlayeh@9258 3701 +#endif
gokhlayeh@9258 3702 +
gokhlayeh@9258 3703 +/*
gokhlayeh@9258 3704 + * The DEC_IS_foo(mode) macros are used in "if" statements. If only some
gokhlayeh@9258 3705 + * of the supported modes are enabled, these macros will evaluate to true or
gokhlayeh@9258 3706 + * false at compile time and thus allow the compiler to omit unneeded code.
gokhlayeh@9258 3707 + */
gokhlayeh@9258 3708 +#ifdef XZ_DEC_SINGLE
gokhlayeh@9258 3709 +# define DEC_IS_SINGLE(mode) ((mode) == XZ_SINGLE)
gokhlayeh@9258 3710 +#else
gokhlayeh@9258 3711 +# define DEC_IS_SINGLE(mode) (false)
gokhlayeh@9258 3712 +#endif
gokhlayeh@9258 3713 +
gokhlayeh@9258 3714 +#ifdef XZ_DEC_PREALLOC
gokhlayeh@9258 3715 +# define DEC_IS_PREALLOC(mode) ((mode) == XZ_PREALLOC)
gokhlayeh@9258 3716 +#else
gokhlayeh@9258 3717 +# define DEC_IS_PREALLOC(mode) (false)
gokhlayeh@9258 3718 +#endif
gokhlayeh@9258 3719 +
gokhlayeh@9258 3720 +#ifdef XZ_DEC_DYNALLOC
gokhlayeh@9258 3721 +# define DEC_IS_DYNALLOC(mode) ((mode) == XZ_DYNALLOC)
gokhlayeh@9258 3722 +#else
gokhlayeh@9258 3723 +# define DEC_IS_DYNALLOC(mode) (false)
gokhlayeh@9258 3724 +#endif
gokhlayeh@9258 3725 +
gokhlayeh@9258 3726 +#if !defined(XZ_DEC_SINGLE)
gokhlayeh@9258 3727 +# define DEC_IS_MULTI(mode) (true)
gokhlayeh@9258 3728 +#elif defined(XZ_DEC_PREALLOC) || defined(XZ_DEC_DYNALLOC)
gokhlayeh@9258 3729 +# define DEC_IS_MULTI(mode) ((mode) != XZ_SINGLE)
gokhlayeh@9258 3730 +#else
gokhlayeh@9258 3731 +# define DEC_IS_MULTI(mode) (false)
gokhlayeh@9258 3732 +#endif
gokhlayeh@9258 3733 +
gokhlayeh@9258 3734 +/*
gokhlayeh@9258 3735 + * If any of the BCJ filter decoders are wanted, define XZ_DEC_BCJ.
gokhlayeh@9258 3736 + * XZ_DEC_BCJ is used to enable generic support for BCJ decoders.
gokhlayeh@9258 3737 + */
gokhlayeh@9258 3738 +#ifndef XZ_DEC_BCJ
gokhlayeh@9258 3739 +# if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \
gokhlayeh@9258 3740 + || defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \
gokhlayeh@9258 3741 + || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \
gokhlayeh@9258 3742 + || defined(XZ_DEC_SPARC)
gokhlayeh@9258 3743 +# define XZ_DEC_BCJ
gokhlayeh@9258 3744 +# endif
gokhlayeh@9258 3745 +#endif
gokhlayeh@9258 3746 +
gokhlayeh@9258 3747 +/*
gokhlayeh@9258 3748 + * Allocate memory for LZMA2 decoder. xz_dec_lzma2_reset() must be used
gokhlayeh@9258 3749 + * before calling xz_dec_lzma2_run().
gokhlayeh@9258 3750 + */
gokhlayeh@9258 3751 +XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode,
gokhlayeh@9258 3752 + uint32_t dict_max);
gokhlayeh@9258 3753 +
gokhlayeh@9258 3754 +/*
gokhlayeh@9258 3755 + * Decode the LZMA2 properties (one byte) and reset the decoder. Return
gokhlayeh@9258 3756 + * XZ_OK on success, XZ_MEMLIMIT_ERROR if the preallocated dictionary is not
gokhlayeh@9258 3757 + * big enough, and XZ_OPTIONS_ERROR if props indicates something that this
gokhlayeh@9258 3758 + * decoder doesn't support.
gokhlayeh@9258 3759 + */
gokhlayeh@9258 3760 +XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s,
gokhlayeh@9258 3761 + uint8_t props);
gokhlayeh@9258 3762 +
gokhlayeh@9258 3763 +/* Decode raw LZMA2 stream from b->in to b->out. */
gokhlayeh@9258 3764 +XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s,
gokhlayeh@9258 3765 + struct xz_buf *b);
gokhlayeh@9258 3766 +
gokhlayeh@9258 3767 +/* Free the memory allocated for the LZMA2 decoder. */
gokhlayeh@9258 3768 +XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s);
gokhlayeh@9258 3769 +
gokhlayeh@9258 3770 +#ifdef XZ_DEC_BCJ
gokhlayeh@9258 3771 +/*
gokhlayeh@9258 3772 + * Allocate memory for BCJ decoders. xz_dec_bcj_reset() must be used before
gokhlayeh@9258 3773 + * calling xz_dec_bcj_run().
gokhlayeh@9258 3774 + */
gokhlayeh@9258 3775 +XZ_EXTERN struct xz_dec_bcj *xz_dec_bcj_create(bool single_call);
gokhlayeh@9258 3776 +
gokhlayeh@9258 3777 +/*
gokhlayeh@9258 3778 + * Decode the Filter ID of a BCJ filter. This implementation doesn't
gokhlayeh@9258 3779 + * support custom start offsets, so no decoding of Filter Properties
gokhlayeh@9258 3780 + * is needed. Returns XZ_OK if the given Filter ID is supported.
gokhlayeh@9258 3781 + * Otherwise XZ_OPTIONS_ERROR is returned.
gokhlayeh@9258 3782 + */
gokhlayeh@9258 3783 +XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id);
gokhlayeh@9258 3784 +
gokhlayeh@9258 3785 +/*
gokhlayeh@9258 3786 + * Decode raw BCJ + LZMA2 stream. This must be used only if there actually is
gokhlayeh@9258 3787 + * a BCJ filter in the chain. If the chain has only LZMA2, xz_dec_lzma2_run()
gokhlayeh@9258 3788 + * must be called directly.
gokhlayeh@9258 3789 + */
gokhlayeh@9258 3790 +XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s,
gokhlayeh@9258 3791 + struct xz_dec_lzma2 *lzma2,
gokhlayeh@9258 3792 + struct xz_buf *b);
gokhlayeh@9258 3793 +
gokhlayeh@9258 3794 +/* Free the memory allocated for the BCJ filters. */
gokhlayeh@9258 3795 +#define xz_dec_bcj_end(s) kfree(s)
gokhlayeh@9258 3796 +#endif
gokhlayeh@9258 3797 +
gokhlayeh@9258 3798 +#endif
gokhlayeh@9258 3799 diff --git a/lib/xz/xz_stream.h b/lib/xz/xz_stream.h
gokhlayeh@9258 3800 new file mode 100644
gokhlayeh@9258 3801 index 0000000..66cb5a7
gokhlayeh@9258 3802 --- /dev/null
gokhlayeh@9258 3803 +++ b/lib/xz/xz_stream.h
gokhlayeh@9258 3804 @@ -0,0 +1,62 @@
gokhlayeh@9258 3805 +/*
gokhlayeh@9258 3806 + * Definitions for handling the .xz file format
gokhlayeh@9258 3807 + *
gokhlayeh@9258 3808 + * Author: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 3809 + *
gokhlayeh@9258 3810 + * This file has been put into the public domain.
gokhlayeh@9258 3811 + * You can do whatever you want with this file.
gokhlayeh@9258 3812 + */
gokhlayeh@9258 3813 +
gokhlayeh@9258 3814 +#ifndef XZ_STREAM_H
gokhlayeh@9258 3815 +#define XZ_STREAM_H
gokhlayeh@9258 3816 +
gokhlayeh@9258 3817 +#if defined(__KERNEL__) && !XZ_INTERNAL_CRC32
gokhlayeh@9258 3818 +# include <linux/crc32.h>
gokhlayeh@9258 3819 +# undef crc32
gokhlayeh@9258 3820 +# define xz_crc32(buf, size, crc) \
gokhlayeh@9258 3821 + (~crc32_le(~(uint32_t)(crc), buf, size))
gokhlayeh@9258 3822 +#endif
gokhlayeh@9258 3823 +
gokhlayeh@9258 3824 +/*
gokhlayeh@9258 3825 + * See the .xz file format specification at
gokhlayeh@9258 3826 + * http://tukaani.org/xz/xz-file-format.txt
gokhlayeh@9258 3827 + * to understand the container format.
gokhlayeh@9258 3828 + */
gokhlayeh@9258 3829 +
gokhlayeh@9258 3830 +#define STREAM_HEADER_SIZE 12
gokhlayeh@9258 3831 +
gokhlayeh@9258 3832 +#define HEADER_MAGIC "\3757zXZ"
gokhlayeh@9258 3833 +#define HEADER_MAGIC_SIZE 6
gokhlayeh@9258 3834 +
gokhlayeh@9258 3835 +#define FOOTER_MAGIC "YZ"
gokhlayeh@9258 3836 +#define FOOTER_MAGIC_SIZE 2
gokhlayeh@9258 3837 +
gokhlayeh@9258 3838 +/*
gokhlayeh@9258 3839 + * Variable-length integer can hold a 63-bit unsigned integer or a special
gokhlayeh@9258 3840 + * value indicating that the value is unknown.
gokhlayeh@9258 3841 + *
gokhlayeh@9258 3842 + * Experimental: vli_type can be defined to uint32_t to save a few bytes
gokhlayeh@9258 3843 + * in code size (no effect on speed). Doing so limits the uncompressed and
gokhlayeh@9258 3844 + * compressed size of the file to less than 256 MiB and may also weaken
gokhlayeh@9258 3845 + * error detection slightly.
gokhlayeh@9258 3846 + */
gokhlayeh@9258 3847 +typedef uint64_t vli_type;
gokhlayeh@9258 3848 +
gokhlayeh@9258 3849 +#define VLI_MAX ((vli_type)-1 / 2)
gokhlayeh@9258 3850 +#define VLI_UNKNOWN ((vli_type)-1)
gokhlayeh@9258 3851 +
gokhlayeh@9258 3852 +/* Maximum encoded size of a VLI */
gokhlayeh@9258 3853 +#define VLI_BYTES_MAX (sizeof(vli_type) * 8 / 7)
gokhlayeh@9258 3854 +
gokhlayeh@9258 3855 +/* Integrity Check types */
gokhlayeh@9258 3856 +enum xz_check {
gokhlayeh@9258 3857 + XZ_CHECK_NONE = 0,
gokhlayeh@9258 3858 + XZ_CHECK_CRC32 = 1,
gokhlayeh@9258 3859 + XZ_CHECK_CRC64 = 4,
gokhlayeh@9258 3860 + XZ_CHECK_SHA256 = 10
gokhlayeh@9258 3861 +};
gokhlayeh@9258 3862 +
gokhlayeh@9258 3863 +/* Maximum possible Check ID */
gokhlayeh@9258 3864 +#define XZ_CHECK_MAX 15
gokhlayeh@9258 3865 +
gokhlayeh@9258 3866 +#endif
gokhlayeh@9258 3867 diff --git a/scripts/Makefile.lib b/scripts/Makefile.lib
gokhlayeh@9258 3868 index 54fd1b7..b862007 100644
gokhlayeh@9258 3869 --- a/scripts/Makefile.lib
gokhlayeh@9258 3870 +++ b/scripts/Makefile.lib
gokhlayeh@9258 3871 @@ -246,6 +246,34 @@ cmd_lzo = (cat $(filter-out FORCE,$^) | \
gokhlayeh@9258 3872 lzop -9 && $(call size_append, $(filter-out FORCE,$^))) > $@ || \
gokhlayeh@9258 3873 (rm -f $@ ; false)
gokhlayeh@9258 3874
gokhlayeh@9258 3875 +# XZ
gokhlayeh@9258 3876 +# ---------------------------------------------------------------------------
gokhlayeh@9258 3877 +# Use xzkern to compress the kernel image and xzmisc to compress other things.
gokhlayeh@9258 3878 +#
gokhlayeh@9258 3879 +# xzkern uses a big LZMA2 dictionary since it doesn't increase memory usage
gokhlayeh@9258 3880 +# of the kernel decompressor. A BCJ filter is used if it is available for
gokhlayeh@9258 3881 +# the target architecture. xzkern also appends uncompressed size of the data
gokhlayeh@9258 3882 +# using size_append. The .xz format has the size information available at
gokhlayeh@9258 3883 +# the end of the file too, but it's in more complex format and it's good to
gokhlayeh@9258 3884 +# avoid changing the part of the boot code that reads the uncompressed size.
gokhlayeh@9258 3885 +# Note that the bytes added by size_append will make the xz tool think that
gokhlayeh@9258 3886 +# the file is corrupt. This is expected.
gokhlayeh@9258 3887 +#
gokhlayeh@9258 3888 +# xzmisc doesn't use size_append, so it can be used to create normal .xz
gokhlayeh@9258 3889 +# files. xzmisc uses smaller LZMA2 dictionary than xzkern, because a very
gokhlayeh@9258 3890 +# big dictionary would increase the memory usage too much in the multi-call
gokhlayeh@9258 3891 +# decompression mode. A BCJ filter isn't used either.
gokhlayeh@9258 3892 +quiet_cmd_xzkern = XZKERN $@
gokhlayeh@9258 3893 +cmd_xzkern = (cat $(filter-out FORCE,$^) | \
gokhlayeh@9258 3894 + sh $(srctree)/scripts/xz_wrap.sh && \
gokhlayeh@9258 3895 + $(call size_append, $(filter-out FORCE,$^))) > $@ || \
gokhlayeh@9258 3896 + (rm -f $@ ; false)
gokhlayeh@9258 3897 +
gokhlayeh@9258 3898 +quiet_cmd_xzmisc = XZMISC $@
gokhlayeh@9258 3899 +cmd_xzmisc = (cat $(filter-out FORCE,$^) | \
gokhlayeh@9258 3900 + xz --check=crc32 --lzma2=dict=1MiB) > $@ || \
gokhlayeh@9258 3901 + (rm -f $@ ; false)
gokhlayeh@9258 3902 +
gokhlayeh@9258 3903 # misc stuff
gokhlayeh@9258 3904 # ---------------------------------------------------------------------------
gokhlayeh@9258 3905 quote:="
gokhlayeh@9258 3906 diff --git a/scripts/xz_wrap.sh b/scripts/xz_wrap.sh
gokhlayeh@9258 3907 new file mode 100644
gokhlayeh@9258 3908 index 0000000..17a5798
gokhlayeh@9258 3909 --- /dev/null
gokhlayeh@9258 3910 +++ b/scripts/xz_wrap.sh
gokhlayeh@9258 3911 @@ -0,0 +1,23 @@
gokhlayeh@9258 3912 +#!/bin/sh
gokhlayeh@9258 3913 +#
gokhlayeh@9258 3914 +# This is a wrapper for xz to compress the kernel image using appropriate
gokhlayeh@9258 3915 +# compression options depending on the architecture.
gokhlayeh@9258 3916 +#
gokhlayeh@9258 3917 +# Author: Lasse Collin <lasse.collin@tukaani.org>
gokhlayeh@9258 3918 +#
gokhlayeh@9258 3919 +# This file has been put into the public domain.
gokhlayeh@9258 3920 +# You can do whatever you want with this file.
gokhlayeh@9258 3921 +#
gokhlayeh@9258 3922 +
gokhlayeh@9258 3923 +BCJ=
gokhlayeh@9258 3924 +LZMA2OPTS=
gokhlayeh@9258 3925 +
gokhlayeh@9258 3926 +case $ARCH in
gokhlayeh@9258 3927 + x86|x86_64) BCJ=--x86 ;;
gokhlayeh@9258 3928 + powerpc) BCJ=--powerpc ;;
gokhlayeh@9258 3929 + ia64) BCJ=--ia64; LZMA2OPTS=pb=4 ;;
gokhlayeh@9258 3930 + arm) BCJ=--arm ;;
gokhlayeh@9258 3931 + sparc) BCJ=--sparc ;;
gokhlayeh@9258 3932 +esac
gokhlayeh@9258 3933 +
gokhlayeh@9258 3934 +exec xz --check=crc32 $BCJ --lzma2=$LZMA2OPTS,dict=32MiB