18c2ecf20Sopenharmony_ci/* Lzma decompressor for Linux kernel. Shamelessly snarfed 28c2ecf20Sopenharmony_ci *from busybox 1.1.1 38c2ecf20Sopenharmony_ci * 48c2ecf20Sopenharmony_ci *Linux kernel adaptation 58c2ecf20Sopenharmony_ci *Copyright (C) 2006 Alain < alain@knaff.lu > 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci *Based on small lzma deflate implementation/Small range coder 88c2ecf20Sopenharmony_ci *implementation for lzma. 98c2ecf20Sopenharmony_ci *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > 108c2ecf20Sopenharmony_ci * 118c2ecf20Sopenharmony_ci *Based on LzmaDecode.c from the LZMA SDK 4.22 (https://www.7-zip.org/) 128c2ecf20Sopenharmony_ci *Copyright (C) 1999-2005 Igor Pavlov 138c2ecf20Sopenharmony_ci * 148c2ecf20Sopenharmony_ci *Copyrights of the parts, see headers below. 158c2ecf20Sopenharmony_ci * 168c2ecf20Sopenharmony_ci * 178c2ecf20Sopenharmony_ci *This program is free software; you can redistribute it and/or 188c2ecf20Sopenharmony_ci *modify it under the terms of the GNU Lesser General Public 198c2ecf20Sopenharmony_ci *License as published by the Free Software Foundation; either 208c2ecf20Sopenharmony_ci *version 2.1 of the License, or (at your option) any later version. 218c2ecf20Sopenharmony_ci * 228c2ecf20Sopenharmony_ci *This program is distributed in the hope that it will be useful, 238c2ecf20Sopenharmony_ci *but WITHOUT ANY WARRANTY; without even the implied warranty of 248c2ecf20Sopenharmony_ci *MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 258c2ecf20Sopenharmony_ci *Lesser General Public License for more details. 268c2ecf20Sopenharmony_ci * 278c2ecf20Sopenharmony_ci *You should have received a copy of the GNU Lesser General Public 288c2ecf20Sopenharmony_ci *License along with this library; if not, write to the Free Software 298c2ecf20Sopenharmony_ci *Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 308c2ecf20Sopenharmony_ci */ 318c2ecf20Sopenharmony_ci 328c2ecf20Sopenharmony_ci#ifdef STATIC 338c2ecf20Sopenharmony_ci#define PREBOOT 348c2ecf20Sopenharmony_ci#else 358c2ecf20Sopenharmony_ci#include <linux/decompress/unlzma.h> 368c2ecf20Sopenharmony_ci#endif /* STATIC */ 378c2ecf20Sopenharmony_ci 388c2ecf20Sopenharmony_ci#include <linux/decompress/mm.h> 398c2ecf20Sopenharmony_ci 408c2ecf20Sopenharmony_ci#define MIN(a, b) (((a) < (b)) ? (a) : (b)) 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_cistatic long long INIT read_int(unsigned char *ptr, int size) 438c2ecf20Sopenharmony_ci{ 448c2ecf20Sopenharmony_ci int i; 458c2ecf20Sopenharmony_ci long long ret = 0; 468c2ecf20Sopenharmony_ci 478c2ecf20Sopenharmony_ci for (i = 0; i < size; i++) 488c2ecf20Sopenharmony_ci ret = (ret << 8) | ptr[size-i-1]; 498c2ecf20Sopenharmony_ci return ret; 508c2ecf20Sopenharmony_ci} 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci#define ENDIAN_CONVERT(x) \ 538c2ecf20Sopenharmony_ci x = (typeof(x))read_int((unsigned char *)&x, sizeof(x)) 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_ci 568c2ecf20Sopenharmony_ci/* Small range coder implementation for lzma. 578c2ecf20Sopenharmony_ci *Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > 588c2ecf20Sopenharmony_ci * 598c2ecf20Sopenharmony_ci *Based on LzmaDecode.c from the LZMA SDK 4.22 (https://www.7-zip.org/) 608c2ecf20Sopenharmony_ci *Copyright (c) 1999-2005 Igor Pavlov 618c2ecf20Sopenharmony_ci */ 628c2ecf20Sopenharmony_ci 638c2ecf20Sopenharmony_ci#include <linux/compiler.h> 648c2ecf20Sopenharmony_ci 658c2ecf20Sopenharmony_ci#define LZMA_IOBUF_SIZE 0x10000 668c2ecf20Sopenharmony_ci 678c2ecf20Sopenharmony_cistruct rc { 688c2ecf20Sopenharmony_ci long (*fill)(void*, unsigned long); 698c2ecf20Sopenharmony_ci uint8_t *ptr; 708c2ecf20Sopenharmony_ci uint8_t *buffer; 718c2ecf20Sopenharmony_ci uint8_t *buffer_end; 728c2ecf20Sopenharmony_ci long buffer_size; 738c2ecf20Sopenharmony_ci uint32_t code; 748c2ecf20Sopenharmony_ci uint32_t range; 758c2ecf20Sopenharmony_ci uint32_t bound; 768c2ecf20Sopenharmony_ci void (*error)(char *); 778c2ecf20Sopenharmony_ci}; 788c2ecf20Sopenharmony_ci 798c2ecf20Sopenharmony_ci 808c2ecf20Sopenharmony_ci#define RC_TOP_BITS 24 818c2ecf20Sopenharmony_ci#define RC_MOVE_BITS 5 828c2ecf20Sopenharmony_ci#define RC_MODEL_TOTAL_BITS 11 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci 858c2ecf20Sopenharmony_cistatic long INIT nofill(void *buffer, unsigned long len) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci return -1; 888c2ecf20Sopenharmony_ci} 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci/* Called twice: once at startup and once in rc_normalize() */ 918c2ecf20Sopenharmony_cistatic void INIT rc_read(struct rc *rc) 928c2ecf20Sopenharmony_ci{ 938c2ecf20Sopenharmony_ci rc->buffer_size = rc->fill((char *)rc->buffer, LZMA_IOBUF_SIZE); 948c2ecf20Sopenharmony_ci if (rc->buffer_size <= 0) 958c2ecf20Sopenharmony_ci rc->error("unexpected EOF"); 968c2ecf20Sopenharmony_ci rc->ptr = rc->buffer; 978c2ecf20Sopenharmony_ci rc->buffer_end = rc->buffer + rc->buffer_size; 988c2ecf20Sopenharmony_ci} 998c2ecf20Sopenharmony_ci 1008c2ecf20Sopenharmony_ci/* Called once */ 1018c2ecf20Sopenharmony_cistatic inline void INIT rc_init(struct rc *rc, 1028c2ecf20Sopenharmony_ci long (*fill)(void*, unsigned long), 1038c2ecf20Sopenharmony_ci char *buffer, long buffer_size) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci if (fill) 1068c2ecf20Sopenharmony_ci rc->fill = fill; 1078c2ecf20Sopenharmony_ci else 1088c2ecf20Sopenharmony_ci rc->fill = nofill; 1098c2ecf20Sopenharmony_ci rc->buffer = (uint8_t *)buffer; 1108c2ecf20Sopenharmony_ci rc->buffer_size = buffer_size; 1118c2ecf20Sopenharmony_ci rc->buffer_end = rc->buffer + rc->buffer_size; 1128c2ecf20Sopenharmony_ci rc->ptr = rc->buffer; 1138c2ecf20Sopenharmony_ci 1148c2ecf20Sopenharmony_ci rc->code = 0; 1158c2ecf20Sopenharmony_ci rc->range = 0xFFFFFFFF; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic inline void INIT rc_init_code(struct rc *rc) 1198c2ecf20Sopenharmony_ci{ 1208c2ecf20Sopenharmony_ci int i; 1218c2ecf20Sopenharmony_ci 1228c2ecf20Sopenharmony_ci for (i = 0; i < 5; i++) { 1238c2ecf20Sopenharmony_ci if (rc->ptr >= rc->buffer_end) 1248c2ecf20Sopenharmony_ci rc_read(rc); 1258c2ecf20Sopenharmony_ci rc->code = (rc->code << 8) | *rc->ptr++; 1268c2ecf20Sopenharmony_ci } 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci 1308c2ecf20Sopenharmony_ci/* Called twice, but one callsite is in inline'd rc_is_bit_0_helper() */ 1318c2ecf20Sopenharmony_cistatic void INIT rc_do_normalize(struct rc *rc) 1328c2ecf20Sopenharmony_ci{ 1338c2ecf20Sopenharmony_ci if (rc->ptr >= rc->buffer_end) 1348c2ecf20Sopenharmony_ci rc_read(rc); 1358c2ecf20Sopenharmony_ci rc->range <<= 8; 1368c2ecf20Sopenharmony_ci rc->code = (rc->code << 8) | *rc->ptr++; 1378c2ecf20Sopenharmony_ci} 1388c2ecf20Sopenharmony_cistatic inline void INIT rc_normalize(struct rc *rc) 1398c2ecf20Sopenharmony_ci{ 1408c2ecf20Sopenharmony_ci if (rc->range < (1 << RC_TOP_BITS)) 1418c2ecf20Sopenharmony_ci rc_do_normalize(rc); 1428c2ecf20Sopenharmony_ci} 1438c2ecf20Sopenharmony_ci 1448c2ecf20Sopenharmony_ci/* Called 9 times */ 1458c2ecf20Sopenharmony_ci/* Why rc_is_bit_0_helper exists? 1468c2ecf20Sopenharmony_ci *Because we want to always expose (rc->code < rc->bound) to optimizer 1478c2ecf20Sopenharmony_ci */ 1488c2ecf20Sopenharmony_cistatic inline uint32_t INIT rc_is_bit_0_helper(struct rc *rc, uint16_t *p) 1498c2ecf20Sopenharmony_ci{ 1508c2ecf20Sopenharmony_ci rc_normalize(rc); 1518c2ecf20Sopenharmony_ci rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS); 1528c2ecf20Sopenharmony_ci return rc->bound; 1538c2ecf20Sopenharmony_ci} 1548c2ecf20Sopenharmony_cistatic inline int INIT rc_is_bit_0(struct rc *rc, uint16_t *p) 1558c2ecf20Sopenharmony_ci{ 1568c2ecf20Sopenharmony_ci uint32_t t = rc_is_bit_0_helper(rc, p); 1578c2ecf20Sopenharmony_ci return rc->code < t; 1588c2ecf20Sopenharmony_ci} 1598c2ecf20Sopenharmony_ci 1608c2ecf20Sopenharmony_ci/* Called ~10 times, but very small, thus inlined */ 1618c2ecf20Sopenharmony_cistatic inline void INIT rc_update_bit_0(struct rc *rc, uint16_t *p) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci rc->range = rc->bound; 1648c2ecf20Sopenharmony_ci *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; 1658c2ecf20Sopenharmony_ci} 1668c2ecf20Sopenharmony_cistatic inline void INIT rc_update_bit_1(struct rc *rc, uint16_t *p) 1678c2ecf20Sopenharmony_ci{ 1688c2ecf20Sopenharmony_ci rc->range -= rc->bound; 1698c2ecf20Sopenharmony_ci rc->code -= rc->bound; 1708c2ecf20Sopenharmony_ci *p -= *p >> RC_MOVE_BITS; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_ci/* Called 4 times in unlzma loop */ 1748c2ecf20Sopenharmony_cistatic int INIT rc_get_bit(struct rc *rc, uint16_t *p, int *symbol) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, p)) { 1778c2ecf20Sopenharmony_ci rc_update_bit_0(rc, p); 1788c2ecf20Sopenharmony_ci *symbol *= 2; 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci } else { 1818c2ecf20Sopenharmony_ci rc_update_bit_1(rc, p); 1828c2ecf20Sopenharmony_ci *symbol = *symbol * 2 + 1; 1838c2ecf20Sopenharmony_ci return 1; 1848c2ecf20Sopenharmony_ci } 1858c2ecf20Sopenharmony_ci} 1868c2ecf20Sopenharmony_ci 1878c2ecf20Sopenharmony_ci/* Called once */ 1888c2ecf20Sopenharmony_cistatic inline int INIT rc_direct_bit(struct rc *rc) 1898c2ecf20Sopenharmony_ci{ 1908c2ecf20Sopenharmony_ci rc_normalize(rc); 1918c2ecf20Sopenharmony_ci rc->range >>= 1; 1928c2ecf20Sopenharmony_ci if (rc->code >= rc->range) { 1938c2ecf20Sopenharmony_ci rc->code -= rc->range; 1948c2ecf20Sopenharmony_ci return 1; 1958c2ecf20Sopenharmony_ci } 1968c2ecf20Sopenharmony_ci return 0; 1978c2ecf20Sopenharmony_ci} 1988c2ecf20Sopenharmony_ci 1998c2ecf20Sopenharmony_ci/* Called twice */ 2008c2ecf20Sopenharmony_cistatic inline void INIT 2018c2ecf20Sopenharmony_circ_bit_tree_decode(struct rc *rc, uint16_t *p, int num_levels, int *symbol) 2028c2ecf20Sopenharmony_ci{ 2038c2ecf20Sopenharmony_ci int i = num_levels; 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci *symbol = 1; 2068c2ecf20Sopenharmony_ci while (i--) 2078c2ecf20Sopenharmony_ci rc_get_bit(rc, p + *symbol, symbol); 2088c2ecf20Sopenharmony_ci *symbol -= 1 << num_levels; 2098c2ecf20Sopenharmony_ci} 2108c2ecf20Sopenharmony_ci 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci/* 2138c2ecf20Sopenharmony_ci * Small lzma deflate implementation. 2148c2ecf20Sopenharmony_ci * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > 2158c2ecf20Sopenharmony_ci * 2168c2ecf20Sopenharmony_ci * Based on LzmaDecode.c from the LZMA SDK 4.22 (https://www.7-zip.org/) 2178c2ecf20Sopenharmony_ci * Copyright (C) 1999-2005 Igor Pavlov 2188c2ecf20Sopenharmony_ci */ 2198c2ecf20Sopenharmony_ci 2208c2ecf20Sopenharmony_ci 2218c2ecf20Sopenharmony_cistruct lzma_header { 2228c2ecf20Sopenharmony_ci uint8_t pos; 2238c2ecf20Sopenharmony_ci uint32_t dict_size; 2248c2ecf20Sopenharmony_ci uint64_t dst_size; 2258c2ecf20Sopenharmony_ci} __attribute__ ((packed)) ; 2268c2ecf20Sopenharmony_ci 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci#define LZMA_BASE_SIZE 1846 2298c2ecf20Sopenharmony_ci#define LZMA_LIT_SIZE 768 2308c2ecf20Sopenharmony_ci 2318c2ecf20Sopenharmony_ci#define LZMA_NUM_POS_BITS_MAX 4 2328c2ecf20Sopenharmony_ci 2338c2ecf20Sopenharmony_ci#define LZMA_LEN_NUM_LOW_BITS 3 2348c2ecf20Sopenharmony_ci#define LZMA_LEN_NUM_MID_BITS 3 2358c2ecf20Sopenharmony_ci#define LZMA_LEN_NUM_HIGH_BITS 8 2368c2ecf20Sopenharmony_ci 2378c2ecf20Sopenharmony_ci#define LZMA_LEN_CHOICE 0 2388c2ecf20Sopenharmony_ci#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) 2398c2ecf20Sopenharmony_ci#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) 2408c2ecf20Sopenharmony_ci#define LZMA_LEN_MID (LZMA_LEN_LOW \ 2418c2ecf20Sopenharmony_ci + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) 2428c2ecf20Sopenharmony_ci#define LZMA_LEN_HIGH (LZMA_LEN_MID \ 2438c2ecf20Sopenharmony_ci +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) 2448c2ecf20Sopenharmony_ci#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) 2458c2ecf20Sopenharmony_ci 2468c2ecf20Sopenharmony_ci#define LZMA_NUM_STATES 12 2478c2ecf20Sopenharmony_ci#define LZMA_NUM_LIT_STATES 7 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci#define LZMA_START_POS_MODEL_INDEX 4 2508c2ecf20Sopenharmony_ci#define LZMA_END_POS_MODEL_INDEX 14 2518c2ecf20Sopenharmony_ci#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) 2528c2ecf20Sopenharmony_ci 2538c2ecf20Sopenharmony_ci#define LZMA_NUM_POS_SLOT_BITS 6 2548c2ecf20Sopenharmony_ci#define LZMA_NUM_LEN_TO_POS_STATES 4 2558c2ecf20Sopenharmony_ci 2568c2ecf20Sopenharmony_ci#define LZMA_NUM_ALIGN_BITS 4 2578c2ecf20Sopenharmony_ci 2588c2ecf20Sopenharmony_ci#define LZMA_MATCH_MIN_LEN 2 2598c2ecf20Sopenharmony_ci 2608c2ecf20Sopenharmony_ci#define LZMA_IS_MATCH 0 2618c2ecf20Sopenharmony_ci#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) 2628c2ecf20Sopenharmony_ci#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) 2638c2ecf20Sopenharmony_ci#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) 2648c2ecf20Sopenharmony_ci#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) 2658c2ecf20Sopenharmony_ci#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) 2668c2ecf20Sopenharmony_ci#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ 2678c2ecf20Sopenharmony_ci + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) 2688c2ecf20Sopenharmony_ci#define LZMA_SPEC_POS (LZMA_POS_SLOT \ 2698c2ecf20Sopenharmony_ci +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) 2708c2ecf20Sopenharmony_ci#define LZMA_ALIGN (LZMA_SPEC_POS \ 2718c2ecf20Sopenharmony_ci + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) 2728c2ecf20Sopenharmony_ci#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) 2738c2ecf20Sopenharmony_ci#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) 2748c2ecf20Sopenharmony_ci#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) 2758c2ecf20Sopenharmony_ci 2768c2ecf20Sopenharmony_ci 2778c2ecf20Sopenharmony_cistruct writer { 2788c2ecf20Sopenharmony_ci uint8_t *buffer; 2798c2ecf20Sopenharmony_ci uint8_t previous_byte; 2808c2ecf20Sopenharmony_ci size_t buffer_pos; 2818c2ecf20Sopenharmony_ci int bufsize; 2828c2ecf20Sopenharmony_ci size_t global_pos; 2838c2ecf20Sopenharmony_ci long (*flush)(void*, unsigned long); 2848c2ecf20Sopenharmony_ci struct lzma_header *header; 2858c2ecf20Sopenharmony_ci}; 2868c2ecf20Sopenharmony_ci 2878c2ecf20Sopenharmony_cistruct cstate { 2888c2ecf20Sopenharmony_ci int state; 2898c2ecf20Sopenharmony_ci uint32_t rep0, rep1, rep2, rep3; 2908c2ecf20Sopenharmony_ci}; 2918c2ecf20Sopenharmony_ci 2928c2ecf20Sopenharmony_cistatic inline size_t INIT get_pos(struct writer *wr) 2938c2ecf20Sopenharmony_ci{ 2948c2ecf20Sopenharmony_ci return 2958c2ecf20Sopenharmony_ci wr->global_pos + wr->buffer_pos; 2968c2ecf20Sopenharmony_ci} 2978c2ecf20Sopenharmony_ci 2988c2ecf20Sopenharmony_cistatic inline uint8_t INIT peek_old_byte(struct writer *wr, 2998c2ecf20Sopenharmony_ci uint32_t offs) 3008c2ecf20Sopenharmony_ci{ 3018c2ecf20Sopenharmony_ci if (!wr->flush) { 3028c2ecf20Sopenharmony_ci int32_t pos; 3038c2ecf20Sopenharmony_ci while (offs > wr->header->dict_size) 3048c2ecf20Sopenharmony_ci offs -= wr->header->dict_size; 3058c2ecf20Sopenharmony_ci pos = wr->buffer_pos - offs; 3068c2ecf20Sopenharmony_ci return wr->buffer[pos]; 3078c2ecf20Sopenharmony_ci } else { 3088c2ecf20Sopenharmony_ci uint32_t pos = wr->buffer_pos - offs; 3098c2ecf20Sopenharmony_ci while (pos >= wr->header->dict_size) 3108c2ecf20Sopenharmony_ci pos += wr->header->dict_size; 3118c2ecf20Sopenharmony_ci return wr->buffer[pos]; 3128c2ecf20Sopenharmony_ci } 3138c2ecf20Sopenharmony_ci 3148c2ecf20Sopenharmony_ci} 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_cistatic inline int INIT write_byte(struct writer *wr, uint8_t byte) 3178c2ecf20Sopenharmony_ci{ 3188c2ecf20Sopenharmony_ci wr->buffer[wr->buffer_pos++] = wr->previous_byte = byte; 3198c2ecf20Sopenharmony_ci if (wr->flush && wr->buffer_pos == wr->header->dict_size) { 3208c2ecf20Sopenharmony_ci wr->buffer_pos = 0; 3218c2ecf20Sopenharmony_ci wr->global_pos += wr->header->dict_size; 3228c2ecf20Sopenharmony_ci if (wr->flush((char *)wr->buffer, wr->header->dict_size) 3238c2ecf20Sopenharmony_ci != wr->header->dict_size) 3248c2ecf20Sopenharmony_ci return -1; 3258c2ecf20Sopenharmony_ci } 3268c2ecf20Sopenharmony_ci return 0; 3278c2ecf20Sopenharmony_ci} 3288c2ecf20Sopenharmony_ci 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_cistatic inline int INIT copy_byte(struct writer *wr, uint32_t offs) 3318c2ecf20Sopenharmony_ci{ 3328c2ecf20Sopenharmony_ci return write_byte(wr, peek_old_byte(wr, offs)); 3338c2ecf20Sopenharmony_ci} 3348c2ecf20Sopenharmony_ci 3358c2ecf20Sopenharmony_cistatic inline int INIT copy_bytes(struct writer *wr, 3368c2ecf20Sopenharmony_ci uint32_t rep0, int len) 3378c2ecf20Sopenharmony_ci{ 3388c2ecf20Sopenharmony_ci do { 3398c2ecf20Sopenharmony_ci if (copy_byte(wr, rep0)) 3408c2ecf20Sopenharmony_ci return -1; 3418c2ecf20Sopenharmony_ci len--; 3428c2ecf20Sopenharmony_ci } while (len != 0 && wr->buffer_pos < wr->header->dst_size); 3438c2ecf20Sopenharmony_ci 3448c2ecf20Sopenharmony_ci return len; 3458c2ecf20Sopenharmony_ci} 3468c2ecf20Sopenharmony_ci 3478c2ecf20Sopenharmony_cistatic inline int INIT process_bit0(struct writer *wr, struct rc *rc, 3488c2ecf20Sopenharmony_ci struct cstate *cst, uint16_t *p, 3498c2ecf20Sopenharmony_ci int pos_state, uint16_t *prob, 3508c2ecf20Sopenharmony_ci int lc, uint32_t literal_pos_mask) { 3518c2ecf20Sopenharmony_ci int mi = 1; 3528c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob); 3538c2ecf20Sopenharmony_ci prob = (p + LZMA_LITERAL + 3548c2ecf20Sopenharmony_ci (LZMA_LIT_SIZE 3558c2ecf20Sopenharmony_ci * (((get_pos(wr) & literal_pos_mask) << lc) 3568c2ecf20Sopenharmony_ci + (wr->previous_byte >> (8 - lc)))) 3578c2ecf20Sopenharmony_ci ); 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci if (cst->state >= LZMA_NUM_LIT_STATES) { 3608c2ecf20Sopenharmony_ci int match_byte = peek_old_byte(wr, cst->rep0); 3618c2ecf20Sopenharmony_ci do { 3628c2ecf20Sopenharmony_ci int bit; 3638c2ecf20Sopenharmony_ci uint16_t *prob_lit; 3648c2ecf20Sopenharmony_ci 3658c2ecf20Sopenharmony_ci match_byte <<= 1; 3668c2ecf20Sopenharmony_ci bit = match_byte & 0x100; 3678c2ecf20Sopenharmony_ci prob_lit = prob + 0x100 + bit + mi; 3688c2ecf20Sopenharmony_ci if (rc_get_bit(rc, prob_lit, &mi)) { 3698c2ecf20Sopenharmony_ci if (!bit) 3708c2ecf20Sopenharmony_ci break; 3718c2ecf20Sopenharmony_ci } else { 3728c2ecf20Sopenharmony_ci if (bit) 3738c2ecf20Sopenharmony_ci break; 3748c2ecf20Sopenharmony_ci } 3758c2ecf20Sopenharmony_ci } while (mi < 0x100); 3768c2ecf20Sopenharmony_ci } 3778c2ecf20Sopenharmony_ci while (mi < 0x100) { 3788c2ecf20Sopenharmony_ci uint16_t *prob_lit = prob + mi; 3798c2ecf20Sopenharmony_ci rc_get_bit(rc, prob_lit, &mi); 3808c2ecf20Sopenharmony_ci } 3818c2ecf20Sopenharmony_ci if (cst->state < 4) 3828c2ecf20Sopenharmony_ci cst->state = 0; 3838c2ecf20Sopenharmony_ci else if (cst->state < 10) 3848c2ecf20Sopenharmony_ci cst->state -= 3; 3858c2ecf20Sopenharmony_ci else 3868c2ecf20Sopenharmony_ci cst->state -= 6; 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ci return write_byte(wr, mi); 3898c2ecf20Sopenharmony_ci} 3908c2ecf20Sopenharmony_ci 3918c2ecf20Sopenharmony_cistatic inline int INIT process_bit1(struct writer *wr, struct rc *rc, 3928c2ecf20Sopenharmony_ci struct cstate *cst, uint16_t *p, 3938c2ecf20Sopenharmony_ci int pos_state, uint16_t *prob) { 3948c2ecf20Sopenharmony_ci int offset; 3958c2ecf20Sopenharmony_ci uint16_t *prob_len; 3968c2ecf20Sopenharmony_ci int num_bits; 3978c2ecf20Sopenharmony_ci int len; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob); 4008c2ecf20Sopenharmony_ci prob = p + LZMA_IS_REP + cst->state; 4018c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, prob)) { 4028c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob); 4038c2ecf20Sopenharmony_ci cst->rep3 = cst->rep2; 4048c2ecf20Sopenharmony_ci cst->rep2 = cst->rep1; 4058c2ecf20Sopenharmony_ci cst->rep1 = cst->rep0; 4068c2ecf20Sopenharmony_ci cst->state = cst->state < LZMA_NUM_LIT_STATES ? 0 : 3; 4078c2ecf20Sopenharmony_ci prob = p + LZMA_LEN_CODER; 4088c2ecf20Sopenharmony_ci } else { 4098c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob); 4108c2ecf20Sopenharmony_ci prob = p + LZMA_IS_REP_G0 + cst->state; 4118c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, prob)) { 4128c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob); 4138c2ecf20Sopenharmony_ci prob = (p + LZMA_IS_REP_0_LONG 4148c2ecf20Sopenharmony_ci + (cst->state << 4158c2ecf20Sopenharmony_ci LZMA_NUM_POS_BITS_MAX) + 4168c2ecf20Sopenharmony_ci pos_state); 4178c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, prob)) { 4188c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob); 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_ci cst->state = cst->state < LZMA_NUM_LIT_STATES ? 4218c2ecf20Sopenharmony_ci 9 : 11; 4228c2ecf20Sopenharmony_ci return copy_byte(wr, cst->rep0); 4238c2ecf20Sopenharmony_ci } else { 4248c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob); 4258c2ecf20Sopenharmony_ci } 4268c2ecf20Sopenharmony_ci } else { 4278c2ecf20Sopenharmony_ci uint32_t distance; 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob); 4308c2ecf20Sopenharmony_ci prob = p + LZMA_IS_REP_G1 + cst->state; 4318c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, prob)) { 4328c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob); 4338c2ecf20Sopenharmony_ci distance = cst->rep1; 4348c2ecf20Sopenharmony_ci } else { 4358c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob); 4368c2ecf20Sopenharmony_ci prob = p + LZMA_IS_REP_G2 + cst->state; 4378c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, prob)) { 4388c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob); 4398c2ecf20Sopenharmony_ci distance = cst->rep2; 4408c2ecf20Sopenharmony_ci } else { 4418c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob); 4428c2ecf20Sopenharmony_ci distance = cst->rep3; 4438c2ecf20Sopenharmony_ci cst->rep3 = cst->rep2; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci cst->rep2 = cst->rep1; 4468c2ecf20Sopenharmony_ci } 4478c2ecf20Sopenharmony_ci cst->rep1 = cst->rep0; 4488c2ecf20Sopenharmony_ci cst->rep0 = distance; 4498c2ecf20Sopenharmony_ci } 4508c2ecf20Sopenharmony_ci cst->state = cst->state < LZMA_NUM_LIT_STATES ? 8 : 11; 4518c2ecf20Sopenharmony_ci prob = p + LZMA_REP_LEN_CODER; 4528c2ecf20Sopenharmony_ci } 4538c2ecf20Sopenharmony_ci 4548c2ecf20Sopenharmony_ci prob_len = prob + LZMA_LEN_CHOICE; 4558c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, prob_len)) { 4568c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob_len); 4578c2ecf20Sopenharmony_ci prob_len = (prob + LZMA_LEN_LOW 4588c2ecf20Sopenharmony_ci + (pos_state << 4598c2ecf20Sopenharmony_ci LZMA_LEN_NUM_LOW_BITS)); 4608c2ecf20Sopenharmony_ci offset = 0; 4618c2ecf20Sopenharmony_ci num_bits = LZMA_LEN_NUM_LOW_BITS; 4628c2ecf20Sopenharmony_ci } else { 4638c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob_len); 4648c2ecf20Sopenharmony_ci prob_len = prob + LZMA_LEN_CHOICE_2; 4658c2ecf20Sopenharmony_ci if (rc_is_bit_0(rc, prob_len)) { 4668c2ecf20Sopenharmony_ci rc_update_bit_0(rc, prob_len); 4678c2ecf20Sopenharmony_ci prob_len = (prob + LZMA_LEN_MID 4688c2ecf20Sopenharmony_ci + (pos_state << 4698c2ecf20Sopenharmony_ci LZMA_LEN_NUM_MID_BITS)); 4708c2ecf20Sopenharmony_ci offset = 1 << LZMA_LEN_NUM_LOW_BITS; 4718c2ecf20Sopenharmony_ci num_bits = LZMA_LEN_NUM_MID_BITS; 4728c2ecf20Sopenharmony_ci } else { 4738c2ecf20Sopenharmony_ci rc_update_bit_1(rc, prob_len); 4748c2ecf20Sopenharmony_ci prob_len = prob + LZMA_LEN_HIGH; 4758c2ecf20Sopenharmony_ci offset = ((1 << LZMA_LEN_NUM_LOW_BITS) 4768c2ecf20Sopenharmony_ci + (1 << LZMA_LEN_NUM_MID_BITS)); 4778c2ecf20Sopenharmony_ci num_bits = LZMA_LEN_NUM_HIGH_BITS; 4788c2ecf20Sopenharmony_ci } 4798c2ecf20Sopenharmony_ci } 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci rc_bit_tree_decode(rc, prob_len, num_bits, &len); 4828c2ecf20Sopenharmony_ci len += offset; 4838c2ecf20Sopenharmony_ci 4848c2ecf20Sopenharmony_ci if (cst->state < 4) { 4858c2ecf20Sopenharmony_ci int pos_slot; 4868c2ecf20Sopenharmony_ci 4878c2ecf20Sopenharmony_ci cst->state += LZMA_NUM_LIT_STATES; 4888c2ecf20Sopenharmony_ci prob = 4898c2ecf20Sopenharmony_ci p + LZMA_POS_SLOT + 4908c2ecf20Sopenharmony_ci ((len < 4918c2ecf20Sopenharmony_ci LZMA_NUM_LEN_TO_POS_STATES ? len : 4928c2ecf20Sopenharmony_ci LZMA_NUM_LEN_TO_POS_STATES - 1) 4938c2ecf20Sopenharmony_ci << LZMA_NUM_POS_SLOT_BITS); 4948c2ecf20Sopenharmony_ci rc_bit_tree_decode(rc, prob, 4958c2ecf20Sopenharmony_ci LZMA_NUM_POS_SLOT_BITS, 4968c2ecf20Sopenharmony_ci &pos_slot); 4978c2ecf20Sopenharmony_ci if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { 4988c2ecf20Sopenharmony_ci int i, mi; 4998c2ecf20Sopenharmony_ci num_bits = (pos_slot >> 1) - 1; 5008c2ecf20Sopenharmony_ci cst->rep0 = 2 | (pos_slot & 1); 5018c2ecf20Sopenharmony_ci if (pos_slot < LZMA_END_POS_MODEL_INDEX) { 5028c2ecf20Sopenharmony_ci cst->rep0 <<= num_bits; 5038c2ecf20Sopenharmony_ci prob = p + LZMA_SPEC_POS + 5048c2ecf20Sopenharmony_ci cst->rep0 - pos_slot - 1; 5058c2ecf20Sopenharmony_ci } else { 5068c2ecf20Sopenharmony_ci num_bits -= LZMA_NUM_ALIGN_BITS; 5078c2ecf20Sopenharmony_ci while (num_bits--) 5088c2ecf20Sopenharmony_ci cst->rep0 = (cst->rep0 << 1) | 5098c2ecf20Sopenharmony_ci rc_direct_bit(rc); 5108c2ecf20Sopenharmony_ci prob = p + LZMA_ALIGN; 5118c2ecf20Sopenharmony_ci cst->rep0 <<= LZMA_NUM_ALIGN_BITS; 5128c2ecf20Sopenharmony_ci num_bits = LZMA_NUM_ALIGN_BITS; 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci i = 1; 5158c2ecf20Sopenharmony_ci mi = 1; 5168c2ecf20Sopenharmony_ci while (num_bits--) { 5178c2ecf20Sopenharmony_ci if (rc_get_bit(rc, prob + mi, &mi)) 5188c2ecf20Sopenharmony_ci cst->rep0 |= i; 5198c2ecf20Sopenharmony_ci i <<= 1; 5208c2ecf20Sopenharmony_ci } 5218c2ecf20Sopenharmony_ci } else 5228c2ecf20Sopenharmony_ci cst->rep0 = pos_slot; 5238c2ecf20Sopenharmony_ci if (++(cst->rep0) == 0) 5248c2ecf20Sopenharmony_ci return 0; 5258c2ecf20Sopenharmony_ci if (cst->rep0 > wr->header->dict_size 5268c2ecf20Sopenharmony_ci || cst->rep0 > get_pos(wr)) 5278c2ecf20Sopenharmony_ci return -1; 5288c2ecf20Sopenharmony_ci } 5298c2ecf20Sopenharmony_ci 5308c2ecf20Sopenharmony_ci len += LZMA_MATCH_MIN_LEN; 5318c2ecf20Sopenharmony_ci 5328c2ecf20Sopenharmony_ci return copy_bytes(wr, cst->rep0, len); 5338c2ecf20Sopenharmony_ci} 5348c2ecf20Sopenharmony_ci 5358c2ecf20Sopenharmony_ci 5368c2ecf20Sopenharmony_ci 5378c2ecf20Sopenharmony_ciSTATIC inline int INIT unlzma(unsigned char *buf, long in_len, 5388c2ecf20Sopenharmony_ci long (*fill)(void*, unsigned long), 5398c2ecf20Sopenharmony_ci long (*flush)(void*, unsigned long), 5408c2ecf20Sopenharmony_ci unsigned char *output, 5418c2ecf20Sopenharmony_ci long *posp, 5428c2ecf20Sopenharmony_ci void(*error)(char *x) 5438c2ecf20Sopenharmony_ci ) 5448c2ecf20Sopenharmony_ci{ 5458c2ecf20Sopenharmony_ci struct lzma_header header; 5468c2ecf20Sopenharmony_ci int lc, pb, lp; 5478c2ecf20Sopenharmony_ci uint32_t pos_state_mask; 5488c2ecf20Sopenharmony_ci uint32_t literal_pos_mask; 5498c2ecf20Sopenharmony_ci uint16_t *p; 5508c2ecf20Sopenharmony_ci int num_probs; 5518c2ecf20Sopenharmony_ci struct rc rc; 5528c2ecf20Sopenharmony_ci int i, mi; 5538c2ecf20Sopenharmony_ci struct writer wr; 5548c2ecf20Sopenharmony_ci struct cstate cst; 5558c2ecf20Sopenharmony_ci unsigned char *inbuf; 5568c2ecf20Sopenharmony_ci int ret = -1; 5578c2ecf20Sopenharmony_ci 5588c2ecf20Sopenharmony_ci rc.error = error; 5598c2ecf20Sopenharmony_ci 5608c2ecf20Sopenharmony_ci if (buf) 5618c2ecf20Sopenharmony_ci inbuf = buf; 5628c2ecf20Sopenharmony_ci else 5638c2ecf20Sopenharmony_ci inbuf = malloc(LZMA_IOBUF_SIZE); 5648c2ecf20Sopenharmony_ci if (!inbuf) { 5658c2ecf20Sopenharmony_ci error("Could not allocate input buffer"); 5668c2ecf20Sopenharmony_ci goto exit_0; 5678c2ecf20Sopenharmony_ci } 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci cst.state = 0; 5708c2ecf20Sopenharmony_ci cst.rep0 = cst.rep1 = cst.rep2 = cst.rep3 = 1; 5718c2ecf20Sopenharmony_ci 5728c2ecf20Sopenharmony_ci wr.header = &header; 5738c2ecf20Sopenharmony_ci wr.flush = flush; 5748c2ecf20Sopenharmony_ci wr.global_pos = 0; 5758c2ecf20Sopenharmony_ci wr.previous_byte = 0; 5768c2ecf20Sopenharmony_ci wr.buffer_pos = 0; 5778c2ecf20Sopenharmony_ci 5788c2ecf20Sopenharmony_ci rc_init(&rc, fill, inbuf, in_len); 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_ci for (i = 0; i < sizeof(header); i++) { 5818c2ecf20Sopenharmony_ci if (rc.ptr >= rc.buffer_end) 5828c2ecf20Sopenharmony_ci rc_read(&rc); 5838c2ecf20Sopenharmony_ci ((unsigned char *)&header)[i] = *rc.ptr++; 5848c2ecf20Sopenharmony_ci } 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci if (header.pos >= (9 * 5 * 5)) { 5878c2ecf20Sopenharmony_ci error("bad header"); 5888c2ecf20Sopenharmony_ci goto exit_1; 5898c2ecf20Sopenharmony_ci } 5908c2ecf20Sopenharmony_ci 5918c2ecf20Sopenharmony_ci mi = 0; 5928c2ecf20Sopenharmony_ci lc = header.pos; 5938c2ecf20Sopenharmony_ci while (lc >= 9) { 5948c2ecf20Sopenharmony_ci mi++; 5958c2ecf20Sopenharmony_ci lc -= 9; 5968c2ecf20Sopenharmony_ci } 5978c2ecf20Sopenharmony_ci pb = 0; 5988c2ecf20Sopenharmony_ci lp = mi; 5998c2ecf20Sopenharmony_ci while (lp >= 5) { 6008c2ecf20Sopenharmony_ci pb++; 6018c2ecf20Sopenharmony_ci lp -= 5; 6028c2ecf20Sopenharmony_ci } 6038c2ecf20Sopenharmony_ci pos_state_mask = (1 << pb) - 1; 6048c2ecf20Sopenharmony_ci literal_pos_mask = (1 << lp) - 1; 6058c2ecf20Sopenharmony_ci 6068c2ecf20Sopenharmony_ci ENDIAN_CONVERT(header.dict_size); 6078c2ecf20Sopenharmony_ci ENDIAN_CONVERT(header.dst_size); 6088c2ecf20Sopenharmony_ci 6098c2ecf20Sopenharmony_ci if (header.dict_size == 0) 6108c2ecf20Sopenharmony_ci header.dict_size = 1; 6118c2ecf20Sopenharmony_ci 6128c2ecf20Sopenharmony_ci if (output) 6138c2ecf20Sopenharmony_ci wr.buffer = output; 6148c2ecf20Sopenharmony_ci else { 6158c2ecf20Sopenharmony_ci wr.bufsize = MIN(header.dst_size, header.dict_size); 6168c2ecf20Sopenharmony_ci wr.buffer = large_malloc(wr.bufsize); 6178c2ecf20Sopenharmony_ci } 6188c2ecf20Sopenharmony_ci if (wr.buffer == NULL) 6198c2ecf20Sopenharmony_ci goto exit_1; 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ci num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)); 6228c2ecf20Sopenharmony_ci p = (uint16_t *) large_malloc(num_probs * sizeof(*p)); 6238c2ecf20Sopenharmony_ci if (p == NULL) 6248c2ecf20Sopenharmony_ci goto exit_2; 6258c2ecf20Sopenharmony_ci num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); 6268c2ecf20Sopenharmony_ci for (i = 0; i < num_probs; i++) 6278c2ecf20Sopenharmony_ci p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; 6288c2ecf20Sopenharmony_ci 6298c2ecf20Sopenharmony_ci rc_init_code(&rc); 6308c2ecf20Sopenharmony_ci 6318c2ecf20Sopenharmony_ci while (get_pos(&wr) < header.dst_size) { 6328c2ecf20Sopenharmony_ci int pos_state = get_pos(&wr) & pos_state_mask; 6338c2ecf20Sopenharmony_ci uint16_t *prob = p + LZMA_IS_MATCH + 6348c2ecf20Sopenharmony_ci (cst.state << LZMA_NUM_POS_BITS_MAX) + pos_state; 6358c2ecf20Sopenharmony_ci if (rc_is_bit_0(&rc, prob)) { 6368c2ecf20Sopenharmony_ci if (process_bit0(&wr, &rc, &cst, p, pos_state, prob, 6378c2ecf20Sopenharmony_ci lc, literal_pos_mask)) { 6388c2ecf20Sopenharmony_ci error("LZMA data is corrupt"); 6398c2ecf20Sopenharmony_ci goto exit_3; 6408c2ecf20Sopenharmony_ci } 6418c2ecf20Sopenharmony_ci } else { 6428c2ecf20Sopenharmony_ci if (process_bit1(&wr, &rc, &cst, p, pos_state, prob)) { 6438c2ecf20Sopenharmony_ci error("LZMA data is corrupt"); 6448c2ecf20Sopenharmony_ci goto exit_3; 6458c2ecf20Sopenharmony_ci } 6468c2ecf20Sopenharmony_ci if (cst.rep0 == 0) 6478c2ecf20Sopenharmony_ci break; 6488c2ecf20Sopenharmony_ci } 6498c2ecf20Sopenharmony_ci if (rc.buffer_size <= 0) 6508c2ecf20Sopenharmony_ci goto exit_3; 6518c2ecf20Sopenharmony_ci } 6528c2ecf20Sopenharmony_ci 6538c2ecf20Sopenharmony_ci if (posp) 6548c2ecf20Sopenharmony_ci *posp = rc.ptr-rc.buffer; 6558c2ecf20Sopenharmony_ci if (!wr.flush || wr.flush(wr.buffer, wr.buffer_pos) == wr.buffer_pos) 6568c2ecf20Sopenharmony_ci ret = 0; 6578c2ecf20Sopenharmony_ciexit_3: 6588c2ecf20Sopenharmony_ci large_free(p); 6598c2ecf20Sopenharmony_ciexit_2: 6608c2ecf20Sopenharmony_ci if (!output) 6618c2ecf20Sopenharmony_ci large_free(wr.buffer); 6628c2ecf20Sopenharmony_ciexit_1: 6638c2ecf20Sopenharmony_ci if (!buf) 6648c2ecf20Sopenharmony_ci free(inbuf); 6658c2ecf20Sopenharmony_ciexit_0: 6668c2ecf20Sopenharmony_ci return ret; 6678c2ecf20Sopenharmony_ci} 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci#ifdef PREBOOT 6708c2ecf20Sopenharmony_ciSTATIC int INIT __decompress(unsigned char *buf, long in_len, 6718c2ecf20Sopenharmony_ci long (*fill)(void*, unsigned long), 6728c2ecf20Sopenharmony_ci long (*flush)(void*, unsigned long), 6738c2ecf20Sopenharmony_ci unsigned char *output, long out_len, 6748c2ecf20Sopenharmony_ci long *posp, 6758c2ecf20Sopenharmony_ci void (*error)(char *x)) 6768c2ecf20Sopenharmony_ci{ 6778c2ecf20Sopenharmony_ci return unlzma(buf, in_len - 4, fill, flush, output, posp, error); 6788c2ecf20Sopenharmony_ci} 6798c2ecf20Sopenharmony_ci#endif 680