Skip to content

Commit 553fd8b

Browse files
kumajayaniclimcy
authored andcommitted
Squashed commit LZ4 compressor and decompressor support
commit ee5b44f54e8c402f59cdabb2d7a90506ecea81da Author: Rasmus Villemoes <linux@rasmusvillemoes.dk> Date: Tue Feb 10 11:12:21 2015 +0100 lib/lz4: Pull out constant tables There's no reason to allocate the dec{32,64}table on the stack; it just wastes a bunch of instructions setting them up and, of course, also consumes quite a bit of stack. Using size_t for such small integers is a little excessive. $ scripts/bloat-o-meter /tmp/built-in.o lib/built-in.o add/remove: 2/2 grow/shrink: 2/0 up/down: 1304/-1548 (-244) function old new delta lz4_decompress_unknownoutputsize 55 718 +663 lz4_decompress 55 632 +577 dec64table - 32 +32 dec32table - 32 +32 lz4_uncompress 747 - -747 lz4_uncompress_unknownoutputsize 801 - -801 The now inlined lz4_uncompress functions used to have a stack footprint of 176 bytes (according to -fstack-usage); their inlinees have increased their stack use from 32 bytes to 48 and 80 bytes, respectively. Signed-off-by: Rasmus Villemoes <linux@rasmusvillemoes.dk> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Change-Id: I99e353a74605cac603eba77b8d6d1fda3906c7c1 commit 4430a4270dbedbf93267908cc47b24c62c2548ce Author: JeHyeon Yeon <tom.yeon@windriver.com> Date: Mon Mar 16 01:03:19 2015 +0000 LZ4 : fix the data abort issue If the part of the compression data are corrupted, or the compression data is totally fake, the memory access over the limit is possible. This is the log from my system usning lz4 decompression. [6502]data abort, halting [6503]r0 0x00000000 r1 0x00000000 r2 0xdcea0ffc r3 0xdcea0ffc [6509]r4 0xb9ab0bfd r5 0xdcea0ffc r6 0xdcea0ff8 r7 0xdce80000 [6515]r8 0x00000000 r9 0x00000000 r10 0x00000000 r11 0xb9a98000 [6522]r12 0xdcea1000 usp 0x00000000 ulr 0x00000000 pc 0x820149bc [6528]spsr 0x400001f3 and the memory addresses of some variables at the moment are ref:0xdcea0ffc, op:0xdcea0ffc, oend:0xdcea1000 As you can see, COPYLENGH is 8bytes, so @ref and @op can access the momory over @Oend. Signed-off-by: JeHyeon Yeon <tom.yeon@windriver.com> Reviewed-by: David Sterba <dsterba@suse.cz> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Change-Id: I7d2375be2402adce78b6e7b966401ff4768fd3ea commit 7a68637ba4f62dc4cd335c65fa080d8b1217ff3c Author: Shashank Shekhar <shashank.shekhar@motorola.com> Date: Fri Dec 12 13:31:13 2014 -0600 lib: lz4: Set ARM_EFFICIENT_UNALIGNED_ACCESS Set ARM_EFFICIENT_UNALIGNED_ACCESS to improve performance in lz4 compression and decompression. On msm8x26 cortex-a7, LZO LZ4 LZ4 w/ UA decompress (bs=4k) 121.21 115.52 148.7 LZO LZ4 LZ4 w/ UA compress (bs=4k) 37.5 34.5 44.8 Change-Id: Ib4daa0e702125096d46095121a13c337e386b161 commit f5295807d7dac4ee04af913fd6108b6b651c4f27 Author: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Date: Thu Jul 3 16:06:57 2014 -0700 lz4: add overrun checks to lz4_uncompress_unknownoutputsize() Jan points out that I forgot to make the needed fixes to the lz4_uncompress_unknownoutputsize() function to mirror the changes done in lz4_decompress() with regards to potential pointer overflows. The only in-kernel user of this function is the zram code, which only takes data from a valid compressed buffer that it made itself, so it's not a big issue. But due to external kernel modules using this function, it's better to be safe here. Change-Id: I06ac5790c1ce72f173371281483200d8a34396f2 Reported-by: Jan Beulich <JBeulich@suse.com> Cc: "Don A. Bailey" <donb@securitymouse.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> commit 48c64e75cd033380af75b9d6945c6ed3580d22d3 Author: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Date: Tue Jun 24 16:59:01 2014 -0400 lz4: fix another possible overrun There is one other possible overrun in the lz4 code as implemented by Linux at this point in time (which differs from the upstream lz4 codebase, but will get synced at in a future kernel release.) As pointed out by Don, we also need to check the overflow in the data itself. While we are at it, replace the odd error return value with just a "simple" -1 value as the return value is never used for anything other than a basic "did this work or not" check. Change-Id: I0ec95989e2f47889297eeb9f7fb88753b0fbf345 Reported-by: "Don A. Bailey" <donb@securitymouse.com> Reported-by: Willy Tarreau <w@1wt.eu> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> commit eb543b3d1a1a4b2485c7ee8e046b8c2b625efb76 Author: Greg Kroah-Hartman <gregkh@linuxfoundation.org> Date: Fri Jun 20 22:01:41 2014 -0700 lz4: ensure length does not wrap Given some pathologically compressed data, lz4 could possibly decide to wrap a few internal variables, causing unknown things to happen. Catch this before the wrapping happens and abort the decompression. Change-Id: I8bba00490ae0885bf9c80e81bb2cdcfc479cf35c Reported-by: "Don A. Bailey" <donb@securitymouse.com> Cc: stable <stable@vger.kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> commit adabcdfbb8f5cd91d2998b68bd141aae26ceb69e Author: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Date: Wed Sep 11 14:26:32 2013 -0700 lz4: fix compression/decompression signedness mismatch LZ4 compression and decompression functions require different in signedness input/output parameters: unsigned char for compression and signed char for decompression. Change decompression API to require "(const) unsigned char *". Change-Id: Id636e5998463a7a1e50e031825f4665c3858e03d Signed-off-by: Sergey Senozhatsky <sergey.senozhatsky@gmail.com> Cc: Kyungsik Lee <kyungsik.lee@lge.com> Cc: Geert Uytterhoeven <geert@linux-m68k.org> Cc: Yann Collet <yann.collet.73@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> commit 5bb7a87dc54dee886e5dae275a15c5f1968546cd Author: Richard Laager <rlaager@wiktel.com> Date: Thu Aug 22 16:35:47 2013 -0700 lib/lz4: correct the LZ4 license The LZ4 code is listed as using the "BSD 2-Clause License". Signed-off-by: Richard Laager <rlaager@wiktel.com> Acked-by: Kyungsik Lee <kyungsik.lee@lge.com> Cc: Chanho Min <chanho.min@lge.com> Cc: Richard Yao <ryao@gentoo.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> [ The 2-clause BSD can be just converted into GPL, but that's rude and pointless, so don't do it - Linus ] Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Change-Id: I336084fb5ea5994847880b21767154cb579391f6 commit 3af00fc70c00a6be5e377a676aa82841f59e480c Author: Chanho Min <chanho.min@lge.com> Date: Mon Jul 8 16:01:49 2013 -0700 lib: add lz4 compressor module This patchset is for supporting LZ4 compression and the crypto API using it. As shown below, the size of data is a little bit bigger but compressing speed is faster under the enabled unaligned memory access. We can use lz4 de/compression through crypto API as well. Also, It will be useful for another potential user of lz4 compression. lz4 Compression Benchmark: Compiler: ARM gcc 4.6.4 ARMv7, 1 GHz based board Kernel: linux 3.4 Uncompressed data Size: 101 MB Compressed Size compression Speed LZO 72.1MB 32.1MB/s, 33.0MB/s(UA) LZ4 75.1MB 30.4MB/s, 35.9MB/s(UA) LZ4HC 59.8MB 2.4MB/s, 2.5MB/s(UA) - UA: Unaligned memory Access support - Latest patch set for LZO applied This patch: Add support for LZ4 compression in the Linux Kernel. LZ4 Compression APIs for kernel are based on LZ4 implementation by Yann Collet and were changed for kernel coding style. LZ4 homepage : http://fastcompression.blogspot.com/p/lz4.html LZ4 source repository : http://code.google.com/p/lz4/ svn revision : r90 Two APIs are added: lz4_compress() support basic lz4 compression whereas lz4hc_compress() support high compression or CPU performance get lower but compression ratio get higher. Also, we require the pre-allocated working memory with the defined size and destination buffer must be allocated with the size of lz4_compressbound. [akpm@linux-foundation.org: make lz4_compresshcctx() static] Signed-off-by: Chanho Min <chanho.min@lge.com> Cc: "Darrick J. Wong" <djwong@us.ibm.com> Cc: Bob Pearson <rpearson@systemfabricworks.com> Cc: Richard Weinberger <richard@nod.at> Cc: Herbert Xu <herbert@gondor.hengli.com.au> Cc: Yann Collet <yann.collet.73@gmail.com> Cc: Kyungsik Lee <kyungsik.lee@lge.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Change-Id: Iedb8562bae1d0982e5faafbd473b015f3f982e00 commit 9cb7aca4376101544f30fa43f46d05a65d4f3ee2 Author: Kyungsik Lee <kyungsik.lee@lge.com> Date: Mon Jul 8 16:01:46 2013 -0700 lib: add support for LZ4-compressed kernel Add support for extracting LZ4-compressed kernel images, as well as LZ4-compressed ramdisk images in the kernel boot process. Change-Id: I276e53c72fc3ab6afc65326d4445e38e8a0cb77b Signed-off-by: Kyungsik Lee <kyungsik.lee@lge.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Borislav Petkov <bp@alien8.de> Cc: Florian Fainelli <florian@openwrt.org> Cc: Yann Collet <yann.collet.73@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> commit a74b42c0d347eb20c923745dbdf490f17201b1a3 Author: Kyungsik Lee <kyungsik.lee@lge.com> Date: Mon Jul 8 16:01:45 2013 -0700 decompressor: add LZ4 decompressor module Add support for LZ4 decompression in the Linux Kernel. LZ4 Decompression APIs for kernel are based on LZ4 implementation by Yann Collet. Benchmark Results(PATCH v3) Compiler: Linaro ARM gcc 4.6.2 1. ARMv7, 1.5GHz based board Kernel: linux 3.4 Uncompressed Kernel Size: 14MB Compressed Size Decompression Speed LZO 6.7MB 20.1MB/s, 25.2MB/s(UA) LZ4 7.3MB 29.1MB/s, 45.6MB/s(UA) 2. ARMv7, 1.7GHz based board Kernel: linux 3.7 Uncompressed Kernel Size: 14MB Compressed Size Decompression Speed LZO 6.0MB 34.1MB/s, 52.2MB/s(UA) LZ4 6.5MB 86.7MB/s - UA: Unaligned memory Access support - Latest patch set for LZO applied This patch set is for adding support for LZ4-compressed Kernel. LZ4 is a very fast lossless compression algorithm and it also features an extremely fast decoder [1]. But we have five of decompressors already and one question which does arise, however, is that of where do we stop adding new ones? This issue had been discussed and came to the conclusion [2]. Russell King said that we should have: - one decompressor which is the fastest - one decompressor for the highest compression ratio - one popular decompressor (eg conventional gzip) If we have a replacement one for one of these, then it should do exactly that: replace it. The benchmark shows that an 8% increase in image size vs a 66% increase in decompression speed compared to LZO(which has been known as the fastest decompressor in the Kernel). Therefore the "fast but may not be small" compression title has clearly been taken by LZ4 [3]. [1] http://code.google.com/p/lz4/ [2] http://thread.gmane.org/gmane.linux.kbuild.devel/9157 [3] http://thread.gmane.org/gmane.linux.kbuild.devel/9347 LZ4 homepage: http://fastcompression.blogspot.com/p/lz4.html LZ4 source repository: http://code.google.com/p/lz4/ Change-Id: Ib7d1226ac0facea4c66f3ff50661242294ba6746 Signed-off-by: Kyungsik Lee <kyungsik.lee@lge.com> Signed-off-by: Yann Collet <yann.collet.73@gmail.com> Cc: "H. Peter Anvin" <hpa@zytor.com> Cc: Ingo Molnar <mingo@elte.hu> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Russell King <rmk@arm.linux.org.uk> Cc: Borislav Petkov <bp@alien8.de> Cc: Florian Fainelli <florian@openwrt.org> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org> Change-Id: I94c29bd9067c947e06f8dd1da4d3fa7fed88732c Signed-off-by: Ketut P. Kumajaya <ketut.kumajaya@gmail.com>
1 parent 99fc830 commit 553fd8b

