uboot/fs/jffs2/compr_lzo.c
<<
>>
Prefs
   1/*
   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
  68
  69#include <config.h>
  70#include <linux/stddef.h>
  71#include <jffs2/jffs2.h>
  72#include <jffs2/compr_rubin.h>
  73
  74/* Integral types that have *exactly* the same number of bits as a lzo_voidp */
  75typedef unsigned long lzo_ptr_t;
  76typedef long lzo_sptr_t;
  77
  78/* data type definitions */
  79#define U32 unsigned long
  80#define S32 signed long
  81#define I32 long
  82#define U16 unsigned short
  83#define S16 signed short
  84#define I16 short
  85#define U8 unsigned char
  86#define S8 signed char
  87#define I8 char
  88
  89#define M1_MAX_OFFSET   0x0400
  90#define M2_MAX_OFFSET   0x0800
  91#define M3_MAX_OFFSET   0x4000
  92#define M4_MAX_OFFSET   0xbfff
  93
  94#define __COPY4(dst,src)  * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
  95#define COPY4(dst,src)  __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
  96
  97#define TEST_IP         (ip < ip_end)
  98#define TEST_OP         (op <= op_end)
  99
 100#define NEED_IP(x) \
 101            if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x))  goto input_overrun
 102#define NEED_OP(x) \
 103            if ((lzo_uint)(op_end - op) < (lzo_uint)(x))  goto output_overrun
 104#define TEST_LOOKBEHIND(m_pos,out)    if (m_pos < out) goto lookbehind_overrun
 105
 106typedef U32 lzo_uint32;
 107typedef I32 lzo_int32;
 108typedef U32 lzo_uint;
 109typedef I32 lzo_int;
 110typedef int lzo_bool;
 111
 112#define lzo_byte                U8
 113#define lzo_bytep               U8 *
 114#define lzo_charp               char *
 115#define lzo_voidp               void *
 116#define lzo_shortp              short *
 117#define lzo_ushortp             unsigned short *
 118#define lzo_uint32p             lzo_uint32 *
 119#define lzo_int32p              lzo_int32 *
 120#define lzo_uintp               lzo_uint *
 121#define lzo_intp                lzo_int *
 122#define lzo_voidpp              lzo_voidp *
 123#define lzo_bytepp              lzo_bytep *
 124#define lzo_sizeof_dict_t               sizeof(lzo_bytep)
 125
 126#define LZO_E_OK                    0
 127#define LZO_E_ERROR                 (-1)
 128#define LZO_E_OUT_OF_MEMORY         (-2)        /* not used right now */
 129#define LZO_E_NOT_COMPRESSIBLE      (-3)        /* not used right now */
 130#define LZO_E_INPUT_OVERRUN         (-4)
 131#define LZO_E_OUTPUT_OVERRUN        (-5)
 132#define LZO_E_LOOKBEHIND_OVERRUN    (-6)
 133#define LZO_E_EOF_NOT_FOUND         (-7)
 134#define LZO_E_INPUT_NOT_CONSUMED    (-8)
 135
 136#define PTR(a)                          ((lzo_ptr_t) (a))
 137#define PTR_LINEAR(a)           PTR(a)
 138#define PTR_ALIGNED_4(a)        ((PTR_LINEAR(a) & 3) == 0)
 139#define PTR_ALIGNED_8(a)        ((PTR_LINEAR(a) & 7) == 0)
 140#define PTR_ALIGNED2_4(a,b)     (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
 141#define PTR_ALIGNED2_8(a,b)     (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
 142#define PTR_LT(a,b)                     (PTR(a) < PTR(b))
 143#define PTR_GE(a,b)                     (PTR(a) >= PTR(b))
 144#define PTR_DIFF(a,b)           ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
 145#define pd(a,b)                 ((lzo_uint) ((a)-(b)))
 146
 147typedef ptrdiff_t lzo_ptrdiff_t;
 148
 149static int
 150lzo1x_decompress (const lzo_byte * in, lzo_uint in_len,
 151                  lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
 152{
 153        register lzo_byte *op;
 154        register const lzo_byte *ip;
 155        register lzo_uint t;
 156
 157        register const lzo_byte *m_pos;
 158
 159        const lzo_byte *const ip_end = in + in_len;
 160        lzo_byte *const op_end = out + *out_len;
 161
 162        *out_len = 0;
 163
 164        op = out;
 165        ip = in;
 166
 167        if (*ip > 17)
 168        {
 169                t = *ip++ - 17;
 170                if (t < 4)
 171                        goto match_next;
 172                NEED_OP (t);
 173                NEED_IP (t + 1);
 174                do
 175                        *op++ = *ip++;
 176                while (--t > 0);
 177                goto first_literal_run;
 178        }
 179
 180        while (TEST_IP && TEST_OP)
 181        {
 182                t = *ip++;
 183                if (t >= 16)
 184                        goto match;
 185                if (t == 0)
 186                {
 187                        NEED_IP (1);
 188                        while (*ip == 0)
 189                        {
 190                                t += 255;
 191                                ip++;
 192                                NEED_IP (1);
 193                        }
 194                        t += 15 + *ip++;
 195                }
 196                NEED_OP (t + 3);
 197                NEED_IP (t + 4);
 198                if (PTR_ALIGNED2_4 (op, ip))
 199                {
 200                        COPY4 (op, ip);
 201
 202                        op += 4;
 203                        ip += 4;
 204                        if (--t > 0)
 205                        {
 206                                if (t >= 4)
 207                                {
 208                                        do
 209                                        {
 210                                                COPY4 (op, ip);
 211                                                op += 4;
 212                                                ip += 4;
 213                                                t -= 4;
 214                                        }
 215                                        while (t >= 4);
 216                                        if (t > 0)
 217                                                do
 218                                                        *op++ = *ip++;
 219                                                while (--t > 0);
 220                                }
 221                                else
 222                                        do
 223                                                *op++ = *ip++;
 224                                        while (--t > 0);
 225                        }
 226                }
 227                else
 228                {
 229                        *op++ = *ip++;
 230                        *op++ = *ip++;
 231                        *op++ = *ip++;
 232                        do
 233                                *op++ = *ip++;
 234                        while (--t > 0);
 235                }
 236              first_literal_run:
 237
 238                t = *ip++;
 239                if (t >= 16)
 240                        goto match;
 241
 242                m_pos = op - (1 + M2_MAX_OFFSET);
 243                m_pos -= t >> 2;
 244                m_pos -= *ip++ << 2;
 245                TEST_LOOKBEHIND (m_pos, out);
 246                NEED_OP (3);
 247                *op++ = *m_pos++;
 248                *op++ = *m_pos++;
 249                *op++ = *m_pos;
 250
 251                goto match_done;
 252
 253                while (TEST_IP && TEST_OP)
 254                {
 255                      match:
 256                        if (t >= 64)
 257                        {
 258                                m_pos = op - 1;
 259                                m_pos -= (t >> 2) & 7;
 260                                m_pos -= *ip++ << 3;
 261                                t = (t >> 5) - 1;
 262                                TEST_LOOKBEHIND (m_pos, out);
 263                                NEED_OP (t + 3 - 1);
 264                                goto copy_match;
 265
 266                        }
 267                        else if (t >= 32)
 268                        {
 269                                t &= 31;
 270                                if (t == 0)
 271                                {
 272                                        NEED_IP (1);
 273                                        while (*ip == 0)
 274                                        {
 275                                                t += 255;
 276                                                ip++;
 277                                                NEED_IP (1);
 278                                        }
 279                                        t += 31 + *ip++;
 280                                }
 281
 282                                m_pos = op - 1;
 283                                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
 284
 285                                ip += 2;
 286                        }
 287                        else if (t >= 16)
 288                        {
 289                                m_pos = op;
 290                                m_pos -= (t & 8) << 11;
 291
 292                                t &= 7;
 293                                if (t == 0)
 294                                {
 295                                        NEED_IP (1);
 296                                        while (*ip == 0)
 297                                        {
 298                                                t += 255;
 299                                                ip++;
 300                                                NEED_IP (1);
 301                                        }
 302                                        t += 7 + *ip++;
 303                                }
 304
 305                                m_pos -= (ip[0] >> 2) + (ip[1] << 6);
 306
 307                                ip += 2;
 308                                if (m_pos == op)
 309                                        goto eof_found;
 310                                m_pos -= 0x4000;
 311                        }
 312                        else
 313                        {
 314
 315                                m_pos = op - 1;
 316                                m_pos -= t >> 2;
 317                                m_pos -= *ip++ << 2;
 318                                TEST_LOOKBEHIND (m_pos, out);
 319                                NEED_OP (2);
 320                                *op++ = *m_pos++;
 321                                *op++ = *m_pos;
 322
 323                                goto match_done;
 324                        }
 325
 326                        TEST_LOOKBEHIND (m_pos, out);
 327                        NEED_OP (t + 3 - 1);
 328                        if (t >= 2 * 4 - (3 - 1)
 329                            && PTR_ALIGNED2_4 (op, m_pos))
 330                        {
 331                                COPY4 (op, m_pos);
 332                                op += 4;
 333                                m_pos += 4;
 334                                t -= 4 - (3 - 1);
 335                                do
 336                                {
 337                                        COPY4 (op, m_pos);
 338                                        op += 4;
 339                                        m_pos += 4;
 340                                        t -= 4;
 341                                }
 342                                while (t >= 4);
 343                                if (t > 0)
 344                                        do
 345                                                *op++ = *m_pos++;
 346                                        while (--t > 0);
 347                        }
 348                        else
 349
 350                        {
 351                              copy_match:
 352                                *op++ = *m_pos++;
 353                                *op++ = *m_pos++;
 354                                do
 355                                        *op++ = *m_pos++;
 356                                while (--t > 0);
 357                        }
 358
 359                      match_done:
 360                        t = ip[-2] & 3;
 361
 362                        if (t == 0)
 363                                break;
 364
 365                      match_next:
 366                        NEED_OP (t);
 367                        NEED_IP (t + 1);
 368                        do
 369                                *op++ = *ip++;
 370                        while (--t > 0);
 371                        t = *ip++;
 372                }
 373        }
 374        *out_len = op - out;
 375        return LZO_E_EOF_NOT_FOUND;
 376
 377      eof_found:
 378        *out_len = op - out;
 379        return (ip == ip_end ? LZO_E_OK :
 380                (ip <
 381                 ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
 382
 383      input_overrun:
 384        *out_len = op - out;
 385        return LZO_E_INPUT_OVERRUN;
 386
 387      output_overrun:
 388        *out_len = op - out;
 389        return LZO_E_OUTPUT_OVERRUN;
 390
 391      lookbehind_overrun:
 392        *out_len = op - out;
 393        return LZO_E_LOOKBEHIND_OVERRUN;
 394}
 395
 396int lzo_decompress(unsigned char *data_in, unsigned char *cpage_out,
 397                      u32 srclen, u32 destlen)
 398{
 399        lzo_uint outlen = destlen;
 400        return lzo1x_decompress (data_in, srclen, cpage_out, &outlen, NULL);
 401}
 402