VisionFive2 Linux kernel

StarFive Tech Linux Kernel for VisionFive (JH7110) boards (mirror)

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