Orange Pi5 kernel

Deprecated Linux kernel 5.10.110 for OrangePi 5/5B/5+ boards

3 Commits   0 Branches   0 Tags
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   1) // SPDX-License-Identifier: GPL-2.0-only
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   2) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   3)  *  LZO1X Compressor from LZO
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   4)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   5)  *  Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   6)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   7)  *  The full LZO package can be found at:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   8)  *  http://www.oberhumer.com/opensource/lzo/
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300   9)  *
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  10)  *  Changed for Linux kernel use by:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  11)  *  Nitin Gupta <nitingupta910@gmail.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  12)  *  Richard Purdie <rpurdie@openedhand.com>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  13)  */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  14) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  15) #include <linux/module.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  16) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  17) #include <asm/unaligned.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  18) #include <linux/lzo.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  19) #include "lzodefs.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  20) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  21) static noinline size_t
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  22) lzo1x_1_do_compress(const unsigned char *in, size_t in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  23) 		    unsigned char *out, size_t *out_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  24) 		    size_t ti, void *wrkmem, signed char *state_offset,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  25) 		    const unsigned char bitstream_version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  26) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  27) 	const unsigned char *ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  28) 	unsigned char *op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  29) 	const unsigned char * const in_end = in + in_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  30) 	const unsigned char * const ip_end = in + in_len - 20;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  31) 	const unsigned char *ii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  32) 	lzo_dict_t * const dict = (lzo_dict_t *) wrkmem;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  33) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  34) 	op = out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  35) 	ip = in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  36) 	ii = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  37) 	ip += ti < 4 ? 4 - ti : 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  38) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  39) 	for (;;) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  40) 		const unsigned char *m_pos = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  41) 		size_t t, m_len, m_off;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  42) 		u32 dv;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  43) 		u32 run_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  44) literal:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  45) 		ip += 1 + ((ip - ii) >> 5);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  46) next:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  47) 		if (unlikely(ip >= ip_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  48) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  49) 		dv = get_unaligned_le32(ip);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  50) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  51) 		if (dv == 0 && bitstream_version) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  52) 			const unsigned char *ir = ip + 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  53) 			const unsigned char *limit = ip_end
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  54) 				< (ip + MAX_ZERO_RUN_LENGTH + 1)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  55) 				? ip_end : ip + MAX_ZERO_RUN_LENGTH + 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  56) #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && \
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  57) 	defined(LZO_FAST_64BIT_MEMORY_ACCESS)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  58) 			u64 dv64;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  59) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  60) 			for (; (ir + 32) <= limit; ir += 32) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  61) 				dv64 = get_unaligned((u64 *)ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  62) 				dv64 |= get_unaligned((u64 *)ir + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  63) 				dv64 |= get_unaligned((u64 *)ir + 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  64) 				dv64 |= get_unaligned((u64 *)ir + 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  65) 				if (dv64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  66) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  67) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  68) 			for (; (ir + 8) <= limit; ir += 8) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  69) 				dv64 = get_unaligned((u64 *)ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  70) 				if (dv64) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  71) #  if defined(__LITTLE_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  72) 					ir += __builtin_ctzll(dv64) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  73) #  elif defined(__BIG_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  74) 					ir += __builtin_clzll(dv64) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  75) #  else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  76) #    error "missing endian definition"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  77) #  endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  78) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  79) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  80) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  81) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  82) 			while ((ir < (const unsigned char *)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  83) 					ALIGN((uintptr_t)ir, 4)) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  84) 					(ir < limit) && (*ir == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  85) 				ir++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  86) 			if (IS_ALIGNED((uintptr_t)ir, 4)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  87) 				for (; (ir + 4) <= limit; ir += 4) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  88) 					dv = *((u32 *)ir);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  89) 					if (dv) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  90) #  if defined(__LITTLE_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  91) 						ir += __builtin_ctz(dv) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  92) #  elif defined(__BIG_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  93) 						ir += __builtin_clz(dv) >> 3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  94) #  else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  95) #    error "missing endian definition"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  96) #  endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  97) 						break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  98) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300  99) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) 			while (likely(ir < limit) && unlikely(*ir == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) 				ir++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) 			run_length = ir - ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105) 			if (run_length > MAX_ZERO_RUN_LENGTH)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) 				run_length = MAX_ZERO_RUN_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108) 			t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) 			m_pos = in + dict[t];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) 			dict[t] = (lzo_dict_t) (ip - in);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) 			if (unlikely(dv != get_unaligned_le32(m_pos)))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112) 				goto literal;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) 		ii -= ti;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) 		ti = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117) 		t = ip - ii;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) 		if (t != 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) 			if (t <= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) 				op[*state_offset] |= t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) 				COPY4(op, ii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122) 				op += t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) 			} else if (t <= 16) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) 				*op++ = (t - 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) 				COPY8(op, ii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) 				COPY8(op + 8, ii + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) 				op += t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) 			} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) 				if (t <= 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) 					*op++ = (t - 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) 				} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) 					size_t tt = t - 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) 					*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134) 					while (unlikely(tt > 255)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) 						tt -= 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) 						*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) 					}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) 					*op++ = tt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 139) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 140) 				do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 141) 					COPY8(op, ii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 142) 					COPY8(op + 8, ii + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 143) 					op += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 144) 					ii += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 145) 					t -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 146) 				} while (t >= 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 147) 				if (t > 0) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 148) 					*op++ = *ii++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 149) 				} while (--t > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 150) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 151) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 152) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 153) 		if (unlikely(run_length)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 154) 			ip += run_length;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 155) 			run_length -= MIN_ZERO_RUN_LENGTH;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 156) 			put_unaligned_le32((run_length << 21) | 0xfffc18
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 157) 					   | (run_length & 0x7), op);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 158) 			op += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 159) 			run_length = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 160) 			*state_offset = -3;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 161) 			goto finished_writing_instruction;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 162) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 163) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 164) 		m_len = 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 165) 		{
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 166) #if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 167) 		u64 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 168) 		v = get_unaligned((const u64 *) (ip + m_len)) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 169) 		    get_unaligned((const u64 *) (m_pos + m_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 170) 		if (unlikely(v == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 171) 			do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 172) 				m_len += 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 173) 				v = get_unaligned((const u64 *) (ip + m_len)) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 174) 				    get_unaligned((const u64 *) (m_pos + m_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 175) 				if (unlikely(ip + m_len >= ip_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 176) 					goto m_len_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 177) 			} while (v == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 178) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 179) #  if defined(__LITTLE_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 180) 		m_len += (unsigned) __builtin_ctzll(v) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 181) #  elif defined(__BIG_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 182) 		m_len += (unsigned) __builtin_clzll(v) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 183) #  else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 184) #    error "missing endian definition"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 185) #  endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 186) #elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 187) 		u32 v;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 188) 		v = get_unaligned((const u32 *) (ip + m_len)) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 189) 		    get_unaligned((const u32 *) (m_pos + m_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 190) 		if (unlikely(v == 0)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 191) 			do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 192) 				m_len += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 193) 				v = get_unaligned((const u32 *) (ip + m_len)) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 194) 				    get_unaligned((const u32 *) (m_pos + m_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 195) 				if (v != 0)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 196) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 197) 				m_len += 4;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 198) 				v = get_unaligned((const u32 *) (ip + m_len)) ^
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 199) 				    get_unaligned((const u32 *) (m_pos + m_len));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 200) 				if (unlikely(ip + m_len >= ip_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 201) 					goto m_len_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 202) 			} while (v == 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 203) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 204) #  if defined(__LITTLE_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 205) 		m_len += (unsigned) __builtin_ctz(v) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 206) #  elif defined(__BIG_ENDIAN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 207) 		m_len += (unsigned) __builtin_clz(v) / 8;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 208) #  else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 209) #    error "missing endian definition"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 210) #  endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 211) #else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 212) 		if (unlikely(ip[m_len] == m_pos[m_len])) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 213) 			do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 214) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 215) 				if (ip[m_len] != m_pos[m_len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 216) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 217) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 218) 				if (ip[m_len] != m_pos[m_len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 219) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 220) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 221) 				if (ip[m_len] != m_pos[m_len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 222) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 223) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 224) 				if (ip[m_len] != m_pos[m_len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 225) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 226) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 227) 				if (ip[m_len] != m_pos[m_len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 228) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 229) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 230) 				if (ip[m_len] != m_pos[m_len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 231) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 232) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 233) 				if (ip[m_len] != m_pos[m_len])
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 234) 					break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 235) 				m_len += 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 236) 				if (unlikely(ip + m_len >= ip_end))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 237) 					goto m_len_done;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 238) 			} while (ip[m_len] == m_pos[m_len]);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 239) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 240) #endif
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 241) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 242) m_len_done:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 243) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 244) 		m_off = ip - m_pos;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 245) 		ip += m_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 246) 		if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 247) 			m_off -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 248) 			*op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 249) 			*op++ = (m_off >> 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 250) 		} else if (m_off <= M3_MAX_OFFSET) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 251) 			m_off -= 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 252) 			if (m_len <= M3_MAX_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 253) 				*op++ = (M3_MARKER | (m_len - 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 254) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 255) 				m_len -= M3_MAX_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 256) 				*op++ = M3_MARKER | 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 257) 				while (unlikely(m_len > 255)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 258) 					m_len -= 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 259) 					*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 260) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 261) 				*op++ = (m_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 262) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 263) 			*op++ = (m_off << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 264) 			*op++ = (m_off >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 265) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 266) 			m_off -= 0x4000;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 267) 			if (m_len <= M4_MAX_LEN)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 268) 				*op++ = (M4_MARKER | ((m_off >> 11) & 8)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 269) 						| (m_len - 2));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 270) 			else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 271) 				if (unlikely(((m_off & 0x403f) == 0x403f)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 272) 						&& (m_len >= 261)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 273) 						&& (m_len <= 264))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 274) 						&& likely(bitstream_version)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 275) 					// Under lzo-rle, block copies
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 276) 					// for 261 <= length <= 264 and
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 277) 					// (distance & 0x80f3) == 0x80f3
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 278) 					// can result in ambiguous
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 279) 					// output. Adjust length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 280) 					// to 260 to prevent ambiguity.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 281) 					ip -= m_len - 260;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 282) 					m_len = 260;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 283) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 284) 				m_len -= M4_MAX_LEN;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 285) 				*op++ = (M4_MARKER | ((m_off >> 11) & 8));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 286) 				while (unlikely(m_len > 255)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 287) 					m_len -= 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 288) 					*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 289) 				}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 290) 				*op++ = (m_len);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 291) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 292) 			*op++ = (m_off << 2);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 293) 			*op++ = (m_off >> 6);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 294) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 295) 		*state_offset = -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 296) finished_writing_instruction:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 297) 		ii = ip;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 298) 		goto next;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 299) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 300) 	*out_len = op - out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 301) 	return in_end - (ii - ti);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 302) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 303) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 304) int lzogeneric1x_1_compress(const unsigned char *in, size_t in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 305) 		     unsigned char *out, size_t *out_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 306) 		     void *wrkmem, const unsigned char bitstream_version)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 307) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 308) 	const unsigned char *ip = in;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 309) 	unsigned char *op = out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 310) 	unsigned char *data_start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 311) 	size_t l = in_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 312) 	size_t t = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 313) 	signed char state_offset = -2;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 314) 	unsigned int m4_max_offset;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 315) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 316) 	// LZO v0 will never write 17 as first byte (except for zero-length
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 317) 	// input), so this is used to version the bitstream
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 318) 	if (bitstream_version > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 319) 		*op++ = 17;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 320) 		*op++ = bitstream_version;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 321) 		m4_max_offset = M4_MAX_OFFSET_V1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 322) 	} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 323) 		m4_max_offset = M4_MAX_OFFSET_V0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 324) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 325) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 326) 	data_start = op;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 327) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 328) 	while (l > 20) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 329) 		size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 330) 		uintptr_t ll_end = (uintptr_t) ip + ll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 331) 		if ((ll_end + ((t + ll) >> 5)) <= ll_end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 332) 			break;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 333) 		BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 334) 		memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 335) 		t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 336) 					&state_offset, bitstream_version);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 337) 		ip += ll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 338) 		op += *out_len;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 339) 		l  -= ll;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 340) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 341) 	t += l;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 342) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 343) 	if (t > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 344) 		const unsigned char *ii = in + in_len - t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 345) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 346) 		if (op == data_start && t <= 238) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 347) 			*op++ = (17 + t);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 348) 		} else if (t <= 3) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 349) 			op[state_offset] |= t;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 350) 		} else if (t <= 18) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 351) 			*op++ = (t - 3);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 352) 		} else {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 353) 			size_t tt = t - 18;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 354) 			*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 355) 			while (tt > 255) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 356) 				tt -= 255;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 357) 				*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 358) 			}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 359) 			*op++ = tt;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 360) 		}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 361) 		if (t >= 16) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 362) 			COPY8(op, ii);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 363) 			COPY8(op + 8, ii + 8);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 364) 			op += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 365) 			ii += 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 366) 			t -= 16;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 367) 		} while (t >= 16);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 368) 		if (t > 0) do {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 369) 			*op++ = *ii++;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 370) 		} while (--t > 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 371) 	}
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 372) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 373) 	*op++ = M4_MARKER | 1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 374) 	*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 375) 	*op++ = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 376) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 377) 	*out_len = op - out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 378) 	return LZO_E_OK;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 379) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 380) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 381) int lzo1x_1_compress(const unsigned char *in, size_t in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 382) 		     unsigned char *out, size_t *out_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 383) 		     void *wrkmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 384) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 385) 	return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 386) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 387) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 388) int lzorle1x_1_compress(const unsigned char *in, size_t in_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 389) 		     unsigned char *out, size_t *out_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 390) 		     void *wrkmem)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 391) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 392) 	return lzogeneric1x_1_compress(in, in_len, out, out_len,
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 393) 				       wrkmem, LZO_VERSION);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 394) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 395) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 396) EXPORT_SYMBOL_GPL(lzo1x_1_compress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 397) EXPORT_SYMBOL_GPL(lzorle1x_1_compress);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 398) 
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 399) MODULE_LICENSE("GPL");
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 400) MODULE_DESCRIPTION("LZO1X-1 Compressor");