wok diff syslinux/stuff/extra/loadhigh.u @ rev 18757

syslinux: compress c32 modules
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Dec 29 08:59:31 2015 +0100 (2015-12-29)
parents
children 924e6ea5da10
line diff
     1.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     1.2 +++ b/syslinux/stuff/extra/loadhigh.u	Tue Dec 29 08:59:31 2015 +0100
     1.3 @@ -0,0 +1,554 @@
     1.4 +--- core/fs/loadhigh.c
     1.5 ++++ core/fs/loadhigh.c
     1.6 +@@ -36,6 +36,11 @@
     1.7 + #include <minmax.h>
     1.8 + #include "core.h"
     1.9 + #include "fs.h"
    1.10 ++#define LZLOAD	".c32 modules can be compressed with lz4 or lzma"
    1.11 ++#ifdef LZLOAD
    1.12 ++#include "../unlz4.c"
    1.13 ++#include "../unlzma.c"
    1.14 ++#endif
    1.15 + 
    1.16 + #define MAX_CHUNK	(1 << 20) /* 1 MB */
    1.17 + 
    1.18 +@@ -51,6 +56,10 @@
    1.19 +     uint32_t sector_mask;
    1.20 +     size_t pad;
    1.21 +     uint32_t retflags = 0;
    1.22 ++#ifdef LZLOAD
    1.23 ++    char *unpacked = (char *) regs->edi.l;
    1.24 ++    size_t unpackedsz;
    1.25 ++#endif
    1.26 + 
    1.27 +     bytes     = regs->eax.l;
    1.28 +     zero_mask = regs->edx.w[0];
    1.29 +@@ -101,6 +110,27 @@
    1.30 + 	    break;
    1.31 + 	}
    1.32 +     }
    1.33 ++
    1.34 ++#ifdef LZLOAD
    1.35 ++    unpackedsz = buf - unpacked;
    1.36 ++    switch (* (short *) unpacked) {
    1.37 ++	char *packed;
    1.38 ++    case 0x005D:
    1.39 ++	packed = unpacked + * (unsigned long *) (unpacked + 5)
    1.40 ++			- unpackedsz + 1024;
    1.41 ++
    1.42 ++	if (packed < unpacked + 1024)
    1.43 ++		packed = unpacked + 1024;
    1.44 ++	memmove(packed, unpacked, unpackedsz);
    1.45 ++	unlzma(packed, unpacked, packed + unpackedsz /* head */);
    1.46 ++	buf = packed;
    1.47 ++	break;
    1.48 ++    case 0x2204:
    1.49 ++    case 0x2102:
    1.50 ++	buf = unlz4(unpacked, buf);
    1.51 ++	break;
    1.52 ++    }
    1.53 ++#endif
    1.54 + 
    1.55 +     pad = (size_t)buf & zero_mask;
    1.56 +     if (pad)
    1.57 +--- /dev/null
    1.58 ++++ core/unlzma.c
    1.59 +@@ -0,0 +1,383 @@
    1.60 ++typedef unsigned char uint8_t;
    1.61 ++typedef unsigned short uint16_t;
    1.62 ++typedef unsigned uint32_t;
    1.63 ++typedef unsigned long long uint64_t;
    1.64 ++typedef unsigned size_t;
    1.65 ++#define SWAP_LE32(x)	(x)
    1.66 ++#define SWAP_LE64(x)	(x)
    1.67 ++/* vi: set sw=4 ts=4: */
    1.68 ++/*
    1.69 ++ * Small lzma deflate implementation.
    1.70 ++ * Copyright (C) 2006  Aurelien Jacobs <aurel@gnuage.org>
    1.71 ++ *
    1.72 ++ * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
    1.73 ++ * Copyright (C) 1999-2005  Igor Pavlov
    1.74 ++ *
    1.75 ++ * Licensed under GPLv2 or later, see file LICENSE in this source tree.
    1.76 ++ */
    1.77 ++
    1.78 ++#define PACKED __attribute__ ((packed))
    1.79 ++#define ALWAYS_INLINE inline
    1.80 ++#define speed_inline
    1.81 ++#define size_inline ALWAYS_INLINE
    1.82 ++
    1.83 ++
    1.84 ++typedef struct {
    1.85 ++	uint8_t *ptr;
    1.86 ++
    1.87 ++	uint32_t code;
    1.88 ++	uint32_t range;
    1.89 ++	uint32_t bound;
    1.90 ++} rc_t;
    1.91 ++
    1.92 ++#define RC_TOP_BITS 24
    1.93 ++#define RC_MOVE_BITS 5
    1.94 ++#define RC_MODEL_TOTAL_BITS 11
    1.95 ++
    1.96 ++/* Called twice, but one callsite is in speed_inline'd rc_is_bit_1() */
    1.97 ++static void rc_do_normalize(rc_t *rc)
    1.98 ++{
    1.99 ++	rc->range <<= 8;
   1.100 ++	rc->code = (rc->code << 8) | *rc->ptr++;
   1.101 ++}
   1.102 ++
   1.103 ++static ALWAYS_INLINE void rc_normalize(rc_t *rc)
   1.104 ++{
   1.105 ++	if (rc->range < (1 << RC_TOP_BITS)) {
   1.106 ++		rc_do_normalize(rc);
   1.107 ++	}
   1.108 ++}
   1.109 ++
   1.110 ++/* Called once */
   1.111 ++static void rc_init(rc_t *rc) /*, int buffer_size) */
   1.112 ++{
   1.113 ++	int i;
   1.114 ++
   1.115 ++	rc->range = 0;
   1.116 ++	for (i = 0; i < 5; i++) {
   1.117 ++		rc_do_normalize(rc);
   1.118 ++	}
   1.119 ++	rc->range = 0xffffffff;
   1.120 ++}
   1.121 ++
   1.122 ++/* rc_is_bit_1 is called 9 times */
   1.123 ++static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p)
   1.124 ++{
   1.125 ++	rc_normalize(rc);
   1.126 ++	rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
   1.127 ++	if (rc->code < rc->bound) {
   1.128 ++		rc->range = rc->bound;
   1.129 ++		*p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
   1.130 ++		return 0;
   1.131 ++	}
   1.132 ++	rc->range -= rc->bound;
   1.133 ++	rc->code -= rc->bound;
   1.134 ++	*p -= *p >> RC_MOVE_BITS;
   1.135 ++	return 1;
   1.136 ++}
   1.137 ++
   1.138 ++/* Called 4 times in unlzma loop */
   1.139 ++static ALWAYS_INLINE int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol)
   1.140 ++{
   1.141 ++	int ret = rc_is_bit_1(rc, p);
   1.142 ++	*symbol = *symbol * 2 + ret;
   1.143 ++	return ret;
   1.144 ++}
   1.145 ++
   1.146 ++/* Called once */
   1.147 ++static ALWAYS_INLINE int rc_direct_bit(rc_t *rc)
   1.148 ++{
   1.149 ++	rc_normalize(rc);
   1.150 ++	rc->range >>= 1;
   1.151 ++	if (rc->code >= rc->range) {
   1.152 ++		rc->code -= rc->range;
   1.153 ++		return 1;
   1.154 ++	}
   1.155 ++	return 0;
   1.156 ++}
   1.157 ++
   1.158 ++/* Called twice */
   1.159 ++static speed_inline void
   1.160 ++rc_bit_tree_decode(rc_t *rc, uint16_t *p, int num_levels, int *symbol)
   1.161 ++{
   1.162 ++	int i = num_levels;
   1.163 ++
   1.164 ++	*symbol = 1;
   1.165 ++	while (i--)
   1.166 ++		rc_get_bit(rc, p + *symbol, symbol);
   1.167 ++	*symbol -= 1 << num_levels;
   1.168 ++}
   1.169 ++
   1.170 ++
   1.171 ++typedef struct {
   1.172 ++	uint8_t pos;
   1.173 ++	uint32_t dict_size;
   1.174 ++	uint64_t dst_size;
   1.175 ++} PACKED lzma_header_t;
   1.176 ++
   1.177 ++
   1.178 ++/* #defines will force compiler to compute/optimize each one with each usage.
   1.179 ++ * Have heart and use enum instead. */
   1.180 ++enum {
   1.181 ++	LZMA_BASE_SIZE = 1846,
   1.182 ++	LZMA_LIT_SIZE  = 768,
   1.183 ++
   1.184 ++	LZMA_NUM_POS_BITS_MAX = 4,
   1.185 ++
   1.186 ++	LZMA_LEN_NUM_LOW_BITS  = 3,
   1.187 ++	LZMA_LEN_NUM_MID_BITS  = 3,
   1.188 ++	LZMA_LEN_NUM_HIGH_BITS = 8,
   1.189 ++
   1.190 ++	LZMA_LEN_CHOICE     = 0,
   1.191 ++	LZMA_LEN_CHOICE_2   = (LZMA_LEN_CHOICE + 1),
   1.192 ++	LZMA_LEN_LOW        = (LZMA_LEN_CHOICE_2 + 1),
   1.193 ++	LZMA_LEN_MID        = (LZMA_LEN_LOW \
   1.194 ++	                      + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))),
   1.195 ++	LZMA_LEN_HIGH       = (LZMA_LEN_MID \
   1.196 ++	                      + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))),
   1.197 ++	LZMA_NUM_LEN_PROBS  = (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)),
   1.198 ++
   1.199 ++	LZMA_NUM_STATES     = 12,
   1.200 ++	LZMA_NUM_LIT_STATES = 7,
   1.201 ++
   1.202 ++	LZMA_START_POS_MODEL_INDEX = 4,
   1.203 ++	LZMA_END_POS_MODEL_INDEX   = 14,
   1.204 ++	LZMA_NUM_FULL_DISTANCES    = (1 << (LZMA_END_POS_MODEL_INDEX >> 1)),
   1.205 ++
   1.206 ++	LZMA_NUM_POS_SLOT_BITS = 6,
   1.207 ++	LZMA_NUM_LEN_TO_POS_STATES = 4,
   1.208 ++
   1.209 ++	LZMA_NUM_ALIGN_BITS = 4,
   1.210 ++
   1.211 ++	LZMA_MATCH_MIN_LEN  = 2,
   1.212 ++
   1.213 ++	LZMA_IS_MATCH       = 0,
   1.214 ++	LZMA_IS_REP         = (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
   1.215 ++	LZMA_IS_REP_G0      = (LZMA_IS_REP + LZMA_NUM_STATES),
   1.216 ++	LZMA_IS_REP_G1      = (LZMA_IS_REP_G0 + LZMA_NUM_STATES),
   1.217 ++	LZMA_IS_REP_G2      = (LZMA_IS_REP_G1 + LZMA_NUM_STATES),
   1.218 ++	LZMA_IS_REP_0_LONG  = (LZMA_IS_REP_G2 + LZMA_NUM_STATES),
   1.219 ++	LZMA_POS_SLOT       = (LZMA_IS_REP_0_LONG \
   1.220 ++	                      + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
   1.221 ++	LZMA_SPEC_POS       = (LZMA_POS_SLOT \
   1.222 ++	                      + (LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)),
   1.223 ++	LZMA_ALIGN          = (LZMA_SPEC_POS \
   1.224 ++	                      + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX),
   1.225 ++	LZMA_LEN_CODER      = (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)),
   1.226 ++	LZMA_REP_LEN_CODER  = (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS),
   1.227 ++	LZMA_LITERAL        = (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS),
   1.228 ++};
   1.229 ++
   1.230 ++
   1.231 ++void unlzma(char *from, char *to, char *heap)
   1.232 ++{
   1.233 ++	lzma_header_t header;
   1.234 ++	int lc, pb, lp;
   1.235 ++	uint32_t pos_state_mask;
   1.236 ++	uint32_t literal_pos_mask;
   1.237 ++	uint16_t *p;
   1.238 ++	rc_t *rc = (rc_t *) heap;
   1.239 ++	int i;
   1.240 ++	uint8_t *buffer = (void *) to;
   1.241 ++	uint8_t previous_byte = 0;
   1.242 ++	size_t buffer_pos = 0;
   1.243 ++	int len = 0;
   1.244 ++	int state = 0;
   1.245 ++	uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
   1.246 ++
   1.247 ++	memcpy(&header, from, sizeof(header));
   1.248 ++	from += sizeof(header);
   1.249 ++	heap += sizeof(*rc);
   1.250 ++	rc->ptr = (void *) from;
   1.251 ++
   1.252 ++	i = header.pos / 9;
   1.253 ++	lc = header.pos % 9;
   1.254 ++	pb = i / 5;
   1.255 ++	lp = i % 5;
   1.256 ++	pos_state_mask = (1 << pb) - 1;
   1.257 ++	literal_pos_mask = (1 << lp) - 1;
   1.258 ++
   1.259 ++	/* Example values from linux-3.3.4.tar.lzma:
   1.260 ++	 * dict_size: 64M, dst_size: 2^64-1
   1.261 ++	 */
   1.262 ++	header.dict_size = SWAP_LE32(header.dict_size);
   1.263 ++	header.dst_size = SWAP_LE64(header.dst_size);
   1.264 ++
   1.265 ++	//if (header.dict_size == 0)
   1.266 ++	//	header.dict_size++;
   1.267 ++
   1.268 ++	rc_init(rc);
   1.269 ++
   1.270 ++	{
   1.271 ++		int num_probs;
   1.272 ++
   1.273 ++		num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
   1.274 ++		//p = xmalloc(num_probs * sizeof(*p));
   1.275 ++		p = (void *) heap;
   1.276 ++		num_probs += LZMA_LITERAL - LZMA_BASE_SIZE;
   1.277 ++		for (i = 0; i < num_probs; i++)
   1.278 ++			p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
   1.279 ++	}
   1.280 ++
   1.281 ++
   1.282 ++	while (buffer_pos < header.dst_size) {
   1.283 ++		int pos_state = buffer_pos & pos_state_mask;
   1.284 ++		uint16_t *prob = p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
   1.285 ++
   1.286 ++		if (!rc_is_bit_1(rc, prob)) {
   1.287 ++			static const char next_state[LZMA_NUM_STATES] =
   1.288 ++				{ 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
   1.289 ++			int mi = 1;
   1.290 ++
   1.291 ++			prob = (p + LZMA_LITERAL
   1.292 ++			        + (LZMA_LIT_SIZE * (((buffer_pos & literal_pos_mask) << lc)
   1.293 ++			                            + (previous_byte >> (8 - lc))
   1.294 ++			                           )
   1.295 ++			          )
   1.296 ++			);
   1.297 ++
   1.298 ++			if (state >= LZMA_NUM_LIT_STATES) {
   1.299 ++				int match_byte;
   1.300 ++				uint32_t pos = buffer_pos - rep0;
   1.301 ++
   1.302 ++				while (pos >= header.dict_size)
   1.303 ++					pos += header.dict_size;
   1.304 ++				match_byte = buffer[pos];
   1.305 ++				do {
   1.306 ++					int bit;
   1.307 ++
   1.308 ++					match_byte <<= 1;
   1.309 ++					bit = match_byte & 0x100;
   1.310 ++					bit ^= (rc_get_bit(rc, prob + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */
   1.311 ++					if (bit)
   1.312 ++						break;
   1.313 ++				} while (mi < 0x100);
   1.314 ++			}
   1.315 ++			while (mi < 0x100) {
   1.316 ++				rc_get_bit(rc, prob + mi, &mi);
   1.317 ++			}
   1.318 ++
   1.319 ++			state = next_state[state];
   1.320 ++
   1.321 ++			previous_byte = (uint8_t) mi;
   1.322 ++			len = 1;
   1.323 ++			goto one_byte2;
   1.324 ++		} else {
   1.325 ++			int num_bits;
   1.326 ++			int offset;
   1.327 ++			uint16_t *prob2;
   1.328 ++#define prob_len prob2
   1.329 ++
   1.330 ++			prob2 = p + LZMA_IS_REP + state;
   1.331 ++			if (!rc_is_bit_1(rc, prob2)) {
   1.332 ++				rep3 = rep2;
   1.333 ++				rep2 = rep1;
   1.334 ++				rep1 = rep0;
   1.335 ++				state = state < LZMA_NUM_LIT_STATES ? 0 : 3;
   1.336 ++				prob2 = p + LZMA_LEN_CODER;
   1.337 ++			} else {
   1.338 ++				prob2 += LZMA_IS_REP_G0 - LZMA_IS_REP;
   1.339 ++				if (!rc_is_bit_1(rc, prob2)) {
   1.340 ++					prob2 = (p + LZMA_IS_REP_0_LONG
   1.341 ++					        + (state << LZMA_NUM_POS_BITS_MAX)
   1.342 ++					        + pos_state
   1.343 ++					);
   1.344 ++					if (!rc_is_bit_1(rc, prob2)) {
   1.345 ++						state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
   1.346 ++						len = 1;
   1.347 ++						goto string;
   1.348 ++					}
   1.349 ++				} else {
   1.350 ++					uint32_t distance;
   1.351 ++
   1.352 ++					prob2 += LZMA_IS_REP_G1 - LZMA_IS_REP_G0;
   1.353 ++					distance = rep1;
   1.354 ++					if (rc_is_bit_1(rc, prob2)) {
   1.355 ++						prob2 += LZMA_IS_REP_G2 - LZMA_IS_REP_G1;
   1.356 ++						distance = rep2;
   1.357 ++						if (rc_is_bit_1(rc, prob2)) {
   1.358 ++							distance = rep3;
   1.359 ++							rep3 = rep2;
   1.360 ++						}
   1.361 ++						rep2 = rep1;
   1.362 ++					}
   1.363 ++					rep1 = rep0;
   1.364 ++					rep0 = distance;
   1.365 ++				}
   1.366 ++				state = state < LZMA_NUM_LIT_STATES ? 8 : 11;
   1.367 ++				prob2 = p + LZMA_REP_LEN_CODER;
   1.368 ++			}
   1.369 ++
   1.370 ++			prob_len = prob2 + LZMA_LEN_CHOICE;
   1.371 ++			num_bits = LZMA_LEN_NUM_LOW_BITS;
   1.372 ++			if (!rc_is_bit_1(rc, prob_len)) {
   1.373 ++				prob_len += LZMA_LEN_LOW - LZMA_LEN_CHOICE
   1.374 ++				            + (pos_state << LZMA_LEN_NUM_LOW_BITS);
   1.375 ++				offset = 0;
   1.376 ++			} else {
   1.377 ++				prob_len += LZMA_LEN_CHOICE_2 - LZMA_LEN_CHOICE;
   1.378 ++				if (!rc_is_bit_1(rc, prob_len)) {
   1.379 ++					prob_len += LZMA_LEN_MID - LZMA_LEN_CHOICE_2
   1.380 ++					            + (pos_state << LZMA_LEN_NUM_MID_BITS);
   1.381 ++					offset = 1 << LZMA_LEN_NUM_LOW_BITS;
   1.382 ++					num_bits += LZMA_LEN_NUM_MID_BITS - LZMA_LEN_NUM_LOW_BITS;
   1.383 ++				} else {
   1.384 ++					prob_len += LZMA_LEN_HIGH - LZMA_LEN_CHOICE_2;
   1.385 ++					offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
   1.386 ++					          + (1 << LZMA_LEN_NUM_MID_BITS));
   1.387 ++					num_bits += LZMA_LEN_NUM_HIGH_BITS - LZMA_LEN_NUM_LOW_BITS;
   1.388 ++				}
   1.389 ++			}
   1.390 ++			rc_bit_tree_decode(rc, prob_len, num_bits, &len);
   1.391 ++			len += offset;
   1.392 ++
   1.393 ++			if (state < 4) {
   1.394 ++				int pos_slot;
   1.395 ++				uint16_t *prob3;
   1.396 ++
   1.397 ++				state += LZMA_NUM_LIT_STATES;
   1.398 ++				prob3 = p + LZMA_POS_SLOT +
   1.399 ++				       ((len < LZMA_NUM_LEN_TO_POS_STATES ? len :
   1.400 ++				         LZMA_NUM_LEN_TO_POS_STATES - 1)
   1.401 ++				         << LZMA_NUM_POS_SLOT_BITS);
   1.402 ++				rc_bit_tree_decode(rc, prob3,
   1.403 ++					LZMA_NUM_POS_SLOT_BITS, &pos_slot);
   1.404 ++				rep0 = pos_slot;
   1.405 ++				if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
   1.406 ++					int i2, mi2, num_bits2 = (pos_slot >> 1) - 1;
   1.407 ++					rep0 = 2 | (pos_slot & 1);
   1.408 ++					if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
   1.409 ++						rep0 <<= num_bits2;
   1.410 ++						prob3 = p + LZMA_SPEC_POS + rep0 - pos_slot - 1;
   1.411 ++					} else {
   1.412 ++						for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--)
   1.413 ++							rep0 = (rep0 << 1) | rc_direct_bit(rc);
   1.414 ++						rep0 <<= LZMA_NUM_ALIGN_BITS;
   1.415 ++						prob3 = p + LZMA_ALIGN;
   1.416 ++					}
   1.417 ++					i2 = 1;
   1.418 ++					mi2 = 1;
   1.419 ++					while (num_bits2--) {
   1.420 ++						if (rc_get_bit(rc, prob3 + mi2, &mi2))
   1.421 ++							rep0 |= i2;
   1.422 ++						i2 <<= 1;
   1.423 ++					}
   1.424 ++				}
   1.425 ++				if (++rep0 == 0)
   1.426 ++					break;
   1.427 ++			}
   1.428 ++
   1.429 ++			len += LZMA_MATCH_MIN_LEN;
   1.430 ++ string:
   1.431 ++			do {
   1.432 ++				uint32_t pos = buffer_pos - rep0;
   1.433 ++				while (pos >= header.dict_size)
   1.434 ++					pos += header.dict_size;
   1.435 ++				previous_byte = buffer[pos];
   1.436 ++ one_byte2:
   1.437 ++				buffer[buffer_pos++] = previous_byte;
   1.438 ++				len--;
   1.439 ++			} while (len != 0 && buffer_pos < header.dst_size);
   1.440 ++		}
   1.441 ++	}
   1.442 ++}
   1.443 +--- /dev/null
   1.444 ++++ core/unlz4.c
   1.445 +@@ -0,0 +1,112 @@
   1.446 ++/*
   1.447 ++ * Copyright (C) 2015, pascal.bellard@slitaz.org
   1.448 ++ *
   1.449 ++ * This program is free software; you can redistribute it and/or modify
   1.450 ++ * it under the terms of the GNU General Public License version 2 as
   1.451 ++ * published by the Free Software Foundation.
   1.452 ++ */
   1.453 ++
   1.454 ++#define LZ4_MAGIC	0x184D2204	/* Spec 1.5.0 */
   1.455 ++#define LZ4_LEGACY	0x184C2102
   1.456 ++#define LZ4_SKIP(n)	((((n) - 0x184D2A50) >> 4) == 0)
   1.457 ++
   1.458 ++static unsigned lz4cnt(unsigned char **p, unsigned n)
   1.459 ++{
   1.460 ++	int i;
   1.461 ++
   1.462 ++	if (n == 0xF) do {
   1.463 ++		i = *(*p)++;
   1.464 ++		n += i;
   1.465 ++	} while (i == 0xFF);
   1.466 ++	return n;
   1.467 ++}
   1.468 ++
   1.469 ++char *unlz4(unsigned char *from, unsigned char *end)
   1.470 ++{
   1.471 ++	unsigned char *p, *end_chunk, *to, flags, mask;
   1.472 ++	long magic;
   1.473 ++	unsigned i, n, size;
   1.474 ++
   1.475 ++	for (p = from, flags = size = 0; p < end;) {
   1.476 ++		while (1) {
   1.477 ++			magic = * (long *) p;
   1.478 ++			p += sizeof(long);
   1.479 ++			if (magic == LZ4_LEGACY) continue;
   1.480 ++			if (magic != LZ4_MAGIC) break;
   1.481 ++			flags = *p;
   1.482 ++			if (flags & 8) {
   1.483 ++				size = * (unsigned *) (p + 2);
   1.484 ++				goto sizefound;
   1.485 ++			}
   1.486 ++			p += 3; /* skip FLG BD HC */
   1.487 ++		}
   1.488 ++		if (LZ4_SKIP(magic)) {
   1.489 ++			p += 4 + * (long *) p;
   1.490 ++			continue;
   1.491 ++		}
   1.492 ++		mask = 4; /* Content checksum */
   1.493 ++		if (magic) {
   1.494 ++			if (magic > 0)
   1.495 ++			for (end_chunk = p + magic; p < end_chunk;) {
   1.496 ++				unsigned char token = *p++;
   1.497 ++
   1.498 ++				n = lz4cnt(&p, token >> 4);
   1.499 ++				size += n;
   1.500 ++				p += n;
   1.501 ++				if (p >= end_chunk) break;
   1.502 ++				p += sizeof(unsigned short);
   1.503 ++				size += 4 + lz4cnt(&p, token & 0xF);
   1.504 ++			}
   1.505 ++			else {
   1.506 ++				magic &= 0x7FffFFff;
   1.507 ++				p += magic;
   1.508 ++				size += magic;
   1.509 ++			}
   1.510 ++			mask = 0x10; /* Block checksum */
   1.511 ++		}
   1.512 ++		if (flags & mask) p += 4; /* skip block checksum */
   1.513 ++	}
   1.514 ++sizefound:
   1.515 ++	size += 16 - (p - from);
   1.516 ++	memmove(from + size, from, p - from);
   1.517 ++	for (to = from, p = from += size, end += size, flags = 0; p < end;) {
   1.518 ++		while (1) {
   1.519 ++			magic = * (long *) p;
   1.520 ++			p += sizeof(long);
   1.521 ++			if (magic == LZ4_LEGACY) continue;
   1.522 ++			if (magic != LZ4_MAGIC) break;
   1.523 ++			flags = *p;
   1.524 ++			if (flags & 8) p += 8; /* skip size */
   1.525 ++			p += 3; /* skip FLG BD HC */
   1.526 ++		}
   1.527 ++		if (LZ4_SKIP(magic)) {
   1.528 ++			p += 4 + * (long *) p;
   1.529 ++			continue;
   1.530 ++		}
   1.531 ++		mask = 4; /* Content checksum */
   1.532 ++		if (magic) {
   1.533 ++			if (magic > 0)
   1.534 ++			for (end_chunk = p + magic; p < end_chunk;) {
   1.535 ++				char *dico;
   1.536 ++				unsigned char token = *p++;
   1.537 ++
   1.538 ++				n = lz4cnt(&p, token >> 4);
   1.539 ++				for (i = 0; i < n; i++)
   1.540 ++					*to++ = *p++;
   1.541 ++				if (p >= end_chunk) break;
   1.542 ++				dico = to - (* (unsigned short *) p);
   1.543 ++				p += sizeof(unsigned short);
   1.544 ++				n = 4 + lz4cnt(&p, token & 0xF);
   1.545 ++				for (i = 0; i < n; i++)
   1.546 ++					*to++ = *dico++;
   1.547 ++			}
   1.548 ++			else for (end_chunk = p + (magic & 0x7FffFFff);
   1.549 ++				  p < end_chunk;) {
   1.550 ++				*to++ = *p++;
   1.551 ++			}
   1.552 ++			mask = 0x10; /* Block checksum */
   1.553 ++		}
   1.554 ++		if (flags & mask) p += 4; /* Skip checksum */
   1.555 ++	}
   1.556 ++	return to;
   1.557 ++}