brintos

brintos / linux-shallow public Read only

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