xref: /openbmc/u-boot/fs/jffs2/compr_lzo.c (revision e99e9575bbeba1b7c48e046547cae065ec0071de)
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