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