14 files changed

Lines changed: 1811 additions & 1 deletion

File tree

include/linux/decompress/unlz4.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
#ifndef DECOMPRESS_UNLZ4_H
2+
#define DECOMPRESS_UNLZ4_H
3+
4+
int unlz4(unsigned char *inbuf, int len,
5+
int(*fill)(void*, unsigned int),
6+
int(*flush)(void*, unsigned int),
7+
unsigned char *output,
8+
int *pos,
9+
void(*error)(char *x));
10+
#endif

include/linux/lz4.h

Lines changed: 87 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,87 @@
1+
#ifndef __LZ4_H__
2+
#define __LZ4_H__
3+
/*
4+
* LZ4 Kernel Interface
5+
*
6+
* Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
7+
*
8+
* This program is free software; you can redistribute it and/or modify
9+
* it under the terms of the GNU General Public License version 2 as
10+
* published by the Free Software Foundation.
11+
*/
12+
#define LZ4_MEM_COMPRESS (4096 * sizeof(unsigned char *))
13+
#define LZ4HC_MEM_COMPRESS (65538 * sizeof(unsigned char *))
14+
15+
/*
16+
* lz4_compressbound()
17+
* Provides the maximum size that LZ4 may output in a "worst case" scenario
18+
* (input data not compressible)
19+
*/
20+
static inline size_t lz4_compressbound(size_t isize)
21+
{
22+
return isize + (isize / 255) + 16;
23+
}
24+
25+
/*
26+
* lz4_compress()
27+
* src : source address of the original data
28+
* src_len : size of the original data
29+
* dst : output buffer address of the compressed data
30+
* This requires 'dst' of size LZ4_COMPRESSBOUND.
31+
* dst_len : is the output size, which is returned after compress done
32+
* workmem : address of the working memory.
33+
* This requires 'workmem' of size LZ4_MEM_COMPRESS.
34+
* return : Success if return 0
35+
* Error if return (< 0)
36+
* note : Destination buffer and workmem must be already allocated with
37+
* the defined size.
38+
*/
39+
int lz4_compress(const unsigned char *src, size_t src_len,
40+
unsigned char *dst, size_t *dst_len, void *wrkmem);
41+
42+
/*
43+
* lz4hc_compress()
44+
* src : source address of the original data
45+
* src_len : size of the original data
46+
* dst : output buffer address of the compressed data
47+
* This requires 'dst' of size LZ4_COMPRESSBOUND.
48+
* dst_len : is the output size, which is returned after compress done
49+
* workmem : address of the working memory.
50+
* This requires 'workmem' of size LZ4HC_MEM_COMPRESS.
51+
* return : Success if return 0
52+
* Error if return (< 0)
53+
* note : Destination buffer and workmem must be already allocated with
54+
* the defined size.
55+
*/
56+
int lz4hc_compress(const unsigned char *src, size_t src_len,
57+
unsigned char *dst, size_t *dst_len, void *wrkmem);
58+
59+
/*
60+
* lz4_decompress()
61+
* src : source address of the compressed data
62+
* src_len : is the input size, whcih is returned after decompress done
63+
* dest : output buffer address of the decompressed data
64+
* actual_dest_len: is the size of uncompressed data, supposing it's known
65+
* return : Success if return 0
66+
* Error if return (< 0)
67+
* note : Destination buffer must be already allocated.
68+
* slightly faster than lz4_decompress_unknownoutputsize()
69+
*/
70+
int lz4_decompress(const unsigned char *src, size_t *src_len,
71+
unsigned char *dest, size_t actual_dest_len);
72+
73+
/*
74+
* lz4_decompress_unknownoutputsize()
75+
* src : source address of the compressed data
76+
* src_len : is the input size, therefore the compressed size
77+
* dest : output buffer address of the decompressed data
78+
* dest_len: is the max size of the destination buffer, which is
79+
* returned with actual size of decompressed data after
80+
* decompress done
81+
* return : Success if return 0
82+
* Error if return (< 0)
83+
* note : Destination buffer must be already allocated.
84+
*/
85+
int lz4_decompress_unknownoutputsize(const unsigned char *src, size_t src_len,
86+
unsigned char *dest, size_t *dest_len);
87+
#endif

