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