18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * LZO1X Compressor from LZO 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (C) 1996-2012 Markus F.X.J. Oberhumer <markus@oberhumer.com> 68c2ecf20Sopenharmony_ci * 78c2ecf20Sopenharmony_ci * The full LZO package can be found at: 88c2ecf20Sopenharmony_ci * http://www.oberhumer.com/opensource/lzo/ 98c2ecf20Sopenharmony_ci * 108c2ecf20Sopenharmony_ci * Changed for Linux kernel use by: 118c2ecf20Sopenharmony_ci * Nitin Gupta <nitingupta910@gmail.com> 128c2ecf20Sopenharmony_ci * Richard Purdie <rpurdie@openedhand.com> 138c2ecf20Sopenharmony_ci */ 148c2ecf20Sopenharmony_ci 158c2ecf20Sopenharmony_ci#include <linux/module.h> 168c2ecf20Sopenharmony_ci#include <linux/kernel.h> 178c2ecf20Sopenharmony_ci#include <asm/unaligned.h> 188c2ecf20Sopenharmony_ci#include <linux/lzo.h> 198c2ecf20Sopenharmony_ci#include "lzodefs.h" 208c2ecf20Sopenharmony_ci 218c2ecf20Sopenharmony_cistatic noinline size_t 228c2ecf20Sopenharmony_cilzo1x_1_do_compress(const unsigned char *in, size_t in_len, 238c2ecf20Sopenharmony_ci unsigned char *out, size_t *out_len, 248c2ecf20Sopenharmony_ci size_t ti, void *wrkmem, signed char *state_offset, 258c2ecf20Sopenharmony_ci const unsigned char bitstream_version) 268c2ecf20Sopenharmony_ci{ 278c2ecf20Sopenharmony_ci const unsigned char *ip; 288c2ecf20Sopenharmony_ci unsigned char *op; 298c2ecf20Sopenharmony_ci const unsigned char * const in_end = in + in_len; 308c2ecf20Sopenharmony_ci const unsigned char * const ip_end = in + in_len - 20; 318c2ecf20Sopenharmony_ci const unsigned char *ii; 328c2ecf20Sopenharmony_ci lzo_dict_t * const dict = (lzo_dict_t *) wrkmem; 338c2ecf20Sopenharmony_ci 348c2ecf20Sopenharmony_ci op = out; 358c2ecf20Sopenharmony_ci ip = in; 368c2ecf20Sopenharmony_ci ii = ip; 378c2ecf20Sopenharmony_ci ip += ti < 4 ? 4 - ti : 0; 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_ci for (;;) { 408c2ecf20Sopenharmony_ci const unsigned char *m_pos = NULL; 418c2ecf20Sopenharmony_ci size_t t, m_len, m_off; 428c2ecf20Sopenharmony_ci u32 dv; 438c2ecf20Sopenharmony_ci u32 run_length = 0; 448c2ecf20Sopenharmony_ciliteral: 458c2ecf20Sopenharmony_ci ip += 1 + ((ip - ii) >> 5); 468c2ecf20Sopenharmony_cinext: 478c2ecf20Sopenharmony_ci if (unlikely(ip >= ip_end)) 488c2ecf20Sopenharmony_ci break; 498c2ecf20Sopenharmony_ci dv = get_unaligned_le32(ip); 508c2ecf20Sopenharmony_ci 518c2ecf20Sopenharmony_ci if (dv == 0 && bitstream_version) { 528c2ecf20Sopenharmony_ci const unsigned char *ir = ip + 4; 538c2ecf20Sopenharmony_ci const unsigned char *limit = ip_end 548c2ecf20Sopenharmony_ci < (ip + MAX_ZERO_RUN_LENGTH + 1) 558c2ecf20Sopenharmony_ci ? ip_end : ip + MAX_ZERO_RUN_LENGTH + 1; 568c2ecf20Sopenharmony_ci#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && \ 578c2ecf20Sopenharmony_ci defined(LZO_FAST_64BIT_MEMORY_ACCESS) 588c2ecf20Sopenharmony_ci u64 dv64; 598c2ecf20Sopenharmony_ci 608c2ecf20Sopenharmony_ci for (; (ir + 32) <= limit; ir += 32) { 618c2ecf20Sopenharmony_ci dv64 = get_unaligned((u64 *)ir); 628c2ecf20Sopenharmony_ci dv64 |= get_unaligned((u64 *)ir + 1); 638c2ecf20Sopenharmony_ci dv64 |= get_unaligned((u64 *)ir + 2); 648c2ecf20Sopenharmony_ci dv64 |= get_unaligned((u64 *)ir + 3); 658c2ecf20Sopenharmony_ci if (dv64) 668c2ecf20Sopenharmony_ci break; 678c2ecf20Sopenharmony_ci } 688c2ecf20Sopenharmony_ci for (; (ir + 8) <= limit; ir += 8) { 698c2ecf20Sopenharmony_ci dv64 = get_unaligned((u64 *)ir); 708c2ecf20Sopenharmony_ci if (dv64) { 718c2ecf20Sopenharmony_ci# if defined(__LITTLE_ENDIAN) 728c2ecf20Sopenharmony_ci ir += __builtin_ctzll(dv64) >> 3; 738c2ecf20Sopenharmony_ci# elif defined(__BIG_ENDIAN) 748c2ecf20Sopenharmony_ci ir += __builtin_clzll(dv64) >> 3; 758c2ecf20Sopenharmony_ci# else 768c2ecf20Sopenharmony_ci# error "missing endian definition" 778c2ecf20Sopenharmony_ci# endif 788c2ecf20Sopenharmony_ci break; 798c2ecf20Sopenharmony_ci } 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci#else 828c2ecf20Sopenharmony_ci while ((ir < (const unsigned char *) 838c2ecf20Sopenharmony_ci ALIGN((uintptr_t)ir, 4)) && 848c2ecf20Sopenharmony_ci (ir < limit) && (*ir == 0)) 858c2ecf20Sopenharmony_ci ir++; 868c2ecf20Sopenharmony_ci if (IS_ALIGNED((uintptr_t)ir, 4)) { 878c2ecf20Sopenharmony_ci for (; (ir + 4) <= limit; ir += 4) { 888c2ecf20Sopenharmony_ci dv = *((u32 *)ir); 898c2ecf20Sopenharmony_ci if (dv) { 908c2ecf20Sopenharmony_ci# if defined(__LITTLE_ENDIAN) 918c2ecf20Sopenharmony_ci ir += __builtin_ctz(dv) >> 3; 928c2ecf20Sopenharmony_ci# elif defined(__BIG_ENDIAN) 938c2ecf20Sopenharmony_ci ir += __builtin_clz(dv) >> 3; 948c2ecf20Sopenharmony_ci# else 958c2ecf20Sopenharmony_ci# error "missing endian definition" 968c2ecf20Sopenharmony_ci# endif 978c2ecf20Sopenharmony_ci break; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci } 1008c2ecf20Sopenharmony_ci } 1018c2ecf20Sopenharmony_ci#endif 1028c2ecf20Sopenharmony_ci while (likely(ir < limit) && unlikely(*ir == 0)) 1038c2ecf20Sopenharmony_ci ir++; 1048c2ecf20Sopenharmony_ci run_length = ir - ip; 1058c2ecf20Sopenharmony_ci if (run_length > MAX_ZERO_RUN_LENGTH) 1068c2ecf20Sopenharmony_ci run_length = MAX_ZERO_RUN_LENGTH; 1078c2ecf20Sopenharmony_ci } else { 1088c2ecf20Sopenharmony_ci t = ((dv * 0x1824429d) >> (32 - D_BITS)) & D_MASK; 1098c2ecf20Sopenharmony_ci m_pos = in + dict[t]; 1108c2ecf20Sopenharmony_ci dict[t] = (lzo_dict_t) (ip - in); 1118c2ecf20Sopenharmony_ci if (unlikely(dv != get_unaligned_le32(m_pos))) 1128c2ecf20Sopenharmony_ci goto literal; 1138c2ecf20Sopenharmony_ci } 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_ci ii -= ti; 1168c2ecf20Sopenharmony_ci ti = 0; 1178c2ecf20Sopenharmony_ci t = ip - ii; 1188c2ecf20Sopenharmony_ci if (t != 0) { 1198c2ecf20Sopenharmony_ci if (t <= 3) { 1208c2ecf20Sopenharmony_ci op[*state_offset] |= t; 1218c2ecf20Sopenharmony_ci COPY4(op, ii); 1228c2ecf20Sopenharmony_ci op += t; 1238c2ecf20Sopenharmony_ci } else if (t <= 16) { 1248c2ecf20Sopenharmony_ci *op++ = (t - 3); 1258c2ecf20Sopenharmony_ci COPY8(op, ii); 1268c2ecf20Sopenharmony_ci COPY8(op + 8, ii + 8); 1278c2ecf20Sopenharmony_ci op += t; 1288c2ecf20Sopenharmony_ci } else { 1298c2ecf20Sopenharmony_ci if (t <= 18) { 1308c2ecf20Sopenharmony_ci *op++ = (t - 3); 1318c2ecf20Sopenharmony_ci } else { 1328c2ecf20Sopenharmony_ci size_t tt = t - 18; 1338c2ecf20Sopenharmony_ci *op++ = 0; 1348c2ecf20Sopenharmony_ci while (unlikely(tt > 255)) { 1358c2ecf20Sopenharmony_ci tt -= 255; 1368c2ecf20Sopenharmony_ci *op++ = 0; 1378c2ecf20Sopenharmony_ci } 1388c2ecf20Sopenharmony_ci *op++ = tt; 1398c2ecf20Sopenharmony_ci } 1408c2ecf20Sopenharmony_ci do { 1418c2ecf20Sopenharmony_ci COPY8(op, ii); 1428c2ecf20Sopenharmony_ci COPY8(op + 8, ii + 8); 1438c2ecf20Sopenharmony_ci op += 16; 1448c2ecf20Sopenharmony_ci ii += 16; 1458c2ecf20Sopenharmony_ci t -= 16; 1468c2ecf20Sopenharmony_ci } while (t >= 16); 1478c2ecf20Sopenharmony_ci if (t > 0) do { 1488c2ecf20Sopenharmony_ci *op++ = *ii++; 1498c2ecf20Sopenharmony_ci } while (--t > 0); 1508c2ecf20Sopenharmony_ci } 1518c2ecf20Sopenharmony_ci } 1528c2ecf20Sopenharmony_ci 1538c2ecf20Sopenharmony_ci if (unlikely(run_length)) { 1548c2ecf20Sopenharmony_ci ip += run_length; 1558c2ecf20Sopenharmony_ci run_length -= MIN_ZERO_RUN_LENGTH; 1568c2ecf20Sopenharmony_ci put_unaligned_le32((run_length << 21) | 0xfffc18 1578c2ecf20Sopenharmony_ci | (run_length & 0x7), op); 1588c2ecf20Sopenharmony_ci op += 4; 1598c2ecf20Sopenharmony_ci run_length = 0; 1608c2ecf20Sopenharmony_ci *state_offset = -3; 1618c2ecf20Sopenharmony_ci goto finished_writing_instruction; 1628c2ecf20Sopenharmony_ci } 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci m_len = 4; 1658c2ecf20Sopenharmony_ci { 1668c2ecf20Sopenharmony_ci#if defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ64) 1678c2ecf20Sopenharmony_ci u64 v; 1688c2ecf20Sopenharmony_ci v = get_unaligned((const u64 *) (ip + m_len)) ^ 1698c2ecf20Sopenharmony_ci get_unaligned((const u64 *) (m_pos + m_len)); 1708c2ecf20Sopenharmony_ci if (unlikely(v == 0)) { 1718c2ecf20Sopenharmony_ci do { 1728c2ecf20Sopenharmony_ci m_len += 8; 1738c2ecf20Sopenharmony_ci v = get_unaligned((const u64 *) (ip + m_len)) ^ 1748c2ecf20Sopenharmony_ci get_unaligned((const u64 *) (m_pos + m_len)); 1758c2ecf20Sopenharmony_ci if (unlikely(ip + m_len >= ip_end)) 1768c2ecf20Sopenharmony_ci goto m_len_done; 1778c2ecf20Sopenharmony_ci } while (v == 0); 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci# if defined(__LITTLE_ENDIAN) 1808c2ecf20Sopenharmony_ci m_len += (unsigned) __builtin_ctzll(v) / 8; 1818c2ecf20Sopenharmony_ci# elif defined(__BIG_ENDIAN) 1828c2ecf20Sopenharmony_ci m_len += (unsigned) __builtin_clzll(v) / 8; 1838c2ecf20Sopenharmony_ci# else 1848c2ecf20Sopenharmony_ci# error "missing endian definition" 1858c2ecf20Sopenharmony_ci# endif 1868c2ecf20Sopenharmony_ci#elif defined(CONFIG_HAVE_EFFICIENT_UNALIGNED_ACCESS) && defined(LZO_USE_CTZ32) 1878c2ecf20Sopenharmony_ci u32 v; 1888c2ecf20Sopenharmony_ci v = get_unaligned((const u32 *) (ip + m_len)) ^ 1898c2ecf20Sopenharmony_ci get_unaligned((const u32 *) (m_pos + m_len)); 1908c2ecf20Sopenharmony_ci if (unlikely(v == 0)) { 1918c2ecf20Sopenharmony_ci do { 1928c2ecf20Sopenharmony_ci m_len += 4; 1938c2ecf20Sopenharmony_ci v = get_unaligned((const u32 *) (ip + m_len)) ^ 1948c2ecf20Sopenharmony_ci get_unaligned((const u32 *) (m_pos + m_len)); 1958c2ecf20Sopenharmony_ci if (v != 0) 1968c2ecf20Sopenharmony_ci break; 1978c2ecf20Sopenharmony_ci m_len += 4; 1988c2ecf20Sopenharmony_ci v = get_unaligned((const u32 *) (ip + m_len)) ^ 1998c2ecf20Sopenharmony_ci get_unaligned((const u32 *) (m_pos + m_len)); 2008c2ecf20Sopenharmony_ci if (unlikely(ip + m_len >= ip_end)) 2018c2ecf20Sopenharmony_ci goto m_len_done; 2028c2ecf20Sopenharmony_ci } while (v == 0); 2038c2ecf20Sopenharmony_ci } 2048c2ecf20Sopenharmony_ci# if defined(__LITTLE_ENDIAN) 2058c2ecf20Sopenharmony_ci m_len += (unsigned) __builtin_ctz(v) / 8; 2068c2ecf20Sopenharmony_ci# elif defined(__BIG_ENDIAN) 2078c2ecf20Sopenharmony_ci m_len += (unsigned) __builtin_clz(v) / 8; 2088c2ecf20Sopenharmony_ci# else 2098c2ecf20Sopenharmony_ci# error "missing endian definition" 2108c2ecf20Sopenharmony_ci# endif 2118c2ecf20Sopenharmony_ci#else 2128c2ecf20Sopenharmony_ci if (unlikely(ip[m_len] == m_pos[m_len])) { 2138c2ecf20Sopenharmony_ci do { 2148c2ecf20Sopenharmony_ci m_len += 1; 2158c2ecf20Sopenharmony_ci if (ip[m_len] != m_pos[m_len]) 2168c2ecf20Sopenharmony_ci break; 2178c2ecf20Sopenharmony_ci m_len += 1; 2188c2ecf20Sopenharmony_ci if (ip[m_len] != m_pos[m_len]) 2198c2ecf20Sopenharmony_ci break; 2208c2ecf20Sopenharmony_ci m_len += 1; 2218c2ecf20Sopenharmony_ci if (ip[m_len] != m_pos[m_len]) 2228c2ecf20Sopenharmony_ci break; 2238c2ecf20Sopenharmony_ci m_len += 1; 2248c2ecf20Sopenharmony_ci if (ip[m_len] != m_pos[m_len]) 2258c2ecf20Sopenharmony_ci break; 2268c2ecf20Sopenharmony_ci m_len += 1; 2278c2ecf20Sopenharmony_ci if (ip[m_len] != m_pos[m_len]) 2288c2ecf20Sopenharmony_ci break; 2298c2ecf20Sopenharmony_ci m_len += 1; 2308c2ecf20Sopenharmony_ci if (ip[m_len] != m_pos[m_len]) 2318c2ecf20Sopenharmony_ci break; 2328c2ecf20Sopenharmony_ci m_len += 1; 2338c2ecf20Sopenharmony_ci if (ip[m_len] != m_pos[m_len]) 2348c2ecf20Sopenharmony_ci break; 2358c2ecf20Sopenharmony_ci m_len += 1; 2368c2ecf20Sopenharmony_ci if (unlikely(ip + m_len >= ip_end)) 2378c2ecf20Sopenharmony_ci goto m_len_done; 2388c2ecf20Sopenharmony_ci } while (ip[m_len] == m_pos[m_len]); 2398c2ecf20Sopenharmony_ci } 2408c2ecf20Sopenharmony_ci#endif 2418c2ecf20Sopenharmony_ci } 2428c2ecf20Sopenharmony_cim_len_done: 2438c2ecf20Sopenharmony_ci 2448c2ecf20Sopenharmony_ci m_off = ip - m_pos; 2458c2ecf20Sopenharmony_ci ip += m_len; 2468c2ecf20Sopenharmony_ci if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET) { 2478c2ecf20Sopenharmony_ci m_off -= 1; 2488c2ecf20Sopenharmony_ci *op++ = (((m_len - 1) << 5) | ((m_off & 7) << 2)); 2498c2ecf20Sopenharmony_ci *op++ = (m_off >> 3); 2508c2ecf20Sopenharmony_ci } else if (m_off <= M3_MAX_OFFSET) { 2518c2ecf20Sopenharmony_ci m_off -= 1; 2528c2ecf20Sopenharmony_ci if (m_len <= M3_MAX_LEN) 2538c2ecf20Sopenharmony_ci *op++ = (M3_MARKER | (m_len - 2)); 2548c2ecf20Sopenharmony_ci else { 2558c2ecf20Sopenharmony_ci m_len -= M3_MAX_LEN; 2568c2ecf20Sopenharmony_ci *op++ = M3_MARKER | 0; 2578c2ecf20Sopenharmony_ci while (unlikely(m_len > 255)) { 2588c2ecf20Sopenharmony_ci m_len -= 255; 2598c2ecf20Sopenharmony_ci *op++ = 0; 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci *op++ = (m_len); 2628c2ecf20Sopenharmony_ci } 2638c2ecf20Sopenharmony_ci *op++ = (m_off << 2); 2648c2ecf20Sopenharmony_ci *op++ = (m_off >> 6); 2658c2ecf20Sopenharmony_ci } else { 2668c2ecf20Sopenharmony_ci m_off -= 0x4000; 2678c2ecf20Sopenharmony_ci if (m_len <= M4_MAX_LEN) 2688c2ecf20Sopenharmony_ci *op++ = (M4_MARKER | ((m_off >> 11) & 8) 2698c2ecf20Sopenharmony_ci | (m_len - 2)); 2708c2ecf20Sopenharmony_ci else { 2718c2ecf20Sopenharmony_ci if (unlikely(((m_off & 0x403f) == 0x403f) 2728c2ecf20Sopenharmony_ci && (m_len >= 261) 2738c2ecf20Sopenharmony_ci && (m_len <= 264)) 2748c2ecf20Sopenharmony_ci && likely(bitstream_version)) { 2758c2ecf20Sopenharmony_ci // Under lzo-rle, block copies 2768c2ecf20Sopenharmony_ci // for 261 <= length <= 264 and 2778c2ecf20Sopenharmony_ci // (distance & 0x80f3) == 0x80f3 2788c2ecf20Sopenharmony_ci // can result in ambiguous 2798c2ecf20Sopenharmony_ci // output. Adjust length 2808c2ecf20Sopenharmony_ci // to 260 to prevent ambiguity. 2818c2ecf20Sopenharmony_ci ip -= m_len - 260; 2828c2ecf20Sopenharmony_ci m_len = 260; 2838c2ecf20Sopenharmony_ci } 2848c2ecf20Sopenharmony_ci m_len -= M4_MAX_LEN; 2858c2ecf20Sopenharmony_ci *op++ = (M4_MARKER | ((m_off >> 11) & 8)); 2868c2ecf20Sopenharmony_ci while (unlikely(m_len > 255)) { 2878c2ecf20Sopenharmony_ci m_len -= 255; 2888c2ecf20Sopenharmony_ci *op++ = 0; 2898c2ecf20Sopenharmony_ci } 2908c2ecf20Sopenharmony_ci *op++ = (m_len); 2918c2ecf20Sopenharmony_ci } 2928c2ecf20Sopenharmony_ci *op++ = (m_off << 2); 2938c2ecf20Sopenharmony_ci *op++ = (m_off >> 6); 2948c2ecf20Sopenharmony_ci } 2958c2ecf20Sopenharmony_ci *state_offset = -2; 2968c2ecf20Sopenharmony_cifinished_writing_instruction: 2978c2ecf20Sopenharmony_ci ii = ip; 2988c2ecf20Sopenharmony_ci goto next; 2998c2ecf20Sopenharmony_ci } 3008c2ecf20Sopenharmony_ci *out_len = op - out; 3018c2ecf20Sopenharmony_ci return in_end - (ii - ti); 3028c2ecf20Sopenharmony_ci} 3038c2ecf20Sopenharmony_ci 3048c2ecf20Sopenharmony_ciint lzogeneric1x_1_compress(const unsigned char *in, size_t in_len, 3058c2ecf20Sopenharmony_ci unsigned char *out, size_t *out_len, 3068c2ecf20Sopenharmony_ci void *wrkmem, const unsigned char bitstream_version) 3078c2ecf20Sopenharmony_ci{ 3088c2ecf20Sopenharmony_ci const unsigned char *ip = in; 3098c2ecf20Sopenharmony_ci unsigned char *op = out; 3108c2ecf20Sopenharmony_ci unsigned char *data_start; 3118c2ecf20Sopenharmony_ci size_t l = in_len; 3128c2ecf20Sopenharmony_ci size_t t = 0; 3138c2ecf20Sopenharmony_ci signed char state_offset = -2; 3148c2ecf20Sopenharmony_ci unsigned int m4_max_offset; 3158c2ecf20Sopenharmony_ci 3168c2ecf20Sopenharmony_ci // LZO v0 will never write 17 as first byte (except for zero-length 3178c2ecf20Sopenharmony_ci // input), so this is used to version the bitstream 3188c2ecf20Sopenharmony_ci if (bitstream_version > 0) { 3198c2ecf20Sopenharmony_ci *op++ = 17; 3208c2ecf20Sopenharmony_ci *op++ = bitstream_version; 3218c2ecf20Sopenharmony_ci m4_max_offset = M4_MAX_OFFSET_V1; 3228c2ecf20Sopenharmony_ci } else { 3238c2ecf20Sopenharmony_ci m4_max_offset = M4_MAX_OFFSET_V0; 3248c2ecf20Sopenharmony_ci } 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci data_start = op; 3278c2ecf20Sopenharmony_ci 3288c2ecf20Sopenharmony_ci while (l > 20) { 3298c2ecf20Sopenharmony_ci size_t ll = l <= (m4_max_offset + 1) ? l : (m4_max_offset + 1); 3308c2ecf20Sopenharmony_ci uintptr_t ll_end = (uintptr_t) ip + ll; 3318c2ecf20Sopenharmony_ci if ((ll_end + ((t + ll) >> 5)) <= ll_end) 3328c2ecf20Sopenharmony_ci break; 3338c2ecf20Sopenharmony_ci BUILD_BUG_ON(D_SIZE * sizeof(lzo_dict_t) > LZO1X_1_MEM_COMPRESS); 3348c2ecf20Sopenharmony_ci memset(wrkmem, 0, D_SIZE * sizeof(lzo_dict_t)); 3358c2ecf20Sopenharmony_ci t = lzo1x_1_do_compress(ip, ll, op, out_len, t, wrkmem, 3368c2ecf20Sopenharmony_ci &state_offset, bitstream_version); 3378c2ecf20Sopenharmony_ci ip += ll; 3388c2ecf20Sopenharmony_ci op += *out_len; 3398c2ecf20Sopenharmony_ci l -= ll; 3408c2ecf20Sopenharmony_ci } 3418c2ecf20Sopenharmony_ci t += l; 3428c2ecf20Sopenharmony_ci 3438c2ecf20Sopenharmony_ci if (t > 0) { 3448c2ecf20Sopenharmony_ci const unsigned char *ii = in + in_len - t; 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_ci if (op == data_start && t <= 238) { 3478c2ecf20Sopenharmony_ci *op++ = (17 + t); 3488c2ecf20Sopenharmony_ci } else if (t <= 3) { 3498c2ecf20Sopenharmony_ci op[state_offset] |= t; 3508c2ecf20Sopenharmony_ci } else if (t <= 18) { 3518c2ecf20Sopenharmony_ci *op++ = (t - 3); 3528c2ecf20Sopenharmony_ci } else { 3538c2ecf20Sopenharmony_ci size_t tt = t - 18; 3548c2ecf20Sopenharmony_ci *op++ = 0; 3558c2ecf20Sopenharmony_ci while (tt > 255) { 3568c2ecf20Sopenharmony_ci tt -= 255; 3578c2ecf20Sopenharmony_ci *op++ = 0; 3588c2ecf20Sopenharmony_ci } 3598c2ecf20Sopenharmony_ci *op++ = tt; 3608c2ecf20Sopenharmony_ci } 3618c2ecf20Sopenharmony_ci if (t >= 16) do { 3628c2ecf20Sopenharmony_ci COPY8(op, ii); 3638c2ecf20Sopenharmony_ci COPY8(op + 8, ii + 8); 3648c2ecf20Sopenharmony_ci op += 16; 3658c2ecf20Sopenharmony_ci ii += 16; 3668c2ecf20Sopenharmony_ci t -= 16; 3678c2ecf20Sopenharmony_ci } while (t >= 16); 3688c2ecf20Sopenharmony_ci if (t > 0) do { 3698c2ecf20Sopenharmony_ci *op++ = *ii++; 3708c2ecf20Sopenharmony_ci } while (--t > 0); 3718c2ecf20Sopenharmony_ci } 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci *op++ = M4_MARKER | 1; 3748c2ecf20Sopenharmony_ci *op++ = 0; 3758c2ecf20Sopenharmony_ci *op++ = 0; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci *out_len = op - out; 3788c2ecf20Sopenharmony_ci return LZO_E_OK; 3798c2ecf20Sopenharmony_ci} 3808c2ecf20Sopenharmony_ci 3818c2ecf20Sopenharmony_ciint lzo1x_1_compress(const unsigned char *in, size_t in_len, 3828c2ecf20Sopenharmony_ci unsigned char *out, size_t *out_len, 3838c2ecf20Sopenharmony_ci void *wrkmem) 3848c2ecf20Sopenharmony_ci{ 3858c2ecf20Sopenharmony_ci return lzogeneric1x_1_compress(in, in_len, out, out_len, wrkmem, 0); 3868c2ecf20Sopenharmony_ci} 3878c2ecf20Sopenharmony_ci 3888c2ecf20Sopenharmony_ciint lzorle1x_1_compress(const unsigned char *in, size_t in_len, 3898c2ecf20Sopenharmony_ci unsigned char *out, size_t *out_len, 3908c2ecf20Sopenharmony_ci void *wrkmem) 3918c2ecf20Sopenharmony_ci{ 3928c2ecf20Sopenharmony_ci return lzogeneric1x_1_compress(in, in_len, out, out_len, 3938c2ecf20Sopenharmony_ci wrkmem, LZO_VERSION); 3948c2ecf20Sopenharmony_ci} 3958c2ecf20Sopenharmony_ci 3968c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(lzo1x_1_compress); 3978c2ecf20Sopenharmony_ciEXPORT_SYMBOL_GPL(lzorle1x_1_compress); 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL"); 4008c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("LZO1X-1 Compressor"); 401