xref: /openbmc/linux/fs/jffs2/compr_rubin.c (revision e5451c8f8330e03ad3cfa16048b4daf961af434f)
11da177e4SLinus Torvalds /*
21da177e4SLinus Torvalds  * JFFS2 -- Journalling Flash File System, Version 2.
31da177e4SLinus Torvalds  *
4c00c310eSDavid Woodhouse  * Copyright © 2001-2007 Red Hat, Inc.
56088c058SDavid Woodhouse  * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org>
61da177e4SLinus Torvalds  *
71da177e4SLinus Torvalds  * Created by Arjan van de Ven <arjanv@redhat.com>
81da177e4SLinus Torvalds  *
91da177e4SLinus Torvalds  * For licensing information, see the file 'LICENCE' in this directory.
101da177e4SLinus Torvalds  *
111da177e4SLinus Torvalds  */
121da177e4SLinus Torvalds 
13*5a528957SJoe Perches #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
14*5a528957SJoe Perches 
151da177e4SLinus Torvalds #include <linux/string.h>
161da177e4SLinus Torvalds #include <linux/types.h>
171da177e4SLinus Torvalds #include <linux/jffs2.h>
18c00c310eSDavid Woodhouse #include <linux/errno.h>
191da177e4SLinus Torvalds #include "compr.h"
201da177e4SLinus Torvalds 
21c00c310eSDavid Woodhouse 
22c00c310eSDavid Woodhouse #define RUBIN_REG_SIZE   16
23c00c310eSDavid Woodhouse #define UPPER_BIT_RUBIN    (((long) 1)<<(RUBIN_REG_SIZE-1))
24c00c310eSDavid Woodhouse #define LOWER_BITS_RUBIN   ((((long) 1)<<(RUBIN_REG_SIZE-1))-1)
25c00c310eSDavid Woodhouse 
26c00c310eSDavid Woodhouse 
27c00c310eSDavid Woodhouse #define BIT_DIVIDER_MIPS 1043
280bc4382aSDavid Woodhouse static int bits_mips[8] = { 277, 249, 290, 267, 229, 341, 212, 241};
29c00c310eSDavid Woodhouse 
30c00c310eSDavid Woodhouse struct pushpull {
31c00c310eSDavid Woodhouse 	unsigned char *buf;
32c00c310eSDavid Woodhouse 	unsigned int buflen;
33c00c310eSDavid Woodhouse 	unsigned int ofs;
34c00c310eSDavid Woodhouse 	unsigned int reserve;
35c00c310eSDavid Woodhouse };
36c00c310eSDavid Woodhouse 
37f6449f4eSAndrew Morton struct rubin_state {
38f6449f4eSAndrew Morton 	unsigned long p;
39f6449f4eSAndrew Morton 	unsigned long q;
40f6449f4eSAndrew Morton 	unsigned long rec_q;
41f6449f4eSAndrew Morton 	long bit_number;
42f6449f4eSAndrew Morton 	struct pushpull pp;
43f6449f4eSAndrew Morton 	int bit_divider;
44f6449f4eSAndrew Morton 	int bits[8];
45f6449f4eSAndrew Morton };
46c00c310eSDavid Woodhouse 
init_pushpull(struct pushpull * pp,char * buf,unsigned buflen,unsigned ofs,unsigned reserve)470bc4382aSDavid Woodhouse static inline void init_pushpull(struct pushpull *pp, char *buf,
480bc4382aSDavid Woodhouse 				 unsigned buflen, unsigned ofs,
490bc4382aSDavid Woodhouse 				 unsigned reserve)
50c00c310eSDavid Woodhouse {
51c00c310eSDavid Woodhouse 	pp->buf = buf;
52c00c310eSDavid Woodhouse 	pp->buflen = buflen;
53c00c310eSDavid Woodhouse 	pp->ofs = ofs;
54c00c310eSDavid Woodhouse 	pp->reserve = reserve;
55c00c310eSDavid Woodhouse }
56c00c310eSDavid Woodhouse 
pushbit(struct pushpull * pp,int bit,int use_reserved)57c00c310eSDavid Woodhouse static inline int pushbit(struct pushpull *pp, int bit, int use_reserved)
58c00c310eSDavid Woodhouse {
590bc4382aSDavid Woodhouse 	if (pp->ofs >= pp->buflen - (use_reserved?0:pp->reserve))
60c00c310eSDavid Woodhouse 		return -ENOSPC;
61c00c310eSDavid Woodhouse 
620bc4382aSDavid Woodhouse 	if (bit)
63c00c310eSDavid Woodhouse 		pp->buf[pp->ofs >> 3] |= (1<<(7-(pp->ofs & 7)));
640bc4382aSDavid Woodhouse 	else
65c00c310eSDavid Woodhouse 		pp->buf[pp->ofs >> 3] &= ~(1<<(7-(pp->ofs & 7)));
660bc4382aSDavid Woodhouse 
67c00c310eSDavid Woodhouse 	pp->ofs++;
68c00c310eSDavid Woodhouse 
69c00c310eSDavid Woodhouse 	return 0;
70c00c310eSDavid Woodhouse }
71c00c310eSDavid Woodhouse 
pushedbits(struct pushpull * pp)72c00c310eSDavid Woodhouse static inline int pushedbits(struct pushpull *pp)
73c00c310eSDavid Woodhouse {
74c00c310eSDavid Woodhouse 	return pp->ofs;
75c00c310eSDavid Woodhouse }
76c00c310eSDavid Woodhouse 
pullbit(struct pushpull * pp)77c00c310eSDavid Woodhouse static inline int pullbit(struct pushpull *pp)
78c00c310eSDavid Woodhouse {
79c00c310eSDavid Woodhouse 	int bit;
80c00c310eSDavid Woodhouse 
81c00c310eSDavid Woodhouse 	bit = (pp->buf[pp->ofs >> 3] >> (7-(pp->ofs & 7))) & 1;
82c00c310eSDavid Woodhouse 
83c00c310eSDavid Woodhouse 	pp->ofs++;
84c00c310eSDavid Woodhouse 	return bit;
85c00c310eSDavid Woodhouse }
86c00c310eSDavid Woodhouse 
87c00c310eSDavid Woodhouse 
init_rubin(struct rubin_state * rs,int div,int * bits)881da177e4SLinus Torvalds static void init_rubin(struct rubin_state *rs, int div, int *bits)
891da177e4SLinus Torvalds {
901da177e4SLinus Torvalds 	int c;
911da177e4SLinus Torvalds 
921da177e4SLinus Torvalds 	rs->q = 0;
931da177e4SLinus Torvalds 	rs->p = (long) (2 * UPPER_BIT_RUBIN);
941da177e4SLinus Torvalds 	rs->bit_number = (long) 0;
951da177e4SLinus Torvalds 	rs->bit_divider = div;
960bc4382aSDavid Woodhouse 
971da177e4SLinus Torvalds 	for (c=0; c<8; c++)
981da177e4SLinus Torvalds 		rs->bits[c] = bits[c];
991da177e4SLinus Torvalds }
1001da177e4SLinus Torvalds 
1011da177e4SLinus Torvalds 
encode(struct rubin_state * rs,long A,long B,int symbol)1021da177e4SLinus Torvalds static int encode(struct rubin_state *rs, long A, long B, int symbol)
1031da177e4SLinus Torvalds {
1041da177e4SLinus Torvalds 
1051da177e4SLinus Torvalds 	long i0, i1;
1061da177e4SLinus Torvalds 	int ret;
1071da177e4SLinus Torvalds 
1080bc4382aSDavid Woodhouse 	while ((rs->q >= UPPER_BIT_RUBIN) ||
1090bc4382aSDavid Woodhouse 	       ((rs->p + rs->q) <= UPPER_BIT_RUBIN)) {
1101da177e4SLinus Torvalds 		rs->bit_number++;
1111da177e4SLinus Torvalds 
1121da177e4SLinus Torvalds 		ret = pushbit(&rs->pp, (rs->q & UPPER_BIT_RUBIN) ? 1 : 0, 0);
1131da177e4SLinus Torvalds 		if (ret)
1141da177e4SLinus Torvalds 			return ret;
1151da177e4SLinus Torvalds 		rs->q &= LOWER_BITS_RUBIN;
1161da177e4SLinus Torvalds 		rs->q <<= 1;
1171da177e4SLinus Torvalds 		rs->p <<= 1;
1181da177e4SLinus Torvalds 	}
1191da177e4SLinus Torvalds 	i0 = A * rs->p / (A + B);
1200bc4382aSDavid Woodhouse 	if (i0 <= 0)
1211da177e4SLinus Torvalds 		i0 = 1;
1220bc4382aSDavid Woodhouse 
1230bc4382aSDavid Woodhouse 	if (i0 >= rs->p)
1241da177e4SLinus Torvalds 		i0 = rs->p - 1;
1250bc4382aSDavid Woodhouse 
1261da177e4SLinus Torvalds 	i1 = rs->p - i0;
1271da177e4SLinus Torvalds 
1281da177e4SLinus Torvalds 	if (symbol == 0)
1291da177e4SLinus Torvalds 		rs->p = i0;
1301da177e4SLinus Torvalds 	else {
1311da177e4SLinus Torvalds 		rs->p = i1;
1321da177e4SLinus Torvalds 		rs->q += i0;
1331da177e4SLinus Torvalds 	}
1341da177e4SLinus Torvalds 	return 0;
1351da177e4SLinus Torvalds }
1361da177e4SLinus Torvalds 
1371da177e4SLinus Torvalds 
end_rubin(struct rubin_state * rs)1381da177e4SLinus Torvalds static void end_rubin(struct rubin_state *rs)
1391da177e4SLinus Torvalds {
1401da177e4SLinus Torvalds 
1411da177e4SLinus Torvalds 	int i;
1421da177e4SLinus Torvalds 
1431da177e4SLinus Torvalds 	for (i = 0; i < RUBIN_REG_SIZE; i++) {
1441da177e4SLinus Torvalds 		pushbit(&rs->pp, (UPPER_BIT_RUBIN & rs->q) ? 1 : 0, 1);
1451da177e4SLinus Torvalds 		rs->q &= LOWER_BITS_RUBIN;
1461da177e4SLinus Torvalds 		rs->q <<= 1;
1471da177e4SLinus Torvalds 	}
1481da177e4SLinus Torvalds }
1491da177e4SLinus Torvalds 
1501da177e4SLinus Torvalds 
init_decode(struct rubin_state * rs,int div,int * bits)1511da177e4SLinus Torvalds static void init_decode(struct rubin_state *rs, int div, int *bits)
1521da177e4SLinus Torvalds {
1531da177e4SLinus Torvalds 	init_rubin(rs, div, bits);
1541da177e4SLinus Torvalds 
1551da177e4SLinus Torvalds 	/* behalve lower */
1561da177e4SLinus Torvalds 	rs->rec_q = 0;
1571da177e4SLinus Torvalds 
1580bc4382aSDavid Woodhouse 	for (rs->bit_number = 0; rs->bit_number++ < RUBIN_REG_SIZE;
1590bc4382aSDavid Woodhouse 	     rs->rec_q = rs->rec_q * 2 + (long) (pullbit(&rs->pp)))
1601da177e4SLinus Torvalds 		;
1611da177e4SLinus Torvalds }
1621da177e4SLinus Torvalds 
__do_decode(struct rubin_state * rs,unsigned long p,unsigned long q)1630bc4382aSDavid Woodhouse static void __do_decode(struct rubin_state *rs, unsigned long p,
1640bc4382aSDavid Woodhouse 			unsigned long q)
1651da177e4SLinus Torvalds {
1661da177e4SLinus Torvalds 	register unsigned long lower_bits_rubin = LOWER_BITS_RUBIN;
1671da177e4SLinus Torvalds 	unsigned long rec_q;
1681da177e4SLinus Torvalds 	int c, bits = 0;
1691da177e4SLinus Torvalds 
1701da177e4SLinus Torvalds 	/*
1711da177e4SLinus Torvalds 	 * First, work out how many bits we need from the input stream.
1721da177e4SLinus Torvalds 	 * Note that we have already done the initial check on this
1731da177e4SLinus Torvalds 	 * loop prior to calling this function.
1741da177e4SLinus Torvalds 	 */
1751da177e4SLinus Torvalds 	do {
1761da177e4SLinus Torvalds 		bits++;
1771da177e4SLinus Torvalds 		q &= lower_bits_rubin;
1781da177e4SLinus Torvalds 		q <<= 1;
1791da177e4SLinus Torvalds 		p <<= 1;
1801da177e4SLinus Torvalds 	} while ((q >= UPPER_BIT_RUBIN) || ((p + q) <= UPPER_BIT_RUBIN));
1811da177e4SLinus Torvalds 
1821da177e4SLinus Torvalds 	rs->p = p;
1831da177e4SLinus Torvalds 	rs->q = q;
1841da177e4SLinus Torvalds 
1851da177e4SLinus Torvalds 	rs->bit_number += bits;
1861da177e4SLinus Torvalds 
1871da177e4SLinus Torvalds 	/*
1881da177e4SLinus Torvalds 	 * Now get the bits.  We really want this to be "get n bits".
1891da177e4SLinus Torvalds 	 */
1901da177e4SLinus Torvalds 	rec_q = rs->rec_q;
1911da177e4SLinus Torvalds 	do {
1921da177e4SLinus Torvalds 		c = pullbit(&rs->pp);
1931da177e4SLinus Torvalds 		rec_q &= lower_bits_rubin;
1941da177e4SLinus Torvalds 		rec_q <<= 1;
1951da177e4SLinus Torvalds 		rec_q += c;
1961da177e4SLinus Torvalds 	} while (--bits);
1971da177e4SLinus Torvalds 	rs->rec_q = rec_q;
1981da177e4SLinus Torvalds }
1991da177e4SLinus Torvalds 
decode(struct rubin_state * rs,long A,long B)2001da177e4SLinus Torvalds static int decode(struct rubin_state *rs, long A, long B)
2011da177e4SLinus Torvalds {
2021da177e4SLinus Torvalds 	unsigned long p = rs->p, q = rs->q;
2031da177e4SLinus Torvalds 	long i0, threshold;
2041da177e4SLinus Torvalds 	int symbol;
2051da177e4SLinus Torvalds 
2061da177e4SLinus Torvalds 	if (q >= UPPER_BIT_RUBIN || ((p + q) <= UPPER_BIT_RUBIN))
2071da177e4SLinus Torvalds 		__do_decode(rs, p, q);
2081da177e4SLinus Torvalds 
2091da177e4SLinus Torvalds 	i0 = A * rs->p / (A + B);
2100bc4382aSDavid Woodhouse 	if (i0 <= 0)
2111da177e4SLinus Torvalds 		i0 = 1;
2120bc4382aSDavid Woodhouse 
2130bc4382aSDavid Woodhouse 	if (i0 >= rs->p)
2141da177e4SLinus Torvalds 		i0 = rs->p - 1;
2151da177e4SLinus Torvalds 
2161da177e4SLinus Torvalds 	threshold = rs->q + i0;
2171da177e4SLinus Torvalds 	symbol = rs->rec_q >= threshold;
2181da177e4SLinus Torvalds 	if (rs->rec_q >= threshold) {
2191da177e4SLinus Torvalds 		rs->q += i0;
2201da177e4SLinus Torvalds 		i0 = rs->p - i0;
2211da177e4SLinus Torvalds 	}
2221da177e4SLinus Torvalds 
2231da177e4SLinus Torvalds 	rs->p = i0;
2241da177e4SLinus Torvalds 
2251da177e4SLinus Torvalds 	return symbol;
2261da177e4SLinus Torvalds }
2271da177e4SLinus Torvalds 
2281da177e4SLinus Torvalds 
2291da177e4SLinus Torvalds 
out_byte(struct rubin_state * rs,unsigned char byte)2301da177e4SLinus Torvalds static int out_byte(struct rubin_state *rs, unsigned char byte)
2311da177e4SLinus Torvalds {
2321da177e4SLinus Torvalds 	int i, ret;
2331da177e4SLinus Torvalds 	struct rubin_state rs_copy;
2341da177e4SLinus Torvalds 	rs_copy = *rs;
2351da177e4SLinus Torvalds 
2361da177e4SLinus Torvalds 	for (i=0; i<8; i++) {
2370bc4382aSDavid Woodhouse 		ret = encode(rs, rs->bit_divider-rs->bits[i],
2380bc4382aSDavid Woodhouse 			     rs->bits[i], byte & 1);
2391da177e4SLinus Torvalds 		if (ret) {
2401da177e4SLinus Torvalds 			/* Failed. Restore old state */
2411da177e4SLinus Torvalds 			*rs = rs_copy;
2421da177e4SLinus Torvalds 			return ret;
2431da177e4SLinus Torvalds 		}
2440bc4382aSDavid Woodhouse 		byte >>= 1 ;
2451da177e4SLinus Torvalds 	}
2461da177e4SLinus Torvalds 	return 0;
2471da177e4SLinus Torvalds }
2481da177e4SLinus Torvalds 
in_byte(struct rubin_state * rs)2491da177e4SLinus Torvalds static int in_byte(struct rubin_state *rs)
2501da177e4SLinus Torvalds {
2511da177e4SLinus Torvalds 	int i, result = 0, bit_divider = rs->bit_divider;
2521da177e4SLinus Torvalds 
2531da177e4SLinus Torvalds 	for (i = 0; i < 8; i++)
2540bc4382aSDavid Woodhouse 		result |= decode(rs, bit_divider - rs->bits[i],
2550bc4382aSDavid Woodhouse 				 rs->bits[i]) << i;
2561da177e4SLinus Torvalds 
2571da177e4SLinus Torvalds 	return result;
2581da177e4SLinus Torvalds }
2591da177e4SLinus Torvalds 
2601da177e4SLinus Torvalds 
2611da177e4SLinus Torvalds 
rubin_do_compress(int bit_divider,int * bits,unsigned char * data_in,unsigned char * cpage_out,uint32_t * sourcelen,uint32_t * dstlen)2621da177e4SLinus Torvalds static int rubin_do_compress(int bit_divider, int *bits, unsigned char *data_in,
2630bc4382aSDavid Woodhouse 			     unsigned char *cpage_out, uint32_t *sourcelen,
2640bc4382aSDavid Woodhouse 			     uint32_t *dstlen)
2651da177e4SLinus Torvalds 	{
2661da177e4SLinus Torvalds 	int outpos = 0;
2671da177e4SLinus Torvalds 	int pos=0;
2681da177e4SLinus Torvalds 	struct rubin_state rs;
2691da177e4SLinus Torvalds 
2701da177e4SLinus Torvalds 	init_pushpull(&rs.pp, cpage_out, *dstlen * 8, 0, 32);
2711da177e4SLinus Torvalds 
2721da177e4SLinus Torvalds 	init_rubin(&rs, bit_divider, bits);
2731da177e4SLinus Torvalds 
2741da177e4SLinus Torvalds 	while (pos < (*sourcelen) && !out_byte(&rs, data_in[pos]))
2751da177e4SLinus Torvalds 		pos++;
2761da177e4SLinus Torvalds 
2771da177e4SLinus Torvalds 	end_rubin(&rs);
2781da177e4SLinus Torvalds 
2791da177e4SLinus Torvalds 	if (outpos > pos) {
2801da177e4SLinus Torvalds 		/* We failed */
2811da177e4SLinus Torvalds 		return -1;
2821da177e4SLinus Torvalds 	}
2831da177e4SLinus Torvalds 
2841da177e4SLinus Torvalds 	/* Tell the caller how much we managed to compress,
2851da177e4SLinus Torvalds 	 * and how much space it took */
2861da177e4SLinus Torvalds 
2871da177e4SLinus Torvalds 	outpos = (pushedbits(&rs.pp)+7)/8;
2881da177e4SLinus Torvalds 
2891da177e4SLinus Torvalds 	if (outpos >= pos)
2901da177e4SLinus Torvalds 		return -1; /* We didn't actually compress */
2911da177e4SLinus Torvalds 	*sourcelen = pos;
2921da177e4SLinus Torvalds 	*dstlen = outpos;
2931da177e4SLinus Torvalds 	return 0;
2941da177e4SLinus Torvalds }
2951da177e4SLinus Torvalds #if 0
2961da177e4SLinus Torvalds /* _compress returns the compressed size, -1 if bigger */
2971da177e4SLinus Torvalds int jffs2_rubinmips_compress(unsigned char *data_in, unsigned char *cpage_out,
298088bd455SMike Frysinger 		   uint32_t *sourcelen, uint32_t *dstlen)
2991da177e4SLinus Torvalds {
3000bc4382aSDavid Woodhouse 	return rubin_do_compress(BIT_DIVIDER_MIPS, bits_mips, data_in,
3010bc4382aSDavid Woodhouse 				 cpage_out, sourcelen, dstlen);
3021da177e4SLinus Torvalds }
3031da177e4SLinus Torvalds #endif
jffs2_dynrubin_compress(unsigned char * data_in,unsigned char * cpage_out,uint32_t * sourcelen,uint32_t * dstlen)30475c96f85SAdrian Bunk static int jffs2_dynrubin_compress(unsigned char *data_in,
30575c96f85SAdrian Bunk 				   unsigned char *cpage_out,
306088bd455SMike Frysinger 				   uint32_t *sourcelen, uint32_t *dstlen)
3071da177e4SLinus Torvalds {
3081da177e4SLinus Torvalds 	int bits[8];
3091da177e4SLinus Torvalds 	unsigned char histo[256];
3101da177e4SLinus Torvalds 	int i;
3111da177e4SLinus Torvalds 	int ret;
3121da177e4SLinus Torvalds 	uint32_t mysrclen, mydstlen;
3131da177e4SLinus Torvalds 
3141da177e4SLinus Torvalds 	mysrclen = *sourcelen;
3151da177e4SLinus Torvalds 	mydstlen = *dstlen - 8;
3161da177e4SLinus Torvalds 
3171da177e4SLinus Torvalds 	if (*dstlen <= 12)
3181da177e4SLinus Torvalds 		return -1;
3191da177e4SLinus Torvalds 
3201da177e4SLinus Torvalds 	memset(histo, 0, 256);
3210bc4382aSDavid Woodhouse 	for (i=0; i<mysrclen; i++)
3221da177e4SLinus Torvalds 		histo[data_in[i]]++;
3231da177e4SLinus Torvalds 	memset(bits, 0, sizeof(int)*8);
3241da177e4SLinus Torvalds 	for (i=0; i<256; i++) {
3251da177e4SLinus Torvalds 		if (i&128)
3261da177e4SLinus Torvalds 			bits[7] += histo[i];
3271da177e4SLinus Torvalds 		if (i&64)
3281da177e4SLinus Torvalds 			bits[6] += histo[i];
3291da177e4SLinus Torvalds 		if (i&32)
3301da177e4SLinus Torvalds 			bits[5] += histo[i];
3311da177e4SLinus Torvalds 		if (i&16)
3321da177e4SLinus Torvalds 			bits[4] += histo[i];
3331da177e4SLinus Torvalds 		if (i&8)
3341da177e4SLinus Torvalds 			bits[3] += histo[i];
3351da177e4SLinus Torvalds 		if (i&4)
3361da177e4SLinus Torvalds 			bits[2] += histo[i];
3371da177e4SLinus Torvalds 		if (i&2)
3381da177e4SLinus Torvalds 			bits[1] += histo[i];
3391da177e4SLinus Torvalds 		if (i&1)
3401da177e4SLinus Torvalds 			bits[0] += histo[i];
3411da177e4SLinus Torvalds 	}
3421da177e4SLinus Torvalds 
3431da177e4SLinus Torvalds 	for (i=0; i<8; i++) {
3441da177e4SLinus Torvalds 		bits[i] = (bits[i] * 256) / mysrclen;
3451da177e4SLinus Torvalds 		if (!bits[i]) bits[i] = 1;
3461da177e4SLinus Torvalds 		if (bits[i] > 255) bits[i] = 255;
3471da177e4SLinus Torvalds 		cpage_out[i] = bits[i];
3481da177e4SLinus Torvalds 	}
3491da177e4SLinus Torvalds 
3500bc4382aSDavid Woodhouse 	ret = rubin_do_compress(256, bits, data_in, cpage_out+8, &mysrclen,
3510bc4382aSDavid Woodhouse 				&mydstlen);
3521da177e4SLinus Torvalds 	if (ret)
3531da177e4SLinus Torvalds 		return ret;
3541da177e4SLinus Torvalds 
3551da177e4SLinus Torvalds 	/* Add back the 8 bytes we took for the probabilities */
3561da177e4SLinus Torvalds 	mydstlen += 8;
3571da177e4SLinus Torvalds 
3581da177e4SLinus Torvalds 	if (mysrclen <= mydstlen) {
3591da177e4SLinus Torvalds 		/* We compressed */
3601da177e4SLinus Torvalds 		return -1;
3611da177e4SLinus Torvalds 	}
3621da177e4SLinus Torvalds 
3631da177e4SLinus Torvalds 	*sourcelen = mysrclen;
3641da177e4SLinus Torvalds 	*dstlen = mydstlen;
3651da177e4SLinus Torvalds 	return 0;
3661da177e4SLinus Torvalds }
3671da177e4SLinus Torvalds 
rubin_do_decompress(int bit_divider,int * bits,unsigned char * cdata_in,unsigned char * page_out,uint32_t srclen,uint32_t destlen)3680bc4382aSDavid Woodhouse static void rubin_do_decompress(int bit_divider, int *bits,
3690bc4382aSDavid Woodhouse 				unsigned char *cdata_in,
3700bc4382aSDavid Woodhouse 				unsigned char *page_out, uint32_t srclen,
3710bc4382aSDavid Woodhouse 				uint32_t destlen)
3721da177e4SLinus Torvalds {
3731da177e4SLinus Torvalds 	int outpos = 0;
3741da177e4SLinus Torvalds 	struct rubin_state rs;
3751da177e4SLinus Torvalds 
3761da177e4SLinus Torvalds 	init_pushpull(&rs.pp, cdata_in, srclen, 0, 0);
3771da177e4SLinus Torvalds 	init_decode(&rs, bit_divider, bits);
3781da177e4SLinus Torvalds 
3790bc4382aSDavid Woodhouse 	while (outpos < destlen)
3801da177e4SLinus Torvalds 		page_out[outpos++] = in_byte(&rs);
3811da177e4SLinus Torvalds }
3821da177e4SLinus Torvalds 
3831da177e4SLinus Torvalds 
jffs2_rubinmips_decompress(unsigned char * data_in,unsigned char * cpage_out,uint32_t sourcelen,uint32_t dstlen)38475c96f85SAdrian Bunk static int jffs2_rubinmips_decompress(unsigned char *data_in,
38575c96f85SAdrian Bunk 				      unsigned char *cpage_out,
386088bd455SMike Frysinger 				      uint32_t sourcelen, uint32_t dstlen)
3871da177e4SLinus Torvalds {
3880bc4382aSDavid Woodhouse 	rubin_do_decompress(BIT_DIVIDER_MIPS, bits_mips, data_in,
3890bc4382aSDavid Woodhouse 			    cpage_out, sourcelen, dstlen);
3901da177e4SLinus Torvalds 	return 0;
3911da177e4SLinus Torvalds }
3921da177e4SLinus Torvalds 
jffs2_dynrubin_decompress(unsigned char * data_in,unsigned char * cpage_out,uint32_t sourcelen,uint32_t dstlen)39375c96f85SAdrian Bunk static int jffs2_dynrubin_decompress(unsigned char *data_in,
39475c96f85SAdrian Bunk 				     unsigned char *cpage_out,
395088bd455SMike Frysinger 				     uint32_t sourcelen, uint32_t dstlen)
3961da177e4SLinus Torvalds {
3971da177e4SLinus Torvalds 	int bits[8];
3981da177e4SLinus Torvalds 	int c;
3991da177e4SLinus Torvalds 
4001da177e4SLinus Torvalds 	for (c=0; c<8; c++)
4011da177e4SLinus Torvalds 		bits[c] = data_in[c];
4021da177e4SLinus Torvalds 
4030bc4382aSDavid Woodhouse 	rubin_do_decompress(256, bits, data_in+8, cpage_out, sourcelen-8,
4040bc4382aSDavid Woodhouse 			    dstlen);
4051da177e4SLinus Torvalds 	return 0;
4061da177e4SLinus Torvalds }
4071da177e4SLinus Torvalds 
4081da177e4SLinus Torvalds static struct jffs2_compressor jffs2_rubinmips_comp = {
4091da177e4SLinus Torvalds 	.priority = JFFS2_RUBINMIPS_PRIORITY,
4101da177e4SLinus Torvalds 	.name = "rubinmips",
4111da177e4SLinus Torvalds 	.compr = JFFS2_COMPR_DYNRUBIN,
4121da177e4SLinus Torvalds 	.compress = NULL, /*&jffs2_rubinmips_compress,*/
4131da177e4SLinus Torvalds 	.decompress = &jffs2_rubinmips_decompress,
4141da177e4SLinus Torvalds #ifdef JFFS2_RUBINMIPS_DISABLED
4151da177e4SLinus Torvalds 	.disabled = 1,
4161da177e4SLinus Torvalds #else
4171da177e4SLinus Torvalds 	.disabled = 0,
4181da177e4SLinus Torvalds #endif
4191da177e4SLinus Torvalds };
4201da177e4SLinus Torvalds 
jffs2_rubinmips_init(void)4211da177e4SLinus Torvalds int jffs2_rubinmips_init(void)
4221da177e4SLinus Torvalds {
4231da177e4SLinus Torvalds 	return jffs2_register_compressor(&jffs2_rubinmips_comp);
4241da177e4SLinus Torvalds }
4251da177e4SLinus Torvalds 
jffs2_rubinmips_exit(void)4261da177e4SLinus Torvalds void jffs2_rubinmips_exit(void)
4271da177e4SLinus Torvalds {
4281da177e4SLinus Torvalds 	jffs2_unregister_compressor(&jffs2_rubinmips_comp);
4291da177e4SLinus Torvalds }
4301da177e4SLinus Torvalds 
4311da177e4SLinus Torvalds static struct jffs2_compressor jffs2_dynrubin_comp = {
4321da177e4SLinus Torvalds 	.priority = JFFS2_DYNRUBIN_PRIORITY,
4331da177e4SLinus Torvalds 	.name = "dynrubin",
4341da177e4SLinus Torvalds 	.compr = JFFS2_COMPR_RUBINMIPS,
4351da177e4SLinus Torvalds 	.compress = jffs2_dynrubin_compress,
4361da177e4SLinus Torvalds 	.decompress = &jffs2_dynrubin_decompress,
4371da177e4SLinus Torvalds #ifdef JFFS2_DYNRUBIN_DISABLED
4381da177e4SLinus Torvalds 	.disabled = 1,
4391da177e4SLinus Torvalds #else
4401da177e4SLinus Torvalds 	.disabled = 0,
4411da177e4SLinus Torvalds #endif
4421da177e4SLinus Torvalds };
4431da177e4SLinus Torvalds 
jffs2_dynrubin_init(void)4441da177e4SLinus Torvalds int jffs2_dynrubin_init(void)
4451da177e4SLinus Torvalds {
4461da177e4SLinus Torvalds 	return jffs2_register_compressor(&jffs2_dynrubin_comp);
4471da177e4SLinus Torvalds }
4481da177e4SLinus Torvalds 
jffs2_dynrubin_exit(void)4491da177e4SLinus Torvalds void jffs2_dynrubin_exit(void)
4501da177e4SLinus Torvalds {
4511da177e4SLinus Torvalds 	jffs2_unregister_compressor(&jffs2_dynrubin_comp);
4521da177e4SLinus Torvalds }
453