init/Kconfig

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -98,10 +98,13 @@ config HAVE_KERNEL_XZ
9898
config HAVE_KERNEL_LZO
9999
bool
100100

101+
config HAVE_KERNEL_LZ4
102+
bool
103+
101104
choice
102105
prompt "Kernel compression mode"
103106
default KERNEL_GZIP
104-
depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO
107+
depends on HAVE_KERNEL_GZIP || HAVE_KERNEL_BZIP2 || HAVE_KERNEL_LZMA || HAVE_KERNEL_XZ || HAVE_KERNEL_LZO || HAVE_KERNEL_LZ4
105108
help
106109
The linux kernel is a kind of self-extracting executable.
107110
Several compression algorithms are available, which differ
@@ -168,6 +171,18 @@ config KERNEL_LZO
168171
size is about 10% bigger than gzip; however its speed
169172
(both compression and decompression) is the fastest.
170173

174+
config KERNEL_LZ4
175+
bool "LZ4"
176+
depends on HAVE_KERNEL_LZ4
177+
help
178+
LZ4 is an LZ77-type compressor with a fixed, byte-oriented encoding.
179+
A preliminary version of LZ4 de/compression tool is available at
180+
<https://code.google.com/p/lz4/>.
181+
182+
Its compression ratio is worse than LZO. The size of the kernel
183+
is about 8% bigger than LZO. But the decompression speed is
184+
faster than LZO.
185+
171186
endchoice
172187

