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