1bc22c17eSAlain Knaff /* Lzma decompressor for Linux kernel. Shamelessly snarfed
2bc22c17eSAlain Knaff *from busybox 1.1.1
3bc22c17eSAlain Knaff *
4bc22c17eSAlain Knaff *Linux kernel adaptation
5bc22c17eSAlain Knaff *Copyright (C) 2006 Alain < alain@knaff.lu >
6bc22c17eSAlain Knaff *
7bc22c17eSAlain Knaff *Based on small lzma deflate implementation/Small range coder
8bc22c17eSAlain Knaff *implementation for lzma.
9bc22c17eSAlain Knaff *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
10bc22c17eSAlain Knaff *
11*d89775fcSAlexander A. Klimov *Based on LzmaDecode.c from the LZMA SDK 4.22 (https://www.7-zip.org/)
12bc22c17eSAlain Knaff *Copyright (C) 1999-2005 Igor Pavlov
13bc22c17eSAlain Knaff *
14bc22c17eSAlain Knaff *Copyrights of the parts, see headers below.
15bc22c17eSAlain Knaff *
16bc22c17eSAlain Knaff *
17bc22c17eSAlain Knaff *This program is free software; you can redistribute it and/or
18bc22c17eSAlain Knaff *modify it under the terms of the GNU Lesser General Public
19bc22c17eSAlain Knaff *License as published by the Free Software Foundation; either
20bc22c17eSAlain Knaff *version 2.1 of the License, or (at your option) any later version.
21bc22c17eSAlain Knaff *
22bc22c17eSAlain Knaff *This program is distributed in the hope that it will be useful,
23bc22c17eSAlain Knaff *but WITHOUT ANY WARRANTY; without even the implied warranty of
24bc22c17eSAlain Knaff *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
25bc22c17eSAlain Knaff *Lesser General Public License for more details.
26bc22c17eSAlain Knaff *
27bc22c17eSAlain Knaff *You should have received a copy of the GNU Lesser General Public
28bc22c17eSAlain Knaff *License along with this library; if not, write to the Free Software
29bc22c17eSAlain Knaff *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
30bc22c17eSAlain Knaff */
31bc22c17eSAlain Knaff
32b1af4315SPhillip Lougher #ifdef STATIC
33b1af4315SPhillip Lougher #define PREBOOT
34b1af4315SPhillip Lougher #else
35bc22c17eSAlain Knaff #include <linux/decompress/unlzma.h>
36bc22c17eSAlain Knaff #endif /* STATIC */
37bc22c17eSAlain Knaff
38bc22c17eSAlain Knaff #include <linux/decompress/mm.h>
39bc22c17eSAlain Knaff
40bc22c17eSAlain Knaff #define MIN(a, b) (((a) < (b)) ? (a) : (b))
41bc22c17eSAlain Knaff
read_int(unsigned char * ptr,int size)42bc22c17eSAlain Knaff static long long INIT read_int(unsigned char *ptr, int size)
43bc22c17eSAlain Knaff {
44bc22c17eSAlain Knaff int i;
45bc22c17eSAlain Knaff long long ret = 0;
46bc22c17eSAlain Knaff
47bc22c17eSAlain Knaff for (i = 0; i < size; i++)
48bc22c17eSAlain Knaff ret = (ret << 8) | ptr[size-i-1];
49bc22c17eSAlain Knaff return ret;
50bc22c17eSAlain Knaff }
51bc22c17eSAlain Knaff
52bc22c17eSAlain Knaff #define ENDIAN_CONVERT(x) \
53bc22c17eSAlain Knaff x = (typeof(x))read_int((unsigned char *)&x, sizeof(x))
54bc22c17eSAlain Knaff
55bc22c17eSAlain Knaff
56bc22c17eSAlain Knaff /* Small range coder implementation for lzma.
57bc22c17eSAlain Knaff *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
58bc22c17eSAlain Knaff *
59*d89775fcSAlexander A. Klimov *Based on LzmaDecode.c from the LZMA SDK 4.22 (https://www.7-zip.org/)
60bc22c17eSAlain Knaff *Copyright (c) 1999-2005 Igor Pavlov
61bc22c17eSAlain Knaff */
62bc22c17eSAlain Knaff
63bc22c17eSAlain Knaff #include <linux/compiler.h>
64bc22c17eSAlain Knaff
65bc22c17eSAlain Knaff #define LZMA_IOBUF_SIZE 0x10000
66bc22c17eSAlain Knaff
67bc22c17eSAlain Knaff struct rc {
68d97b07c5SYinghai Lu long (*fill)(void*, unsigned long);
69bc22c17eSAlain Knaff uint8_t *ptr;
70bc22c17eSAlain Knaff uint8_t *buffer;
71bc22c17eSAlain Knaff uint8_t *buffer_end;
72d97b07c5SYinghai Lu long buffer_size;
73bc22c17eSAlain Knaff uint32_t code;
74bc22c17eSAlain Knaff uint32_t range;
75bc22c17eSAlain Knaff uint32_t bound;
7693685ad2SLasse Collin void (*error)(char *);
77bc22c17eSAlain Knaff };
78bc22c17eSAlain Knaff
79bc22c17eSAlain Knaff
80bc22c17eSAlain Knaff #define RC_TOP_BITS 24
81bc22c17eSAlain Knaff #define RC_MOVE_BITS 5
82bc22c17eSAlain Knaff #define RC_MODEL_TOTAL_BITS 11
83bc22c17eSAlain Knaff
84bc22c17eSAlain Knaff
nofill(void * buffer,unsigned long len)85d97b07c5SYinghai Lu static long INIT nofill(void *buffer, unsigned long len)
866a881162SPhillip Lougher {
876a881162SPhillip Lougher return -1;
886a881162SPhillip Lougher }
896a881162SPhillip Lougher
90bc22c17eSAlain Knaff /* Called twice: once at startup and once in rc_normalize() */
rc_read(struct rc * rc)91bc22c17eSAlain Knaff static void INIT rc_read(struct rc *rc)
92bc22c17eSAlain Knaff {
93bc22c17eSAlain Knaff rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE);
94bc22c17eSAlain Knaff if (rc->buffer_size <= 0)
9593685ad2SLasse Collin rc->error("unexpected EOF");
96bc22c17eSAlain Knaff rc->ptr = rc->buffer;
97bc22c17eSAlain Knaff rc->buffer_end = rc->buffer + rc->buffer_size;
98bc22c17eSAlain Knaff }
99bc22c17eSAlain Knaff
100bc22c17eSAlain Knaff /* Called once */
rc_init(struct rc * rc,long (* fill)(void *,unsigned long),char * buffer,long buffer_size)101bc22c17eSAlain Knaff static inline void INIT rc_init(struct rc *rc,
102d97b07c5SYinghai Lu long (*fill)(void*, unsigned long),
103d97b07c5SYinghai Lu char *buffer, long buffer_size)
104bc22c17eSAlain Knaff {
1056a881162SPhillip Lougher if (fill)
106bc22c17eSAlain Knaff rc->fill = fill;
1076a881162SPhillip Lougher else
1086a881162SPhillip Lougher rc->fill = nofill;
109bc22c17eSAlain Knaff rc->buffer = (uint8_t *)buffer;
110bc22c17eSAlain Knaff rc->buffer_size = buffer_size;
111bc22c17eSAlain Knaff rc->buffer_end = rc->buffer + rc->buffer_size;
112bc22c17eSAlain Knaff rc->ptr = rc->buffer;
113bc22c17eSAlain Knaff
114bc22c17eSAlain Knaff rc->code = 0;
115bc22c17eSAlain Knaff rc->range = 0xFFFFFFFF;
116bc22c17eSAlain Knaff }
117bc22c17eSAlain Knaff
rc_init_code(struct rc * rc)118bc22c17eSAlain Knaff static inline void INIT rc_init_code(struct rc *rc)
119bc22c17eSAlain Knaff {
120bc22c17eSAlain Knaff int i;
121bc22c17eSAlain Knaff
122bc22c17eSAlain Knaff for (i = 0; i < 5; i++) {
123bc22c17eSAlain Knaff if (rc->ptr >= rc->buffer_end)
124bc22c17eSAlain Knaff rc_read(rc);
125bc22c17eSAlain Knaff rc->code = (rc->code << 8) | *rc->ptr++;
126bc22c17eSAlain Knaff }
127bc22c17eSAlain Knaff }
128bc22c17eSAlain Knaff
129bc22c17eSAlain Knaff
130bc22c17eSAlain Knaff /* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */
rc_do_normalize(struct rc * rc)131bc22c17eSAlain Knaff static void INIT rc_do_normalize(struct rc *rc)
132bc22c17eSAlain Knaff {
133bc22c17eSAlain Knaff if (rc->ptr >= rc->buffer_end)
134bc22c17eSAlain Knaff rc_read(rc);
135bc22c17eSAlain Knaff rc->range <<= 8;
136bc22c17eSAlain Knaff rc->code = (rc->code << 8) | *rc->ptr++;
137bc22c17eSAlain Knaff }
rc_normalize(struct rc * rc)138bc22c17eSAlain Knaff static inline void INIT rc_normalize(struct rc *rc)
139bc22c17eSAlain Knaff {
140bc22c17eSAlain Knaff if (rc->range < (1 << RC_TOP_BITS))
141bc22c17eSAlain Knaff rc_do_normalize(rc);
142bc22c17eSAlain Knaff }
143bc22c17eSAlain Knaff
144bc22c17eSAlain Knaff /* Called 9 times */
145bc22c17eSAlain Knaff /* Why rc_is_bit_0_helper exists?
146bc22c17eSAlain Knaff *Because we want to always expose (rc->code < rc->bound) to optimizer
147bc22c17eSAlain Knaff */
rc_is_bit_0_helper(struct rc * rc,uint16_t * p)148bc22c17eSAlain Knaff static inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p)
149bc22c17eSAlain Knaff {
150bc22c17eSAlain Knaff rc_normalize(rc);
151bc22c17eSAlain Knaff rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
152bc22c17eSAlain Knaff return rc->bound;
153bc22c17eSAlain Knaff }
rc_is_bit_0(struct rc * rc,uint16_t * p)154bc22c17eSAlain Knaff static inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p)
155bc22c17eSAlain Knaff {
156bc22c17eSAlain Knaff uint32_t t = rc_is_bit_0_helper(rc, p);
157bc22c17eSAlain Knaff return rc->code < t;
158bc22c17eSAlain Knaff }
159bc22c17eSAlain Knaff
160bc22c17eSAlain Knaff /* Called ~10 times, but very small, thus inlined */
rc_update_bit_0(struct rc * rc,uint16_t * p)161bc22c17eSAlain Knaff static inline void INIT rc_update_bit_0(struct rc *rc, uint16_t *p)
162bc22c17eSAlain Knaff {
163bc22c17eSAlain Knaff rc->range = rc->bound;
164bc22c17eSAlain Knaff *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
165bc22c17eSAlain Knaff }
rc_update_bit_1(struct rc * rc,uint16_t * p)1666b01ed64SLasse Collin static inline void INIT rc_update_bit_1(struct rc *rc, uint16_t *p)
167bc22c17eSAlain Knaff {
168bc22c17eSAlain Knaff rc->range -= rc->bound;
169bc22c17eSAlain Knaff rc->code -= rc->bound;
170bc22c17eSAlain Knaff *p -= *p >> RC_MOVE_BITS;
171bc22c17eSAlain Knaff }
172bc22c17eSAlain Knaff
173bc22c17eSAlain Knaff /* Called 4 times in unlzma loop */
rc_get_bit(struct rc * rc,uint16_t * p,int * symbol)174bc22c17eSAlain Knaff static int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol)
175bc22c17eSAlain Knaff {
176bc22c17eSAlain Knaff if (rc_is_bit_0(rc, p)) {
177bc22c17eSAlain Knaff rc_update_bit_0(rc, p);
178bc22c17eSAlain Knaff *symbol *= 2;
179bc22c17eSAlain Knaff return 0;
180bc22c17eSAlain Knaff } else {
181bc22c17eSAlain Knaff rc_update_bit_1(rc, p);
182bc22c17eSAlain Knaff *symbol = *symbol * 2 + 1;
183bc22c17eSAlain Knaff return 1;
184bc22c17eSAlain Knaff }
185bc22c17eSAlain Knaff }
186bc22c17eSAlain Knaff
187bc22c17eSAlain Knaff /* Called once */
rc_direct_bit(struct rc * rc)188bc22c17eSAlain Knaff static inline int INIT rc_direct_bit(struct rc *rc)
189bc22c17eSAlain Knaff {
190bc22c17eSAlain Knaff rc_normalize(rc);
191bc22c17eSAlain Knaff rc->range >>= 1;
192bc22c17eSAlain Knaff if (rc->code >= rc->range) {
193bc22c17eSAlain Knaff rc->code -= rc->range;
194bc22c17eSAlain Knaff return 1;
195bc22c17eSAlain Knaff }
196bc22c17eSAlain Knaff return 0;
197bc22c17eSAlain Knaff }
198bc22c17eSAlain Knaff
199bc22c17eSAlain Knaff /* Called twice */
200bc22c17eSAlain Knaff static inline void INIT
rc_bit_tree_decode(struct rc * rc,uint16_t * p,int num_levels,int * symbol)201bc22c17eSAlain Knaff rc_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol)
202bc22c17eSAlain Knaff {
203bc22c17eSAlain Knaff int i = num_levels;
204bc22c17eSAlain Knaff
205bc22c17eSAlain Knaff *symbol = 1;
206bc22c17eSAlain Knaff while (i--)
207bc22c17eSAlain Knaff rc_get_bit(rc, p + *symbol, symbol);
208bc22c17eSAlain Knaff *symbol -= 1 << num_levels;
209bc22c17eSAlain Knaff }
210bc22c17eSAlain Knaff
211bc22c17eSAlain Knaff
212bc22c17eSAlain Knaff /*
213bc22c17eSAlain Knaff * Small lzma deflate implementation.
214bc22c17eSAlain Knaff * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org >
215bc22c17eSAlain Knaff *
216*d89775fcSAlexander A. Klimov * Based on LzmaDecode.c from the LZMA SDK 4.22 (https://www.7-zip.org/)
217bc22c17eSAlain Knaff * Copyright (C) 1999-2005 Igor Pavlov
218bc22c17eSAlain Knaff */
219bc22c17eSAlain Knaff
220bc22c17eSAlain Knaff
221bc22c17eSAlain Knaff struct lzma_header {
222bc22c17eSAlain Knaff uint8_t pos;
223bc22c17eSAlain Knaff uint32_t dict_size;
224bc22c17eSAlain Knaff uint64_t dst_size;
225bc22c17eSAlain Knaff } __attribute__ ((packed)) ;
226bc22c17eSAlain Knaff
227bc22c17eSAlain Knaff
228bc22c17eSAlain Knaff #define LZMA_BASE_SIZE 1846
229bc22c17eSAlain Knaff #define LZMA_LIT_SIZE 768
230bc22c17eSAlain Knaff
231bc22c17eSAlain Knaff #define LZMA_NUM_POS_BITS_MAX 4
232bc22c17eSAlain Knaff
233bc22c17eSAlain Knaff #define LZMA_LEN_NUM_LOW_BITS 3
234bc22c17eSAlain Knaff #define LZMA_LEN_NUM_MID_BITS 3
235bc22c17eSAlain Knaff #define LZMA_LEN_NUM_HIGH_BITS 8
236bc22c17eSAlain Knaff
237bc22c17eSAlain Knaff #define LZMA_LEN_CHOICE 0
238bc22c17eSAlain Knaff #define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1)
239bc22c17eSAlain Knaff #define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1)
240bc22c17eSAlain Knaff #define LZMA_LEN_MID (LZMA_LEN_LOW \
241bc22c17eSAlain Knaff + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS)))
242bc22c17eSAlain Knaff #define LZMA_LEN_HIGH (LZMA_LEN_MID \
243bc22c17eSAlain Knaff +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS)))
244bc22c17eSAlain Knaff #define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS))
245bc22c17eSAlain Knaff
246bc22c17eSAlain Knaff #define LZMA_NUM_STATES 12
247bc22c17eSAlain Knaff #define LZMA_NUM_LIT_STATES 7
248bc22c17eSAlain Knaff
249bc22c17eSAlain Knaff #define LZMA_START_POS_MODEL_INDEX 4
250bc22c17eSAlain Knaff #define LZMA_END_POS_MODEL_INDEX 14
251bc22c17eSAlain Knaff #define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1))
252bc22c17eSAlain Knaff
253bc22c17eSAlain Knaff #define LZMA_NUM_POS_SLOT_BITS 6
254bc22c17eSAlain Knaff #define LZMA_NUM_LEN_TO_POS_STATES 4
255bc22c17eSAlain Knaff
256bc22c17eSAlain Knaff #define LZMA_NUM_ALIGN_BITS 4
257bc22c17eSAlain Knaff
258bc22c17eSAlain Knaff #define LZMA_MATCH_MIN_LEN 2
259bc22c17eSAlain Knaff
260bc22c17eSAlain Knaff #define LZMA_IS_MATCH 0
261bc22c17eSAlain Knaff #define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
262bc22c17eSAlain Knaff #define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES)
263bc22c17eSAlain Knaff #define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES)
264bc22c17eSAlain Knaff #define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES)
265bc22c17eSAlain Knaff #define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES)
266bc22c17eSAlain Knaff #define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \
267bc22c17eSAlain Knaff + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX))
268bc22c17eSAlain Knaff #define LZMA_SPEC_POS (LZMA_POS_SLOT \
269bc22c17eSAlain Knaff +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS))
270bc22c17eSAlain Knaff #define LZMA_ALIGN (LZMA_SPEC_POS \
271bc22c17eSAlain Knaff + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX)
272bc22c17eSAlain Knaff #define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS))
273bc22c17eSAlain Knaff #define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS)
274bc22c17eSAlain Knaff #define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS)
275bc22c17eSAlain Knaff
276bc22c17eSAlain Knaff
277bc22c17eSAlain Knaff struct writer {
278bc22c17eSAlain Knaff uint8_t *buffer;
279bc22c17eSAlain Knaff uint8_t previous_byte;
280bc22c17eSAlain Knaff size_t buffer_pos;
281bc22c17eSAlain Knaff int bufsize;
282bc22c17eSAlain Knaff size_t global_pos;
283d97b07c5SYinghai Lu long (*flush)(void*, unsigned long);
284bc22c17eSAlain Knaff struct lzma_header *header;
285bc22c17eSAlain Knaff };
286bc22c17eSAlain Knaff
287bc22c17eSAlain Knaff struct cstate {
288bc22c17eSAlain Knaff int state;
289bc22c17eSAlain Knaff uint32_t rep0, rep1, rep2, rep3;
290bc22c17eSAlain Knaff };
291bc22c17eSAlain Knaff
get_pos(struct writer * wr)292bc22c17eSAlain Knaff static inline size_t INIT get_pos(struct writer *wr)
293bc22c17eSAlain Knaff {
294bc22c17eSAlain Knaff return
295bc22c17eSAlain Knaff wr->global_pos + wr->buffer_pos;
296bc22c17eSAlain Knaff }
297bc22c17eSAlain Knaff
peek_old_byte(struct writer * wr,uint32_t offs)298bc22c17eSAlain Knaff static inline uint8_t INIT peek_old_byte(struct writer *wr,
299bc22c17eSAlain Knaff uint32_t offs)
300bc22c17eSAlain Knaff {
301bc22c17eSAlain Knaff if (!wr->flush) {
302bc22c17eSAlain Knaff int32_t pos;
303bc22c17eSAlain Knaff while (offs > wr->header->dict_size)
304bc22c17eSAlain Knaff offs -= wr->header->dict_size;
305bc22c17eSAlain Knaff pos = wr->buffer_pos - offs;
306bc22c17eSAlain Knaff return wr->buffer[pos];
307bc22c17eSAlain Knaff } else {
308bc22c17eSAlain Knaff uint32_t pos = wr->buffer_pos - offs;
309bc22c17eSAlain Knaff while (pos >= wr->header->dict_size)
310bc22c17eSAlain Knaff pos += wr->header->dict_size;
311bc22c17eSAlain Knaff return wr->buffer[pos];
312bc22c17eSAlain Knaff }
313bc22c17eSAlain Knaff
314bc22c17eSAlain Knaff }
315bc22c17eSAlain Knaff
write_byte(struct writer * wr,uint8_t byte)316528941caSLasse Collin static inline int INIT write_byte(struct writer *wr, uint8_t byte)
317bc22c17eSAlain Knaff {
318bc22c17eSAlain Knaff wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte;
319bc22c17eSAlain Knaff if (wr->flush && wr->buffer_pos == wr->header->dict_size) {
320bc22c17eSAlain Knaff wr->buffer_pos = 0;
321bc22c17eSAlain Knaff wr->global_pos += wr->header->dict_size;
322528941caSLasse Collin if (wr->flush((char *)wr->buffer, wr->header->dict_size)
323528941caSLasse Collin != wr->header->dict_size)
324528941caSLasse Collin return -1;
325bc22c17eSAlain Knaff }
326528941caSLasse Collin return 0;
327bc22c17eSAlain Knaff }
328bc22c17eSAlain Knaff
329bc22c17eSAlain Knaff
copy_byte(struct writer * wr,uint32_t offs)330528941caSLasse Collin static inline int INIT copy_byte(struct writer *wr, uint32_t offs)
331bc22c17eSAlain Knaff {
332528941caSLasse Collin return write_byte(wr, peek_old_byte(wr, offs));
333bc22c17eSAlain Knaff }
334bc22c17eSAlain Knaff
copy_bytes(struct writer * wr,uint32_t rep0,int len)335528941caSLasse Collin static inline int INIT copy_bytes(struct writer *wr,
336bc22c17eSAlain Knaff uint32_t rep0, int len)
337bc22c17eSAlain Knaff {
338bc22c17eSAlain Knaff do {
339528941caSLasse Collin if (copy_byte(wr, rep0))
340528941caSLasse Collin return -1;
341bc22c17eSAlain Knaff len--;
342bc22c17eSAlain Knaff } while (len != 0 && wr->buffer_pos < wr->header->dst_size);
343528941caSLasse Collin
344528941caSLasse Collin return len;
345bc22c17eSAlain Knaff }
346bc22c17eSAlain Knaff
process_bit0(struct writer * wr,struct rc * rc,struct cstate * cst,uint16_t * p,int pos_state,uint16_t * prob,int lc,uint32_t literal_pos_mask)347528941caSLasse Collin static inline int INIT process_bit0(struct writer *wr, struct rc *rc,
348bc22c17eSAlain Knaff struct cstate *cst, uint16_t *p,
349bc22c17eSAlain Knaff int pos_state, uint16_t *prob,
350bc22c17eSAlain Knaff int lc, uint32_t literal_pos_mask) {
351bc22c17eSAlain Knaff int mi = 1;
352bc22c17eSAlain Knaff rc_update_bit_0(rc, prob);
353bc22c17eSAlain Knaff prob = (p + LZMA_LITERAL +
354bc22c17eSAlain Knaff (LZMA_LIT_SIZE
355bc22c17eSAlain Knaff * (((get_pos(wr) & literal_pos_mask) << lc)
356bc22c17eSAlain Knaff + (wr->previous_byte >> (8 - lc))))
357bc22c17eSAlain Knaff );
358bc22c17eSAlain Knaff
359bc22c17eSAlain Knaff if (cst->state >= LZMA_NUM_LIT_STATES) {
360bc22c17eSAlain Knaff int match_byte = peek_old_byte(wr, cst->rep0);
361bc22c17eSAlain Knaff do {
362bc22c17eSAlain Knaff int bit;
363bc22c17eSAlain Knaff uint16_t *prob_lit;
364bc22c17eSAlain Knaff
365bc22c17eSAlain Knaff match_byte <<= 1;
366bc22c17eSAlain Knaff bit = match_byte & 0x100;
367bc22c17eSAlain Knaff prob_lit = prob + 0x100 + bit + mi;
368bc22c17eSAlain Knaff if (rc_get_bit(rc, prob_lit, &mi)) {
369bc22c17eSAlain Knaff if (!bit)
370bc22c17eSAlain Knaff break;
371bc22c17eSAlain Knaff } else {
372bc22c17eSAlain Knaff if (bit)
373bc22c17eSAlain Knaff break;
374bc22c17eSAlain Knaff }
375bc22c17eSAlain Knaff } while (mi < 0x100);
376bc22c17eSAlain Knaff }
377bc22c17eSAlain Knaff while (mi < 0x100) {
378bc22c17eSAlain Knaff uint16_t *prob_lit = prob + mi;
379bc22c17eSAlain Knaff rc_get_bit(rc, prob_lit, &mi);
380bc22c17eSAlain Knaff }
381bc22c17eSAlain Knaff if (cst->state < 4)
382bc22c17eSAlain Knaff cst->state = 0;
383bc22c17eSAlain Knaff else if (cst->state < 10)
384bc22c17eSAlain Knaff cst->state -= 3;
385bc22c17eSAlain Knaff else
386bc22c17eSAlain Knaff cst->state -= 6;
387528941caSLasse Collin
388528941caSLasse Collin return write_byte(wr, mi);
389bc22c17eSAlain Knaff }
390bc22c17eSAlain Knaff
process_bit1(struct writer * wr,struct rc * rc,struct cstate * cst,uint16_t * p,int pos_state,uint16_t * prob)391528941caSLasse Collin static inline int INIT process_bit1(struct writer *wr, struct rc *rc,
392bc22c17eSAlain Knaff struct cstate *cst, uint16_t *p,
393bc22c17eSAlain Knaff int pos_state, uint16_t *prob) {
394bc22c17eSAlain Knaff int offset;
395bc22c17eSAlain Knaff uint16_t *prob_len;
396bc22c17eSAlain Knaff int num_bits;
397bc22c17eSAlain Knaff int len;
398bc22c17eSAlain Knaff
399bc22c17eSAlain Knaff rc_update_bit_1(rc, prob);
400bc22c17eSAlain Knaff prob = p + LZMA_IS_REP + cst->state;
401bc22c17eSAlain Knaff if (rc_is_bit_0(rc, prob)) {
402bc22c17eSAlain Knaff rc_update_bit_0(rc, prob);
403bc22c17eSAlain Knaff cst->rep3 = cst->rep2;
404bc22c17eSAlain Knaff cst->rep2 = cst->rep1;
405bc22c17eSAlain Knaff cst->rep1 = cst->rep0;
406bc22c17eSAlain Knaff cst->state = cst->state < LZMA_NUM_LIT_STATES ? 0 : 3;
407bc22c17eSAlain Knaff prob = p + LZMA_LEN_CODER;
408bc22c17eSAlain Knaff } else {
409bc22c17eSAlain Knaff rc_update_bit_1(rc, prob);
410bc22c17eSAlain Knaff prob = p + LZMA_IS_REP_G0 + cst->state;
411bc22c17eSAlain Knaff if (rc_is_bit_0(rc, prob)) {
412bc22c17eSAlain Knaff rc_update_bit_0(rc, prob);
413bc22c17eSAlain Knaff prob = (p + LZMA_IS_REP_0_LONG
414bc22c17eSAlain Knaff + (cst->state <<
415bc22c17eSAlain Knaff LZMA_NUM_POS_BITS_MAX) +
416bc22c17eSAlain Knaff pos_state);
417bc22c17eSAlain Knaff if (rc_is_bit_0(rc, prob)) {
418bc22c17eSAlain Knaff rc_update_bit_0(rc, prob);
419bc22c17eSAlain Knaff
420bc22c17eSAlain Knaff cst->state = cst->state < LZMA_NUM_LIT_STATES ?
421bc22c17eSAlain Knaff 9 : 11;
422528941caSLasse Collin return copy_byte(wr, cst->rep0);
423bc22c17eSAlain Knaff } else {
424bc22c17eSAlain Knaff rc_update_bit_1(rc, prob);
425bc22c17eSAlain Knaff }
426bc22c17eSAlain Knaff } else {
427bc22c17eSAlain Knaff uint32_t distance;
428bc22c17eSAlain Knaff
429bc22c17eSAlain Knaff rc_update_bit_1(rc, prob);
430bc22c17eSAlain Knaff prob = p + LZMA_IS_REP_G1 + cst->state;
431bc22c17eSAlain Knaff if (rc_is_bit_0(rc, prob)) {
432bc22c17eSAlain Knaff rc_update_bit_0(rc, prob);
433bc22c17eSAlain Knaff distance = cst->rep1;
434bc22c17eSAlain Knaff } else {
435bc22c17eSAlain Knaff rc_update_bit_1(rc, prob);
436bc22c17eSAlain Knaff prob = p + LZMA_IS_REP_G2 + cst->state;
437bc22c17eSAlain Knaff if (rc_is_bit_0(rc, prob)) {
438bc22c17eSAlain Knaff rc_update_bit_0(rc, prob);
439bc22c17eSAlain Knaff distance = cst->rep2;
440bc22c17eSAlain Knaff } else {
441bc22c17eSAlain Knaff rc_update_bit_1(rc, prob);
442bc22c17eSAlain Knaff distance = cst->rep3;
443bc22c17eSAlain Knaff cst->rep3 = cst->rep2;
444bc22c17eSAlain Knaff }
445bc22c17eSAlain Knaff cst->rep2 = cst->rep1;
446bc22c17eSAlain Knaff }
447bc22c17eSAlain Knaff cst->rep1 = cst->rep0;
448bc22c17eSAlain Knaff cst->rep0 = distance;
449bc22c17eSAlain Knaff }
450bc22c17eSAlain Knaff cst->state = cst->state < LZMA_NUM_LIT_STATES ? 8 : 11;
451bc22c17eSAlain Knaff prob = p + LZMA_REP_LEN_CODER;
452bc22c17eSAlain Knaff }
453bc22c17eSAlain Knaff
454bc22c17eSAlain Knaff prob_len = prob + LZMA_LEN_CHOICE;
455bc22c17eSAlain Knaff if (rc_is_bit_0(rc, prob_len)) {
456bc22c17eSAlain Knaff rc_update_bit_0(rc, prob_len);
457bc22c17eSAlain Knaff prob_len = (prob + LZMA_LEN_LOW
458bc22c17eSAlain Knaff + (pos_state <<
459bc22c17eSAlain Knaff LZMA_LEN_NUM_LOW_BITS));
460bc22c17eSAlain Knaff offset = 0;
461bc22c17eSAlain Knaff num_bits = LZMA_LEN_NUM_LOW_BITS;
462bc22c17eSAlain Knaff } else {
463bc22c17eSAlain Knaff rc_update_bit_1(rc, prob_len);
464bc22c17eSAlain Knaff prob_len = prob + LZMA_LEN_CHOICE_2;
465bc22c17eSAlain Knaff if (rc_is_bit_0(rc, prob_len)) {
466bc22c17eSAlain Knaff rc_update_bit_0(rc, prob_len);
467bc22c17eSAlain Knaff prob_len = (prob + LZMA_LEN_MID
468bc22c17eSAlain Knaff + (pos_state <<
469bc22c17eSAlain Knaff LZMA_LEN_NUM_MID_BITS));
470bc22c17eSAlain Knaff offset = 1 << LZMA_LEN_NUM_LOW_BITS;
471bc22c17eSAlain Knaff num_bits = LZMA_LEN_NUM_MID_BITS;
472bc22c17eSAlain Knaff } else {
473bc22c17eSAlain Knaff rc_update_bit_1(rc, prob_len);
474bc22c17eSAlain Knaff prob_len = prob + LZMA_LEN_HIGH;
475bc22c17eSAlain Knaff offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
476bc22c17eSAlain Knaff + (1 << LZMA_LEN_NUM_MID_BITS));
477bc22c17eSAlain Knaff num_bits = LZMA_LEN_NUM_HIGH_BITS;
478bc22c17eSAlain Knaff }
479bc22c17eSAlain Knaff }
480bc22c17eSAlain Knaff
481bc22c17eSAlain Knaff rc_bit_tree_decode(rc, prob_len, num_bits, &len);
482bc22c17eSAlain Knaff len += offset;
483bc22c17eSAlain Knaff
484bc22c17eSAlain Knaff if (cst->state < 4) {
485bc22c17eSAlain Knaff int pos_slot;
486bc22c17eSAlain Knaff
487bc22c17eSAlain Knaff cst->state += LZMA_NUM_LIT_STATES;
488bc22c17eSAlain Knaff prob =
489bc22c17eSAlain Knaff p + LZMA_POS_SLOT +
490bc22c17eSAlain Knaff ((len <
491bc22c17eSAlain Knaff LZMA_NUM_LEN_TO_POS_STATES ? len :
492bc22c17eSAlain Knaff LZMA_NUM_LEN_TO_POS_STATES - 1)
493bc22c17eSAlain Knaff << LZMA_NUM_POS_SLOT_BITS);
494bc22c17eSAlain Knaff rc_bit_tree_decode(rc, prob,
495bc22c17eSAlain Knaff LZMA_NUM_POS_SLOT_BITS,
496bc22c17eSAlain Knaff &pos_slot);
497bc22c17eSAlain Knaff if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
498bc22c17eSAlain Knaff int i, mi;
499bc22c17eSAlain Knaff num_bits = (pos_slot >> 1) - 1;
500bc22c17eSAlain Knaff cst->rep0 = 2 | (pos_slot & 1);
501bc22c17eSAlain Knaff if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
502bc22c17eSAlain Knaff cst->rep0 <<= num_bits;
503bc22c17eSAlain Knaff prob = p + LZMA_SPEC_POS +
504bc22c17eSAlain Knaff cst->rep0 - pos_slot - 1;
505bc22c17eSAlain Knaff } else {
506bc22c17eSAlain Knaff num_bits -= LZMA_NUM_ALIGN_BITS;
507bc22c17eSAlain Knaff while (num_bits--)
508bc22c17eSAlain Knaff cst->rep0 = (cst->rep0 << 1) |
509bc22c17eSAlain Knaff rc_direct_bit(rc);
510bc22c17eSAlain Knaff prob = p + LZMA_ALIGN;
511bc22c17eSAlain Knaff cst->rep0 <<= LZMA_NUM_ALIGN_BITS;
512bc22c17eSAlain Knaff num_bits = LZMA_NUM_ALIGN_BITS;
513bc22c17eSAlain Knaff }
514bc22c17eSAlain Knaff i = 1;
515bc22c17eSAlain Knaff mi = 1;
516bc22c17eSAlain Knaff while (num_bits--) {
517bc22c17eSAlain Knaff if (rc_get_bit(rc, prob + mi, &mi))
518bc22c17eSAlain Knaff cst->rep0 |= i;
519bc22c17eSAlain Knaff i <<= 1;
520bc22c17eSAlain Knaff }
521bc22c17eSAlain Knaff } else
522bc22c17eSAlain Knaff cst->rep0 = pos_slot;
523bc22c17eSAlain Knaff if (++(cst->rep0) == 0)
524528941caSLasse Collin return 0;
525eb0cf3e1SLasse Collin if (cst->rep0 > wr->header->dict_size
526eb0cf3e1SLasse Collin || cst->rep0 > get_pos(wr))
527eb0cf3e1SLasse Collin return -1;
528bc22c17eSAlain Knaff }
529bc22c17eSAlain Knaff
530bc22c17eSAlain Knaff len += LZMA_MATCH_MIN_LEN;
531bc22c17eSAlain Knaff
532528941caSLasse Collin return copy_bytes(wr, cst->rep0, len);
533bc22c17eSAlain Knaff }
534bc22c17eSAlain Knaff
535bc22c17eSAlain Knaff
536bc22c17eSAlain Knaff
unlzma(unsigned char * buf,long in_len,long (* fill)(void *,unsigned long),long (* flush)(void *,unsigned long),unsigned char * output,long * posp,void (* error)(char * x))537d97b07c5SYinghai Lu STATIC inline int INIT unlzma(unsigned char *buf, long in_len,
538d97b07c5SYinghai Lu long (*fill)(void*, unsigned long),
539d97b07c5SYinghai Lu long (*flush)(void*, unsigned long),
540bc22c17eSAlain Knaff unsigned char *output,
541d97b07c5SYinghai Lu long *posp,
54293685ad2SLasse Collin void(*error)(char *x)
543bc22c17eSAlain Knaff )
544bc22c17eSAlain Knaff {
545bc22c17eSAlain Knaff struct lzma_header header;
546bc22c17eSAlain Knaff int lc, pb, lp;
547bc22c17eSAlain Knaff uint32_t pos_state_mask;
548bc22c17eSAlain Knaff uint32_t literal_pos_mask;
549bc22c17eSAlain Knaff uint16_t *p;
550bc22c17eSAlain Knaff int num_probs;
551bc22c17eSAlain Knaff struct rc rc;
552bc22c17eSAlain Knaff int i, mi;
553bc22c17eSAlain Knaff struct writer wr;
554bc22c17eSAlain Knaff struct cstate cst;
555bc22c17eSAlain Knaff unsigned char *inbuf;
556bc22c17eSAlain Knaff int ret = -1;
557bc22c17eSAlain Knaff
55893685ad2SLasse Collin rc.error = error;
559b1af4315SPhillip Lougher
560bc22c17eSAlain Knaff if (buf)
561bc22c17eSAlain Knaff inbuf = buf;
562bc22c17eSAlain Knaff else
563bc22c17eSAlain Knaff inbuf = malloc(LZMA_IOBUF_SIZE);
564bc22c17eSAlain Knaff if (!inbuf) {
56590802ed9SPaul Bolle error("Could not allocate input buffer");
566bc22c17eSAlain Knaff goto exit_0;
567bc22c17eSAlain Knaff }
568bc22c17eSAlain Knaff
569bc22c17eSAlain Knaff cst.state = 0;
570bc22c17eSAlain Knaff cst.rep0 = cst.rep1 = cst.rep2 = cst.rep3 = 1;
571bc22c17eSAlain Knaff
572bc22c17eSAlain Knaff wr.header = &header;
573bc22c17eSAlain Knaff wr.flush = flush;
574bc22c17eSAlain Knaff wr.global_pos = 0;
575bc22c17eSAlain Knaff wr.previous_byte = 0;
576bc22c17eSAlain Knaff wr.buffer_pos = 0;
577bc22c17eSAlain Knaff
578bc22c17eSAlain Knaff rc_init(&rc, fill, inbuf, in_len);
579bc22c17eSAlain Knaff
580bc22c17eSAlain Knaff for (i = 0; i < sizeof(header); i++) {
581bc22c17eSAlain Knaff if (rc.ptr >= rc.buffer_end)
582bc22c17eSAlain Knaff rc_read(&rc);
583bc22c17eSAlain Knaff ((unsigned char *)&header)[i] = *rc.ptr++;
584bc22c17eSAlain Knaff }
585bc22c17eSAlain Knaff
5868218a437SLasse Collin if (header.pos >= (9 * 5 * 5)) {
587bc22c17eSAlain Knaff error("bad header");
5888218a437SLasse Collin goto exit_1;
5898218a437SLasse Collin }
590bc22c17eSAlain Knaff
591bc22c17eSAlain Knaff mi = 0;
592bc22c17eSAlain Knaff lc = header.pos;
593bc22c17eSAlain Knaff while (lc >= 9) {
594bc22c17eSAlain Knaff mi++;
595bc22c17eSAlain Knaff lc -= 9;
596bc22c17eSAlain Knaff }
597bc22c17eSAlain Knaff pb = 0;
598bc22c17eSAlain Knaff lp = mi;
599bc22c17eSAlain Knaff while (lp >= 5) {
600bc22c17eSAlain Knaff pb++;
601bc22c17eSAlain Knaff lp -= 5;
602bc22c17eSAlain Knaff }
603bc22c17eSAlain Knaff pos_state_mask = (1 << pb) - 1;
604bc22c17eSAlain Knaff literal_pos_mask = (1 << lp) - 1;
605bc22c17eSAlain Knaff
606bc22c17eSAlain Knaff ENDIAN_CONVERT(header.dict_size);
607bc22c17eSAlain Knaff ENDIAN_CONVERT(header.dst_size);
608bc22c17eSAlain Knaff
609bc22c17eSAlain Knaff if (header.dict_size == 0)
610bc22c17eSAlain Knaff header.dict_size = 1;
611bc22c17eSAlain Knaff
612bc22c17eSAlain Knaff if (output)
613bc22c17eSAlain Knaff wr.buffer = output;
614bc22c17eSAlain Knaff else {
615bc22c17eSAlain Knaff wr.bufsize = MIN(header.dst_size, header.dict_size);
616bc22c17eSAlain Knaff wr.buffer = large_malloc(wr.bufsize);
617bc22c17eSAlain Knaff }
618bc22c17eSAlain Knaff if (wr.buffer == NULL)
619bc22c17eSAlain Knaff goto exit_1;
620bc22c17eSAlain Knaff
621bc22c17eSAlain Knaff num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
622bc22c17eSAlain Knaff p = (uint16_t *) large_malloc(num_probs * sizeof(*p));
623e4e29dc4SFabio Estevam if (p == NULL)
624bc22c17eSAlain Knaff goto exit_2;
625bc22c17eSAlain Knaff num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp));
626bc22c17eSAlain Knaff for (i = 0; i < num_probs; i++)
627bc22c17eSAlain Knaff p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
628bc22c17eSAlain Knaff
629bc22c17eSAlain Knaff rc_init_code(&rc);
630bc22c17eSAlain Knaff
631bc22c17eSAlain Knaff while (get_pos(&wr) < header.dst_size) {
632bc22c17eSAlain Knaff int pos_state = get_pos(&wr) & pos_state_mask;
633bc22c17eSAlain Knaff uint16_t *prob = p + LZMA_IS_MATCH +
634bc22c17eSAlain Knaff (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state;
635528941caSLasse Collin if (rc_is_bit_0(&rc, prob)) {
636528941caSLasse Collin if (process_bit0(&wr, &rc, &cst, p, pos_state, prob,
637528941caSLasse Collin lc, literal_pos_mask)) {
638528941caSLasse Collin error("LZMA data is corrupt");
639528941caSLasse Collin goto exit_3;
640528941caSLasse Collin }
641528941caSLasse Collin } else {
642528941caSLasse Collin if (process_bit1(&wr, &rc, &cst, p, pos_state, prob)) {
643528941caSLasse Collin error("LZMA data is corrupt");
644528941caSLasse Collin goto exit_3;
645528941caSLasse Collin }
646bc22c17eSAlain Knaff if (cst.rep0 == 0)
647bc22c17eSAlain Knaff break;
648bc22c17eSAlain Knaff }
649278208d9SLasse Collin if (rc.buffer_size <= 0)
650278208d9SLasse Collin goto exit_3;
651bc22c17eSAlain Knaff }
652bc22c17eSAlain Knaff
653bc22c17eSAlain Knaff if (posp)
654bc22c17eSAlain Knaff *posp = rc.ptr-rc.buffer;
655528941caSLasse Collin if (!wr.flush || wr.flush(wr.buffer, wr.buffer_pos) == wr.buffer_pos)
656bc22c17eSAlain Knaff ret = 0;
657278208d9SLasse Collin exit_3:
658bc22c17eSAlain Knaff large_free(p);
659bc22c17eSAlain Knaff exit_2:
660bc22c17eSAlain Knaff if (!output)
661bc22c17eSAlain Knaff large_free(wr.buffer);
662bc22c17eSAlain Knaff exit_1:
663bc22c17eSAlain Knaff if (!buf)
664bc22c17eSAlain Knaff free(inbuf);
665bc22c17eSAlain Knaff exit_0:
666bc22c17eSAlain Knaff return ret;
667bc22c17eSAlain Knaff }
668bc22c17eSAlain Knaff
669b1af4315SPhillip Lougher #ifdef PREBOOT
__decompress(unsigned char * buf,long in_len,long (* fill)(void *,unsigned long),long (* flush)(void *,unsigned long),unsigned char * output,long out_len,long * posp,void (* error)(char * x))6702d3862d2SYinghai Lu STATIC int INIT __decompress(unsigned char *buf, long in_len,
671d97b07c5SYinghai Lu long (*fill)(void*, unsigned long),
672d97b07c5SYinghai Lu long (*flush)(void*, unsigned long),
6732d3862d2SYinghai Lu unsigned char *output, long out_len,
674d97b07c5SYinghai Lu long *posp,
6752d3862d2SYinghai Lu void (*error)(char *x))
676b1af4315SPhillip Lougher {
67793685ad2SLasse Collin return unlzma(buf, in_len - 4, fill, flush, output, posp, error);
678b1af4315SPhillip Lougher }
679b1af4315SPhillip Lougher #endif
680