173188
config DEFAULT_HOSTNAME

lib/Kconfig

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,15 @@ config LZO_COMPRESS
189189
config LZO_DECOMPRESS
190190
tristate
191191

192+
config LZ4_COMPRESS
193+
tristate
194+
195+
config LZ4HC_COMPRESS
196+
tristate
197+
198+
config LZ4_DECOMPRESS
199+
tristate
200+
192201
source "lib/xz/Kconfig"
193202

194203
#
@@ -213,6 +222,10 @@ config DECOMPRESS_LZO
213222
select LZO_DECOMPRESS
214223
tristate
215224

225+
config DECOMPRESS_LZ4
226+
select LZ4_DECOMPRESS
227+
tristate
228+
216229
#
217230
# Generic allocator support is selected if needed
218231
#

lib/Makefile

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,9 @@ obj-$(CONFIG_REED_SOLOMON) += reed_solomon/
7676
obj-$(CONFIG_BCH) += bch.o
7777
obj-$(CONFIG_LZO_COMPRESS) += lzo/
7878
obj-$(CONFIG_LZO_DECOMPRESS) += lzo/
79+
obj-$(CONFIG_LZ4_COMPRESS) += lz4/
80+
obj-$(CONFIG_LZ4HC_COMPRESS) += lz4/
81+
obj-$(CONFIG_LZ4_DECOMPRESS) += lz4/
7982
obj-$(CONFIG_XZ_DEC) += xz/
8083
obj-$(CONFIG_RAID6_PQ) += raid6/
8184

