blob: 892766e12eb781760cb3ca53f9644fb80a846661 [file] [log] [blame]
wdenk07cc0992005-05-05 00:04:14 +00001/*
2 * JFFS2 -- Journalling Flash File System, Version 2.
3 *
4 * Copyright (C) 2004 Patrik Kluba,
5 * University of Szeged, Hungary
6 *
7 * For licensing information, see the file 'LICENCE' in the
8 * jffs2 directory.
9 *
10 * $Id: compr_lzo.c,v 1.3 2004/06/23 16:34:39 havasi Exp $
11 *
12 */
13
14/*
15 LZO1X-1 (and -999) compression module for jffs2
16 based on the original LZO sources
17*/
18
19/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
20
21/*
22 Original copyright notice follows:
23
24 lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
25 lzo_ptr.h -- low-level pointer constructs
26 lzo_swd.ch -- sliding window dictionary
27 lzoconf.h -- configuration for the LZO real-time data compression library
28 lzo_mchw.ch -- matching functions using a window
29 minilzo.c -- mini subset of the LZO real-time data compression library
30 config1x.h -- configuration for the LZO1X algorithm
31 lzo1x.h -- public interface of the LZO1X compression algorithm
32
33 These files are part of the LZO real-time data compression library.
34
35 Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
36 All Rights Reserved.
37
38 The LZO library is free software; you can redistribute it and/or
39 modify it under the terms of the GNU General Public License as
40 published by the Free Software Foundation; either version 2 of
41 the License, or (at your option) any later version.
42
43 The LZO library is distributed in the hope that it will be useful,
44 but WITHOUT ANY WARRANTY; without even the implied warranty of
45 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
46 GNU General Public License for more details.
47
48 You should have received a copy of the GNU General Public License
49 along with the LZO library; see the file COPYING.
50 If not, write to the Free Software Foundation, Inc.,
51 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
52
53 Markus F.X.J. Oberhumer
54 <markus@oberhumer.com>
55*/
56
57/*
58
59 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
60 Initial release
61 -removed all 16 bit code
62 -all sensitive data will be on 4 byte boundary
63 -removed check parts for library use
64 -removed all but LZO1X-* compression
65
66*/
67
wdenk07cc0992005-05-05 00:04:14 +000068#include <config.h>
wdenk07cc0992005-05-05 00:04:14 +000069#include <linux/stddef.h>
70#include <jffs2/jffs2.h>
71#include <jffs2/compr_rubin.h>
72
73/* Integral types that have *exactly* the same number of bits as a lzo_voidp */
74typedef unsigned long lzo_ptr_t;
75typedef long lzo_sptr_t;
76
77/* data type definitions */
78#define U32 unsigned long
79#define S32 signed long
80#define I32 long
81#define U16 unsigned short
82#define S16 signed short
83#define I16 short
84#define U8 unsigned char
85#define S8 signed char
86#define I8 char
87
88#define M1_MAX_OFFSET 0x0400
89#define M2_MAX_OFFSET 0x0800
90#define M3_MAX_OFFSET 0x4000
91#define M4_MAX_OFFSET 0xbfff
92
93#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
94#define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
95
96#define TEST_IP (ip < ip_end)
97#define TEST_OP (op <= op_end)
98
99#define NEED_IP(x) \
100 if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
101#define NEED_OP(x) \
102 if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
103#define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
104
105typedef U32 lzo_uint32;
106typedef I32 lzo_int32;
107typedef U32 lzo_uint;
108typedef I32 lzo_int;
109typedef int lzo_bool;
110
111#define lzo_byte U8
112#define lzo_bytep U8 *
113#define lzo_charp char *
114#define lzo_voidp void *
115#define lzo_shortp short *
116#define lzo_ushortp unsigned short *
117#define lzo_uint32p lzo_uint32 *
118#define lzo_int32p lzo_int32 *
119#define lzo_uintp lzo_uint *
120#define lzo_intp lzo_int *
121#define lzo_voidpp lzo_voidp *
122#define lzo_bytepp lzo_bytep *
123#define lzo_sizeof_dict_t sizeof(lzo_bytep)
124
125#define LZO_E_OK 0
126#define LZO_E_ERROR (-1)
127#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */
128#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */
129#define LZO_E_INPUT_OVERRUN (-4)
130#define LZO_E_OUTPUT_OVERRUN (-5)
131#define LZO_E_LOOKBEHIND_OVERRUN (-6)
132#define LZO_E_EOF_NOT_FOUND (-7)
133#define LZO_E_INPUT_NOT_CONSUMED (-8)
134
135#define PTR(a) ((lzo_ptr_t) (a))
136#define PTR_LINEAR(a) PTR(a)
137#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
138#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
139#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
140#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
141#define PTR_LT(a,b) (PTR(a) < PTR(b))
142#define PTR_GE(a,b) (PTR(a) >= PTR(b))
143#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
144#define pd(a,b) ((lzo_uint) ((a)-(b)))
145
146typedef ptrdiff_t lzo_ptrdiff_t;
147
148static int
149lzo1x_decompress (const lzo_byte * in, lzo_uint in_len,
150 lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
151{
152 register lzo_byte *op;
153 register const lzo_byte *ip;
154 register lzo_uint t;
155
156 register const lzo_byte *m_pos;
157
158 const lzo_byte *const ip_end = in + in_len;
159 lzo_byte *const op_end = out + *out_len;
160
161 *out_len = 0;
162
163 op = out;
164 ip = in;
165
166 if (*ip > 17)
167 {
168 t = *ip++ - 17;
169 if (t < 4)
170 goto match_next;
171 NEED_OP (t);
172 NEED_IP (t + 1);
173 do
174 *op++ = *ip++;
175 while (--t > 0);
176 goto first_literal_run;
177 }
178
179 while (TEST_IP && TEST_OP)
180 {
181 t = *ip++;
182 if (t >= 16)
183 goto match;
184 if (t == 0)
185 {
186 NEED_IP (1);
187 while (*ip == 0)
188 {
189 t += 255;
190 ip++;
191 NEED_IP (1);
192 }
193 t += 15 + *ip++;
194 }
195 NEED_OP (t + 3);
196 NEED_IP (t + 4);
197 if (PTR_ALIGNED2_4 (op, ip))
198 {
199 COPY4 (op, ip);
200
201 op += 4;
202 ip += 4;
203 if (--t > 0)
204 {
205 if (t >= 4)
206 {
207 do
208 {
209 COPY4 (op, ip);
210 op += 4;
211 ip += 4;
212 t -= 4;
213 }
214 while (t >= 4);
215 if (t > 0)
216 do
217 *op++ = *ip++;
218 while (--t > 0);
219 }
220 else
221 do
222 *op++ = *ip++;
223 while (--t > 0);
224 }
225 }
226 else
227 {
228 *op++ = *ip++;
229 *op++ = *ip++;
230 *op++ = *ip++;
231 do
232 *op++ = *ip++;
233 while (--t > 0);
234 }
235 first_literal_run:
236
237 t = *ip++;
238 if (t >= 16)
239 goto match;
240
241 m_pos = op - (1 + M2_MAX_OFFSET);
242 m_pos -= t >> 2;
243 m_pos -= *ip++ << 2;
244 TEST_LOOKBEHIND (m_pos, out);
245 NEED_OP (3);
246 *op++ = *m_pos++;
247 *op++ = *m_pos++;
248 *op++ = *m_pos;
249
250 goto match_done;
251
252 while (TEST_IP && TEST_OP)
253 {
254 match:
255 if (t >= 64)
256 {
257 m_pos = op - 1;
258 m_pos -= (t >> 2) & 7;
259 m_pos -= *ip++ << 3;
260 t = (t >> 5) - 1;
261 TEST_LOOKBEHIND (m_pos, out);
262 NEED_OP (t + 3 - 1);
263 goto copy_match;
264
265 }
266 else if (t >= 32)
267 {
268 t &= 31;
269 if (t == 0)
270 {
271 NEED_IP (1);
272 while (*ip == 0)
273 {
274 t += 255;
275 ip++;
276 NEED_IP (1);
277 }
278 t += 31 + *ip++;
279 }
280
281 m_pos = op - 1;
282 m_pos -= (ip[0] >> 2) + (ip[1] << 6);
283
284 ip += 2;
285 }
286 else if (t >= 16)
287 {
288 m_pos = op;
289 m_pos -= (t & 8) << 11;
290
291 t &= 7;
292 if (t == 0)
293 {
294 NEED_IP (1);
295 while (*ip == 0)
296 {
297 t += 255;
298 ip++;
299 NEED_IP (1);
300 }
301 t += 7 + *ip++;
302 }
303
304 m_pos -= (ip[0] >> 2) + (ip[1] << 6);
305
306 ip += 2;
307 if (m_pos == op)
308 goto eof_found;
309 m_pos -= 0x4000;
310 }
311 else
312 {
313
314 m_pos = op - 1;
315 m_pos -= t >> 2;
316 m_pos -= *ip++ << 2;
317 TEST_LOOKBEHIND (m_pos, out);
318 NEED_OP (2);
319 *op++ = *m_pos++;
320 *op++ = *m_pos;
321
322 goto match_done;
323 }
324
325 TEST_LOOKBEHIND (m_pos, out);
326 NEED_OP (t + 3 - 1);
327 if (t >= 2 * 4 - (3 - 1)
328 && PTR_ALIGNED2_4 (op, m_pos))
329 {
330 COPY4 (op, m_pos);
331 op += 4;
332 m_pos += 4;
333 t -= 4 - (3 - 1);
334 do
335 {
336 COPY4 (op, m_pos);
337 op += 4;
338 m_pos += 4;
339 t -= 4;
340 }
341 while (t >= 4);
342 if (t > 0)
343 do
344 *op++ = *m_pos++;
345 while (--t > 0);
346 }
347 else
348
349 {
350 copy_match:
351 *op++ = *m_pos++;
352 *op++ = *m_pos++;
353 do
354 *op++ = *m_pos++;
355 while (--t > 0);
356 }
357
358 match_done:
359 t = ip[-2] & 3;
360
361 if (t == 0)
362 break;
363
364 match_next:
365 NEED_OP (t);
366 NEED_IP (t + 1);
367 do
368 *op++ = *ip++;
369 while (--t > 0);
370 t = *ip++;
371 }
372 }
373 *out_len = op - out;
374 return LZO_E_EOF_NOT_FOUND;
375
376 eof_found:
377 *out_len = op - out;
378 return (ip == ip_end ? LZO_E_OK :
379 (ip <
380 ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
381
382 input_overrun:
383 *out_len = op - out;
384 return LZO_E_INPUT_OVERRUN;
385
386 output_overrun:
387 *out_len = op - out;
388 return LZO_E_OUTPUT_OVERRUN;
389
390 lookbehind_overrun:
391 *out_len = op - out;
392 return LZO_E_LOOKBEHIND_OVERRUN;
393}
394
395int lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
396 u32 srclen, u32 destlen)
397{
398 lzo_uint outlen = destlen;
399 return lzo1x_decompress (data_in, srclen, cpage_out, &outlen, NULL);
400}