@@ -84,6 +87,7 @@ lib-$(CONFIG_DECOMPRESS_BZIP2) += decompress_bunzip2.o
8487
lib-$(CONFIG_DECOMPRESS_LZMA) += decompress_unlzma.o
8588
lib-$(CONFIG_DECOMPRESS_XZ) += decompress_unxz.o
8689
lib-$(CONFIG_DECOMPRESS_LZO) += decompress_unlzo.o
90+
lib-$(CONFIG_DECOMPRESS_LZ4) += decompress_unlz4.o
8791

8892
obj-$(CONFIG_TEXTSEARCH) += textsearch.o
8993
obj-$(CONFIG_TEXTSEARCH_KMP) += ts_kmp.o

lib/decompress.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
#include <linux/decompress/unxz.h>
1212
#include <linux/decompress/inflate.h>
1313
#include <linux/decompress/unlzo.h>
14+
#include <linux/decompress/unlz4.h>
1415

1516
#include <linux/types.h>
1617
#include <linux/string.h>
@@ -31,6 +32,9 @@
3132
#ifndef CONFIG_DECOMPRESS_LZO
3233
# define unlzo NULL
3334
#endif
35+
#ifndef CONFIG_DECOMPRESS_LZ4
36+
# define unlz4 NULL
37+
#endif
3438

3539
struct compress_format {
3640
unsigned char magic[2];
@@ -45,6 +49,7 @@ static const struct compress_format compressed_formats[] __initconst = {
4549
{ {0x5d, 0x00}, "lzma", unlzma },
4650
{ {0xfd, 0x37}, "xz", unxz },
4751
{ {0x89, 0x4c}, "lzo", unlzo },
52+
{ {0x02, 0x21}, "lz4", unlz4 },
4853
{ {0, 0}, NULL, NULL }
4954
};
5055

lib/decompress_unlz4.c

Lines changed: 187 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,187 @@
1+
/*
2+
* Wrapper for decompressing LZ4-compressed kernel, initramfs, and initrd
3+
*
4+
* Copyright (C) 2013, LG Electronics, Kyungsik Lee <kyungsik.lee@lge.com>
5+
*
6+
* This program is free software; you can redistribute it and/or modify
7+
* it under the terms of the GNU General Public License version 2 as
8+
* published by the Free Software Foundation.
9+
*/
10+
11+
#ifdef STATIC
12+
#define PREBOOT
13+
#include "lz4/lz4_decompress.c"
14+
#else
15+
#include <linux/decompress/unlz4.h>
16+
#endif
17+
#include <linux/types.h>
18+
#include <linux/lz4.h>
19+
#include <linux/decompress/mm.h>
20+
#include <linux/compiler.h>
21+
22+
#include <asm/unaligned.h>
23+
24+
/*
25+
* Note: Uncompressed chunk size is used in the compressor side
26+
* (userspace side for compression).
27+
* It is hardcoded because there is not proper way to extract it
28+
* from the binary stream which is generated by the preliminary
29+
* version of LZ4 tool so far.
30+
*/
31+
#define LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE (8 << 20)
32+
#define ARCHIVE_MAGICNUMBER 0x184C2102
33+
34+
STATIC inline int INIT unlz4(u8 *input, int in_len,
35+
int (*fill) (void *, unsigned int),
36+
int (*flush) (void *, unsigned int),
37+
u8 *output, int *posp,
38+
void (*error) (char *x))
39+
{
40+
int ret = -1;
41+
size_t chunksize = 0;
42+
size_t uncomp_chunksize = LZ4_DEFAULT_UNCOMPRESSED_CHUNK_SIZE;
43+
u8 *inp;
44+
u8 *inp_start;
45+
u8 *outp;
46+
int size = in_len;
47+
#ifdef PREBOOT
48+
size_t out_len = get_unaligned_le32(input + in_len);
49+
#endif
50+
size_t dest_len;
51+
52+
53+
if (output) {
54+
outp = output;
55+
} else if (!flush) {
56+
error("NULL output pointer and no flush function provided");
57+
goto exit_0;
58+
} else {
59+
outp = large_malloc(uncomp_chunksize);
60+
if (!outp) {
61+
error("Could not allocate output buffer");
62+
goto exit_0;
63+
}
64+
}
65+
66+
if (input && fill) {
67+
error("Both input pointer and fill function provided,");
68+
goto exit_1;
69+
} else if (input) {
70+
inp = input;
71+
} else if (!fill) {
72+
error("NULL input pointer and missing fill function");
73+
goto exit_1;
74+
} else {
75+
inp = large_malloc(lz4_compressbound(uncomp_chunksize));
76+
if (!inp) {
77+
error("Could not allocate input buffer");
78+
goto exit_1;
79+
}
80+
}
81+
inp_start = inp;
82+
83+
if (posp)
84+
*posp = 0;
85+
86+
if (fill)
87+
fill(inp, 4);
88+
89+
chunksize = get_unaligned_le32(inp);
90+
if (chunksize == ARCHIVE_MAGICNUMBER) {
91+
inp += 4;
92+
size -= 4;
93+
} else {
94+
error("invalid header");
95+
goto exit_2;
96+
}
97+
98+
if (posp)
99+
*posp += 4;
100+
101+
for (;;) {
102+
103+
if (fill)
104+
fill(inp, 4);
105+
106+
chunksize = get_unaligned_le32(inp);
107+
if (chunksize == ARCHIVE_MAGICNUMBER) {
108+
inp += 4;
109+
size -= 4;
110+
if (posp)
111+
*posp += 4;
112+
continue;
113+
}
114+
inp += 4;
115+
size -= 4;
116+
117+
if (posp)
118+
*posp += 4;
119+
120+
if (fill) {
121+
if (chunksize > lz4_compressbound(uncomp_chunksize)) {
122+
error("chunk length is longer than allocated");
123+
goto exit_2;
124+
}
125+
fill(inp, chunksize);
126+
}
127+
#ifdef PREBOOT
128+
if (out_len >= uncomp_chunksize) {
129+
dest_len = uncomp_chunksize;
130+
out_len -= dest_len;
131+
} else
132+
dest_len = out_len;
133+
ret = lz4_decompress(inp, &chunksize, outp, dest_len);
134+
#else
135+
dest_len = uncomp_chunksize;
136+
ret = lz4_decompress_unknownoutputsize(inp, chunksize, outp,
137+
&dest_len);
138+
#endif
139+
if (ret < 0) {
140+
error("Decoding failed");
141+
goto exit_2;
142+
}
143+
144+
if (flush && flush(outp, dest_len) != dest_len)
145+
goto exit_2;
146+
if (output)
147+
outp += dest_len;
148+
if (posp)
149+
*posp += chunksize;
150+
151+
size -= chunksize;
152+
153+
if (size == 0)
154+
break;
155+
else if (size < 0) {
156+
error("data corrupted");
157+
goto exit_2;
158+
}
159+
160+
inp += chunksize;
161+
if (fill)
162+
inp = inp_start;
163+
}
164+
165+
ret = 0;
166+
exit_2:
167+
if (!input)
168+
large_free(inp_start);
169+
exit_1:
170+
if (!output)
171+
large_free(outp);
172+
exit_0:
173+
return ret;
174+
}
175+
176+
#ifdef PREBOOT
177+
STATIC int INIT decompress(unsigned char *buf, int in_len,
178+
int(*fill)(void*, unsigned int),
179+
int(*flush)(void*, unsigned int),
180+
unsigned char *output,
181+
int *posp,
182+
void(*error)(char *x)
183+
)
184+
{
185+
return unlz4(buf, in_len - 4, fill, flush, output, posp, error);
186+
}
187+
#endif

lib/lz4/Makefile

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
obj-$(CONFIG_LZ4_COMPRESS) += lz4_compress.o
2+
obj-$(CONFIG_LZ4HC_COMPRESS) += lz4hc_compress.o
3+
obj-$(CONFIG_LZ4_DECOMPRESS) += lz4_decompress.o

0 commit comments

Comments
 (0)