Root/target/linux/generic-2.4/patches/003-jffs2_compression.patch

1--- a/Documentation/Configure.help
2+++ b/Documentation/Configure.help
3@@ -17592,6 +17592,32 @@ CONFIG_JFFS2_FS_DEBUG
4   If reporting bugs, please try to have available a full dump of the
5   messages at debug level 1 while the misbehaviour was occurring.
6 
7+ARMLIB compression support for BBC (EXPERIMENTAL)
8+CONFIG_JFFS2_BBC_ARMLIB
9+ This enables ARMLIB support for BBC.
10+
11+LZO1X-* compression support for BBC (EXPERIMENTAL)
12+CONFIG_JFFS2_BBC_LZO
13+ This enables LZO1X-1 and LZO1X-999 support for BBC. (fast & good
14+ compressor, beats ZLIB in everything)
15+
16+LZARI compression support for BBC (EXPERIMENTAL)
17+CONFIG_JFFS2_BBC_LZARI
18+ This enables LempelZiv-Storer-Szymanski compression for BBC with
19+ additional arithmetic coding (damn slow, but best compresor).
20+
21+LZHD compression support for BBC (EXPERIMENTAL)
22+CONFIG_JFFS2_BBC_LZHD
23+ This enables LempelZiv-Storer-Szymanski compression for BBC with
24+ additional dynamic Huffman coding (a little faster than LZARI, and
25+ it's compression ratio is a little worse than LZARI's)
26+
27+LZSS compression support for BBC (EXPERIMENTAL)
28+CONFIG_JFFS2_BBC_LZSS
29+ This enables simple LempelZiv-Storer-Szymanski compression for BBC
30+ (faster than LZHD, and, and has a not-so-good compression ratio,
31+ was included just for testing)
32+
33 JFFS stats available in /proc filesystem
34 CONFIG_JFFS_PROC_FS
35   Enabling this option will cause statistics from mounted JFFS file systems
36--- a/fs/Config.in
37+++ b/fs/Config.in
38@@ -50,6 +50,12 @@ dep_tristate 'Journalling Flash File Sys
39 if [ "$CONFIG_JFFS2_FS" = "y" -o "$CONFIG_JFFS2_FS" = "m" ] ; then
40    int 'JFFS2 debugging verbosity (0 = quiet, 2 = noisy)' CONFIG_JFFS2_FS_DEBUG 0
41 fi
42+dep_mbool ' ARMLIB compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_ARMLIB $CONFIG_JFFS2_FS
43+dep_mbool ' LZO1X-* compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZO $CONFIG_JFFS2_FS
44+dep_mbool ' LZARI compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZARI $CONFIG_JFFS2_FS
45+dep_mbool ' LZHD compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZHD $CONFIG_JFFS2_FS
46+dep_mbool ' LZSS compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZSS $CONFIG_JFFS2_FS
47+
48 tristate 'Compressed ROM file system support' CONFIG_CRAMFS
49 tristate 'Squashed file system support' CONFIG_SQUASHFS
50 if [ "$CONFIG_SQUASHFS" = "y" -o "$CONFIG_SQUASHFS" = "m" ] ; then
51--- /dev/null
52+++ b/fs/jffs2/Config.in.bbc.inc
53@@ -0,0 +1,5 @@
54+dep_mbool ' ARMLIB compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_ARMLIB $CONFIG_JFFS2_FS
55+dep_mbool ' LZO1X-* compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZO $CONFIG_JFFS2_FS
56+dep_mbool ' LZARI compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZARI $CONFIG_JFFS2_FS
57+dep_mbool ' LZHD compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZHD $CONFIG_JFFS2_FS
58+dep_mbool ' LZSS compression support for BBC (EXPERIMENTAL)' CONFIG_JFFS2_BBC_LZSS $CONFIG_JFFS2_FS
59--- /dev/null
60+++ b/fs/jffs2/Configure.help.bbc.inc
61@@ -0,0 +1,25 @@
62+ARMLIB compression support for BBC (EXPERIMENTAL)
63+CONFIG_JFFS2_BBC_ARMLIB
64+ This enables ARMLIB support for BBC.
65+
66+LZO1X-* compression support for BBC (EXPERIMENTAL)
67+CONFIG_JFFS2_BBC_LZO
68+ This enables LZO1X-1 and LZO1X-999 support for BBC. (fast & good
69+ compressor, beats ZLIB in everything)
70+
71+LZARI compression support for BBC (EXPERIMENTAL)
72+CONFIG_JFFS2_BBC_LZARI
73+ This enables LempelZiv-Storer-Szymanski compression for BBC with
74+ additional arithmetic coding (damn slow, but best compresor).
75+
76+LZHD compression support for BBC (EXPERIMENTAL)
77+CONFIG_JFFS2_BBC_LZHD
78+ This enables LempelZiv-Storer-Szymanski compression for BBC with
79+ additional dynamic Huffman coding (a little faster than LZARI, and
80+ it's compression ratio is a little worse than LZARI's)
81+
82+LZSS compression support for BBC (EXPERIMENTAL)
83+CONFIG_JFFS2_BBC_LZSS
84+ This enables simple LempelZiv-Storer-Szymanski compression for BBC
85+ (faster than LZHD, and, and has a not-so-good compression ratio,
86+ was included just for testing)
87--- /dev/null
88+++ b/fs/jffs2/Kconfig.bbc.inc
89@@ -0,0 +1,40 @@
90+config JFFS2_BBC_ARMLIB
91+ bool "ARMLIB compression support for BBC (EXPERIMENTAL)"
92+ depends on JFFS2_FS && EXPERIMENTAL
93+ default y
94+ help
95+ This enables ARMLIB support for BBC.
96+
97+config JFFS2_BBC_LZO
98+ bool "LZO1X-* compression support for BBC (EXPERIMENTAL)"
99+ depends on JFFS2_FS && EXPERIMENTAL
100+ default y
101+ help
102+ This enables LZO1X-1 and LZO1X-999 support for BBC. (fast & good
103+ compressor)
104+
105+config JFFS2_BBC_LZARI
106+ bool "LZARI compression support for BBC (EXPERIMENTAL)"
107+ depends on JFFS2_FS && EXPERIMENTAL
108+ default y
109+ help
110+ This enables LempelZiv-Storer-Szymanski compression for BBC with
111+ additional arithmetic coding (damn slow, but best compresor).
112+
113+config JFFS2_BBC_LZHD
114+ bool "LZHD compression support for BBC (EXPERIMENTAL)"
115+ depends on JFFS2_FS && EXPERIMENTAL
116+ default y
117+ help
118+ This enables LempelZiv-Storer-Szymanski compression for BBC with
119+ additional dynamic Huffman coding (a little faster than LZARI, and
120+ it's compression ratio is a little worse than LZARI's)
121+
122+config JFFS2_BBC_LZSS
123+ bool "LZSS compression support for BBC (EXPERIMENTAL)"
124+ depends on JFFS2_FS && EXPERIMENTAL
125+ default y
126+ help
127+ This enables simple LempelZiv-Storer-Szymanski compression for BBC
128+ (faster than LZHD, and, and has a not-so-good compression ratio,
129+ was included just for testing)
130--- a/fs/jffs2/Makefile
131+++ b/fs/jffs2/Makefile
132@@ -10,9 +10,23 @@
133 # Note 2! The CFLAGS definitions are now in the main makefile...
134 
135 
136+JFFS2_BBC_KERNEL_OBJS-y = jffs2_bbc_framework.o jffs2_bbc_fs.o
137+
138+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_ARMLIB) += jffs2_bbc_armlib_comp.o
139+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZO) += jffs2_bbc_lzo_comp.o
140+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZSS) += jffs2_bbc_lzss_comp.o
141+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZARI) += jffs2_bbc_lzari_comp.o
142+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZHD) += jffs2_bbc_lzhd_comp.o
143+
144+JFFS2_BBC_KERNEL_OBJS := $(JFFS2_BBC_KERNEL_OBJS-y)
145+
146+JFFS2_BBC_MKFS_OBJS = jffs2_bbc_mkfs.o jffs2_bbc_framework.o jffs2_bbc_armlib_comp.o jffs2_bbc_lzo_comp.o\
147+ jffs2_bbc_lzss_comp.o jffs2_bbc_lzari_comp.o jffs2_bbc_lzhd_comp.o
148+
149 COMPR_OBJS := compr.o compr_rubin.o compr_rtime.o pushpull.o \
150             compr_zlib.o
151 JFFS2_OBJS := dir.o file.o ioctl.o nodelist.o malloc.o \
152+ $(JFFS2_BBC_KERNEL_OBJS) \
153     read.o nodemgmt.o readinode.o super.o write.o scan.o gc.o \
154     symlink.o build.o erase.o background.o
155 
156--- /dev/null
157+++ b/fs/jffs2/Makefile.bbc.inc
158@@ -0,0 +1,12 @@
159+JFFS2_BBC_KERNEL_OBJS-y = jffs2_bbc_framework.o jffs2_bbc_fs.o
160+
161+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_ARMLIB) += jffs2_bbc_armlib_comp.o
162+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZO) += jffs2_bbc_lzo_comp.o
163+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZSS) += jffs2_bbc_lzss_comp.o
164+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZARI) += jffs2_bbc_lzari_comp.o
165+JFFS2_BBC_KERNEL_OBJS-$(CONFIG_JFFS2_BBC_LZHD) += jffs2_bbc_lzhd_comp.o
166+
167+JFFS2_BBC_KERNEL_OBJS := $(JFFS2_BBC_KERNEL_OBJS-y)
168+
169+JFFS2_BBC_MKFS_OBJS = jffs2_bbc_mkfs.o jffs2_bbc_framework.o jffs2_bbc_armlib_comp.o jffs2_bbc_lzo_comp.o\
170+ jffs2_bbc_lzss_comp.o jffs2_bbc_lzari_comp.o jffs2_bbc_lzhd_comp.o
171--- a/fs/jffs2/compr_zlib.c
172+++ b/fs/jffs2/compr_zlib.c
173@@ -85,7 +85,7 @@ void jffs2_zlib_exit(void)
174     vfree(inflate_workspace);
175 }
176 
177-int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
178+int jffs2_zlib_compress2(unsigned char *data_in, unsigned char *cpage_out,
179            __u32 *sourcelen, __u32 *dstlen)
180 {
181     z_stream strm;
182@@ -145,7 +145,7 @@ int zlib_compress(unsigned char *data_in
183     return 0;
184 }
185 
186-void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
187+void jffs2_zlib_decompress2(unsigned char *data_in, unsigned char *cpage_out,
188               __u32 srclen, __u32 destlen)
189 {
190     z_stream strm;
191@@ -175,3 +175,19 @@ void zlib_decompress(unsigned char *data
192     zlib_inflateEnd(&strm);
193     up(&inflate_sem);
194 }
195+
196+extern int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 * sourcelen, __u32 * dstlen);
197+extern void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen);
198+
199+int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
200+ __u32 *sourcelen, __u32 *dstlen)
201+{
202+ return jffs2_zlib_compress(data_in,cpage_out,sourcelen,dstlen);
203+}
204+
205+void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
206+ __u32 srclen, __u32 destlen)
207+{
208+ jffs2_zlib_decompress(data_in,cpage_out,srclen,destlen);
209+}
210+
211--- a/fs/jffs2/file.c
212+++ b/fs/jffs2/file.c
213@@ -35,6 +35,7 @@
214  *
215  */
216 
217+#include "jffs2_bbc_framework.h" /**BBC**/
218 #include <linux/kernel.h>
219 #include <linux/mtd/compatmac.h> /* for min() */
220 #include <linux/slab.h>
221@@ -459,6 +460,7 @@ int jffs2_commit_write (struct file *fil
222 
223         comprbuf = kmalloc(cdatalen, GFP_KERNEL);
224         if (comprbuf) {
225+ jffs2_bbc_model_set_act_sb(c); /**BBC**/
226             comprtype = jffs2_compress(page_address(pg)+ (file_ofs & (PAGE_CACHE_SIZE-1)), comprbuf, &datalen, &cdatalen);
227         }
228         if (comprtype == JFFS2_COMPR_NONE) {
229--- a/fs/jffs2/gc.c
230+++ b/fs/jffs2/gc.c
231@@ -35,6 +35,7 @@
232  *
233  */
234 
235+#include "jffs2_bbc_framework.h" /**BBC**/
236 #include <linux/kernel.h>
237 #include <linux/mtd/mtd.h>
238 #include <linux/slab.h>
239@@ -651,6 +652,7 @@ static int jffs2_garbage_collect_dnode(s
240         writebuf = pg_ptr + (offset & (PAGE_CACHE_SIZE -1));
241 
242         if (comprbuf) {
243+ jffs2_bbc_model_set_act_sb(c); /**BBC**/
244             comprtype = jffs2_compress(writebuf, comprbuf, &datalen, &cdatalen);
245         }
246         if (comprtype) {
247--- /dev/null
248+++ b/fs/jffs2/hpatch
249@@ -0,0 +1,191 @@
250+#!/usr/bin/perl
251+# A patch-like utility
252+# Designed for patching different version of jffs2 with the same hpatch file
253+#
254+# Copyright (C) 2004, Ferenc Havasi
255+#
256+# This program is free software; you can redistribute it and/or
257+# modify it under the terms of the GNU General Public License
258+# as published by the Free Software Foundation; either version 2
259+# of the License, or (at your option) any later version.
260+#
261+# This program is distributed in the hope that it will be useful,
262+# but WITHOUT ANY WARRANTY; without even the implied warranty of
263+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
264+# GNU General Public License for more details.
265+#
266+# You should have received a copy of the GNU General Public License
267+# along with this program; if not, write to the Free Software
268+# Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
269+
270+$filename_tmp1="file1.tmp";
271+$filename_tmp2="file2.tmp";
272+
273+$filename_in="";
274+$filename_out=$filename_tmp1;
275+$filename_cnt=0;
276+
277+# Modes:
278+# 0: expecting =
279+# 1: normal_cmd
280+# 2: skip until =
281+# 3: expecting F (first state)
282+$mode=3;
283+
284+%rules = ();
285+
286+sub file_end {
287+ if (($mode!=2)&&($modified==1)) {
288+ while (<SRC>) {
289+ print DST $_;
290+ }
291+ close(SRC);
292+ close(DST);
293+ if ($cmd_name ne "") { $rules{"$cmd_name"}=1; }
294+ $filename_result=$filename_out;
295+ if ($filename_result ne $filename_in_save) {
296+ open(RES,"<$filename_result") or die "Cannot open $filename_result.\n";
297+ open(DST,">$filename_in_save") or die "Cannot open $filename_in_save.\n";
298+ while (<RES>) {
299+ print DST $_;
300+ }
301+ close(DST);
302+ close(RES);
303+ }
304+ unlink($filename_tmp1) && unlink($filename_tmp2);
305+ }
306+ else {
307+ close(SRC);
308+ close(DST);
309+ $filename_result=$filename_in;
310+ if ($filename_result ne $filename_in_save) {
311+ open(RES,"<$filename_result") or die "Cannot open $filename_result.\n";
312+ open(DST,">$filename_in_save") or die "Cannot open $filename_in_save.\n";
313+ while (<RES>) {
314+ print DST $_;
315+ }
316+ close(DST);
317+ close(RES);
318+ }
319+ unlink($filename_tmp1);
320+ }
321+ $modified=0;
322+ foreach $rulename (keys %rules) {
323+ if ($rules{"$rulename"}==0) { print(STDERR "On $filename_in_save error applying rule $rulename.\n"); }
324+ }
325+ %rules = ();
326+}
327+
328+if ($#ARGV<0) {
329+ print ("usage: hpatch hpatch_file\n");
330+ exit;
331+}
332+
333+open(CMD,"<$ARGV[0]") or die "Cannot open $ARGV[0].\n";
334+$cmd_linenum=0;
335+
336+while (chomp($cmd_line=<CMD>)) {
337+ $cmd_linenum++;
338+ if ($cmd_line eq "") {next;}
339+ #$cmd_line =~ s/\#.*//;
340+ $cmd_line =~ s/\ *$//;
341+ if ($cmd_line eq "") {next;}
342+ if ($cmd_line =~ /^F(.*)/) {
343+ $tmp_filename_in=$1;
344+ if ($mode!=3) {
345+ file_end();
346+ }
347+ $filename_in=$tmp_filename_in;
348+ $filename_in_save=$filename_in;
349+ open(SRC,"<$filename_in") or die "Cannot open $filename_in.\n";
350+ open(DST,">$filename_out") or die "Cannot open $filename_out.\n";;
351+ $modified=0;
352+ $mode=0;
353+ next;
354+ }
355+ if ($mode==3) {die "error: F expression expected in line $cmd_linenum\n";}
356+ if ($cmd_line =~ /^=(.*)/) {
357+ $tmp_cmd_name=$1;
358+ if (($mode!=2)&&($modified==1)) {
359+ while (<SRC>) {
360+ print DST $_;
361+ }
362+ close(SRC);
363+ close(DST);
364+ if (($cmd_name ne "")) {$rules{"$cmd_name"}=1;};
365+ $filename_cnt++;
366+ if ($filename_cnt%2==1) {
367+ $filename_in=$filename_tmp1;
368+ $filename_out=$filename_tmp2;
369+ }
370+ else {
371+ $filename_in=$filename_tmp2;
372+ $filename_out=$filename_tmp1;
373+ }
374+ }
375+ else {
376+ close(SRC);
377+ close(DST);
378+ }
379+ $mode=1;
380+ $cmd_name=$tmp_cmd_name;
381+ if (($cmd_name ne "")) {
382+ if ($rules{"$cmd_name"}==1) {
383+ $mode=2;
384+ }
385+ else {
386+ $rules{"$cmd_name"}=0;
387+ }
388+ }
389+ open(SRC,"<$filename_in") or die "Cannot open $filename_in.\n";
390+ open(DST,">$filename_out") or die "Cannot open $filename_out.\n";
391+ $modified=0;
392+ next;
393+ }
394+ if ($mode == 0) {die "error: = expression expected in line $cmd_linenum\n";}
395+ if ($mode == 2) {next;}
396+ if ($cmd_line =~ /^!(.*)/) {
397+ print "$1\n";
398+ $modified=1;
399+ next;
400+ }
401+ if ($cmd_line =~ /^\?(.*)/) {
402+ $search_str=$1;
403+ $found=0;
404+ while (<SRC>) {
405+ print DST $_;
406+ if (index($_,$search_str)>=0) {$found=1; last;}
407+ }
408+ if ($found==0) { $mode=2; }
409+ next;
410+ }
411+ if ($cmd_line =~ /^\+(.*)/) {
412+ print DST "$1\n";
413+ $modified=1;
414+ next;
415+ }
416+ if ($cmd_line =~ /^\-(.*)/) {
417+ $search_str=$1;
418+ $found=0;
419+ while (<SRC>) {
420+ if (index($_,$search_str)>=0) {$saved_line=$_; $found=1; $modified=1; last;}
421+ print DST $_;
422+ }
423+ if ($found==0) { $mode=2; }
424+ next;
425+ }
426+ if ($cmd_line =~ /^i(.*)/) {
427+ $filename_inc=$1;
428+ open(INCSRC,"<$filename_inc") or die "Cannot open $filename_inc.\n";
429+ while (<INCSRC>) {
430+ print DST $_;
431+ }
432+ next;
433+ }
434+ if ($cmd_line =~ /^I/) {
435+ print DST $saved_line;
436+ next;
437+ }
438+}
439+file_end();
440+close(CMD);
441--- /dev/null
442+++ b/fs/jffs2/jffs2_bbc_armlib_comp.c
443@@ -0,0 +1,2224 @@
444+/*
445+ * JFFS2-BBC: armlib compressor plugin
446+ *
447+ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
448+ *
449+ * Copyright (C) 2004, Ferenc Havasi & Tamas Gergely
450+ *
451+ * This program is free software; you can redistribute it and/or
452+ * modify it under the terms of the GNU General Public License
453+ * as published by the Free Software Foundation; either version 2
454+ * of the License, or (at your option) any later version.
455+ *
456+ * This program is distributed in the hope that it will be useful,
457+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
458+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
459+ * GNU General Public License for more details.
460+ *
461+ * You should have received a copy of the GNU General Public License
462+ * along with this program; if not, write to the Free Software
463+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
464+ *
465+ */
466+
467+#include "jffs2_bbc_framework.h"
468+
469+#ifdef __KERNEL__
470+#include <linux/string.h>
471+#else
472+#include <string.h>
473+#endif
474+
475+//ORIGIN: include/DataStructures/TypeDefs.h
476+
477+/*******************************************************************************
478+* FILE: TypeDefs.h
479+* AUTHOR: Tamás Gergely
480+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
481+*******************************************************************************/
482+
483+#ifndef TYPEDEFS_H
484+#define TYPEDEFS_H
485+
486+#pragma pack(4)
487+
488+#ifndef bool
489+#define bool char
490+#define true 1
491+#define false 0
492+#endif
493+
494+#ifndef u8
495+#define u8 unsigned char
496+#endif
497+#ifndef u16
498+#define u16 unsigned short
499+#endif
500+#ifndef u32
501+#define u32 unsigned long
502+#endif
503+#ifndef s8
504+#define s8 signed char
505+#endif
506+#ifndef s16
507+#define s16 signed short
508+#endif
509+#ifndef s32
510+#define s32 signed long
511+#endif
512+
513+typedef struct
514+{
515+ u32 capacity;
516+ u32 size;
517+ u32 alloc_size;
518+ void *ptr;
519+} vector;
520+
521+#define VECTOR_P_END(vct) ((void*)(((char*)((vct)->ptr)) + (vct)->size))
522+#define VECTOR_S_END(vct) ((void*)(((char*)((vct).ptr)) + (vct).size))
523+
524+static void vector_clear(vector *);
525+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
526+static void vector_reset(vector *);
527+static void vector_clr_ptr(vector *);
528+static void vector_add_u8(vector *, u8);
529+static void vector_add_u16(vector *, u16);
530+static void vector_add_u32(vector *, u32);
531+static void vector_add_s8(vector *, s8);
532+static void vector_add_s16(vector *, s16);
533+static void vector_add_s32(vector *, s32);
534+static void vector_add_ptr(vector *, void *);
535+static void vector_concat(vector *, vector *);
536+#endif
537+
538+#endif
539+
540+//ORIGIN: include/DataStructures/DataTypes.h
541+
542+/*******************************************************************************
543+* FILE: DataTypes.h
544+* AUTHOR: Tamás Gergely
545+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
546+*******************************************************************************/
547+
548+#ifndef DATATYPES_H
549+#define DATATYPES_H
550+
551+//#include "DataStructures/TypeDefs.h"
552+
553+typedef u16 THUMB_DataType;
554+typedef u32 ARM_DataType;
555+typedef u8 TokenType;
556+typedef u8 PredictorType;
557+typedef u8 *ProbDist;
558+
559+typedef vector RawData;
560+typedef vector RawBlocks;
561+typedef vector TokenStream;
562+typedef vector TokenBlocks;
563+typedef vector LatType;
564+
565+#define THUMB_DATA_LENGTH 16
566+#define ARM_DATA_LENGTH 32
567+#define TOKEN_LENGTH 8
568+#define TOKEN_MAXVALUE 0xff
569+#define PREDICTOR_LENGTH 8
570+#define PREDICTOR_MAXVALUE 0xff
571+
572+#endif
573+
574+//ORIGIN: include/DataStructures/BitVector.h
575+
576+/*******************************************************************************
577+* FILE: BitVector.h
578+* AUTHOR: Tamás Gergely
579+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
580+*******************************************************************************/
581+
582+#ifndef BITVECTOR_H
583+#define BITVECTOR_H
584+
585+//#include "DataStructures/TypeDefs.h"
586+
587+typedef vector BitBlocks;
588+
589+#pragma pack(4)
590+
591+typedef struct
592+{
593+ u32 freebits;
594+ u32 capacity;
595+ u32 size;
596+ u8 *base;
597+ u8 *ptr;
598+} BitVector;
599+
600+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
601+static void bitblocks_clear(BitBlocks *);
602+static void bitvector_clear(BitVector *);
603+static void bitvector_W_reset(BitVector *);
604+static void bitvector_W_add0(BitVector *);
605+static void bitvector_W_add1(BitVector *);
606+static void bitvector_W_concat_b(BitVector *, BitVector *);
607+static void bitvector_W_concat_v(BitVector *, vector *);
608+static void bitvector_W_flush(BitVector *);
609+static void bitvector_R_reset(BitVector *);
610+static u8 bitvector_R_get1(BitVector *);
611+static u8 bitvector_R_get8(BitVector *);
612+#endif
613+
614+#define BITVECTOR_P_END(bv) ((void*)(((bv)->base)+((bv)->size)))
615+#define BITVECTOR_S_END(bv) ((void*)( ((bv).base)+ ((bv).size)))
616+#define BITVECTOR_SKIP(bv,num) ((bv)->ptr) += (num)
617+
618+#endif
619+
620+//ORIGIN: include/DataStructures/DecisionTree.h
621+
622+/*******************************************************************************
623+* FILE: DecisionTree.h
624+* AUTHOR: Tamás Gergely
625+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
626+*******************************************************************************/
627+
628+#ifndef DECISIONTREE_H
629+#define DECISIONTREE_H
630+
631+//#include "DataStructures/DataTypes.h"
632+
633+#pragma pack(4)
634+
635+#define TREENODETYPE_NULLNODE 0
636+#define TREENODETYPE_NODE_BINARY_EQ 1
637+#define TREENODETYPE_LEAF_P 2
638+#define TREENODETYPE_LEAF_C 3
639+#define TREENODETYPE_NODE_BINARY_LT 5
640+#define TREENODETYPE_IS_NODE(n) (((n) == TREENODETYPE_NODE_BINARY_EQ) || \
641+ ((n) == TREENODETYPE_NODE_BINARY_LT))
642+#define TREENODETYPE_IS_NODE_BINARY(n) (((n) == TREENODETYPE_NODE_BINARY_EQ) || \
643+ ((n) == TREENODETYPE_NODE_BINARY_LT))
644+
645+#define TREENODETYPE_IS_LEAF(n) (((n) == TREENODETYPE_LEAF_P) || \
646+ ((n) == TREENODETYPE_LEAF_C))
647+
648+
649+#define TREE_SUBTREE_RELATION_LEFT_EQ !=
650+#define TREE_SUBTREE_RELATION_RIGHT_EQ ==
651+#define TREE_SUBTREE_RELATION_LEFT_LT <
652+#define TREE_SUBTREE_RELATION_RIGHT_LT >=
653+
654+#define GET_NODE_PTR_TYPE(n) (((TreeNodeDummy*)(n))->type)
655+
656+typedef struct
657+{
658+ u8 type;
659+} TreeNodeDummy;
660+
661+typedef struct
662+{
663+ u8 type; // [TREENODETYPE_NODE_BINARY]
664+ u8 attribute;
665+ PredictorType value;
666+ void *left;
667+ void *right;
668+} TreeNodeBinary;
669+
670+typedef struct
671+{
672+ u8 type; // [TREENODETYPE_LEAF_P]
673+ u16 pairs;
674+ PredictorType *probabilities;
675+} TreeLeafP;
676+
677+typedef struct
678+{
679+ u8 type; // [TREENODETYPE_LEAF_C]
680+ PredictorType predicted_class;
681+} TreeLeafC;
682+
683+typedef struct
684+{
685+ u32 high;
686+ u32 low;
687+ u32 max;
688+} ProbabilityType;
689+
690+
691+typedef struct
692+{
693+ void *root;
694+ u16 number_of_classes;
695+ u16 number_of_predictors;
696+ PredictorType *predictor_max_values;
697+} DecisionTree;
698+
699+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
700+static void decisiontree_delete(DecisionTree *);
701+static void decisiontree_get_probability_for_token(void *, PredictorType *, TokenType, ProbabilityType *);
702+static TokenType decisiontree_get_token_for_range(void *, PredictorType *, u32, u32, ProbabilityType *);
703+#endif
704+
705+#endif
706+
707+//ORIGIN: include/DataStructures/PredictorTable.h
708+
709+/*******************************************************************************
710+* FILE: PredictorTable.h
711+* AUTHOR: Tamás Gergely
712+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
713+*******************************************************************************/
714+
715+#ifndef PREDICTORTABLE_H
716+#define PREDICTORTABLE_H
717+
718+//#include "DataStructures/TypeDefs.h"
719+//#include "DataStructures/DataTypes.h"
720+////#include "DataStructures/Filter.h"
721+////#include "DataStructures/Converter.h"
722+////#include "DataStructures/Manipulator.h"
723+
724+#define NUMBER_OF_PREDICTORS_ARM 17
725+
726+#ifndef __KERNEL__
727+#define NUMBER_OF_PREDICTORS_TXT 2
728+#else
729+#undef TXT_TOKENS
730+#endif // __KERNEL__
731+
732+#ifdef TXT_TOKENS
733+#define NUMBER_OF_PREDICTORS NUMBER_OF_PREDICTORS_TXT
734+#define predictortable_reset predictortable_resetTXT
735+#define predictortable_update predictortable_updateTXT
736+#define predictortable_minvalue predictortable_minvalueTXT
737+#define predictortable_maxvalue predictortable_maxvalueTXT
738+#else
739+#define NUMBER_OF_PREDICTORS NUMBER_OF_PREDICTORS_ARM
740+#define predictortable_reset predictortable_resetARM
741+#define predictortable_update predictortable_updateARM
742+#define predictortable_minvalue predictortable_minvalueARM
743+#define predictortable_maxvalue predictortable_maxvalueARM
744+#endif
745+
746+
747+#pragma pack(4)
748+
749+typedef struct
750+{
751+ PredictorType *predictors;
752+} PredictorTable;
753+
754+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
755+static void predictortable_clear(PredictorTable *);
756+static void predictortable_free(PredictorTable *);
757+static void predictortable_resetARM(PredictorTable *);
758+static void predictortable_updateARM(PredictorTable *, TokenType);
759+static PredictorType predictortable_minvalueARM(PredictorTable *, u32);
760+static PredictorType predictortable_maxvalueARM(PredictorTable *, u32);
761+#endif
762+
763+#ifndef __KERNEL__
764+/*
765+static void predictortable_resetTXT(PredictorTable *);
766+static void predictortable_updateTXT(PredictorTable *, TokenType);
767+static PredictorType predictortable_minvalueTXT(PredictorTable *, u32);
768+static PredictorType predictortable_maxvalueTXT(PredictorTable *, u32);
769+*/
770+#endif // __KERNEL__
771+
772+#endif
773+
774+//ORIGIN: include/DataStructures/ipack_model.h
775+
776+/*******************************************************************************
777+* FILE: ipack_model.h
778+* AUTHOR: Tamás Gergely
779+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
780+*******************************************************************************/
781+
782+#ifndef IPACK_MODEL_H
783+#define IPACK_MODEL_H
784+
785+//#include "DataStructures/DataTypes.h"
786+//#include "DataStructures/DecisionTree.h"
787+//#include "DataStructures/PredictorTable.h"
788+
789+#define PROBABILITY_SHIFT 12
790+#define PROBABILITY_MAX 0x00001000l
791+
792+#define NUMBER_OF_TOKENS_ARM 16
793+#define NUMBER_OF_TOKENS_PER_INSTRUCTION_ARM 8
794+
795+#ifndef __KERNEL__
796+#define NUMBER_OF_TOKENS_TXT 256
797+#define NUMBER_OF_TOKENS_PER_INSTRUCTION_TXT 4
798+#else
799+#undef TXT_TOKENS
800+#endif // __KERNEL__
801+
802+#ifdef TXT_TOKENS
803+#define NUMBER_OF_TOKENS NUMBER_OF_TOKENS_TXT
804+#define NUMBER_OF_TOKENS_PER_INSTRUCTION NUMBER_OF_TOKENS_PER_INSTRUCTION_TXT
805+#else
806+#define NUMBER_OF_TOKENS NUMBER_OF_TOKENS_ARM
807+#define NUMBER_OF_TOKENS_PER_INSTRUCTION NUMBER_OF_TOKENS_PER_INSTRUCTION_ARM
808+#endif
809+
810+#pragma pack(4)
811+
812+/*
813+ Data structure of an internal node of the tree
814+*/
815+typedef struct
816+{
817+ PredictorType *attribute_ptr;
818+ u32 value; // PredictorType
819+ void *right_child_ptr;
820+} ipack_treenodeBin;
821+/*
822+ Data structure of a leaf with probabilities
823+*/
824+typedef struct
825+{
826+ u16 probabilities[0]; // PredictorType[0]
827+} ipack_treeleafP;
828+/*
829+ Data structure of a leaf with class prediction
830+*/
831+typedef struct
832+{
833+ PredictorType predicted_class; // PredictorType
834+} ipack_treeleafC;
835+/*
836+ Possible data structures of a tree node
837+*/
838+typedef union
839+{
840+ ipack_treenodeBin nodeBin;
841+ ipack_treeleafP leafP;
842+ ipack_treeleafC leafC;
843+} ipack_node_data;
844+/*
845+ Tree node
846+*/
847+typedef struct
848+{
849+ u32 type; // u8
850+ ipack_node_data data; // ipack_node_data
851+} ipack_nodetype;
852+/*
853+ Nullnode
854+*/
855+typedef struct
856+{
857+ u32 type;
858+ u16 probabilities[NUMBER_OF_TOKENS];
859+} ipack_nullnode;
860+/*
861+ Model for ipack project
862+*/
863+typedef struct
864+{
865+ char ID[4]; // char[4]
866+ char block_sign[4]; // only the first 2 are used!
867+ void *tree_root_ptr; // void*
868+ void *tree_code; // generated ARM code
869+ PredictorType *predictors_ptr; // PredictorType*
870+ ipack_nullnode nullnode;
871+} ipack_model_type;
872+
873+typedef struct
874+{
875+ u32 high;
876+ u32 low;
877+} ipack_probability_type;
878+
879+
880+static void ipack_model_get_probability_for_token(ipack_nodetype *, TokenType, ipack_probability_type *);
881+static TokenType ipack_model_get_token_for_range(ipack_nodetype *, u32, u32, ipack_probability_type *);
882+/*void ipack_model_predictortable_reset (PredictorType*);
883+void ipack_model_predictortable_update (PredictorType*, TokenType);*/
884+
885+#ifndef __KERNEL__
886+/*static void ipack_model_printinfo(ipack_model_type *);
887+static void ipack_dumpmodel(void *);*/
888+#endif
889+
890+#endif
891+
892+//ORIGIN: include/Builders/PredictorGenerator.h
893+
894+/*******************************************************************************
895+* FILE: PredictorGenerator.h
896+* AUTHOR: Tamás Gergely
897+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
898+*******************************************************************************/
899+
900+#ifndef PREDICTORGENERATOR_H
901+#define PREDICTORGENERATOR_H
902+
903+//#include "DataStructures.h"
904+
905+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
906+static PredictorTable *predictorgenerator_generate(void);
907+#endif
908+
909+#endif
910+
911+//ORIGIN: include/Builders/Coder.h
912+
913+/*******************************************************************************
914+* FILE: Coder.h
915+* AUTHOR: Tamás Gergely
916+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
917+*******************************************************************************/
918+
919+#ifndef CODER_H
920+#define CODER_H
921+
922+#define CODER_VALUEBITS 16
923+#define CODER_VALUEMAX 0x00010000l
924+#define CODER_VALUE3RD 0x0000c000l
925+#define CODER_VALUEHLF 0x00008000l
926+#define CODER_VALUE1ST 0x00004000l
927+
928+#endif
929+
930+//ORIGIN: DataStructures/src/TypeDefs.c
931+
932+/*******************************************************************************
933+* FILE: TypeDefs.c
934+* AUTHOR: Tamás Gergely
935+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
936+*******************************************************************************/
937+
938+//#include "ipack_common.h"
939+//#include "DataStructures/TypeDefs.h"
940+#ifndef __KERNEL__
941+#include <memory.h>
942+#endif
943+
944+#define VECTOR_ALLOC_SIZE 0x00001000
945+
946+static void vector_clear(vector * vct)
947+{
948+ if (vct->ptr)
949+ jffs2_bbc_free(vct->ptr);
950+ vct->capacity = 0;
951+ vct->size = 0;
952+ vct->ptr = 0;
953+}
954+
955+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
956+static void vector_extend(vector * vct)
957+{
958+ void *tmp;
959+ vct->capacity += vct->alloc_size;
960+ tmp = jffs2_bbc_malloc(vct->capacity);
961+ if (vct->ptr) {
962+ memcpy(tmp, vct->ptr, vct->size);
963+ jffs2_bbc_free(vct->ptr);
964+ }
965+ vct->ptr = tmp;
966+}
967+
968+static void vector_reset(vector * vct)
969+{
970+ vct->capacity = 0;
971+ vct->size = 0;
972+ vct->alloc_size = VECTOR_ALLOC_SIZE;
973+ vct->ptr = 0;
974+}
975+
976+static void vector_clr_ptr(vector * vct)
977+{
978+ void **it;
979+ void *end_it;
980+ for (it = vct->ptr, end_it = (((char *) (vct->ptr)) + vct->size); it != end_it; it++) {
981+ vector_clear(*it);
982+ jffs2_bbc_free(*it);
983+ }
984+ if (vct->ptr)
985+ jffs2_bbc_free(vct->ptr);
986+ vct->capacity = 0;
987+ vct->size = 0;
988+ vct->ptr = 0;
989+}
990+
991+static void vector_add_u8(vector * vct, u8 val)
992+{
993+ if ((vct->size) + sizeof(u8) > (vct->capacity)) {
994+ vector_extend(vct);
995+ }
996+ *(u8 *) ((char *) (vct->ptr) + (vct->size)) = val;
997+ vct->size += sizeof(u8);
998+};
999+
1000+static void vector_add_u16(vector * vct, u16 val)
1001+{
1002+ if ((vct->size) + sizeof(u16) > (vct->capacity)) {
1003+ vector_extend(vct);
1004+ }
1005+ *(u16 *) ((char *) (vct->ptr) + (vct->size)) = val;
1006+ vct->size += sizeof(u16);
1007+};
1008+
1009+static void vector_add_u32(vector * vct, u32 val)
1010+{
1011+ if ((vct->size) + sizeof(u32) > (vct->capacity)) {
1012+ vector_extend(vct);
1013+ }
1014+ *(u32 *) ((char *) (vct->ptr) + (vct->size)) = val;
1015+ vct->size += sizeof(u32);
1016+};
1017+
1018+static void vector_add_s8(vector * vct, s8 val)
1019+{
1020+ if ((vct->size) + sizeof(s8) > (vct->capacity)) {
1021+ vector_extend(vct);
1022+ }
1023+ *(s8 *) ((char *) (vct->ptr) + (vct->size)) = val;
1024+ vct->size += sizeof(s8);
1025+};
1026+
1027+static void vector_add_s16(vector * vct, s16 val)
1028+{
1029+ if ((vct->size) + sizeof(s16) > (vct->capacity)) {
1030+ vector_extend(vct);
1031+ }
1032+ *(s16 *) ((char *) (vct->ptr) + (vct->size)) = val;
1033+ vct->size += sizeof(s16);
1034+};
1035+
1036+static void vector_add_s32(vector * vct, s32 val)
1037+{
1038+ if ((vct->size) + sizeof(s32) > (vct->capacity)) {
1039+ vector_extend(vct);
1040+ }
1041+ *(s32 *) ((char *) (vct->ptr) + (vct->size)) = val;
1042+ vct->size += sizeof(s32);
1043+};
1044+
1045+static void vector_add_ptr(vector * vct, void *ptr)
1046+{
1047+ if ((vct->size) + sizeof(void *) > (vct->capacity)) {
1048+ vector_extend(vct);
1049+ }
1050+ *(void **) ((char *) (vct->ptr) + (vct->size)) = ptr;
1051+ vct->size += sizeof(void *);
1052+}
1053+
1054+static void vector_concat(vector * lhs, vector * rhs)
1055+{
1056+ void *tmp;
1057+ if (!(rhs->size)) {
1058+ return;
1059+ }
1060+ tmp = lhs->ptr;
1061+ lhs->capacity = (lhs->size) + (rhs->size);
1062+ lhs->ptr = jffs2_bbc_malloc(lhs->capacity);
1063+ if (tmp) {
1064+ memcpy(lhs->ptr, tmp, lhs->size);
1065+ jffs2_bbc_free(tmp);
1066+ }
1067+ memcpy((((u8 *) lhs->ptr) + lhs->size), rhs->ptr, rhs->size);
1068+ lhs->size += rhs->size;
1069+}
1070+
1071+#endif
1072+
1073+//ORIGIN: DataStructures/src/BitVector.c
1074+
1075+/*******************************************************************************
1076+* FILE: BitVector.c
1077+* AUTHOR: Tamás Gergely
1078+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
1079+*******************************************************************************/
1080+
1081+//#include "ipack_common.h"
1082+//#include "DataStructures/BitVector.h"
1083+#ifndef __KERNEL__
1084+#include <memory.h>
1085+#endif
1086+
1087+#define VECTOR_ALLOC_SIZE 0x00001000
1088+
1089+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
1090+
1091+static void bitblocks_clear(BitBlocks * this)
1092+{
1093+ BitVector **it;
1094+ void *end_it;
1095+ for (it = this->ptr, end_it = VECTOR_P_END(this); it != end_it; it++) {
1096+ bitvector_clear(*it);
1097+ jffs2_bbc_free(*it);
1098+ }
1099+ jffs2_bbc_free(this->ptr);
1100+ this->ptr = 0;
1101+}
1102+
1103+static void bitvector_clear(BitVector * this)
1104+{
1105+ if (this->base) {
1106+ jffs2_bbc_free(this->base);
1107+ }
1108+ this->freebits = 0;
1109+ this->capacity = 0;
1110+ this->size = 0;
1111+ this->base = 0;
1112+ this->ptr = 0;
1113+}
1114+
1115+static void bitvector_W_reset(BitVector * this)
1116+{
1117+ this->freebits = 0;
1118+ this->capacity = 0;
1119+ this->size = 0;
1120+ this->base = 0;
1121+ this->ptr = 0;
1122+}
1123+
1124+static void bitvector_W_add0(BitVector * this)
1125+{
1126+ if (!(this->freebits)) {
1127+ if (this->size == this->capacity) {
1128+ void *tmp = this->base;
1129+ this->capacity += VECTOR_ALLOC_SIZE;
1130+ this->base = jffs2_bbc_malloc(this->capacity);
1131+ this->ptr = ((u8 *) (this->base)) + this->size;
1132+ memcpy(this->base, tmp, this->size);
1133+ jffs2_bbc_free(tmp);
1134+ }
1135+ else {
1136+ this->ptr++;
1137+ }
1138+ this->size++;
1139+ this->freebits = 7;
1140+ *(this->ptr) = 0x00;
1141+ }
1142+ else {
1143+ this->freebits--;
1144+ (*(this->ptr)) <<= 1;
1145+ }
1146+}
1147+
1148+static void bitvector_W_add1(BitVector * this)
1149+{
1150+ if (!(this->freebits)) {
1151+ if (this->size == this->capacity) {
1152+ void *tmp = this->base;
1153+ this->capacity += VECTOR_ALLOC_SIZE;
1154+ this->base = jffs2_bbc_malloc(this->capacity);
1155+ this->ptr = ((u8 *) (this->base)) + this->size;
1156+ memcpy(this->base, tmp, this->size);
1157+ jffs2_bbc_free(tmp);
1158+ }
1159+ else {
1160+ this->ptr++;
1161+ }
1162+ this->size++;
1163+ this->freebits = 7;
1164+ *(this->ptr) = 0x01;
1165+ }
1166+ else {
1167+ this->freebits--;
1168+ (*(this->ptr)) <<= 1;
1169+ (*(this->ptr)) |= 0x01;
1170+ }
1171+}
1172+
1173+static void bitvector_W_concat_b(BitVector * lhs, BitVector * rhs)
1174+{
1175+ void *tmp;
1176+ if (!(rhs->size)) {
1177+ return;
1178+ }
1179+ tmp = lhs->base;
1180+ lhs->capacity = ((((lhs->size) + (rhs->size) - 1) / VECTOR_ALLOC_SIZE) + 1) * VECTOR_ALLOC_SIZE;
1181+ lhs->base = jffs2_bbc_malloc(lhs->capacity);
1182+ if (tmp) {
1183+ memcpy(lhs->base, tmp, lhs->size);
1184+ jffs2_bbc_free(tmp);
1185+ }
1186+ memcpy((((u8 *) (lhs->base)) + lhs->size), rhs->base, rhs->size);
1187+ lhs->freebits = 0;
1188+ lhs->size += rhs->size;
1189+ lhs->ptr = ((u8 *) (lhs->base)) + lhs->size;
1190+}
1191+
1192+static void bitvector_W_concat_v(BitVector * lhs, vector * rhs)
1193+{
1194+ void *tmp;
1195+ if (!(rhs->size)) {
1196+ return;
1197+ }
1198+ tmp = lhs->base;
1199+ lhs->capacity = ((((lhs->size) + (rhs->size) - 1) / VECTOR_ALLOC_SIZE) + 1) * VECTOR_ALLOC_SIZE;
1200+ lhs->base = jffs2_bbc_malloc(lhs->capacity);
1201+ if (tmp) {
1202+ memcpy(lhs->base, tmp, lhs->size);
1203+ jffs2_bbc_free(tmp);
1204+ }
1205+ memcpy((((u8 *) (lhs->base)) + lhs->size), rhs->ptr, rhs->size);
1206+ lhs->freebits = 0;
1207+ lhs->size += rhs->size;
1208+ lhs->ptr = ((u8 *) (lhs->base)) + lhs->size;
1209+}
1210+
1211+static void bitvector_W_flush(BitVector * this)
1212+{
1213+ (*(this->ptr)) <<= this->freebits;
1214+ this->freebits = 0;
1215+}
1216+
1217+static void bitvector_R_reset(BitVector * this)
1218+{
1219+ this->freebits = 7;
1220+ this->ptr = this->base;
1221+}
1222+
1223+static u8 bitvector_R_get1(BitVector * this)
1224+{
1225+ u8 tmp = ((*(this->ptr)) >> this->freebits) & 0x01;
1226+ if (!(this->freebits)) {
1227+ this->freebits = 7;
1228+ this->ptr++;
1229+ }
1230+ else {
1231+ this->freebits--;
1232+ }
1233+ return tmp;
1234+}
1235+
1236+static u8 bitvector_R_get8(BitVector * this)
1237+{
1238+ u8 tmp = (*(this->ptr));
1239+ this->ptr++;
1240+ return tmp;
1241+}
1242+
1243+#endif
1244+
1245+//ORIGIN: DataStructures/src/DecisionTree.c
1246+
1247+/*******************************************************************************
1248+* FILE: DecisionTree.c
1249+* AUTHOR: Tamás Gergely
1250+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
1251+*******************************************************************************/
1252+
1253+//#include "ipack_common.h"
1254+//#include "DataStructures/DecisionTree.h"
1255+
1256+static void decisiontree_delete_node(void *root)
1257+{
1258+ u8 tmp = GET_NODE_PTR_TYPE(root);
1259+ if (TREENODETYPE_IS_NODE_BINARY(tmp)) {
1260+ decisiontree_delete_node(((TreeNodeBinary *) root)->left);
1261+ decisiontree_delete_node(((TreeNodeBinary *) root)->right);
1262+ }
1263+ else if ((tmp) == TREENODETYPE_LEAF_P) {
1264+ if (((TreeLeafP *) root)->probabilities) {
1265+ jffs2_bbc_free(((TreeLeafP *) root)->probabilities);
1266+ }
1267+ }
1268+ else if ((tmp) == TREENODETYPE_LEAF_C) {
1269+ }
1270+ jffs2_bbc_free(root);
1271+}
1272+
1273+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
1274+
1275+static void decisiontree_delete(DecisionTree * dt)
1276+{
1277+ decisiontree_delete_node(dt->root);
1278+ jffs2_bbc_free(dt->predictor_max_values);
1279+}
1280+
1281+static void decisiontree_get_probability_for_token(void *root, PredictorType * preds, TokenType token, ProbabilityType * prob)
1282+{
1283+ void *tmp = root;
1284+ while (TREENODETYPE_IS_NODE(((TreeNodeBinary *) tmp)->type)) {
1285+ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_EQ) {
1286+ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_EQ((TreeNodeBinary *) tmp)->value) {
1287+ tmp = ((TreeNodeBinary *) tmp)->left;
1288+ }
1289+ else {
1290+ tmp = ((TreeNodeBinary *) tmp)->right;
1291+ }
1292+ }
1293+ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_LT) {
1294+ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_LT((TreeNodeBinary *) tmp)->value) {
1295+ tmp = ((TreeNodeBinary *) tmp)->left;
1296+ }
1297+ else {
1298+ tmp = ((TreeNodeBinary *) tmp)->right;
1299+ }
1300+ }
1301+ }
1302+ prob->high = 0;
1303+ prob->low = 0;
1304+ prob->max = 0;
1305+ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_P) {
1306+ u32 i;
1307+ u32 lngth = ((TreeLeafP *) tmp)->pairs << 1;
1308+ for (i = 0; i < lngth;) {
1309+ TokenType at = ((TreeLeafP *) tmp)->probabilities[i++];
1310+ TokenType av = ((TreeLeafP *) tmp)->probabilities[i++];
1311+ if (token > at)
1312+ prob->low += av;
1313+ if (token >= at)
1314+ prob->high += av;
1315+ prob->max += av;
1316+ }
1317+ }
1318+ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_C) {
1319+ if (((TreeLeafC *) tmp)->predicted_class == token) {
1320+ prob->high = TOKEN_MAXVALUE;
1321+ prob->max = TOKEN_MAXVALUE;
1322+ }
1323+ }
1324+}
1325+
1326+static TokenType decisiontree_get_token_for_range(void *root, PredictorType * preds, u32 value, u32 range, ProbabilityType * prob)
1327+{
1328+ void *tmp = root;
1329+ TokenType token = 0;
1330+ while (TREENODETYPE_IS_NODE(((TreeNodeBinary *) tmp)->type)) {
1331+ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_EQ) {
1332+ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_EQ((TreeNodeBinary *) tmp)->value) {
1333+ tmp = ((TreeNodeBinary *) tmp)->left;
1334+ }
1335+ else {
1336+ tmp = ((TreeNodeBinary *) tmp)->right;
1337+ }
1338+ }
1339+ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_NODE_BINARY_LT) {
1340+ if (preds[((TreeNodeBinary *) tmp)->attribute] TREE_SUBTREE_RELATION_LEFT_LT((TreeNodeBinary *) tmp)->value) {
1341+ tmp = ((TreeNodeBinary *) tmp)->left;
1342+ }
1343+ else {
1344+ tmp = ((TreeNodeBinary *) tmp)->right;
1345+ }
1346+ }
1347+ }
1348+ prob->high = 0;
1349+ prob->low = 0;
1350+ prob->max = 0;
1351+ if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_P) {
1352+ u32 i;
1353+ u32 norm;
1354+ TokenType at = 0;
1355+ TokenType av;
1356+ u32 lngth = ((TreeLeafP *) tmp)->pairs << 1;
1357+ for (i = 0; i < lngth;) {
1358+ i++;
1359+ prob->max += ((TreeLeafP *) tmp)->probabilities[i++];
1360+ }
1361+ norm = (value * prob->max - 1) / range;
1362+ for (i = 0; prob->high <= norm;) {
1363+ at = ((TreeLeafP *) tmp)->probabilities[i++];
1364+ av = ((TreeLeafP *) tmp)->probabilities[i++];
1365+ prob->high += av;
1366+ if (prob->high <= norm)
1367+ prob->low += av;
1368+ }
1369+ token = at;
1370+ }
1371+ else if (((TreeNodeBinary *) tmp)->type == TREENODETYPE_LEAF_C) {
1372+ token = ((TreeLeafC *) tmp)->predicted_class;
1373+ prob->high = TOKEN_MAXVALUE;
1374+ prob->max = TOKEN_MAXVALUE;
1375+ }
1376+ return token;
1377+}
1378+#endif
1379+
1380+//ORIGIN: DataStructures/src/PredictorTable.c
1381+
1382+/*******************************************************************************
1383+* FILE: PredictorTable.c
1384+* AUTHOR: Tamás Gergely
1385+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
1386+*******************************************************************************/
1387+
1388+//#include "ipack_common.h"
1389+//#include "DataStructures/PredictorTable.h"
1390+
1391+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
1392+
1393+static void predictortable_clear(PredictorTable * table)
1394+{
1395+ table->predictors = 0;
1396+}
1397+
1398+static void predictortable_free(PredictorTable * table)
1399+{
1400+ if (table->predictors) {
1401+ jffs2_bbc_free(table->predictors);
1402+ table->predictors = 0;
1403+ }
1404+}
1405+
1406+static void predictortable_resetARM(PredictorTable * table)
1407+{
1408+ register PredictorType *ptr = table->predictors;
1409+ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS_ARM;
1410+ while (ptr < end) {
1411+ *(ptr++) = 0;
1412+ }
1413+}
1414+
1415+static void predictortable_updateARM(PredictorTable * table, TokenType token)
1416+{
1417+ register PredictorType *ptr = table->predictors;
1418+ register u32 ndx = ptr[0] + 1;
1419+ ptr[ndx + 8] = ptr[ndx];
1420+ ptr[ndx] = token;
1421+ if (ndx == 8) {
1422+ ptr[0] = 0;
1423+ }
1424+ else {
1425+ ++ptr[0];
1426+ }
1427+}
1428+
1429+static PredictorType predictortable_minvalueARM(PredictorTable * table, u32 index)
1430+{
1431+ return 0;
1432+}
1433+
1434+static PredictorType predictortable_maxvalueARM(PredictorTable * table, u32 index)
1435+{
1436+ if (index == 0) {
1437+ return 7;
1438+ }
1439+ else {
1440+ return 15;
1441+ }
1442+}
1443+
1444+#endif
1445+
1446+#ifndef __KERNEL__
1447+
1448+/*static void predictortable_resetTXT(PredictorTable * table)
1449+{
1450+ register PredictorType *ptr = table->predictors;
1451+ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS_TXT;
1452+ while (ptr < end) {
1453+ *(ptr++) = 0;
1454+ }
1455+}
1456+
1457+static void predictortable_updateTXT(PredictorTable * table, TokenType token)
1458+{ //TODO: modify
1459+ register PredictorType *ptr = table->predictors;
1460+// register u32 ndx;
1461+ ptr[0] = token;
1462+ if ((('a' <= token) && (token <= 'z')) || (('A' <= token) && (token <= 'Z'))) {
1463+ ++(ptr[1]);
1464+ }
1465+ else {
1466+ ptr[1] = 0;
1467+ }
1468+}
1469+
1470+static PredictorType predictortable_minvalueTXT(PredictorTable * table, u32 index)
1471+{
1472+ return 0;
1473+}
1474+
1475+static PredictorType predictortable_maxvalueTXT(PredictorTable * table, u32 index)
1476+{ //TODO: modify
1477+ return 254;
1478+}*/
1479+
1480+#endif // __KERNEL__
1481+
1482+//ORIGIN: DataStructures/src/ipack_model.c
1483+
1484+/*******************************************************************************
1485+* FILE: ipack_model.c
1486+* AUTHOR: Tamás Gergely
1487+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
1488+*******************************************************************************/
1489+
1490+//#include "DataStructures/ipack_model.h"
1491+//#include "measuredef.h"
1492+//#include "ipack_common.h"
1493+
1494+#ifdef __MEASURE_TIME_MODEL_GETPROB
1495+#define __MT_P_MAX 256
1496+#define __MT_P_DIV 128
1497+#define __MT_P_MIN 0
1498+#endif
1499+
1500+static void ipack_model_get_probability_for_token(ipack_nodetype * tmp, TokenType token, ipack_probability_type * prob)
1501+{
1502+// register ipack_nodetype* tmp = model->tree_root_ptr;
1503+// register ipack_nodetype* tmp = root;
1504+ while (TREENODETYPE_IS_NODE(tmp->type)) {
1505+ if (tmp->type == TREENODETYPE_NODE_BINARY_EQ) {
1506+ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_EQ tmp->data.nodeBin.value) {
1507+ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
1508+ }
1509+ else {
1510+ tmp = tmp->data.nodeBin.right_child_ptr;
1511+ }
1512+ }
1513+ else if (tmp->type == TREENODETYPE_NODE_BINARY_LT) {
1514+ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_LT tmp->data.nodeBin.value) {
1515+ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
1516+ }
1517+ else {
1518+ tmp = tmp->data.nodeBin.right_child_ptr;
1519+ }
1520+ }
1521+ }
1522+ prob->high = 0;
1523+ prob->low = 0;
1524+// prob->max = 0;
1525+ if (tmp->type == TREENODETYPE_LEAF_P) {
1526+ if (token) {
1527+ prob->low = tmp->data.leafP.probabilities[token - 1];
1528+ }
1529+ prob->high = tmp->data.leafP.probabilities[token];
1530+// prob->max = tmp->data.leafP.probabilities[15];
1531+ }
1532+ else if (tmp->type == TREENODETYPE_LEAF_C) {
1533+ if (tmp->data.leafC.predicted_class == token) {
1534+ prob->high = TOKEN_MAXVALUE;
1535+// prob->max = TOKEN_MAXVALUE;
1536+ }
1537+ }
1538+}
1539+
1540+#ifndef IPACK_ARM_ASM
1541+
1542+//return ipack_model_get_token_for_range2(tmp,value,range,prob);
1543+
1544+static TokenType ipack_model_get_token_for_range(ipack_nodetype * tmp, u32 value, u32 range, ipack_probability_type * prob)
1545+{
1546+// register ipack_nodetype* tmp = model->tree_root_ptr;
1547+// register ipack_nodetype* tmp = root;
1548+ register TokenType token = 0;
1549+ while (TREENODETYPE_IS_NODE(tmp->type)) {
1550+ if (tmp->type == TREENODETYPE_NODE_BINARY_EQ) {
1551+ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_EQ tmp->data.nodeBin.value) {
1552+ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
1553+ }
1554+ else {
1555+ tmp = tmp->data.nodeBin.right_child_ptr;
1556+ }
1557+ }
1558+ else if (tmp->type == TREENODETYPE_NODE_BINARY_LT) {
1559+ if (*(tmp->data.nodeBin.attribute_ptr) TREE_SUBTREE_RELATION_LEFT_LT tmp->data.nodeBin.value) {
1560+ ((char *) tmp) += sizeof(tmp->type) + sizeof(ipack_treenodeBin);
1561+ }
1562+ else {
1563+ tmp = tmp->data.nodeBin.right_child_ptr;
1564+ }
1565+ }
1566+ }
1567+ prob->high = 0;
1568+ prob->low = 0;
1569+// prob->max = 0;
1570+ if (tmp->type == TREENODETYPE_LEAF_P) {
1571+ u32 i;
1572+ u32 norm;
1573+// prob->max = tmp->data.leafP.probabilities[15];
1574+/* norm = (value * prob->max -1)/range;
1575+ for(i = 0; i < 15; ++i) {
1576+ if(tmp->data.leafP.probabilities[i] > norm) {
1577+ break;
1578+ }
1579+ }*/
1580+ norm = ((value << PROBABILITY_SHIFT) - 1);
1581+ for (i = 0; i < NUMBER_OF_TOKENS; ++i) {
1582+ if (range * tmp->data.leafP.probabilities[i] > norm) {
1583+ break;
1584+ }
1585+ }
1586+ token = (TokenType) i;
1587+ prob->high = tmp->data.leafP.probabilities[i];
1588+ if (token) {
1589+ prob->low = tmp->data.leafP.probabilities[token - 1];
1590+ }
1591+ }
1592+ else if (tmp->type == TREENODETYPE_LEAF_C) {
1593+ token = tmp->data.leafC.predicted_class;
1594+ prob->high = PROBABILITY_MAX;
1595+// prob->max = PROBABILITY_MAX;
1596+ }
1597+ return token;
1598+}
1599+#endif
1600+/*
1601+void ipack_model_predictortable_reset(PredictorType* ptr)
1602+{
1603+// register PredictorType* ptr = model->predictors_ptr;
1604+// register PredictorType* ptr = preds;
1605+ register PredictorType* end = ptr + NUMBER_OF_PREDICTORS;
1606+ while(ptr < end) {
1607+ *(ptr++) = 0;
1608+ }
1609+}
1610+
1611+void ipack_model_predictortable_update(PredictorType* ptr, TokenType token)
1612+{
1613+// register PredictorType* ptr = model->predictors_ptr;
1614+// register PredictorType* ptr = preds;
1615+ register u32 ndx = ptr[0] + 1;
1616+ ptr[ndx + 8] = ptr[ndx];
1617+ ptr[ndx] = token;
1618+ if(ndx == 8) {
1619+ ptr[0] = 0;
1620+ } else {
1621+ ++ ptr[0];
1622+ }
1623+}*/
1624+/****************************************************************************/
1625+
1626+#ifndef __KERNEL__
1627+static void ipack_model_countpreds(void *ptr, ipack_nodetype * node, double *table, double val)
1628+{
1629+ if ((node->type == TREENODETYPE_NODE_BINARY_EQ) || (node->type == TREENODETYPE_NODE_BINARY_LT)) {
1630+ table[(u32) (node->data.nodeBin.attribute_ptr) - (u32) (ptr)] += val;
1631+ ipack_model_countpreds(ptr, (void *) (((u8 *) (node)) + sizeof(node->type) + sizeof(ipack_treenodeBin)), table, val / 2);
1632+ ipack_model_countpreds(ptr, node->data.nodeBin.right_child_ptr, table, val / 2);
1633+ }
1634+ else {
1635+ }
1636+}
1637+
1638+/*static void ipack_model_printinfo(ipack_model_type * model)
1639+{
1640+ double *prcnt = jffs2_bbc_malloc(sizeof(double) * NUMBER_OF_PREDICTORS);
1641+ u32 i;
1642+ for (i = 0; i < NUMBER_OF_PREDICTORS; i++) {
1643+ prcnt[i] = 0.0;
1644+ }
1645+ ipack_model_countpreds(model->predictors_ptr, model->tree_root_ptr, prcnt, 100);
1646+ for (i = 0; i < NUMBER_OF_PREDICTORS; i++) {
1647+ jffs2_bbc_print3(" p[%3d] = %10.6lf\n", (int) i, prcnt[i]);
1648+ }
1649+ jffs2_bbc_free(prcnt);
1650+}*/
1651+
1652+static void ipack_dumpnode(unsigned char **ptr, FILE * file, char *prefs)
1653+{
1654+ switch (*((*ptr)++)) {
1655+ u32 i;
1656+ u32 j;
1657+ u32 x;
1658+ u32 y;
1659+ case TREENODETYPE_NODE_BINARY_EQ:
1660+ x = *((*ptr)++);
1661+ y = *((*ptr)++);
1662+ fprintf(file, "%s+->\tBinary node: P[%u] equals %u\n", prefs, (unsigned int)x, (unsigned int)y);
1663+ for (j = 0; j < 4096 && prefs[j]; ++j);
1664+ prefs[j] = '\t';
1665+ prefs[++j] = '|';
1666+ ipack_dumpnode(ptr, file, prefs);
1667+ prefs[j--] = 0;
1668+ ipack_dumpnode(ptr, file, prefs);
1669+ prefs[j] = 0;
1670+ break;
1671+ case TREENODETYPE_NODE_BINARY_LT:
1672+ x = *((*ptr)++);
1673+ y = *((*ptr)++);
1674+ fprintf(file, "%s+->\tBinary node: P[%u] greater than %u\n", prefs, (unsigned int)x, (unsigned int)y);
1675+ for (j = 0; j < 4096 && prefs[j]; ++j);
1676+ prefs[j] = '\t';
1677+ prefs[++j] = '|';
1678+ ipack_dumpnode(ptr, file, prefs);
1679+ prefs[j--] = 0;
1680+ ipack_dumpnode(ptr, file, prefs);
1681+ prefs[j] = 0;
1682+ break;
1683+ case TREENODETYPE_LEAF_P:
1684+ x = *((*ptr)++);
1685+ fprintf(file, "%s+->\tLeaf: %u pairs\n", prefs, (unsigned int)x);
1686+ (*ptr) += (x << 1);
1687+ break;
1688+ case TREENODETYPE_LEAF_C:
1689+ x = *((*ptr)++);
1690+ fprintf(file, "%s+->\tLeaf: class %u\n", prefs, (unsigned int)x);
1691+ break;
1692+ default:
1693+ fprintf(file, "%s+->\tLeaf: nullnode\n", prefs);
1694+ }
1695+}
1696+
1697+/*static void ipack_dumpmodel(void *model)
1698+{
1699+ unsigned char *tmp_ptr = model;
1700+ FILE *file;
1701+ char C[4096];
1702+ if ((file = fopen("DUMPED_MODEL", "wa"))) {
1703+ int i;
1704+ for (i = 0; i < 4096; C[i++] = 0);
1705+ tmp_ptr += 8;
1706+ tmp_ptr += sizeof(u32);
1707+ ipack_dumpnode(&tmp_ptr, file, C);
1708+ fclose(file);
1709+ }
1710+}*/
1711+
1712+#endif
1713+
1714+//ORIGIN: Builders/src/PredictorGenerator.c
1715+
1716+/*******************************************************************************
1717+* FILE: PredictorGenerator.c
1718+* AUTHOR: Tamás Gergely
1719+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
1720+*******************************************************************************/
1721+
1722+//#include "ipack_common.h"
1723+//#include "Builders/PredictorGenerator.h"
1724+
1725+#ifdef JFFS2_BBC_ARMLIB_MODELGEN
1726+static PredictorTable *predictorgenerator_generate( /*PredictorGeneratorSettings* settings */ )
1727+{
1728+ PredictorTable *ptr = jffs2_bbc_malloc(sizeof(PredictorTable));
1729+ predictortable_clear(ptr);
1730+ ptr->predictors = jffs2_bbc_malloc(NUMBER_OF_PREDICTORS * sizeof(PredictorType));
1731+ return ptr;
1732+}
1733+#endif
1734+
1735+//ORIGIN: Builders/src/ipack_armlib_compressor.c
1736+
1737+/*******************************************************************************
1738+* FILE: ipack_armlim_compressor.c
1739+* AUTHOR: Tamás Gergely
1740+* MODIFIED: $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
1741+*******************************************************************************/
1742+
1743+//#include "ipack_common.h"
1744+//#include "DataStructures.h"
1745+//#include "Builders/PredictorGenerator.h"
1746+//#include "Builders/Tokenizer.h"
1747+//#include "Builders/Coder.h"
1748+
1749+#define EC_NO_ERROR 0
1750+#define EC_NOT_IPMF_FILE -1
1751+#define EC_NOT_IPMF_MODEL -2
1752+#define EC_NOT_HG_BLOCK -3
1753+#define EC_WRONG_INPUT_LENGTH -501
1754+#define EC_CODER_WRONG_PROBABILITY 1
1755+#define EC_CODER_WRONG_RANGE 2
1756+#define EC_BUFFER_OVERFLOW 501
1757+#define EC_BUFFER_UNDERFLOW 502
1758+#define EC_UNKNOWN_TOKEN_TYPE 1001
1759+#define EC_UNKNOWN_FILTER 1002
1760+#define EC_UNKNOWN_CONVERTER 1003
1761+#define EC_UNKNOWN_MANIPULATOR 1004
1762+
1763+/*******************************************************************************
1764+
1765+ COMPRESSOR INIT FUNCTIONS
1766+
1767+*******************************************************************************/
1768+
1769+#define ROUND_UP_TO_DWORD(val) ( ( (val) + 3 ) & 0xfffffffc )
1770+
1771+#ifndef __KERNEL__
1772+int ipack_glb_endian_X;
1773+#endif
1774+
1775+static int ipack_compressor_init_tree(unsigned char **ptr, ipack_model_type * model, ipack_nodetype * node, void *nullnode)
1776+{
1777+ int retval = 0;
1778+ node->type = *((*ptr)++);
1779+ switch (node->type) {
1780+ u32 i;
1781+ u32 j;
1782+ u32 lngth;
1783+ u32 tmpret;
1784+ TokenType at;
1785+ u16 av;
1786+ case TREENODETYPE_NODE_BINARY_EQ:
1787+ case TREENODETYPE_NODE_BINARY_LT:
1788+ node->data.nodeBin.attribute_ptr = (model->predictors_ptr) + (*((*ptr)++));
1789+ node->data.nodeBin.value = *((*ptr)++);
1790+ retval = sizeof(node->data.nodeBin);
1791+ retval += ipack_compressor_init_tree(ptr, model, (void *) ROUND_UP_TO_DWORD(((u32) node) + sizeof(node->type) + sizeof(node->data.nodeBin)), nullnode);
1792+ node->data.nodeBin.right_child_ptr = (void *) ROUND_UP_TO_DWORD(((u32) node) + retval + sizeof(node->type));
1793+ retval += ipack_compressor_init_tree(ptr, model, node->data.nodeBin.right_child_ptr, nullnode);
1794+ break;
1795+ case TREENODETYPE_LEAF_P:
1796+ lngth = *((*ptr)++);
1797+ av = 0;
1798+ for (i = 0, j = 0; i < lngth; ++i) {
1799+ at = *((*ptr)++);
1800+ while (j < at) {
1801+ node->data.leafP.probabilities[j++] = av;
1802+ }
1803+ av += *((*ptr)++);
1804+ }
1805+ while (j < NUMBER_OF_TOKENS) {
1806+ node->data.leafP.probabilities[j++] = av;
1807+ }
1808+ for (i = 0; i < NUMBER_OF_TOKENS; ++i) {
1809+ node->data.leafP.probabilities[i] = ((node->data.leafP.probabilities[i] << PROBABILITY_SHIFT) / node->data.leafP.probabilities[NUMBER_OF_TOKENS - 1]);
1810+ }
1811+ retval = ROUND_UP_TO_DWORD(NUMBER_OF_TOKENS * sizeof(u16));
1812+ break;
1813+ case TREENODETYPE_LEAF_C:
1814+ node->data.leafC.predicted_class = *((*ptr)++);
1815+ retval = sizeof(node->data.leafC);
1816+ retval = ROUND_UP_TO_DWORD(retval);
1817+ break;
1818+ default:
1819+ return 0;
1820+ }
1821+ return retval + sizeof(node->type);
1822+}
1823+
1824+#define IPACK_TREE_CONVERT_REPLACE 0
1825+#define IPACK_TREE_CONVERT_KEEP 1
1826+
1827+static void *ipack_tree_to_code(ipack_model_type * model, int *code_size);
1828+
1829+static int ipack_armlib_convert_tree_to_code(ipack_model_type * model_img, int mode)
1830+{
1831+#ifdef IPACK_TREE_TO_CODE
1832+ int tree_size;
1833+
1834+ model_img->tree_code = ipack_tree_to_code(model_img, &tree_size);
1835+ jffs2_bbc_print2("Convertation done. Code size=%d\n", tree_size);
1836+ if (mode == IPACK_TREE_CONVERT_REPLACE) {
1837+ jffs2_bbc_print1("Freeing original tree.\n");
1838+ jffs2_bbc_free(model_img->tree_root_ptr);
1839+ model_img->tree_root_ptr = NULL;
1840+ }
1841+#endif
1842+ return 0;
1843+}
1844+
1845+
1846+static int ipack_armlib_compressor_init(void **model)
1847+{
1848+ int retval = EC_NO_ERROR;
1849+ unsigned char *tmp_ptr = *model;
1850+ u32 i;
1851+ ipack_model_type *model_img;
1852+ char tmp_c[2];
1853+
1854+ if (*(tmp_ptr++) != 'i') {
1855+ return EC_NOT_IPMF_FILE;
1856+ }
1857+ else if (*(tmp_ptr++) != 'P') {
1858+ return EC_NOT_IPMF_FILE;
1859+ }
1860+ else if (*(tmp_ptr++) != 'M') {
1861+ return EC_NOT_IPMF_FILE;
1862+ }
1863+ else if (*(tmp_ptr++) != 'F') {
1864+ return EC_NOT_IPMF_FILE;
1865+ }
1866+ tmp_c[0] = *(tmp_ptr++);
1867+ tmp_c[1] = *(tmp_ptr++);
1868+ tmp_ptr += 2;
1869+
1870+ //model_img = jffs2_bbc_malloc(*((u32*)tmp_ptr));
1871+ model_img = jffs2_bbc_malloc(sizeof(ipack_model_type) + ROUND_UP_TO_DWORD(NUMBER_OF_PREDICTORS));
1872+ model_img->tree_root_ptr = jffs2_bbc_malloc(*((u32 *) tmp_ptr)); //it is smaller a little but, but...
1873+
1874+ tmp_ptr += sizeof(u32);
1875+
1876+ model_img->ID[0] = 'i';
1877+ model_img->ID[1] = 'P';
1878+ model_img->ID[2] = 'M';
1879+ model_img->ID[3] = 'F';
1880+
1881+ model_img->block_sign[0] = tmp_c[0];
1882+ model_img->block_sign[1] = tmp_c[1];
1883+
1884+ model_img->nullnode.type = TREENODETYPE_LEAF_P;
1885+ for (i = 0; i < NUMBER_OF_TOKENS; ++i) {
1886+ model_img->nullnode.probabilities[i] = 0;
1887+ }
1888+ model_img->predictors_ptr = (void *) (((u32) model_img) + sizeof(ipack_model_type));
1889+ //model_img->tree_root_ptr = (void*)ROUND_UP_TO_DWORD(((u32)(model_img->predictors_ptr)) + NUMBER_OF_PREDICTORS);//ALIGN
1890+
1891+ ipack_compressor_init_tree(&tmp_ptr, model_img, model_img->tree_root_ptr, &(model_img->nullnode));
1892+
1893+#ifdef IPACK_TREE_TO_CODE
1894+#ifdef IPACK_AUTO_TREE_TO_CODE
1895+ jffs2_bbc_print1("Automatically converting tree to ARM code...\n");
1896+ ipack_armlib_convert_tree_to_code(model_img, IPACK_TREE_CONVERT_REPLACE);
1897+#else
1898+ model_img->tree_code = NULL;
1899+#endif
1900+#else
1901+ model_img->tree_code = NULL;
1902+#endif
1903+
1904+ jffs2_bbc_free(*model);
1905+ *model = model_img;
1906+ return retval;
1907+}
1908+
1909+/*******************************************************************************
1910+
1911+ COMPRESSOR DEINIT FUNCTIONS
1912+
1913+*******************************************************************************/
1914+
1915+
1916+/* Descructor of compressor (model will be freed with jffs2_bbc_free() after it)*/
1917+static void ipack_armlib_compressor_deinit(void)
1918+{
1919+}
1920+
1921+/*******************************************************************************
1922+
1923+ COMPRESS FUNCTIONS
1924+
1925+*******************************************************************************/
1926+
1927+static int writebits0(unsigned char **dest, u8 * freebits, u32 * opposite, unsigned char *end)
1928+{
1929+ if (!(*freebits)) {
1930+ ++(*dest);
1931+ *freebits = 7;
1932+ **dest = 0x00;
1933+ }
1934+ else {
1935+ --(*freebits);
1936+ (**dest) <<= 1;
1937+ }
1938+ if ((*dest == end) && !(*freebits)) {
1939+ return EC_BUFFER_OVERFLOW;
1940+ }
1941+ while (*opposite) {
1942+ --(*opposite);
1943+ if (!(*freebits)) {
1944+ ++(*dest);
1945+ *freebits = 7;
1946+ **dest = 0x01;
1947+ }
1948+ else {
1949+ --(*freebits);
1950+ (**dest) <<= 1;
1951+ (**dest) |= 0x01;
1952+ }
1953+ if ((*dest == end) && !(*freebits)) {
1954+ return EC_BUFFER_OVERFLOW;
1955+ }
1956+ }
1957+ return 0;
1958+}
1959+
1960+static int writebits1(unsigned char **dest, u8 * freebits, u32 * opposite, unsigned char *end)
1961+{
1962+ if (!(*freebits)) {
1963+ ++(*dest);
1964+ *freebits = 7;
1965+ **dest = 0x01;
1966+ }
1967+ else {
1968+ --(*freebits);
1969+ (**dest) <<= 1;
1970+ (**dest) |= 0x01;
1971+ }
1972+ if ((*dest == end) && !(*freebits)) {
1973+ return EC_BUFFER_OVERFLOW;
1974+ }
1975+ while (*opposite) {
1976+ --(*opposite);
1977+ if (!(*freebits)) {
1978+ ++(*dest);
1979+ *freebits = 7;
1980+ **dest = 0x00;
1981+ }
1982+ else {
1983+ --(*freebits);
1984+ (**dest) <<= 1;
1985+ }
1986+ if ((*dest == end) && !(*freebits)) {
1987+ return EC_BUFFER_OVERFLOW;
1988+ }
1989+ }
1990+ return 0;
1991+}
1992+
1993+
1994+
1995+
1996+/* Compress block
1997+ * *dstlen bytes are allocated.
1998+ * if it is not enough write *sourcelen over to the processed amount of data
1999+ * returns non zero if fails
2000+ */
2001+static int ipack_armlib_compress(void *model, unsigned char *input, unsigned char *output, unsigned long *sourcelen, unsigned long *dstlen)
2002+{
2003+ register u32 coder_high = CODER_VALUEMAX - 1;
2004+ register u32 coder_low = 0;
2005+ u32 coder_opbits = 0;
2006+ u8 bitvector_freebits = 8;
2007+ unsigned char *bitvector_ptr = output;
2008+ unsigned char *bitvector_end = output + (*dstlen - 1);
2009+ ARM_DataType *tmpp;
2010+ TokenStream tmpv;
2011+ TokenType *it;
2012+ void *end_it;
2013+
2014+ ipack_nodetype *treeroot = ((ipack_model_type *) model)->tree_root_ptr;
2015+ PredictorType *predctrs = ((ipack_model_type *) model)->predictors_ptr;
2016+
2017+#ifdef IPACK_TREE_TO_CODE
2018+ void (*treefunc) (ipack_nodetype *, TokenType, ipack_probability_type *);
2019+
2020+ treefunc = ((ipack_model_type *) model)->tree_code;
2021+ if (treefunc != NULL)
2022+ treefunc += 4;
2023+#endif
2024+
2025+ if ((*sourcelen % 4) != 0) {
2026+ return EC_WRONG_INPUT_LENGTH;
2027+ }
2028+ if (*dstlen <= 4) {
2029+ return EC_BUFFER_OVERFLOW;
2030+ }
2031+
2032+ if (((ipack_model_type *) model)->ID[0] != 'i') {
2033+ return EC_NOT_IPMF_MODEL;
2034+ }
2035+ else if (((ipack_model_type *) model)->ID[1] != 'P') {
2036+ return EC_NOT_IPMF_MODEL;
2037+ }
2038+ else if (((ipack_model_type *) model)->ID[2] != 'M') {
2039+ return EC_NOT_IPMF_MODEL;
2040+ }
2041+ else if (((ipack_model_type *) model)->ID[3] != 'F') {
2042+ return EC_NOT_IPMF_MODEL;
2043+ }
2044+#ifdef TXT_TOKENS
2045+ tmpv.capacity = (*sourcelen);
2046+#else
2047+ tmpv.capacity = (*sourcelen) << 1;
2048+#endif
2049+ tmpv.size = tmpv.capacity;
2050+ tmpv.ptr = jffs2_bbc_malloc(tmpv.size);
2051+ it = tmpv.ptr;
2052+
2053+#ifndef __KERNEL__
2054+ if (ipack_glb_endian_X) {
2055+ for (tmpp = (void *) input; (u32) tmpp < (u32) (input + *sourcelen); ++tmpp) {
2056+#ifdef TXT_TOKENS
2057+ *(it++) = (u8) ((*tmpp & 0xff000000) >> 24);
2058+ *(it++) = (u8) ((*tmpp & 0x00ff0000) >> 16);
2059+ *(it++) = (u8) ((*tmpp & 0x0000ff00) >> 8);
2060+ *(it++) = (u8) ((*tmpp & 0x000000ff));
2061+#else
2062+ *(it++) = (u8) ((*tmpp & 0x0000f000) >> 12);
2063+ *(it++) = (u8) ((*tmpp & 0x0000000f));
2064+ *(it++) = (u8) ((*tmpp & 0xf0000000) >> 28);
2065+ *(it++) = (u8) ((*tmpp & 0x000f0000) >> 16);
2066+ *(it++) = (u8) ((*tmpp & 0x00000f00) >> 8);
2067+ *(it++) = (u8) ((*tmpp & 0x00f00000) >> 20);
2068+ *(it++) = (u8) ((*tmpp & 0x0f000000) >> 24);
2069+ *(it++) = (u8) ((*tmpp & 0x000000f0) >> 4);
2070+#endif //TXT_TOKENS
2071+ }
2072+ }
2073+ else {
2074+#endif
2075+ for (tmpp = (void *) input; (u32) tmpp < (u32) (input + *sourcelen); ++tmpp) {
2076+#ifdef TXT_TOKENS
2077+ *(it++) = (u8) ((*tmpp & 0x000000ff));
2078+ *(it++) = (u8) ((*tmpp & 0x0000ff00) >> 8);
2079+ *(it++) = (u8) ((*tmpp & 0x00ff0000) >> 16);
2080+ *(it++) = (u8) ((*tmpp & 0xff000000) >> 24);
2081+#else
2082+ *(it++) = (u8) ((*tmpp & 0x00f00000) >> 20);
2083+ *(it++) = (u8) ((*tmpp & 0x0f000000) >> 24);
2084+ *(it++) = (u8) ((*tmpp & 0x000000f0) >> 4);
2085+ *(it++) = (u8) ((*tmpp & 0x00000f00) >> 8);
2086+ *(it++) = (u8) ((*tmpp & 0x000f0000) >> 16);
2087+ *(it++) = (u8) ((*tmpp & 0x0000f000) >> 12);
2088+ *(it++) = (u8) ((*tmpp & 0x0000000f));
2089+ *(it++) = (u8) ((*tmpp & 0xf0000000) >> 28);
2090+#endif //TXT_TOKENS
2091+ }
2092+#ifndef __KERNEL__
2093+ }
2094+#endif
2095+/*
2096+ ENCODE
2097+*/
2098+ { //predictor reset
2099+ register PredictorType *ptr = predctrs;
2100+ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS;
2101+ while (ptr < end) {
2102+ *(ptr++) = 0;
2103+ }
2104+ }
2105+
2106+ //*(bitvector_ptr++) = 'H';
2107+ //*(bitvector_ptr++) = 'G';
2108+ *(bitvector_ptr++) = ((ipack_model_type *) model)->block_sign[0];
2109+ *(bitvector_ptr++) = ((ipack_model_type *) model)->block_sign[1];
2110+
2111+ *(bitvector_ptr++) = (unsigned char) (((*sourcelen) >> 8) & 0xff);
2112+ *(bitvector_ptr++) = (unsigned char) ((*sourcelen) & 0xff);
2113+ for (it = tmpv.ptr, end_it = VECTOR_S_END(tmpv); it != end_it; ++it) {
2114+ ipack_probability_type prob;
2115+ u32 range;
2116+
2117+#ifdef IPACK_TREE_TO_CODE
2118+ if (treefunc != NULL)
2119+ (*treefunc) (treeroot, *it, &prob);
2120+ else
2121+ ipack_model_get_probability_for_token(treeroot, *it, &prob);
2122+#else
2123+ ipack_model_get_probability_for_token(treeroot, *it, &prob);
2124+#endif
2125+
2126+ if (prob.high == prob.low) {
2127+ vector_clear(&tmpv);
2128+ return EC_CODER_WRONG_PROBABILITY;
2129+ }
2130+ range = coder_high - coder_low + 1;
2131+ coder_high = coder_low + ((range * prob.high) >> PROBABILITY_SHIFT) - 1;
2132+ coder_low += ((range * prob.low) >> PROBABILITY_SHIFT);
2133+ for (;;) {
2134+ if (coder_high < CODER_VALUEHLF) {
2135+ if (writebits0(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
2136+ vector_clear(&tmpv);
2137+ return EC_BUFFER_OVERFLOW;
2138+ }
2139+ }
2140+ else if (coder_low >= CODER_VALUEHLF) {
2141+ if (writebits1(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
2142+ vector_clear(&tmpv);
2143+ return EC_BUFFER_OVERFLOW;
2144+ }
2145+ coder_high -= CODER_VALUEHLF;
2146+ coder_low -= CODER_VALUEHLF;
2147+ }
2148+ else if ((CODER_VALUE1ST <= coder_low) && (coder_high < CODER_VALUE3RD)) {
2149+ ++coder_opbits;
2150+ coder_high -= CODER_VALUE1ST;
2151+ coder_low -= CODER_VALUE1ST;
2152+ }
2153+ else {
2154+ break;
2155+ }
2156+ coder_high <<= 1;
2157+ ++coder_high;
2158+ coder_low <<= 1;
2159+ if (coder_high < coder_low) {
2160+ vector_clear(&tmpv);
2161+ return EC_CODER_WRONG_RANGE;
2162+ }
2163+ }
2164+ {
2165+#ifdef TXT_TOKENS
2166+// register u32 ndx;
2167+ predctrs[0] = *it;
2168+ if ((('a' <= *it) && (*it <= 'z')) || (('A' <= *it) && (*it <= 'Z'))) {
2169+ ++(predctrs[1]);
2170+ }
2171+ else {
2172+ predctrs[1] = 0;
2173+ }
2174+#else
2175+ register u32 ndx = predctrs[0] + 1;
2176+ predctrs[ndx + 8] = predctrs[ndx];
2177+ predctrs[ndx] = *it;
2178+ if (ndx == 8) {
2179+ predctrs[0] = 0;
2180+ }
2181+ else {
2182+ ++predctrs[0];
2183+ }
2184+#endif
2185+ }
2186+
2187+ }
2188+ vector_clear(&tmpv);
2189+ ++coder_opbits;
2190+ if (coder_low < CODER_VALUE1ST) {
2191+ if (writebits0(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
2192+ return EC_BUFFER_OVERFLOW;
2193+ }
2194+ }
2195+ else {
2196+ if (writebits1(&bitvector_ptr, &bitvector_freebits, &coder_opbits, bitvector_end)) {
2197+ return EC_BUFFER_OVERFLOW;
2198+ }
2199+ }
2200+ (*(bitvector_ptr)) <<= bitvector_freebits;
2201+ *dstlen = ((u32) bitvector_ptr - (u32) output + 1);
2202+ return EC_NO_ERROR;
2203+}
2204+
2205+/*******************************************************************************
2206+
2207+ DECOMPRESS FUNCTIONS
2208+
2209+*******************************************************************************/
2210+
2211+typedef struct
2212+{
2213+ u32 high;
2214+ u32 low;
2215+ u32 value;
2216+ u32 overread;
2217+} ipack_decompressor_values;
2218+
2219+typedef struct
2220+{
2221+ u8 freebits;
2222+ unsigned char *ptr;
2223+ unsigned char *end;
2224+} ipack_decompressor_bitvector;
2225+
2226+static u8 ipack_bitvector_R_get1(ipack_decompressor_bitvector * bv)
2227+{
2228+ u8 tmp;
2229+ if (bv->ptr == bv->end) {
2230+ bv->freebits = 0;
2231+ return 0;
2232+ }
2233+ tmp = (*(bv->ptr) >> bv->freebits) & 0x01;
2234+ if (!(bv->freebits)) {
2235+ bv->freebits = 7;
2236+ ++(bv->ptr);
2237+ }
2238+ else {
2239+ --(bv->freebits);
2240+ }
2241+ return tmp;
2242+}
2243+
2244+/* Decompress block
2245+ * returns non zero if fails
2246+ */
2247+static int ipack_armlib_decompress(void *model, unsigned char *input, unsigned char *output, unsigned long sourcelen, unsigned long dstlen)
2248+{
2249+ ARM_DataType *data;
2250+ register u32 coder_high = CODER_VALUEMAX - 1;
2251+ register u32 coder_low = 0;
2252+ register u32 coder_value = 0;
2253+ u32 coder_overread = 0;
2254+ ipack_decompressor_bitvector bitvector;
2255+ u32 lngth;
2256+ u32 i;
2257+ u32 cntbytes;
2258+ TokenType tkns[8];
2259+ TokenType *tptr;
2260+
2261+ ipack_nodetype *treeroot = ((ipack_model_type *) model)->tree_root_ptr;
2262+ PredictorType *predctrs = ((ipack_model_type *) model)->predictors_ptr;
2263+
2264+#ifdef IPACK_TREE_TO_CODE
2265+ TokenType(*treefunc) (ipack_nodetype *, u32, u32, ipack_probability_type *);
2266+
2267+ treefunc = ((ipack_model_type *) model)->tree_code;
2268+#endif
2269+
2270+
2271+ if (((ipack_model_type *) model)->ID[0] != 'i') {
2272+ return EC_NOT_IPMF_MODEL;
2273+ }
2274+ else if (((ipack_model_type *) model)->ID[1] != 'P') {
2275+ return EC_NOT_IPMF_MODEL;
2276+ }
2277+ else if (((ipack_model_type *) model)->ID[2] != 'M') {
2278+ return EC_NOT_IPMF_MODEL;
2279+ }
2280+ else if (((ipack_model_type *) model)->ID[3] != 'F') {
2281+ return EC_NOT_IPMF_MODEL;
2282+ }
2283+
2284+ bitvector.freebits = 7;
2285+ bitvector.ptr = input;
2286+ bitvector.end = input + sourcelen;
2287+
2288+ /*if(*(bitvector.ptr++) != 'H') {
2289+ return EC_NOT_HG_BLOCK;
2290+ } else if(*(bitvector.ptr++) != 'G') {
2291+ return EC_NOT_HG_BLOCK;
2292+ } */
2293+ bitvector.ptr++;
2294+ bitvector.ptr++;
2295+
2296+ data = (void *) output;
2297+ cntbytes = *(bitvector.ptr++);
2298+ cntbytes <<= 8;
2299+ cntbytes += *(bitvector.ptr++);
2300+
2301+ { //predictor reset
2302+ register PredictorType *ptr = predctrs;
2303+ register PredictorType *end = ptr + NUMBER_OF_PREDICTORS;
2304+ while (ptr < end) {
2305+ *(ptr++) = 0;
2306+ }
2307+ }
2308+ for (i = 0; i < CODER_VALUEBITS; ++i) {
2309+ coder_value <<= 1;
2310+ coder_value += ipack_bitvector_R_get1(&bitvector);
2311+ }
2312+ lngth = dstlen >> 2;
2313+ if (lngth > (cntbytes >> 2)) {
2314+ lngth = cntbytes >> 2;
2315+ }
2316+ for (i = 0; (i < lngth); ++i) {
2317+ TokenType itoken;
2318+ u32 j;
2319+ tptr = tkns;
2320+ for (j = 0; j < NUMBER_OF_TOKENS_PER_INSTRUCTION; ++j) {
2321+ ipack_probability_type prob;
2322+ u32 range = coder_high - coder_low + 1;
2323+
2324+#ifdef IPACK_TREE_TO_CODE
2325+ if (treefunc != NULL)
2326+ itoken = (*treefunc) (treeroot, coder_value - coder_low + 1, range, &prob);
2327+ else
2328+#endif
2329+ itoken = ipack_model_get_token_for_range(treeroot, coder_value - coder_low + 1, range, &prob);
2330+
2331+
2332+ if (prob.high == prob.low) {
2333+ return EC_CODER_WRONG_PROBABILITY;
2334+ }
2335+ coder_high = coder_low + ((range * prob.high) >> PROBABILITY_SHIFT) - 1;
2336+ coder_low += ((range * prob.low) >> PROBABILITY_SHIFT);
2337+ for (;;) {
2338+ if (coder_high < CODER_VALUEHLF) {
2339+ }
2340+ else if (CODER_VALUEHLF <= coder_low) {
2341+ coder_value -= CODER_VALUEHLF;
2342+ coder_high -= CODER_VALUEHLF;
2343+ coder_low -= CODER_VALUEHLF;
2344+ }
2345+ else if ((CODER_VALUE1ST <= coder_low) && (coder_high < CODER_VALUE3RD)) {
2346+ coder_value -= CODER_VALUE1ST;
2347+ coder_high -= CODER_VALUE1ST;
2348+ coder_low -= CODER_VALUE1ST;
2349+ }
2350+ else {
2351+ break;
2352+ }
2353+ coder_low <<= 1;
2354+ coder_high <<= 1;
2355+ ++(coder_high);
2356+ coder_value <<= 1;
2357+ if (bitvector.ptr == bitvector.end) {
2358+ bitvector.freebits = 0;
2359+ }
2360+ coder_value += ((*(bitvector.ptr) >> bitvector.freebits) & 0x01);
2361+ if (bitvector.freebits) {
2362+ --bitvector.freebits;
2363+ }
2364+ else {
2365+ bitvector.freebits = 7;
2366+ ++bitvector.ptr;
2367+ }
2368+ if (coder_high < coder_low) {
2369+ return EC_CODER_WRONG_RANGE;
2370+ }
2371+ if ((bitvector.ptr == bitvector.end) && !(bitvector.freebits)) {
2372+ if ((coder_overread++) > CODER_VALUEBITS) {
2373+ return EC_BUFFER_UNDERFLOW;
2374+ }
2375+ }
2376+ }
2377+ {
2378+#ifdef TXT_TOKENS
2379+// register u32 ndx;
2380+ predctrs[0] = itoken;
2381+ if ((('a' <= itoken) && (itoken <= 'z')) || (('A' <= itoken) && (itoken <= 'Z'))) {
2382+ ++(predctrs[1]);
2383+ }
2384+ else {
2385+ predctrs[1] = 0;
2386+ }
2387+
2388+#else
2389+ register u32 ndx = predctrs[0] + 1;
2390+ predctrs[ndx + 8] = predctrs[ndx];
2391+ predctrs[ndx] = itoken;
2392+ if (ndx == 8) {
2393+ predctrs[0] = 0;
2394+ }
2395+ else {
2396+ ++predctrs[0];
2397+ }
2398+#endif
2399+ }
2400+
2401+ (*(tptr++)) = itoken;
2402+ }
2403+ tptr = tkns;
2404+#ifndef __KERNEL__
2405+ if (ipack_glb_endian_X) {
2406+#ifdef TXT_TOKENS
2407+ (*data) = ((*tptr) << 24);
2408+ ++tptr;
2409+ (*data) |= ((*tptr) << 16);
2410+ ++tptr;
2411+ (*data) |= ((*tptr) << 8);
2412+ ++tptr;
2413+ (*data) |= (*tptr);
2414+ ++data;
2415+#else
2416+ (*data) = (((*tptr) & 0xf) << 12);
2417+ ++tptr;
2418+ (*data) |= ((*tptr) & 0xf);
2419+ ++tptr;
2420+ (*data) |= (((*tptr) & 0xf) << 28);
2421+ ++tptr;
2422+ (*data) |= (((*tptr) & 0xf) << 16);
2423+ ++tptr;
2424+ (*data) |= (((*tptr) & 0xf) << 8);
2425+ ++tptr;
2426+ (*data) |= (((*tptr) & 0xf) << 20);
2427+ ++tptr;
2428+ (*data) |= (((*tptr) & 0xf) << 24);
2429+ ++tptr;
2430+ (*data) |= (((*tptr) & 0xf) << 4);
2431+ ++data;
2432+#endif
2433+ }
2434+ else {
2435+#endif
2436+#ifdef TXT_TOKENS
2437+ (*data) = (*tptr);
2438+ ++tptr;
2439+ (*data) |= ((*tptr) << 8);
2440+ ++tptr;
2441+ (*data) |= ((*tptr) << 16);
2442+ ++tptr;
2443+ (*data) |= ((*tptr) << 24);
2444+ ++data;
2445+#else
2446+ (*data) = (((*tptr) & 0xf) << 20);
2447+ ++tptr;
2448+ (*data) |= (((*tptr) & 0xf) << 24);
2449+ ++tptr;
2450+ (*data) |= (((*tptr) & 0xf) << 4);
2451+ ++tptr;
2452+ (*data) |= (((*tptr) & 0xf) << 8);
2453+ ++tptr;
2454+ (*data) |= (((*tptr) & 0xf) << 16);
2455+ ++tptr;
2456+ (*data) |= (((*tptr) & 0xf) << 12);
2457+ ++tptr;
2458+ (*data) |= ((*tptr) & 0xf);
2459+ ++tptr;
2460+ (*data) |= (((*tptr) & 0xf) << 28);
2461+ ++data;
2462+#endif
2463+#ifndef __KERNEL__
2464+ }
2465+#endif
2466+ }
2467+ return EC_NO_ERROR;
2468+}
2469+
2470+static int ipack_armlib_estimate(void *model, unsigned char *input, unsigned long sourcelen, unsigned long *dstlen, unsigned long *readtime, unsigned long *writetime)
2471+{
2472+ int i, tmp, tmp2, max, maxi;
2473+ int cnt_cond[] = { 0, 0, 0, 0 };
2474+ int cnt_inst[] = { 0, 0, 0, 0 };
2475+
2476+ // TODO: make a more precise estimation!!!
2477+ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 6;
2478+ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 2;
2479+
2480+ if (sourcelen % 4 != 0) {
2481+ *dstlen = sourcelen;
2482+ return 0;
2483+ }
2484+ for (i = 0; i < sourcelen; i++, input++) {
2485+ tmp2 = tmp = *input;
2486+ tmp = ((tmp) & 0xf0) >> 4;
2487+ tmp2 = tmp2 & 0xf;
2488+ if (tmp == 14)
2489+ cnt_cond[i % 4]++;
2490+ if ((tmp2 == 2) || (tmp2 == 3))
2491+ cnt_inst[i % 4]++;
2492+ }
2493+ maxi = -1;
2494+ max = -1;
2495+ for (i = 0; i < 4; i++)
2496+ if (max < cnt_cond[i]) {
2497+ max = cnt_cond[i];
2498+ maxi = i;
2499+ }
2500+ /*jffs2_bbc_print("armlib_EST: %d/%d : %d/%d %d/%d %d/%d %d/%d",
2501+ cnt_cond[maxi],cnt_inst[maxi],
2502+ cnt_cond[0],cnt_inst[0],
2503+ cnt_cond[1],cnt_inst[1],
2504+ cnt_cond[2],cnt_inst[2],
2505+ cnt_cond[3],cnt_inst[3]); */
2506+
2507+ if (cnt_cond[maxi] < (sourcelen >> 4)) {
2508+ *dstlen = sourcelen;
2509+ }
2510+ else {
2511+ *dstlen = sourcelen / 3;
2512+ }
2513+
2514+ return 0;
2515+}
2516+
2517+static char *ipack_armlib_proc_info(void);
2518+static int ipack_armlib_proc_command(char *command);
2519+static void ipack_armlib_destroy_model(void **model);
2520+
2521+struct jffs2_bbc_compressor_type jffs2_bbc_armlib = {
2522+ "armlib",
2523+ 0x464d5069,
2524+ {0, 0, 0, 0},
2525+ NULL, // init
2526+ ipack_armlib_compressor_init, // init_model
2527+ ipack_armlib_destroy_model, // destroy_model
2528+ ipack_armlib_compressor_deinit, // deinit
2529+ ipack_armlib_compress,
2530+ ipack_armlib_estimate,
2531+ ipack_armlib_decompress,
2532+ ipack_armlib_proc_info,
2533+ ipack_armlib_proc_command
2534+};
2535+
2536+
2537+static char *ipack_armlib_proc_info()
2538+{
2539+#ifdef IPACK_TREE_TO_CODE
2540+#ifdef IPACK_AUTO_TREE_TO_CODE
2541+ return "automatic tree to code conversion";
2542+#else
2543+ return "manual tree to code conversion possibility";
2544+#endif
2545+#else
2546+ return "tree in memory version";
2547+#endif
2548+}
2549+
2550+static int ipack_armlib_proc_command(char *command)
2551+{
2552+ struct jffs2_bbc_model_list_node *model;
2553+ ipack_model_type *armlib_model;
2554+
2555+ if ((*command == 'g') || (*command == 'G')) {
2556+ jffs2_bbc_print1("Converting tree(s) to ARM code... (keeping original)\n");
2557+ model = jffs2_bbc_armlib.models;
2558+ if (model == NULL)
2559+ jffs2_bbc_print1("no model found!\n");
2560+ while (model != NULL) {
2561+ armlib_model = model->model;
2562+ if (armlib_model == NULL) {
2563+ jffs2_bbc_print1("Error: NULL model!\n");
2564+ }
2565+ else {
2566+ ipack_armlib_convert_tree_to_code(armlib_model, IPACK_TREE_CONVERT_KEEP);
2567+ }
2568+ model = model->next_compr_model;
2569+ }
2570+ }
2571+ else if ((*command == 'r') || (*command == 'R')) {
2572+ jffs2_bbc_print1("Converting tree(s) to ARM code... (deleting original)\n");
2573+ model = jffs2_bbc_armlib.models;
2574+ if (model == NULL)
2575+ jffs2_bbc_print1("no model found!\n");
2576+ while (model != NULL) {
2577+ armlib_model = model->model;
2578+ if (armlib_model == NULL) {
2579+ jffs2_bbc_print1("Error: NULL model!\n");
2580+ }
2581+ else {
2582+ //armlib_model->tree_code = ipack_tree_to_code(armlib_model, &tree_size);
2583+ //jffs2_bbc_print("Convertation done. Code size=%d\n",tree_size);
2584+ ipack_armlib_convert_tree_to_code(armlib_model, IPACK_TREE_CONVERT_REPLACE);
2585+ }
2586+ model = model->next_compr_model;
2587+ }
2588+ }
2589+ else if ((*command == 'c') || (*command == 'C')) {
2590+ jffs2_bbc_print1("Deleting ARM representation of the tree(s)...\n");
2591+ model = jffs2_bbc_armlib.models;
2592+ if (model == NULL)
2593+ jffs2_bbc_print1("no model found!\n");
2594+ while (model != NULL) {
2595+ armlib_model = model->model;
2596+ if (armlib_model == NULL) {
2597+ jffs2_bbc_print1("Error: NULL model!\n");
2598+ }
2599+ else {
2600+ if (armlib_model->tree_code == NULL) {
2601+ jffs2_bbc_print1("already deleted.\n");
2602+ }
2603+ else {
2604+ if (armlib_model->tree_root_ptr == NULL) {
2605+ jffs2_bbc_print1("cannot delete this ARM tree - original tree has deleted\n");
2606+ }
2607+ else {
2608+ jffs2_bbc_print1("deleting...");
2609+ jffs2_bbc_free(armlib_model->tree_code);
2610+ armlib_model->tree_code = NULL;
2611+ jffs2_bbc_print1("done.\n");
2612+ }
2613+ }
2614+ }
2615+ model = model->next_compr_model;
2616+ }
2617+ }
2618+ else if (*command == '?') {
2619+ jffs2_bbc_print1("ARMLIB commands:\n");
2620+ jffs2_bbc_print1(" g: convert TREEs to ARM code and keep the original\n");
2621+ jffs2_bbc_print1(" r: convert TREEs to ARM code and remove the original\n");
2622+ jffs2_bbc_print1(" c: delete the original TREEs - if there is any\n");
2623+ }
2624+ else {
2625+ jffs2_bbc_print1("Unknown command.\n");
2626+ }
2627+ return 0;
2628+}
2629+
2630+static void ipack_armlib_destroy_model(void **model)
2631+{
2632+ ipack_model_type *model_img;
2633+
2634+ model_img = *model;
2635+ if (model_img == NULL) {
2636+ jffs2_bbc_print1("jffs2.bbc: armlib: NULL model at destoying model!\n");
2637+ return;
2638+ }
2639+ if (model_img->tree_code != NULL) {
2640+ //jffs2_bbc_print1("jffs2.bbc: armlib: debug: freeing code...\n");
2641+ jffs2_bbc_free(model_img->tree_code);
2642+ model_img->tree_code = NULL;
2643+ }
2644+ if (model_img->tree_root_ptr != NULL) {
2645+ //jffs2_bbc_print1("jffs2.bbc: armlib: debug: freeing tree...\n");
2646+ jffs2_bbc_free(model_img->tree_root_ptr);
2647+ model_img->tree_root_ptr = NULL;
2648+ }
2649+
2650+ jffs2_bbc_free(model_img);
2651+ *model = NULL;
2652+}
2653+
2654+struct jffs2_bbc_compressor_type *jffs2_bbc_armlib_init(int mode)
2655+{
2656+ if (jffs2_bbc_register_compressor(&jffs2_bbc_armlib) == 0)
2657+ return &jffs2_bbc_armlib;
2658+ else
2659+ return NULL;
2660+}
2661+
2662+void jffs2_bbc_armlib_deinit(void)
2663+{
2664+ jffs2_bbc_unregister_compressor(&jffs2_bbc_armlib);
2665+}
2666+
2667+/*END OF ARMLIB*/
2668--- /dev/null
2669+++ b/fs/jffs2/jffs2_bbc_framework.c
2670@@ -0,0 +1,1324 @@
2671+/*
2672+ * JFFS2-BBC: Compression Framework
2673+ *
2674+ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
2675+ *
2676+ * Copyright (C) 2004, Ferenc Havasi
2677+ *
2678+ * This program is free software; you can redistribute it and/or
2679+ * modify it under the terms of the GNU General Public License
2680+ * as published by the Free Software Foundation; either version 2
2681+ * of the License, or (at your option) any later version.
2682+ *
2683+ * This program is distributed in the hope that it will be useful,
2684+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
2685+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
2686+ * GNU General Public License for more details.
2687+ *
2688+ * You should have received a copy of the GNU General Public License
2689+ * along with this program; if not, write to the Free Software
2690+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
2691+ *
2692+ */
2693+
2694+/* USE JFFS2_BBC_STANDALONE define if you don't want to compile without JFFS2 */
2695+
2696+//#define DEBUG_COMPRESSORS
2697+//#define DEBUG_SHOW_BLOCK_SIZES
2698+
2699+#define JFFS2_BBC_STAT_BUFF_SIZE 8000
2700+
2701+#ifndef __KERNEL__
2702+
2703+#include <stdio.h>
2704+#include <malloc.h>
2705+typedef unsigned long uint32_t;
2706+
2707+#else
2708+
2709+#include <linux/kernel.h>
2710+#include <linux/slab.h>
2711+#include <linux/vmalloc.h>
2712+
2713+#endif
2714+
2715+#define JFFS2_BBC_ZLIB_BLOCK_SIGN_0 (120)
2716+#define JFFS2_BBC_ZLIB_BLOCK_SIGN_1 (94)
2717+
2718+#define JFFS2_BBC_DUMMY_BLOCKSIGN_0 (0x54)
2719+#define JFFS2_BBC_DUMMY_BLOCKSIGN_1 (0x01)
2720+
2721+#ifndef NULL
2722+#define NULL ((void*)(0))
2723+#endif
2724+
2725+#include "jffs2_bbc_framework.h"
2726+
2727+/*********************************************************************
2728+ * Global data *
2729+ *********************************************************************/
2730+
2731+static int jffs2_bbc_compression_mode = JFFS2_BBC_ZLIB_MODE;
2732+static struct jffs2_bbc_compressor_type *jffs2_bbc_manual_compressor = NULL;
2733+static struct jffs2_bbc_compressor_type *jffs2_bbc_compressors = NULL;
2734+static struct jffs2_bbc_model_list_node *jffs2_bbc_model_list = NULL;
2735+static void *last_sb = NULL; /* previously activated sb */
2736+
2737+/*********************************************************************
2738+ * Compressor initialization *
2739+ *********************************************************************/
2740+
2741+#ifndef JFFS2_BBC_STANDALONE
2742+
2743+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_ARMLIB)
2744+struct jffs2_bbc_compressor_type *jffs2_bbc_armlib_init(void);
2745+void jffs2_bbc_armlib_deinit(void);
2746+#endif
2747+
2748+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZO)
2749+struct jffs2_bbc_compressor_type *jffs2_bbc_lzo_init(void);
2750+void jffs2_bbc_lzo_deinit(void);
2751+#endif
2752+
2753+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZSS)
2754+struct jffs2_bbc_compressor_type *jffs2_bbc_lzss_init(void);
2755+void jffs2_bbc_lzss_deinit(void);
2756+#endif
2757+
2758+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZARI)
2759+struct jffs2_bbc_compressor_type *jffs2_bbc_lzari_init(void);
2760+void jffs2_bbc_lzari_deinit(void);
2761+#endif
2762+
2763+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZHD)
2764+struct jffs2_bbc_compressor_type *jffs2_bbc_lzhd_init(void);
2765+void jffs2_bbc_lzhd_deinit(void);
2766+#endif
2767+
2768+void jffs2_bbc_compressor_init()
2769+{
2770+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_ARMLIB)
2771+ jffs2_bbc_armlib_init();
2772+#endif
2773+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZO)
2774+ jffs2_bbc_lzo_init();
2775+#endif
2776+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZSS)
2777+ jffs2_bbc_lzss_init();
2778+#endif
2779+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZARI)
2780+ jffs2_bbc_lzari_init();
2781+#endif
2782+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZHD)
2783+ jffs2_bbc_lzhd_init();
2784+#endif
2785+}
2786+
2787+void jffs2_bbc_compressor_deinit()
2788+{
2789+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZHD)
2790+ jffs2_bbc_lzhd_deinit();
2791+#endif
2792+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZARI)
2793+ jffs2_bbc_lzari_deinit();
2794+#endif
2795+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZSS)
2796+ jffs2_bbc_lzss_deinit();
2797+#endif
2798+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_LZO)
2799+ jffs2_bbc_lzo_deinit();
2800+#endif
2801+#if !defined(__KERNEL__) || defined(CONFIG_JFFS2_BBC_ARMLIB)
2802+ jffs2_bbc_armlib_deinit();
2803+#endif
2804+}
2805+
2806+#endif
2807+
2808+#ifndef JFFS2_BBC_STANDALONE
2809+
2810+/*********************************************************************
2811+ * ZLIB COMPRESSOR *
2812+ *********************************************************************/
2813+
2814+extern int jffs2_zlib_compress2(unsigned char *data_in, unsigned char *cpage_out, uint32_t * sourcelen, uint32_t * dstlen);
2815+extern void jffs2_zlib_decompress2(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen);
2816+
2817+static int jffs2_bbc_zlib_compress(void *model, unsigned char *input, unsigned char *output, unsigned long *sourcelen, unsigned long *dstlen)
2818+{
2819+ return jffs2_zlib_compress2(input, output, sourcelen, dstlen);
2820+}
2821+
2822+static int jffs2_bbc_zlib_decompress(void *model, unsigned char *input, unsigned char *output, unsigned long sourcelen, unsigned long dstlen)
2823+{
2824+ jffs2_zlib_decompress2(input, output, sourcelen, dstlen);
2825+ return 0;
2826+}
2827+
2828+static int jffs2_bbc_zlib_estimate(void *model, unsigned char *input, unsigned long sourcelen, unsigned long *dstlen, unsigned long *readtime, unsigned long *writetime)
2829+{
2830+ *dstlen = sourcelen * 65 / 100;
2831+ *readtime = JFFS2_BBC_ZLIB_READ_TIME;
2832+ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME;
2833+ return 0;
2834+}
2835+
2836+static struct jffs2_bbc_compressor_type jffs2_bbc_zlib = {
2837+ "zlib",
2838+ 0,
2839+ {JFFS2_BBC_ZLIB_BLOCK_SIGN_0, JFFS2_BBC_ZLIB_BLOCK_SIGN_1, 0, 0},
2840+ NULL,
2841+ NULL,
2842+ NULL,
2843+ NULL,
2844+ jffs2_bbc_zlib_compress,
2845+ jffs2_bbc_zlib_estimate,
2846+ jffs2_bbc_zlib_decompress,
2847+ NULL,
2848+ NULL,
2849+ 1
2850+};
2851+
2852+static struct jffs2_bbc_compressor_type *jffs2_bbc_original_compressor = &jffs2_bbc_zlib;
2853+
2854+#endif
2855+
2856+/*********************************************************************
2857+ * Compression mode handling *
2858+ *********************************************************************/
2859+
2860+int jffs2_bbc_get_compression_mode(void)
2861+{
2862+ return jffs2_bbc_compression_mode;
2863+}
2864+
2865+void jffs2_bbc_set_compression_mode(int mode)
2866+{
2867+ jffs2_bbc_compression_mode = mode;
2868+}
2869+
2870+void jffs2_bbc_set_manual_compressor(struct jffs2_bbc_compressor_type *c)
2871+{
2872+ jffs2_bbc_manual_compressor = c;
2873+ jffs2_bbc_set_compression_mode(JFFS2_BBC_MANUAL_MODE);
2874+}
2875+
2876+int jffs2_bbc_set_manual_compressor_by_name(char *name)
2877+{
2878+ struct jffs2_bbc_compressor_type *l;
2879+ int i;
2880+
2881+ l = jffs2_bbc_compressors;
2882+ while (l != NULL) {
2883+ for (i = 0; i < 1000; i++) {
2884+ if (l->name[i] == 0) {
2885+ jffs2_bbc_set_manual_compressor(l);
2886+ return 0;
2887+ }
2888+ else if (name[i] == 0)
2889+ i = 1000;
2890+ else if (name[i] != l->name[i])
2891+ i = 1000;
2892+ }
2893+ l = l->next;
2894+ }
2895+ jffs2_bbc_set_manual_compressor(NULL);
2896+ return 1;
2897+}
2898+
2899+static struct jffs2_bbc_compressor_type *jffs2_bbc_get_compressor_by_name(char *name)
2900+{
2901+ struct jffs2_bbc_compressor_type *l;
2902+ int i;
2903+
2904+#ifndef JFFS2_BBC_STANDALONE
2905+ l = jffs2_bbc_original_compressor;
2906+ for (i = 0; i < 1000; i++) {
2907+ if (l->name[i] == 0) {
2908+ return l;
2909+ }
2910+ else if (name[i] == 0)
2911+ i = 1000;
2912+ else if (name[i] != l->name[i])
2913+ i = 1000;
2914+ }
2915+#endif
2916+
2917+ l = jffs2_bbc_compressors;
2918+ while (l != NULL) {
2919+ for (i = 0; i < 1000; i++) {
2920+ if (l->name[i] == 0) {
2921+ return l;
2922+ }
2923+ else if (name[i] == 0)
2924+ i = 1000;
2925+ else if (name[i] != l->name[i])
2926+ i = 1000;
2927+ }
2928+ l = l->next;
2929+ }
2930+
2931+ return NULL;
2932+}
2933+
2934+int jffs2_bbc_disable_compressor_by_name(char *name)
2935+{
2936+ struct jffs2_bbc_compressor_type *l;
2937+
2938+ l = jffs2_bbc_get_compressor_by_name(name);
2939+ if (l == NULL) return 1;
2940+ l->enabled = 0;
2941+ return 0;
2942+}
2943+
2944+int jffs2_bbc_enable_compressor_by_name(char *name)
2945+{
2946+ struct jffs2_bbc_compressor_type *l;
2947+
2948+ l = jffs2_bbc_get_compressor_by_name(name);
2949+ if (l == NULL) return 1;
2950+ l->enabled = 1;
2951+ return 0;
2952+}
2953+
2954+void jffs2_bbc_compressor_command_by_name(char *name_and_command)
2955+{
2956+ struct jffs2_bbc_compressor_type *l;
2957+ int i;
2958+
2959+ l = jffs2_bbc_compressors;
2960+ while (l != NULL) {
2961+ for (i = 0; i < 1000; i++) {
2962+ if (l->name[i] == 0) {
2963+ if (name_and_command[i] != ':') {
2964+ jffs2_bbc_print1("jffs2.bbc: ':' missing after compressor name\n");
2965+ }
2966+ else {
2967+ if (l->proc_command != NULL)
2968+ l->proc_command(name_and_command + i + 1);
2969+ }
2970+ i = 1000;
2971+ return;
2972+ }
2973+ else if (name_and_command[i] == 0) {
2974+ i = 1000;
2975+ }
2976+ else if (name_and_command[i] != l->name[i]) {
2977+ i = 1000;
2978+ }
2979+ }
2980+ l = l->next;
2981+ }
2982+}
2983+
2984+struct jffs2_bbc_compressor_type *jffs2_bbc_get_manual_compressor(void)
2985+{
2986+ if (jffs2_bbc_get_compression_mode() != JFFS2_BBC_MANUAL_MODE) {
2987+ jffs2_bbc_manual_compressor = NULL;
2988+ }
2989+ return jffs2_bbc_manual_compressor;
2990+}
2991+
2992+/*********************************************************************
2993+ * Compressor handling *
2994+ *********************************************************************/
2995+
2996+struct jffs2_bbc_compressor_type *jffs2_bbc_get_compressor_list(void)
2997+{
2998+ return jffs2_bbc_compressors;
2999+}
3000+
3001+struct jffs2_bbc_model_list_node *jffs2_bbc_get_model_list(void)
3002+{
3003+ return jffs2_bbc_model_list;
3004+}
3005+
3006+int jffs2_bbc_register_compressor(struct jffs2_bbc_compressor_type *c)
3007+{
3008+ struct jffs2_bbc_compressor_type *l;
3009+ struct jffs2_bbc_model_list_node *l2;
3010+ int model_found = 0;
3011+
3012+ l = jffs2_bbc_compressors;
3013+ /* Check for confilcts */
3014+ while (l != NULL) {
3015+ c->name[15] = 0;
3016+ /*if (strcmp(c->name,l->name)==0) {
3017+ jffs2_bbc_print1("jffs2.bbc: compressor is already loaded.");
3018+ return -1;
3019+ } */
3020+ if ((l->model_file_sign == c->model_file_sign) && (c->model_file_sign != 0)) {
3021+ jffs2_bbc_print1("jffs2.bbc: already used model file sign. fail.");
3022+ return -1;
3023+ }
3024+ l = l->next;
3025+ }
3026+ /* Search and initialize model */
3027+ c->models = NULL;
3028+ c->mounted = 0;
3029+ if (c->init != NULL) {
3030+ if (c->init() != 0) {
3031+ jffs2_bbc_print2("jffs2.bbc: cannot initialize compressor %s.\n", c->name);
3032+ return -1;
3033+ }
3034+ }
3035+ if (c->model_file_sign != 0) {
3036+ l2 = jffs2_bbc_model_list;
3037+ while (1) {
3038+ if (l2 == NULL)
3039+ break;
3040+ if (c->model_file_sign == l2->sign) {
3041+ if (l2->compressor != NULL) {
3042+ jffs2_bbc_print2("jffs2.bbc: register for %s: BUG, model file already reserved!!!!\n", c->name);
3043+ }
3044+ else {
3045+ if (c->init_model(&(l2->model)) != 0) {
3046+ jffs2_bbc_print2("jffs2.bbc: cannot initialize compressor %s for a model", c->name);
3047+ }
3048+ else {
3049+ l2->compressor = c;
3050+ l2->next_compr_model = c->models;
3051+ c->models = l2;
3052+ c->mounted++;
3053+ model_found++;
3054+ }
3055+ }
3056+ }
3057+ l2 = l2->next_model;
3058+ }
3059+ /*if (model_found==0) {
3060+ jffs2_bbc_print2("jffs2.bbc: no macthing model file found for %s at this time (maybe later)\n",c->name);
3061+ } */
3062+ }
3063+ /* Insert to the end of the compressor list */
3064+ c->enabled = 1;
3065+ c->buffer = NULL;
3066+ c->buffer_size = 0;
3067+ c->stat_compr_orig = c->stat_compr_new = c->stat_decompr = 0;
3068+ c->next = NULL;
3069+ if (jffs2_bbc_compressors == NULL) {
3070+ jffs2_bbc_compressors = c;
3071+ }
3072+ else {
3073+ l = jffs2_bbc_compressors;
3074+ while (l->next != NULL)
3075+ l = l->next;
3076+ l->next = c;
3077+ }
3078+ return 0;
3079+}
3080+
3081+int jffs2_bbc_unregister_compressor(struct jffs2_bbc_compressor_type *c)
3082+{
3083+ struct jffs2_bbc_compressor_type *l;
3084+ struct jffs2_bbc_model_list_node *l2;
3085+
3086+ if (c->mounted != 0) {
3087+ jffs2_bbc_print1("jffs2.bbc: Compressor is in use. Sorry.");
3088+ return -1;
3089+ }
3090+ if (jffs2_bbc_compressors == NULL) {
3091+ jffs2_bbc_print1("jffs2.bbc: unregister: empty list.");
3092+ return -1;
3093+ }
3094+ else if (jffs2_bbc_compressors == c) {
3095+ if (c->deinit != NULL)
3096+ c->deinit();
3097+ jffs2_bbc_compressors = c->next;
3098+ }
3099+ else {
3100+ l = jffs2_bbc_compressors;
3101+ while (l->next != c) {
3102+ if (l->next == NULL) {
3103+ jffs2_bbc_print2("jffs2.bbc: unregister: cannot find compressor %s in the list.", c->name);
3104+ return -1;
3105+ }
3106+ l = l->next;
3107+ }
3108+ if (c->deinit != NULL)
3109+ c->deinit();
3110+ l->next = c->next;
3111+ }
3112+ if (c->buffer != NULL) {
3113+ jffs2_bbc_free(c->buffer);
3114+ c->buffer = NULL;
3115+ c->buffer_size = 0;
3116+ }
3117+
3118+ l2 = jffs2_bbc_model_list;
3119+ while (l2 != NULL) {
3120+ if (l2->compressor == c) {
3121+ jffs2_bbc_print1("jffs2.bbc: unregister: BUG: model found!!!");
3122+ l2->compressor = NULL;
3123+ l2->next_compr_model = NULL;
3124+ }
3125+ l2 = l2->next_model;
3126+ }
3127+
3128+ return 0;
3129+}
3130+
3131+int jffs2_bbc_model_new(void *sb, int i_num, void *model)
3132+{
3133+ struct jffs2_bbc_model_list_node *node;
3134+ struct jffs2_bbc_compressor_type *l;
3135+ char block_sign[2];
3136+
3137+ int sign;
3138+
3139+ /* check for conflicts... */
3140+ sign = *((int *) model);
3141+ block_sign[0] = *(((char *) model) + 4);
3142+ block_sign[1] = *(((char *) model) + 5);
3143+ node = jffs2_bbc_model_list;
3144+ while (node != NULL) {
3145+ if ((node->block_sign[0] == block_sign[0]) && (node->block_sign[1] == block_sign[1]) && (node->sb == sb)) {
3146+ //jffs2_bbc_print2("jffs2.bbc: model_new: model conflict (inode=%d)!\n",i_num);
3147+ return -1;
3148+ }
3149+ node = node->next_model;
3150+ }
3151+
3152+ /* insertion */
3153+ node = jffs2_bbc_malloc_small((long)sizeof(struct jffs2_bbc_model_list_node));
3154+ node->sb = sb;
3155+ node->model = model;
3156+ node->sign = *((int *) model);
3157+ node->block_sign[0] = *(((char *) model) + 4);
3158+ node->block_sign[1] = *(((char *) model) + 5);
3159+ node->inode = i_num;
3160+ node->next_model = jffs2_bbc_model_list;
3161+ node->compressor = NULL;
3162+ node->stat_decompr = 0;
3163+ node->next_compr_model = NULL;
3164+ jffs2_bbc_model_list = node;
3165+
3166+ /* search for matching compressor */
3167+ l = jffs2_bbc_compressors;
3168+ while (l != NULL) {
3169+ if (l->model_file_sign == sign) {
3170+ //jffs2_bbc_print2("jffs2.bbc: compressor for model found: %s ",l->name);
3171+ if (l->init_model(&(node->model)) != 0) {
3172+ jffs2_bbc_print1("jffs2.bbc: cannot initialize compressor for a model");
3173+ }
3174+ else {
3175+ l->mounted++;
3176+ node->compressor = l;
3177+ node->next_compr_model = l->models;
3178+ l->models = node;
3179+ }
3180+ break;
3181+ }
3182+ l = l->next;
3183+ }
3184+ return 0;
3185+}
3186+
3187+static void jffs2_bbc_model_del_from_compressor(struct jffs2_bbc_model_list_node *node)
3188+{
3189+ struct jffs2_bbc_model_list_node *l;
3190+
3191+ if (node->model != NULL) {
3192+ if (node->compressor != NULL) {
3193+ if (node->compressor->destroy_model == NULL) {
3194+ jffs2_bbc_free(node->model);
3195+ node->model = NULL;
3196+ }
3197+ else {
3198+ node->compressor->destroy_model(&(node->model));
3199+ if (node->model != NULL)
3200+ jffs2_bbc_print1("jffs2.bbc: warning: not NULL model after destroying!\n");
3201+ }
3202+ }
3203+ }
3204+
3205+ if (node->compressor == NULL) {
3206+ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_del_from_compressor: no compressor!\n");
3207+ return;
3208+ }
3209+ l = node->compressor->models;
3210+ if (l == NULL) {
3211+ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_del_from_compressor error, models=NULL!\n");
3212+ return;
3213+ }
3214+ if (l == node) {
3215+ node->compressor->models = node->next_compr_model;
3216+ node->compressor->mounted--;
3217+ return;
3218+ }
3219+ while (1) {
3220+ if (l->next_compr_model == node) {
3221+ l->next_compr_model = node->next_compr_model;
3222+ node->compressor->mounted--;
3223+ return;
3224+ }
3225+ l = l->next_compr_model;
3226+ if (l == NULL) {
3227+ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_del_from_compressor: not found\n");
3228+ return;
3229+ }
3230+ }
3231+}
3232+
3233+void jffs2_bbc_model_del(void *sb)
3234+{
3235+ struct jffs2_bbc_model_list_node *l, *l2;
3236+
3237+ l = jffs2_bbc_model_list;
3238+ if (l == NULL)
3239+ return;
3240+ if (l->sb == sb) {
3241+ jffs2_bbc_model_list = l->next_model;
3242+ jffs2_bbc_model_del_from_compressor(l);
3243+ jffs2_bbc_free_small(l);
3244+ jffs2_bbc_model_del(sb);
3245+ return;
3246+ }
3247+ while (1) {
3248+ if (l->next_model == NULL) {
3249+ break;
3250+ }
3251+ if (l->next_model->sb == sb) {
3252+ l2 = l->next_model;
3253+ l->next_model = l->next_model->next_model;
3254+ jffs2_bbc_model_del_from_compressor(l2);
3255+ jffs2_bbc_free_small(l2);
3256+ jffs2_bbc_model_del(sb);
3257+ return;
3258+ }
3259+ l = l->next_model;
3260+ }
3261+ last_sb = NULL;
3262+}
3263+
3264+void jffs2_bbc_model_set_act_sb(void *sb)
3265+{
3266+ last_sb = sb;
3267+}
3268+
3269+void *jffs2_bbc_model_get_act_sb(void)
3270+{
3271+ return last_sb;
3272+}
3273+
3274+void *jffs2_bbc_model_get_newest(struct jffs2_bbc_compressor_type *compressor)
3275+{
3276+ struct jffs2_bbc_model_list_node *m, *best_m;
3277+ int max_sign, sign;
3278+
3279+ if (compressor == NULL) {
3280+ jffs2_bbc_print1("jffs2.bbc: jffs2_bbc_model_get: NULL!!\n");
3281+ return NULL;
3282+ }
3283+
3284+ best_m = NULL;
3285+ max_sign = -1;
3286+ m = compressor->models;
3287+ while (m != NULL) {
3288+ if (m->sb == last_sb) {
3289+ sign = (int) (m->block_sign[0]) * 256 + (int) (m->block_sign[1]);
3290+ if (sign > max_sign) {
3291+ max_sign = sign;
3292+ best_m = m;
3293+ }
3294+ }
3295+ m = m->next_compr_model;
3296+ }
3297+ if (best_m != NULL)
3298+ return best_m->model;
3299+ else
3300+ return NULL;
3301+}
3302+
3303+/*********************************************************************
3304+ * Statistics *
3305+ *********************************************************************/
3306+
3307+static char *jffs2_bbc_stat_buff = NULL;
3308+
3309+char *jffs2_bbc_get_model_stats(void)
3310+{
3311+ char *b;
3312+ struct jffs2_bbc_model_list_node *m;
3313+ struct jffs2_bbc_compressor_type *c;
3314+
3315+ if (jffs2_bbc_stat_buff == NULL)
3316+ jffs2_bbc_stat_buff = jffs2_bbc_malloc(8000);
3317+
3318+ b = jffs2_bbc_stat_buff;
3319+
3320+ b += sprintf(b, "Loaded compressors:");
3321+ c = jffs2_bbc_compressors;
3322+ while (c != NULL) {
3323+ b += sprintf(b, "\n %s (%d) ", c->name, c->enabled);
3324+ if (c->model_file_sign != 0) {
3325+ b += sprintf(b, "m_sign=%d ", c->model_file_sign);
3326+ b += sprintf(b, "models=");
3327+ m = c->models;
3328+ while (m != NULL) {
3329+ b += sprintf(b, "(inode=%d)", m->inode);
3330+ m = m->next_compr_model;
3331+ }
3332+ }
3333+ else {
3334+ b += sprintf(b, "b_sign=(%d,%d) nomodel", (int) (c->block_sign[0]), (int) (c->block_sign[1]));
3335+ }
3336+ if (c->proc_info != NULL) {
3337+ b += sprintf(b, "\n %s", c->proc_info());
3338+ }
3339+ c = c->next;
3340+ }
3341+
3342+ m = jffs2_bbc_model_list;
3343+
3344+ if (m == NULL) {
3345+ b += sprintf(b, "\nPresent models: NONE\n");
3346+ }
3347+ else {
3348+ b += sprintf(b, "\nPresent models:\n");
3349+ while (m != NULL) {
3350+ b += sprintf(b, " b_sign=(%d,%d),inode=%d,decompr=%d", (int) (m->block_sign[0]), (int) (m->block_sign[1]), m->inode, m->stat_decompr);
3351+ if (m->compressor == NULL)
3352+ b += sprintf(b, ",compressor=NULL\n");
3353+ else
3354+ b += sprintf(b, ",compressor=%s\n", m->compressor->name);
3355+ m = m->next_model;
3356+ }
3357+ }
3358+
3359+ return jffs2_bbc_stat_buff;
3360+}
3361+
3362+/*********************************************************************
3363+ * Memory handling, debug *
3364+ *********************************************************************/
3365+
3366+static int jffs2_bbc_mem_counter = 0;
3367+
3368+#ifdef __KERNEL__
3369+
3370+void *jffs2_bbc_malloc(long size)
3371+{
3372+ void *addr = vmalloc(size);
3373+ if (addr != NULL)
3374+ jffs2_bbc_mem_counter++;
3375+ else {
3376+ jffs2_bbc_print2("DEBUG: not enough memory (%ld)\n", size);
3377+ }
3378+ return addr;
3379+}
3380+
3381+void jffs2_bbc_free(void *addr)
3382+{
3383+ jffs2_bbc_mem_counter--;
3384+ vfree(addr);
3385+}
3386+
3387+void *jffs2_bbc_malloc_small(long size)
3388+{
3389+ void *addr;
3390+ addr = kmalloc(size, 0);
3391+ if (addr != NULL)
3392+ jffs2_bbc_mem_counter++;
3393+ return addr;
3394+}
3395+
3396+void jffs2_bbc_free_small(void *addr)
3397+{
3398+ jffs2_bbc_mem_counter--;
3399+ kfree(addr);
3400+}
3401+
3402+#else
3403+
3404+void *jffs2_bbc_malloc(long size)
3405+{
3406+ void *addr = malloc(size);
3407+ if (addr != NULL)
3408+ jffs2_bbc_mem_counter++;
3409+ return addr;
3410+}
3411+
3412+void jffs2_bbc_free(void *addr)
3413+{
3414+ jffs2_bbc_mem_counter--;
3415+ free(addr);
3416+}
3417+
3418+void *jffs2_bbc_malloc_small(long size)
3419+{
3420+ return jffs2_bbc_malloc(size);
3421+}
3422+
3423+void jffs2_bbc_free_small(void *addr)
3424+{
3425+ jffs2_bbc_free(addr);
3426+}
3427+
3428+#endif
3429+
3430+int jffs2_bbc_test_memory_counter(int verbose)
3431+{
3432+ if (verbose > 0) {
3433+ jffs2_bbc_print2("jffs2.bbc: mem_counter=%d!\n", jffs2_bbc_mem_counter);
3434+ }
3435+ return jffs2_bbc_mem_counter;
3436+}
3437+
3438+int jffs2_bbc_get_memory_counter(void)
3439+{
3440+ return jffs2_bbc_mem_counter;
3441+}
3442+
3443+static char mem_stat[200];
3444+
3445+char *jffs2_bbc_get_mem_stats(void)
3446+{
3447+ sprintf(mem_stat, "Memcounter=%d\n", jffs2_bbc_mem_counter);
3448+ return mem_stat;
3449+}
3450+
3451+void jffs2_bbc_print_flush(void)
3452+{
3453+#ifdef __KERNEL__
3454+ return;
3455+#else
3456+ fflush(stdout);
3457+ fflush(stderr);
3458+#endif
3459+}
3460+
3461+/*********************************************************************
3462+ * FRAMEWORK - ZLIB REPLACEMENT *
3463+ *********************************************************************/
3464+
3465+#ifndef JFFS2_BBC_STANDALONE
3466+
3467+/* Temorary buffers */
3468+static char stat_str[JFFS2_BBC_STAT_BUFF_SIZE];
3469+static int tmp_buffer_size = 0;
3470+static char *tmp_buffer = NULL;
3471+
3472+/* Statistic - used by /proc/jffs2_bbc and mkfs.jffs2 */
3473+char *jffs2_bbc_get_compr_stats(void)
3474+{
3475+ struct jffs2_bbc_compressor_type *l;
3476+ char *s = stat_str;
3477+
3478+ s += sprintf(s, "Compression statistics:\n");
3479+ l = jffs2_bbc_original_compressor;
3480+ //s += sprintf(s, " zlib: compr=%d/%d decompr=%d\n", stat_zlib_compr_new, stat_zlib_compr_orig, stat_zlib_decompr);
3481+ s += sprintf(s, " %s: compr=%d/%d decompr=%d\n", l->name, l->stat_compr_new, l->stat_compr_orig, l->stat_decompr);
3482+ l = jffs2_bbc_get_compressor_list();
3483+ while (l != NULL) {
3484+ s += sprintf(s, " %s: compr=%d/%d decompr=%d\n", l->name, l->stat_compr_new, l->stat_compr_orig, l->stat_decompr);
3485+ l = l->next;
3486+ }
3487+ return stat_str;
3488+}
3489+
3490+static void jffs2_bbc_buffer_fill(unsigned char *buff, int size)
3491+{
3492+ for (; size > 0; size--, buff++)
3493+ *buff = 255;
3494+}
3495+
3496+
3497+static int jffs2_bbc_update_compr_buf(unsigned long size)
3498+{
3499+ struct jffs2_bbc_compressor_type *l;
3500+
3501+ if (size < 5000)
3502+ size = 5000;
3503+ if (tmp_buffer == NULL) {
3504+ tmp_buffer = jffs2_bbc_malloc(size);
3505+ jffs2_bbc_buffer_fill(tmp_buffer, size);
3506+ tmp_buffer_size = size;
3507+ }
3508+ else if (tmp_buffer_size < size) {
3509+ jffs2_bbc_free(tmp_buffer);
3510+ tmp_buffer = jffs2_bbc_malloc(size);
3511+ jffs2_bbc_buffer_fill(tmp_buffer, size);
3512+ tmp_buffer_size = size;
3513+ }
3514+ l = jffs2_bbc_get_compressor_list();
3515+ while (l != NULL) {
3516+ if (l->buffer == NULL) {
3517+ l->buffer_size = size;
3518+ l->buffer = jffs2_bbc_malloc(size);
3519+ jffs2_bbc_buffer_fill(l->buffer, size);
3520+ }
3521+ else if (l->buffer_size < size) {
3522+ jffs2_bbc_free(l->buffer);
3523+ l->buffer_size = size;
3524+ l->buffer = jffs2_bbc_malloc(size);
3525+ jffs2_bbc_buffer_fill(l->buffer, size);
3526+ }
3527+ l = l->next;
3528+ }
3529+ return 0;
3530+}
3531+
3532+#ifdef DEBUG_COMPRESSORS
3533+
3534+static unsigned char *debug_tmp_buff = NULL;
3535+static long debug_orig_srclen = -1;
3536+static long debug_orig_dstlen = -1;
3537+static int debug_mem_counter = -1;
3538+
3539+
3540+void debug_before_compress(struct jffs2_bbc_compressor_type *c, void *model, unsigned char *input, unsigned char *output, long *sourcelen, long *dstlen)
3541+{
3542+
3543+ debug_orig_srclen = *sourcelen; // for buffer overflow test
3544+ debug_orig_dstlen = *dstlen; // for buffer overflow test
3545+ output[debug_orig_dstlen + 1] = 255;
3546+
3547+ debug_mem_counter = jffs2_bbc_get_memory_counter(); // for memory guard
3548+}
3549+
3550+void debug_after_compress(struct jffs2_bbc_compressor_type *c, int back, void *model, unsigned char *input, unsigned char *output, long *sourcelen, long *dstlen)
3551+{
3552+ long dst_len = *dstlen;
3553+ long src_len = *sourcelen;
3554+ int i;
3555+
3556+ // Memory guard
3557+ if (debug_mem_counter != jffs2_bbc_get_memory_counter()) {
3558+ jffs2_bbc_print4("!!!!!!!! %s error: possible COMPRESSOR MEMORY LEAK: %d->%d\n", c->name, debug_mem_counter, jffs2_bbc_get_memory_counter());
3559+ debug_mem_counter = jffs2_bbc_get_memory_counter();
3560+ }
3561+
3562+ // Buffer overflow test
3563+ if (output[debug_orig_dstlen + 1] != 255) {
3564+ jffs2_bbc_print7("!!!!!!!! %s error: BUFFER OVERFLOW !!!!!!!!!!!! b[%d]=%d (srclen=%d dstlen=%d, back=%d)\n", c->name, (int) (debug_orig_dstlen + 1), (int) (output[debug_orig_dstlen + 1]), (int) (debug_orig_srclen), (int) (*dstlen), back);
3565+ }
3566+
3567+ // Decompression check
3568+ if (back == 0) {
3569+ if (debug_tmp_buff == NULL)
3570+ debug_tmp_buff = jffs2_bbc_malloc(17000);
3571+ for (i = 0; i < src_len; i++) debug_tmp_buff[i] = 0xf6;
3572+ c->decompress(model, output, debug_tmp_buff, dst_len, src_len);
3573+ // Memory guard for decompressor
3574+ if (debug_mem_counter != jffs2_bbc_get_memory_counter()) {
3575+ jffs2_bbc_print4("!!!!!!!! %s error: possible DECOMPRESSOR MEMORY LEAK: %d->%d\n", c->name, debug_mem_counter, jffs2_bbc_get_memory_counter());
3576+ debug_mem_counter = jffs2_bbc_get_memory_counter();
3577+ }
3578+
3579+ for (i = 0; i < src_len; i++)
3580+ if (input[i] != debug_tmp_buff[i]) {
3581+ jffs2_bbc_print7("!!!!!!!! %s error: BLOCK DECOMPRESSED BADLY (first bad: %d in %d: %d!=%d (compressed size=%d)) !!!!!!!!!!!!\n", c->name, i, src_len, (int)input[i], (int)debug_tmp_buff[i], dst_len);
3582+ break;
3583+ }
3584+ return;
3585+ }
3586+
3587+ // Return value test
3588+ //jffs2_bbc_print3("!!!!!!!! %s error: %d !!!!!!!!!!!!\n", c->name, back);
3589+}
3590+
3591+#endif
3592+
3593+int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, uint32_t * sourcelen, uint32_t * dstlen)
3594+{
3595+ struct jffs2_bbc_compressor_type *c;
3596+ int back, back_zlib, mode, min, i, i2;
3597+ long tmp = 0, tmp_read_time = 1000, tmp_write_time = 1000, orig_src, orig_dest, src, dest;
3598+ struct jffs2_bbc_model_list_node *m;
3599+ void *sb;
3600+ unsigned char *tmp_p = NULL;
3601+
3602+ sb = jffs2_bbc_model_get_act_sb();
3603+
3604+ orig_src = *sourcelen;
3605+ orig_dest = *dstlen;
3606+
3607+ mode = jffs2_bbc_get_compression_mode();
3608+
3609+ if (mode == JFFS2_BBC_DUMMY_MODE) {
3610+ i=0; i2=0;
3611+ if (*dstlen>2) {
3612+ cpage_out[i++]=JFFS2_BBC_DUMMY_BLOCKSIGN_0;
3613+ cpage_out[i++]=JFFS2_BBC_DUMMY_BLOCKSIGN_1;
3614+ i2=i;
3615+ }
3616+ for (;((i < *dstlen) && (i < (*sourcelen)+i2));i++) {
3617+ cpage_out[i] = data_in[i-i2];
3618+ }
3619+ *sourcelen=i-i2;
3620+ *dstlen=i;
3621+ return 0;
3622+ }
3623+
3624+ if (mode == JFFS2_BBC_ZLIB_MODE) {
3625+ /*if (!jffs2_bbc_original_compressor->enabled) {
3626+ jffs2_bbc_print2("jffs2.bbc: WARNING: ZLIB mode but %s disabled! Enabling for this procedure...\n",jffs2_bbc_original_compressor->name);
3627+ }*/
3628+ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
3629+ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
3630+ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
3631+ return back;
3632+ }
3633+
3634+ jffs2_bbc_update_compr_buf(orig_dest);
3635+
3636+ if (mode == JFFS2_BBC_SIZE_MODE) {
3637+ // Testing all compressors
3638+ if (!jffs2_bbc_original_compressor->enabled) {
3639+ min = -1;
3640+ }
3641+ else {
3642+ back_zlib = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
3643+ min = *dstlen;
3644+ }
3645+ c = jffs2_bbc_get_compressor_list();
3646+ while (c != NULL) {
3647+ c->buffer_cnt = -1;
3648+ if (c->enabled == 0) {
3649+ c = c->next;
3650+ continue;
3651+ }
3652+ if (c->model_file_sign == 0) {
3653+ src = orig_src;
3654+ dest = orig_dest;
3655+#ifdef DEBUG_COMPRESSORS
3656+ debug_before_compress(c, NULL, data_in, c->buffer, &src, &dest);
3657+#endif
3658+ back = c->compress(NULL, data_in, c->buffer, &src, &dest);
3659+#ifdef DEBUG_COMPRESSORS
3660+ debug_after_compress(c, back, NULL, data_in, c->buffer, &src, &dest);
3661+#endif
3662+ if (back == 0) {
3663+ c->buffer_cnt = dest;
3664+ if ((min < 0) || (min > dest))
3665+ min = dest;
3666+ }
3667+ }
3668+ else {
3669+ m = c->models;
3670+ while (m != NULL) {
3671+ src = orig_src;
3672+ dest = orig_dest;
3673+ if (m->sb == sb) {
3674+ if (c->buffer_cnt == -1) {
3675+#ifdef DEBUG_COMPRESSORS
3676+ debug_before_compress(c, m->model, data_in, c->buffer, (long *) (&src), (long *) (&dest));
3677+#endif
3678+ back = c->compress(m->model, data_in, c->buffer, (long *) (&src), (long *) (&dest));
3679+#ifdef DEBUG_COMPRESSORS
3680+ debug_after_compress(c, back, m->model, data_in, c->buffer, (long *) (&src), (long *) (&dest));
3681+#endif
3682+ if (back == 0) {
3683+ c->buffer_cnt = dest;
3684+ if ((min < 0) || (min > dest))
3685+ min = dest;
3686+ }
3687+ }
3688+ else {
3689+#ifdef DEBUG_COMPRESSORS
3690+ debug_before_compress(c, m->model, data_in, tmp_buffer, &src, &dest);
3691+#endif
3692+ back = c->compress(m->model, data_in, tmp_buffer, &src, &dest);
3693+#ifdef DEBUG_COMPRESSORS
3694+ debug_after_compress(c, back, m->model, data_in, tmp_buffer, &src, &dest);
3695+#endif
3696+ if (back == 0) {
3697+ if (c->buffer_cnt > dest) {
3698+ c->buffer_cnt = dest;
3699+ tmp_p = c->buffer;
3700+ c->buffer = tmp_buffer;
3701+ tmp_buffer = tmp_p;
3702+ if ((min < 0) || (min > dest))
3703+ min = dest;
3704+ }
3705+ }
3706+ }
3707+ }
3708+ m = m->next_compr_model;
3709+ }
3710+ }
3711+ c = c->next;
3712+ }
3713+ //Finding the best and copy its result
3714+
3715+#ifdef DEBUG_SHOW_BLOCK_SIZES
3716+ jffs2_bbc_print1("\n");
3717+ if (jffs2_bbc_original_compressor->enabled) {
3718+ if (min == *dstlen) {
3719+ jffs2_bbc_print3("%s:%d* ", jffs2_bbc_original_compressor->name, (int) (*dstlen));
3720+ }
3721+ else {
3722+ jffs2_bbc_print3("%s:%d ", jffs2_bbc_original_compressor->name, (int) (*dstlen));
3723+ }
3724+ }
3725+ c = jffs2_bbc_get_compressor_list();
3726+ while (c != NULL) {
3727+ if (c->enabled == 0) {
3728+ c = c->next;
3729+ continue;
3730+ }
3731+ if (c->buffer_cnt == min)
3732+ jffs2_bbc_print3("%s:%d* ", c->name, c->buffer_cnt);
3733+ else
3734+ jffs2_bbc_print3("%s:%d ", c->name, c->buffer_cnt);
3735+ c = c->next;
3736+ }
3737+#endif
3738+
3739+ if (min == -1) {
3740+ return -1; // none of compressors work (maybe too short output buffer)
3741+ }
3742+
3743+ if (jffs2_bbc_original_compressor->enabled) {
3744+ if (min == *dstlen) {
3745+ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
3746+ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
3747+ return back_zlib;
3748+ }
3749+ }
3750+
3751+ c = jffs2_bbc_get_compressor_list();
3752+ while (c != NULL) {
3753+ if (c->enabled == 0) {
3754+ c = c->next;
3755+ continue;
3756+ }
3757+ if (c->buffer_cnt == min) {
3758+ *dstlen = c->buffer_cnt;
3759+ *sourcelen = orig_src;
3760+ for (i = 0; i < *dstlen; i++) {
3761+ cpage_out[i] = c->buffer[i];
3762+ }
3763+ c->stat_compr_orig += *sourcelen;
3764+ c->stat_compr_new += *dstlen;
3765+ return 0;
3766+ }
3767+ c = c->next;
3768+ }
3769+ jffs2_bbc_print1("jffs2.bbc: compr (full): BUG!!!\n");
3770+ return 0;
3771+ }
3772+
3773+ if ((mode == JFFS2_BBC_FASTR_MODE)||(mode == JFFS2_BBC_FASTW_MODE)||(mode == JFFS2_BBC_FASTS_MODE)) {
3774+ // Estimating all compressors
3775+ if (jffs2_bbc_original_compressor->enabled) {
3776+ back = jffs2_bbc_original_compressor->estimate(NULL, data_in, *sourcelen, &tmp, &tmp_read_time, &tmp_write_time);
3777+ }
3778+ else {
3779+ tmp = -1;
3780+ tmp_read_time = -1;
3781+ tmp_write_time = -1;
3782+ }
3783+ if (mode == JFFS2_BBC_FASTR_MODE) tmp = tmp_read_time;
3784+ if (mode == JFFS2_BBC_FASTW_MODE) tmp = tmp_write_time;
3785+ min = tmp;
3786+ c = jffs2_bbc_get_compressor_list();
3787+ while (c != NULL) {
3788+ src = orig_src;
3789+ dest = orig_dest;
3790+ c->buffer_cnt = -1;
3791+ if (c->enabled == 0) {
3792+ c = c->next;
3793+ continue;
3794+ }
3795+ if ((c->model_file_sign == 0) || (jffs2_bbc_model_get_newest(c) != NULL)) {
3796+ back = c->estimate(jffs2_bbc_model_get_newest(c), data_in, src, &dest, &tmp_read_time, &tmp_write_time);
3797+ if (mode == JFFS2_BBC_FASTR_MODE) dest = tmp_read_time;
3798+ if (mode == JFFS2_BBC_FASTW_MODE) dest = tmp_write_time;
3799+ if (back == 0) {
3800+ c->buffer_cnt = dest;
3801+ if ((min < 0) || (min > dest))
3802+ min = dest;
3803+ }
3804+ else {
3805+ c->buffer_cnt = -1;
3806+ }
3807+ }
3808+ c = c->next;
3809+ }
3810+ // Finding the best and compress with it
3811+ if (min == -1) {
3812+ return -1;
3813+ }
3814+ if (jffs2_bbc_original_compressor->enabled) {
3815+ if (min == tmp) {
3816+ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
3817+ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
3818+ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
3819+ return back;
3820+ }
3821+ }
3822+ c = jffs2_bbc_get_compressor_list();
3823+ while (c != NULL) {
3824+ if (c->enabled == 0) {
3825+ c = c->next;
3826+ continue;
3827+ }
3828+ if (c->buffer_cnt == min) {
3829+ back = c->compress(jffs2_bbc_model_get_newest(c), data_in, cpage_out, (unsigned long*)sourcelen, (unsigned long*)dstlen);
3830+ if ((back == 0) && (*dstlen < orig_dest) && (*dstlen > 4)) {
3831+ c->stat_compr_orig += *sourcelen;
3832+ c->stat_compr_new += *dstlen;
3833+ }
3834+ else { // fallback will always be available
3835+ *sourcelen = orig_src;
3836+ *dstlen = orig_dest;
3837+ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
3838+ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
3839+ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
3840+ return back;
3841+ }
3842+ return 0;
3843+ }
3844+ c = c->next;
3845+ }
3846+ jffs2_bbc_print1("jffs2.bbc: compress (fastX mode): BUG!!!\n");
3847+ return 0;
3848+ }
3849+
3850+ if (mode == JFFS2_BBC_MANUAL_MODE) {
3851+ c = jffs2_bbc_get_manual_compressor();
3852+ if (c != NULL) {
3853+ if (c->model_file_sign == 0) {
3854+ src = orig_src;
3855+ dest = orig_dest;
3856+ back = c->compress(NULL, data_in, cpage_out, &src, &dest);
3857+ if (back == 0) {
3858+ *dstlen = dest;
3859+ *sourcelen = src;
3860+ c->stat_compr_orig += *sourcelen;
3861+ c->stat_compr_new += *dstlen;
3862+ return 0;
3863+ }
3864+ }
3865+ else {
3866+ c->buffer_cnt = -1;
3867+ m = c->models;
3868+ min = -1;
3869+ while (m != NULL) {
3870+ src = orig_src;
3871+ dest = orig_dest;
3872+ if (m->sb == sb) {
3873+ if (min == -1) {
3874+ back = c->compress(m->model, data_in, cpage_out, (unsigned long*)sourcelen, (unsigned long*)dstlen);
3875+ if ((back == 0) && (*dstlen < orig_dest) && (*dstlen > 4)) {
3876+ min = dest;
3877+ tmp_p = cpage_out;
3878+ }
3879+ }
3880+ else {
3881+ back = c->compress(m->model, data_in, tmp_buffer, &src, &dest);
3882+ if ((back == 0) && (dest < orig_dest) && (dest > 4)) {
3883+ if (c->buffer_cnt > dest) {
3884+ if (min > dest) {
3885+ min = dest;
3886+ tmp_p = tmp_buffer;
3887+ }
3888+ }
3889+ }
3890+ }
3891+ }
3892+ m = m->next_compr_model;
3893+ }
3894+ if (min != -1) {
3895+ if (tmp_p != cpage_out) {
3896+ for (i = 0; i < min; i++)
3897+ cpage_out[i] = tmp_p[i];
3898+ *sourcelen = orig_src;
3899+ *dstlen = min;
3900+ }
3901+ c->stat_compr_orig += *sourcelen;
3902+ c->stat_compr_new += *dstlen;
3903+ return 0;
3904+ }
3905+ }
3906+ }
3907+ /*else {
3908+ jffs2_bbc_print1("iPack: manual mode without selected compressor!\n");
3909+ } */
3910+
3911+ /*if (!jffs2_bbc_original_compressor->enabled) {
3912+ jffs2_bbc_print2("jffs2.bbc: WARNING: %s must be enabled! Enabling for this procedure...\n",jffs2_bbc_original_compressor->name);
3913+ }*/
3914+ back = jffs2_bbc_original_compressor->compress(NULL, data_in, cpage_out, sourcelen, dstlen);
3915+ jffs2_bbc_original_compressor->stat_compr_orig += *sourcelen;
3916+ jffs2_bbc_original_compressor->stat_compr_new += *dstlen;
3917+ return back;
3918+
3919+
3920+ }
3921+
3922+ jffs2_bbc_print1("jffs2.bbc: compress: unimlemented compress mode!!!\n");
3923+ return 0;
3924+}
3925+
3926+void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, uint32_t srclen, uint32_t destlen)
3927+{
3928+ struct jffs2_bbc_model_list_node *m;
3929+ struct jffs2_bbc_compressor_type *c;
3930+ char d[2];
3931+ void *sb;
3932+ int i;
3933+
3934+ /* If the input too small... */
3935+ if (destlen<=2) {
3936+ cpage_out[0]=data_in[0];
3937+ if (destlen==2) cpage_out[1]=data_in[1];
3938+ return;
3939+ }
3940+
3941+ sb = jffs2_bbc_model_get_act_sb();
3942+ d[0] = *(data_in);
3943+ d[1] = *(data_in + 1);
3944+
3945+ d[0] &= 0x7f; // Variants support...
3946+
3947+ /* Search for model based decompressors... */
3948+ m = jffs2_bbc_get_model_list();
3949+ while (m != NULL) {
3950+ if ((d[0] == m->block_sign[0]) && (d[1] == m->block_sign[1]) && (sb == m->sb)) {
3951+ if (m->compressor == NULL) {
3952+ jffs2_bbc_print3("jffs2.bbc: decompressor for block_sign (%d,%d) not loaded!\n", (int) (d[0]), (int) (d[1]));
3953+ }
3954+ else {
3955+ m->compressor->decompress(m->model, data_in, cpage_out, srclen, destlen);
3956+ m->compressor->stat_decompr++;
3957+ m->stat_decompr++;
3958+ }
3959+ return;
3960+ }
3961+ m = m->next_model;
3962+ }
3963+ /* Is it ZLIB? */
3964+ if ((((int) d[0]) == (int)(jffs2_bbc_original_compressor->block_sign[0])) && (((int) d[1]) == (int)(jffs2_bbc_original_compressor->block_sign[1]))) {
3965+ jffs2_bbc_original_compressor->decompress(NULL, data_in, cpage_out, srclen, destlen);
3966+ jffs2_bbc_original_compressor->stat_decompr++;
3967+ return;
3968+ }
3969+ /* Search for non model based decompressors... */
3970+ c = jffs2_bbc_get_compressor_list();
3971+ while (c != NULL) {
3972+ if (c->model_file_sign == 0) {
3973+ if (((int) (d[0]) == (int) (c->block_sign[0])) && ((int) (d[1]) == (int) (c->block_sign[1]))) {
3974+ c->decompress(NULL, data_in, cpage_out, srclen, destlen);
3975+ c->stat_decompr++;
3976+ return;
3977+ }
3978+ }
3979+ c = c->next;
3980+ }
3981+ /* Is it DUMMY? */
3982+ if ((((int) d[0]) == JFFS2_BBC_DUMMY_BLOCKSIGN_0) && (((int) d[1]) == JFFS2_BBC_DUMMY_BLOCKSIGN_1)) {
3983+ for (i=0;i<destlen;i++) {
3984+ cpage_out[i]=data_in[i+2];
3985+ }
3986+ return;
3987+ }
3988+ /* No matching decompressor found... */
3989+ jffs2_bbc_print4("jffs2.bbc: cannot find model for decompress: bsign=(%d,%d),sb=%d. Using zlib.\n", (int) d[0], (int) d[1], (int) sb);
3990+ jffs2_bbc_original_compressor->decompress(NULL, data_in, cpage_out, srclen, destlen);
3991+ jffs2_bbc_original_compressor->stat_decompr++;
3992+}
3993+
3994+#endif
3995--- /dev/null
3996+++ b/fs/jffs2/jffs2_bbc_framework.h
3997@@ -0,0 +1,202 @@
3998+/*
3999+ * JFFS2-BBC: Compression Framework - headers
4000+ *
4001+ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
4002+ *
4003+ * Copyright (C) 2004, Ferenc Havasi
4004+ *
4005+ * This program is free software; you can redistribute it and/or
4006+ * modify it under the terms of the GNU General Public License
4007+ * as published by the Free Software Foundation; either version 2
4008+ * of the License, or (at your option) any later version.
4009+ *
4010+ * This program is distributed in the hope that it will be useful,
4011+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4012+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4013+ * GNU General Public License for more details.
4014+ *
4015+ * You should have received a copy of the GNU General Public License
4016+ * along with this program; if not, write to the Free Software
4017+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4018+ *
4019+ */
4020+
4021+#ifndef __JFFS2_BBC_FRAMEWORK_H__
4022+
4023+#define __JFFS2_BBC_FRAMEWORK_H__
4024+
4025+#define JFFS2_BBC_VERSION "0.54.3"
4026+
4027+#define JFFS2_BBC_CONFIG_FILE "bbc.conf"
4028+
4029+/*********************************************************************
4030+ * Compression mode handling *
4031+ *********************************************************************/
4032+
4033+#define JFFS2_BBC_ZLIB_MODE 1
4034+#define JFFS2_BBC_SIZE_MODE 2
4035+#define JFFS2_BBC_FASTR_MODE 3
4036+#define JFFS2_BBC_FASTW_MODE 4
4037+#define JFFS2_BBC_FASTS_MODE 5
4038+#define JFFS2_BBC_MANUAL_MODE 6
4039+#define JFFS2_BBC_DUMMY_MODE 7
4040+
4041+int jffs2_bbc_get_compression_mode(void);
4042+void jffs2_bbc_set_compression_mode(int mode);
4043+
4044+/*********************************************************************
4045+ * Read/write speed unit *
4046+ * everything is relative to the speed of zlib *
4047+ * bigger number means slower speed! *
4048+ *********************************************************************/
4049+
4050+#define JFFS2_BBC_ZLIB_READ_TIME 10000
4051+#define JFFS2_BBC_ZLIB_WRITE_TIME 10000
4052+
4053+/*********************************************************************
4054+ * Compressor handling *
4055+ *********************************************************************/
4056+
4057+struct jffs2_bbc_compressor_type
4058+{
4059+ char name[16];
4060+ int model_file_sign; /* 0 for no model file needed */
4061+ char block_sign[4]; /* only nomodel compressors, and only the first 2 _bytes are used! */
4062+ int (*init)(void);
4063+ int (*init_model)(void **model);
4064+ void (*destroy_model)(void **model);
4065+ void (*deinit)(void);
4066+ /* Compress block
4067+ * *dstlen bytes are allocated.
4068+ * if it is not enough write *sourcelen over to the processed amount of data
4069+ * returns non zero if fails
4070+ */
4071+ int (*compress)(void *model, unsigned char *input, unsigned char *output, unsigned long *sourcelen, unsigned long *dstlen);
4072+ int (*estimate)(void *model, unsigned char *input, unsigned long sourcelen,
4073+ unsigned long *dstlen, unsigned long *readtime, unsigned long *writetime);
4074+ /* Decompress block
4075+ * returns non zero if fails
4076+ */
4077+ int (*decompress)(void *model, unsigned char *input, unsigned char *output, unsigned long sourcelen, unsigned long dstlen);
4078+ char *(*proc_info)(void);
4079+ int (*proc_command)(char *command);
4080+ int enabled; /* filled by BBC */
4081+ int mounted; /* filled by BBC */
4082+ void *models; /* filled by BBC */
4083+ char *buffer; /* filled by BBC */
4084+ int buffer_size; /* filled by BBC */
4085+ int buffer_cnt; /* filled by BBC */
4086+ int buffer_tmp; /* filled by BBC */
4087+ int stat_compr_orig; /* filled by BBC */
4088+ int stat_compr_new; /* filled by BBC */
4089+ int stat_decompr; /* filled by BBC */
4090+ struct jffs2_bbc_compressor_type *next; /* filled by BBC */
4091+};
4092+
4093+/* It sets the compression mode to JFFS2_BBC_MANUAL_MODE */
4094+
4095+void jffs2_bbc_set_manual_compressor(struct jffs2_bbc_compressor_type *c); /* NULL = ZLIB */
4096+int jffs2_bbc_set_manual_compressor_by_name(char *name);
4097+int jffs2_bbc_disable_compressor_by_name(char *name);
4098+int jffs2_bbc_enable_compressor_by_name(char *name);
4099+void jffs2_bbc_compressor_command_by_name(char *name_and_command);
4100+
4101+/* If the compression mode is JFFS2_BCC_MANUAL_MODE the manually setted
4102+ compressor can be get using it. Otherwise it returns with NULL. */
4103+
4104+struct jffs2_bbc_compressor_type *jffs2_bbc_get_manual_compressor(void);
4105+
4106+struct jffs2_bbc_model_list_node
4107+{
4108+ void *sb; /* FS idendifier (JFFS2_SB_INFO(sb) at this moment) */
4109+ void *model; /* model data */
4110+ int sign; /* sign of the model (first 4 bytes) */
4111+ char block_sign[4]; /* block sign - only the first 2 bytes are used! */
4112+ int inode; /* inode number of the model file */
4113+ int stat_decompr;
4114+ struct jffs2_bbc_compressor_type *compressor;
4115+ struct jffs2_bbc_model_list_node *next_model;
4116+ struct jffs2_bbc_model_list_node *next_compr_model;
4117+};
4118+
4119+struct jffs2_bbc_compressor_type *jffs2_bbc_get_compressor_list(void);
4120+struct jffs2_bbc_model_list_node *jffs2_bbc_get_model_list(void);
4121+
4122+int jffs2_bbc_register_compressor(struct jffs2_bbc_compressor_type *c);
4123+int jffs2_bbc_unregister_compressor(struct jffs2_bbc_compressor_type *c);
4124+
4125+int jffs2_bbc_model_new(void *sb, int i_num, void *model);
4126+void jffs2_bbc_model_del(void *sb);
4127+void jffs2_bbc_model_set_act_sb(void *sb);
4128+void *jffs2_bbc_model_get_act_sb(void);
4129+void *jffs2_bbc_model_get_newest(struct jffs2_bbc_compressor_type *compressor);
4130+
4131+/*********************************************************************
4132+ * Compressor init function *
4133+ *********************************************************************/
4134+
4135+void jffs2_bbc_compressor_init(void);
4136+void jffs2_bbc_compressor_deinit(void);
4137+
4138+/*********************************************************************
4139+ * Statistics *
4140+ *********************************************************************/
4141+
4142+char *jffs2_bbc_get_compr_stats(void);
4143+char *jffs2_bbc_get_model_stats(void);
4144+
4145+/*********************************************************************
4146+ * Other *
4147+ *********************************************************************/
4148+
4149+
4150+void jffs2_bbc_print_flush(void);
4151+
4152+#ifdef __KERNEL__
4153+#include <linux/kernel.h>
4154+#define jffs2_bbc_print1(a) printk(a)
4155+#define jffs2_bbc_print2(a,b) printk(a,b)
4156+#define jffs2_bbc_print3(a,b,c) printk(a,b,c)
4157+#define jffs2_bbc_print4(a,b,c,d) printk(a,b,c,d)
4158+#define jffs2_bbc_print5(a,b,c,d,e) printk(a,b,c,d,e)
4159+#define jffs2_bbc_print6(a,b,c,d,e,f) printk(a,b,c,d,e,f)
4160+#define jffs2_bbc_print7(a,b,c,d,e,f,g) printk(a,b,c,d,e,f,g)
4161+#define jffs2_bbc_print8(a,b,c,d,e,f,g,h) printk(a,b,c,d,e,f,g,h)
4162+#define jffs2_bbc_print9(a,b,c,d,e,f,g,h,i) printk(a,b,c,d,e,f,g,h,i)
4163+#else
4164+#include <stdio.h>
4165+#define jffs2_bbc_print1(a) fprintf(stderr,a)
4166+#define jffs2_bbc_print2(a,b) fprintf(stderr,a,b)
4167+#define jffs2_bbc_print3(a,b,c) fprintf(stderr,a,b,c)
4168+#define jffs2_bbc_print4(a,b,c,d) fprintf(stderr,a,b,c,d)
4169+#define jffs2_bbc_print5(a,b,c,d,e) fprintf(stderr,a,b,c,d,e)
4170+#define jffs2_bbc_print6(a,b,c,d,e,f) fprintf(stderr,a,b,c,d,e,f)
4171+#define jffs2_bbc_print7(a,b,c,d,e,f,g) fprintf(stderr,a,b,c,d,e,f,g)
4172+#define jffs2_bbc_print8(a,b,c,d,e,f,g,h) fprintf(stderr,a,b,c,d,e,f,g,h)
4173+#define jffs2_bbc_print9(a,b,c,d,e,f,g,h,i) fprintf(stderr,a,b,c,d,e,f,g,h,i)
4174+#endif
4175+
4176+/* Handle endianness */
4177+#ifndef __KERNEL__
4178+
4179+#define ENDIAN_HOST_AND_TARGET_SAME 0
4180+#define ENDIAN_HOST_AND_TARGET_DIFFERENT 1
4181+
4182+extern int jffs2_bbc_glb_endian_X;
4183+
4184+#endif
4185+
4186+/* Allocating more than one page (tip. 4096 byte) */
4187+void *jffs2_bbc_malloc(long size);
4188+void jffs2_bbc_free(void *addr);
4189+
4190+/* Allocating less than one page (tip. 4096 byte) */
4191+void *jffs2_bbc_malloc_small(long size);
4192+void jffs2_bbc_free_small(void *addr);
4193+
4194+/* Memory guarding */
4195+int jffs2_bbc_test_memory_counter(int verbose);
4196+char *jffs2_bbc_get_mem_stats(void);
4197+int jffs2_bbc_get_memory_counter(void);
4198+
4199+#endif
4200--- /dev/null
4201+++ b/fs/jffs2/jffs2_bbc_fs.c
4202@@ -0,0 +1,331 @@
4203+/*
4204+ * JFFS2-BBC: File System Extension for Linux Kernel
4205+ *
4206+ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
4207+ *
4208+ * Copyright (C) 2004, Ferenc Havasi
4209+ *
4210+ * This program is free software; you can redistribute it and/or
4211+ * modify it under the terms of the GNU General Public License
4212+ * as published by the Free Software Foundation; either version 2
4213+ * of the License, or (at your option) any later version.
4214+ *
4215+ * This program is distributed in the hope that it will be useful,
4216+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4217+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4218+ * GNU General Public License for more details.
4219+ *
4220+ * You should have received a copy of the GNU General Public License
4221+ * along with this program; if not, write to the Free Software
4222+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4223+ *
4224+ */
4225+
4226+#include <linux/kernel.h>
4227+#include <linux/fs.h>
4228+#include <linux/jffs2.h>
4229+#include <linux/proc_fs.h>
4230+#include <linux/version.h>
4231+
4232+#include "nodelist.h"
4233+
4234+#include "jffs2_bbc_framework.h"
4235+
4236+struct jffs2_bbc_fs_sb_list {
4237+ struct super_block *sb;
4238+ struct jffs2_bbc_fs_sb_list *next;
4239+};
4240+
4241+static struct jffs2_bbc_fs_sb_list *sb_list = NULL;
4242+
4243+void jffs2_bbc_proc_init(void);
4244+void jffs2_bbc_proc_deinit(void);
4245+
4246+void jffs2_bbc_load_model(void *sb_par) {
4247+ struct jffs2_sb_info *c;
4248+ //struct jffs2_inode_info *f;
4249+ struct dentry *config_dentry,*model_dentry;
4250+ struct qstr config_name,model_name;
4251+ struct file *config_file,*model_file;
4252+ char *buff=NULL,*model_buff;
4253+ int config_size,model_size;
4254+ int i,prev_i;
4255+ struct super_block *sb;
4256+ struct jffs2_bbc_fs_sb_list *sb_l;
4257+
4258+ sb = sb_par;
4259+ sb_l = jffs2_bbc_malloc_small(sizeof(struct jffs2_bbc_fs_sb_list));
4260+ sb_l->sb = sb;
4261+ sb_l->next = sb_list;
4262+ sb_list = sb_l;
4263+ config_name.name = JFFS2_BBC_CONFIG_FILE;
4264+ config_name.len = strlen(config_name.name);
4265+ config_name.hash = full_name_hash(config_name.name,config_name.len);
4266+ config_dentry = d_alloc(sb->s_root,&config_name);
4267+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
4268+ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,config_dentry);
4269+#else
4270+ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,config_dentry,NULL);
4271+#endif
4272+
4273+ if (config_dentry->d_inode != NULL) {
4274+ config_size = config_dentry->d_inode->i_size;
4275+ //printk("config_file_size=%d\n",config_size);
4276+ if (config_size > 0) {
4277+ buff = jffs2_bbc_malloc(config_size+1);
4278+ config_file = dentry_open(config_dentry,NULL,O_RDONLY);
4279+ kernel_read(config_file,0,buff,config_size);
4280+ buff[config_size] = 0;
4281+ for (prev_i = i = 0 ; i < config_size+1 ; i++) {
4282+ if (buff[i] == '\n') buff[i]=0;
4283+ if (buff[i] == 0) {
4284+ if (prev_i != i) {
4285+ if ((buff[prev_i] == '-') && (buff[prev_i+1] == 0)) break;
4286+ printk("reading model file %s... ",buff+prev_i);
4287+ model_name.name = buff+prev_i;
4288+ model_name.len = strlen(buff+prev_i);
4289+ model_name.hash = full_name_hash(model_name.name,model_name.len);
4290+ model_dentry = d_alloc(sb->s_root,&model_name);
4291+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,0)
4292+ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,model_dentry);
4293+#else
4294+ sb->s_root->d_inode->i_op->lookup(sb->s_root->d_inode,model_dentry,NULL);
4295+#endif
4296+ if (model_dentry->d_inode != NULL) {
4297+ c = JFFS2_SB_INFO(model_dentry->d_inode->i_sb);
4298+ //f = JFFS2_INODE_INFO(model_dentry->d_inode);
4299+ model_size = model_dentry->d_inode->i_size;
4300+ model_buff = jffs2_bbc_malloc(model_size);
4301+ model_file = dentry_open(model_dentry,NULL,O_RDONLY);
4302+ kernel_read(model_file,0,model_buff,model_size);
4303+ if (jffs2_bbc_model_new(c,model_dentry->d_inode->i_ino,model_buff) != 0) {
4304+ printk("already loaded.\n");
4305+ jffs2_bbc_free(model_buff);
4306+ }
4307+ else {
4308+ printk("done (%d bytes readed from inode %d).\n",model_size,(int)(model_dentry->d_inode->i_ino));
4309+ }
4310+ }
4311+ else {
4312+ printk("not found.\n");
4313+ }
4314+ dput(model_dentry);
4315+ }
4316+ prev_i = i+1;
4317+ }
4318+ }
4319+ }
4320+ }
4321+ dput(config_dentry);
4322+ if (buff != NULL) jffs2_bbc_free(buff);
4323+}
4324+
4325+void jffs2_bbc_unload_model(void *sb_par)
4326+{
4327+ struct jffs2_sb_info *c;
4328+ struct super_block *sb = sb_par;
4329+ struct jffs2_bbc_fs_sb_list *sb_l,*sb_l2;
4330+ int done = 0;
4331+
4332+ c = JFFS2_SB_INFO(sb);
4333+ jffs2_bbc_model_del(c);
4334+ if (sb_list == NULL) printk("jffs2.bbc: error! NULL sb list!\n");
4335+ else {
4336+ if (sb_list->sb == sb) {
4337+ jffs2_bbc_free_small(sb_list);
4338+ sb_list = NULL;
4339+ done = 1;
4340+ }
4341+ else {
4342+ sb_l = sb_list;
4343+ while (sb_l->next != NULL) {
4344+ if (sb_l->next->sb == sb) {
4345+ sb_l2 = sb_l->next->next;
4346+ jffs2_bbc_free_small(sb_l->next);
4347+ sb_l->next = sb_l2;
4348+ done = 1;
4349+ }
4350+ sb_l = sb_l->next;
4351+ }
4352+
4353+ }
4354+ if (done == 0) {
4355+ printk("jffs2.bbc: cannot delete sb from sblist!\n");
4356+ }
4357+ }
4358+}
4359+
4360+static int jffs2_bbc_get_mounted(void) {
4361+ struct jffs2_bbc_fs_sb_list *sb_l;
4362+ int num = 0;
4363+
4364+ sb_l = sb_list;
4365+ while (sb_l != NULL) {
4366+ num++;
4367+ sb_l = sb_l->next;
4368+ }
4369+ return num;
4370+
4371+}
4372+
4373+int jffs2_bbc_proc_read(char *buf, char **start, off_t offset, int count, int *eof, void *data)
4374+{
4375+ int len = 0, mode;
4376+
4377+ mode = jffs2_bbc_get_compression_mode();
4378+ len += sprintf(buf + len, "BBC version: %s\n", JFFS2_BBC_VERSION);
4379+ len += sprintf(buf+len,"Mounted jffs2 filesystems: %d\n",jffs2_bbc_get_mounted());
4380+ //len += sprintf(buf+len,"actual model file inode: %d\n",jffs2_bbc_model_get_inum());
4381+ len += sprintf(buf + len, "Compression mode: ");
4382+ if (mode == JFFS2_BBC_ZLIB_MODE)
4383+ len += sprintf(buf + len, "ZLIB mode");
4384+ else if (mode == JFFS2_BBC_SIZE_MODE)
4385+ len += sprintf(buf + len, "SIZE mode");
4386+ else if (mode == JFFS2_BBC_FASTR_MODE)
4387+ len += sprintf(buf + len, "FASTR mode");
4388+ else if (mode == JFFS2_BBC_FASTW_MODE)
4389+ len += sprintf(buf + len, "FASTW mode");
4390+ else if (mode == JFFS2_BBC_FASTS_MODE)
4391+ len += sprintf(buf + len, "FASTS mode");
4392+ else if (mode == JFFS2_BBC_DUMMY_MODE)
4393+ len += sprintf(buf + len, "DUMMY mode");
4394+ else if (mode == JFFS2_BBC_MANUAL_MODE) {
4395+ len += sprintf(buf + len, "MANUAL mode (");
4396+ if (jffs2_bbc_get_manual_compressor() != NULL)
4397+ len += sprintf(buf + len, "%s)", jffs2_bbc_get_manual_compressor()->name);
4398+ else
4399+ len += sprintf(buf + len, "ZLIB)");
4400+ }
4401+ else
4402+ len += sprintf(buf + len, "unknown mode");
4403+ len += sprintf(buf + len, "\n");
4404+ len += sprintf(buf + len, "%s", jffs2_bbc_get_compr_stats());
4405+ len += sprintf(buf + len, "%s", jffs2_bbc_get_model_stats());
4406+ len += sprintf(buf + len, "%s", jffs2_bbc_get_mem_stats());
4407+ *eof = 1;
4408+ return len;
4409+}
4410+
4411+int jffs2_bbc_proc_write(struct file *file, const char *buffer_orig, unsigned long count, void *data)
4412+{
4413+ char *buffer;
4414+ int i;
4415+ struct jffs2_bbc_fs_sb_list *sb_l;
4416+
4417+ if (buffer_orig == NULL) return 0;
4418+
4419+ buffer = jffs2_bbc_malloc(count+2);
4420+ for (i=0;i<count;i++) buffer[i]=buffer_orig[i];
4421+ buffer[count] = 0;
4422+ if ((*buffer == 'z') || (*buffer == 'Z')) {
4423+ jffs2_bbc_set_compression_mode(JFFS2_BBC_ZLIB_MODE);
4424+ jffs2_bbc_print1("jffs2.bbc: ZLIB compression mode activated.\n");
4425+ jffs2_bbc_free(buffer);
4426+ return count;
4427+ }
4428+ else if ((*buffer == 's') || (*buffer == 'S')) {
4429+ jffs2_bbc_set_compression_mode(JFFS2_BBC_SIZE_MODE);
4430+ jffs2_bbc_print1("jffs2.bbc: SIZE compression mode activated.\n");
4431+ jffs2_bbc_free(buffer);
4432+ return count;
4433+ }
4434+ else if ((*buffer == 'd') || (*buffer == 'D')) {
4435+ jffs2_bbc_set_compression_mode(JFFS2_BBC_DUMMY_MODE);
4436+ jffs2_bbc_print1("jffs2.bbc: DUMMY compression mode activated.\n");
4437+ jffs2_bbc_free(buffer);
4438+ return count;
4439+ }
4440+ else if (((*buffer == 'm') || (*buffer == 'M')) && (count >= 3) && (buffer[1] == ':')) {
4441+ jffs2_bbc_print1("jffs2.bbc: activating MANUAL mode.\n");
4442+ jffs2_bbc_set_manual_compressor_by_name(buffer + 2);
4443+ jffs2_bbc_free(buffer);
4444+ return count;
4445+ }
4446+ else if (((*buffer == '0')) && (count >= 3) && (buffer[1] == ':')) {
4447+ jffs2_bbc_print1("jffs2.bbc: disabling a compressor... ");
4448+ if (jffs2_bbc_disable_compressor_by_name(buffer + 2) == 0) {
4449+ jffs2_bbc_print1("done.\n");
4450+ }
4451+ else {
4452+ jffs2_bbc_print1("not found.\n");
4453+ }
4454+ jffs2_bbc_free(buffer);
4455+ return count;
4456+ }
4457+ else if (((*buffer == '1')) && (count >= 3) && (buffer[1] == ':')) {
4458+ jffs2_bbc_print1("jffs2.bbc: enabling a compressor... ");
4459+ if (jffs2_bbc_enable_compressor_by_name(buffer + 2) == 0) {
4460+ jffs2_bbc_print1("done.\n");
4461+ }
4462+ else {
4463+ jffs2_bbc_print1("not found.\n");
4464+ }
4465+ jffs2_bbc_free(buffer);
4466+ return count;
4467+ }
4468+ else if (((*buffer == 'c') || (*buffer == 'C')) && (count >= 3) && (buffer[1] == ':')) {
4469+ jffs2_bbc_compressor_command_by_name(buffer + 2);
4470+ jffs2_bbc_free(buffer);
4471+ return count;
4472+ }
4473+ else if ((*buffer == 'r') || (*buffer == 'R')) {
4474+ jffs2_bbc_print1("jffs2.bbc: reloading model files:\n");
4475+ sb_l = sb_list;
4476+ while (sb_l != NULL) {
4477+ jffs2_bbc_unload_model(sb_l->sb);
4478+ jffs2_bbc_load_model(sb_l->sb);
4479+ sb_l = sb_l->next;
4480+ }
4481+ jffs2_bbc_free(buffer);
4482+ return count;
4483+ }
4484+ else if (((buffer[0] == 'f') || (buffer[0] == 'F'))&&((buffer[1] == 'r') || (buffer[1] == 'R'))) {
4485+ jffs2_bbc_set_compression_mode(JFFS2_BBC_FASTR_MODE);
4486+ jffs2_bbc_print1("jffs2.bbc: FASTR compression mode activated.\n");
4487+ jffs2_bbc_free(buffer);
4488+ return count;
4489+ }
4490+ else if (((buffer[0] == 'f') || (buffer[0] == 'F'))&&((buffer[1] == 'w') || (buffer[1] == 'W'))) {
4491+ jffs2_bbc_set_compression_mode(JFFS2_BBC_FASTW_MODE);
4492+ jffs2_bbc_print1("jffs2.bbc: FASTW compression mode activated.\n");
4493+ jffs2_bbc_free(buffer);
4494+ return count;
4495+ }
4496+ else if (((buffer[0] == 'f') || (buffer[0] == 'F'))&&((buffer[1] == 's') || (buffer[1] == 'S'))) {
4497+ jffs2_bbc_set_compression_mode(JFFS2_BBC_FASTS_MODE);
4498+ jffs2_bbc_print1("jffs2.bbc: FASTS compression mode activated.\n");
4499+ jffs2_bbc_free(buffer);
4500+ return count;
4501+ }
4502+
4503+ jffs2_bbc_print1("jffs2.bbc: unkown command. Valid commands are:\n"
4504+ " z = switch to ZLIB compression mode\n"
4505+ " s = switch to SIZE compression mode\n"
4506+ " d = switch to DUMMY compression mode\n"
4507+ " fr = switch to FASTR compression mode\n"
4508+ " fw = switch to FASTW compression mode\n"
4509+ " fs = switch to FASTS compression mode\n"
4510+ " r = reread model files from actual file system\n"
4511+ " m:compressor_name = switch to MANUAL compression mode\n"
4512+ " 0:compressor_name = disable a compressor\n"
4513+ " 1:compressor_name = enable a compressor\n"
4514+ " c:compressor_name:command = enable a compressor\n");
4515+ jffs2_bbc_free(buffer);
4516+ return count;
4517+}
4518+
4519+void jffs2_bbc_proc_init()
4520+{
4521+ struct proc_dir_entry *res = create_proc_entry("jffs2_bbc", 0, NULL);
4522+ jffs2_bbc_compressor_init();
4523+ if (res) {
4524+ res->read_proc = jffs2_bbc_proc_read;
4525+ res->write_proc = jffs2_bbc_proc_write;
4526+ }
4527+}
4528+
4529+void jffs2_bbc_proc_deinit()
4530+{
4531+ jffs2_bbc_compressor_deinit();
4532+ remove_proc_entry("jffs2_bbc", NULL);
4533+}
4534--- /dev/null
4535+++ b/fs/jffs2/jffs2_bbc_fs.h
4536@@ -0,0 +1,30 @@
4537+/*
4538+ * JFFS2 BBC: File System Extension for Linux Kernel - headers
4539+ *
4540+ * $Id: 301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
4541+ *
4542+ * Copyright (C) 2004, Ferenc Havasi
4543+ *
4544+ * This program is free software; you can redistribute it and/or
4545+ * modify it under the terms of the GNU General Public License
4546+ * as published by the Free Software Foundation; either version 2
4547+ * of the License, or (at your option) any later version.
4548+ *
4549+ * This program is distributed in the hope that it will be useful,
4550+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
4551+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
4552+ * GNU General Public License for more details.
4553+ *
4554+ * You should have received a copy of the GNU General Public License
4555+ * along with this program; if not, write to the Free Software
4556+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
4557+ *
4558+ */
4559+
4560+extern int jffs2_bbc_inode_not_found;
4561+
4562+void jffs2_bbc_load_model(void *sb);
4563+void jffs2_bbc_unload_model(void *sb);
4564+
4565+void jffs2_bbc_proc_init(void);
4566+void jffs2_bbc_proc_deinit(void);
4567--- /dev/null
4568+++ b/fs/jffs2/jffs2_bbc_lzari_comp.c
4569@@ -0,0 +1,788 @@
4570+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
4571+
4572+/*
4573+ jffs2_bbc_lzari_comp.c -- Lempel-Ziv-Arithmetic coding compression module for jffs2
4574+ Copyright (C) 2004 Patrik Kluba
4575+ Based on the LZARI source included in LDS (lossless datacompression sources)
4576+ Block-compression and bitstream modifications by Patrik Kluba
4577+ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
4578+*/
4579+
4580+/*
4581+Original copyright follows:
4582+
4583+**************************************************************
4584+ LZARI.C -- A Data Compression Program
4585+ (tab = 4 spaces)
4586+**************************************************************
4587+ 4/7/1989 Haruhiko Okumura
4588+ Use, distribute, and modify this program freely.
4589+ Please send me your improved versions.
4590+ PC-VAN SCIENCE
4591+ NIFTY-Serve PAF01022
4592+ CompuServe 74050,1022
4593+**************************************************************
4594+
4595+LZARI.C (c)1989 by Haruyasu Yoshizaki, Haruhiko Okumura, and Kenji Rikitake.
4596+All rights reserved. Permission granted for non-commercial use.
4597+
4598+*/
4599+
4600+/*
4601+
4602+ 2004-02-18 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
4603+ Removed unused variables and fixed no return value
4604+
4605+ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
4606+ Initial release
4607+
4608+*/
4609+
4610+/* lzari.c */
4611+
4612+#define N 4096 /* size of ring buffer */
4613+#define F 60 /* upper limit for match_length */
4614+#define THRESHOLD 2 /* encode string into position and length
4615+ if match_length is greater than this */
4616+#define NIL N /* index for root of binary search trees */
4617+
4618+static unsigned char
4619+ text_buf[N + F - 1]; /* ring buffer of size N,
4620+ with extra F-1 bytes to facilitate string comparison */
4621+static unsigned long match_position, match_length, /* of longest match. These are
4622+ set by the InsertNode() procedure. */
4623+ lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children &
4624+ parents -- These constitute binary search trees. */
4625+
4626+static void InitTree(void) /* Initialize trees */
4627+{
4628+ unsigned long i;
4629+
4630+ /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
4631+ left children of node i. These nodes need not be initialized.
4632+ Also, dad[i] is the parent of node i. These are initialized to
4633+ NIL (= N), which stands for 'not used.'
4634+ For i = 0 to 255, rson[N + i + 1] is the root of the tree
4635+ for strings that begin with character i. These are initialized
4636+ to NIL. Note there are 256 trees. */
4637+
4638+ for (i = N + 1; i <= N + 256; i++) rson[i] = NIL; /* root */
4639+ for (i = 0; i < N; i++) dad[i] = NIL; /* node */
4640+}
4641+
4642+static void InsertNode(unsigned long r)
4643+ /* Inserts string of length F, text_buf[r..r+F-1], into one of the
4644+ trees (text_buf[r]'th tree) and returns the longest-match position
4645+ and length via the global variables match_position and match_length.
4646+ If match_length = F, then removes the old node in favor of the new
4647+ one, because the old one will be deleted sooner.
4648+ Note r plays double role, as tree node and position in buffer. */
4649+{
4650+ unsigned long i, p, temp;
4651+ unsigned char *key;
4652+ signed long cmp;
4653+
4654+ cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
4655+ rson[r] = lson[r] = NIL; match_length = 0;
4656+ for ( ; ; ) {
4657+ if (cmp >= 0) {
4658+ if (rson[p] != NIL) p = rson[p];
4659+ else { rson[p] = r; dad[r] = p; return; }
4660+ } else {
4661+ if (lson[p] != NIL) p = lson[p];
4662+ else { lson[p] = r; dad[r] = p; return; }
4663+ }
4664+ for (i = 1; i < F; i++)
4665+ if ((cmp = key[i] - text_buf[p + i]) != 0) break;
4666+ if (i > THRESHOLD) {
4667+ if (i > match_length) {
4668+ match_position = (r - p) & (N - 1);
4669+ if ((match_length = i) >= F) break;
4670+ } else if (i == match_length) {
4671+ if ((temp = (r - p) & (N - 1)) < match_position)
4672+ match_position = temp;
4673+ }
4674+ }
4675+ }
4676+ dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
4677+ dad[lson[p]] = r; dad[rson[p]] = r;
4678+ if (rson[dad[p]] == p) rson[dad[p]] = r;
4679+ else lson[dad[p]] = r;
4680+ dad[p] = NIL; /* remove p */
4681+}
4682+
4683+static void DeleteNode(unsigned long p) /* Delete node p from tree */
4684+{
4685+ unsigned long q;
4686+
4687+ if (dad[p] == NIL) return; /* not in tree */
4688+ if (rson[p] == NIL) q = lson[p];
4689+ else if (lson[p] == NIL) q = rson[p];
4690+ else {
4691+ q = lson[p];
4692+ if (rson[q] != NIL) {
4693+ do { q = rson[q]; } while (rson[q] != NIL);
4694+ rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
4695+ lson[q] = lson[p]; dad[lson[p]] = q;
4696+ }
4697+ rson[q] = rson[p]; dad[rson[p]] = q;
4698+ }
4699+ dad[q] = dad[p];
4700+ if (rson[dad[p]] == p) rson[dad[p]] = q;
4701+ else lson[dad[p]] = q;
4702+ dad[p] = NIL;
4703+}
4704+
4705+/********** Arithmetic Compression **********/
4706+
4707+/* If you are not familiar with arithmetic compression, you should read
4708+ I. E. Witten, R. M. Neal, and J. G. Cleary,
4709+ Communications of the ACM, Vol. 30, pp. 520-540 (1987),
4710+ from which much have been borrowed. */
4711+
4712+#define M 15
4713+
4714+/* Q1 (= 2 to the M) must be sufficiently large, but not so
4715+ large as the unsigned long 4 * Q1 * (Q1 - 1) overflows. */
4716+
4717+#define Q1 (1UL << M)
4718+#define Q2 (2 * Q1)
4719+#define Q3 (3 * Q1)
4720+#define Q4 (4 * Q1)
4721+#define MAX_CUM (Q1 - 1)
4722+
4723+#define N_CHAR (256 - THRESHOLD + F)
4724+ /* character code = 0, 1, ..., N_CHAR - 1 */
4725+
4726+static unsigned long char_to_sym[N_CHAR], sym_to_char[N_CHAR + 1];
4727+static unsigned long
4728+ sym_freq[N_CHAR + 1], /* frequency for symbols */
4729+ sym_cum[N_CHAR + 1], /* cumulative freq for symbols */
4730+ position_cum[N + 1]; /* cumulative freq for positions */
4731+
4732+static void StartModel(void) /* Initialize model */
4733+{
4734+ unsigned long ch, sym, i;
4735+
4736+ sym_cum[N_CHAR] = 0;
4737+ for (sym = N_CHAR; sym >= 1; sym--) {
4738+ ch = sym - 1;
4739+ char_to_sym[ch] = sym; sym_to_char[sym] = ch;
4740+ sym_freq[sym] = 1;
4741+ sym_cum[sym - 1] = sym_cum[sym] + sym_freq[sym];
4742+ }
4743+ sym_freq[0] = 0; /* sentinel (!= sym_freq[1]) */
4744+ position_cum[N] = 0;
4745+ for (i = N; i >= 1; i--)
4746+ position_cum[i - 1] = position_cum[i] + 10000 / (i + 200);
4747+ /* empirical distribution function (quite tentative) */
4748+ /* Please devise a better mechanism! */
4749+}
4750+
4751+static void UpdateModel(unsigned long sym)
4752+{
4753+ unsigned long c, ch_i, ch_sym;
4754+ unsigned long i;
4755+ if (sym_cum[0] >= MAX_CUM) {
4756+ c = 0;
4757+ for (i = N_CHAR; i > 0; i--) {
4758+ sym_cum[i] = c;
4759+ c += (sym_freq[i] = (sym_freq[i] + 1) >> 1);
4760+ }
4761+ sym_cum[0] = c;
4762+ }
4763+ for (i = sym; sym_freq[i] == sym_freq[i - 1]; i--) ;
4764+ if (i < sym) {
4765+ ch_i = sym_to_char[i]; ch_sym = sym_to_char[sym];
4766+ sym_to_char[i] = ch_sym; sym_to_char[sym] = ch_i;
4767+ char_to_sym[ch_i] = sym; char_to_sym[ch_sym] = i;
4768+ }
4769+ sym_freq[i]++;
4770+ while (--i > 0) sym_cum[i]++;
4771+ sym_cum[0]++;
4772+}
4773+
4774+static unsigned long BinarySearchSym(unsigned long x)
4775+ /* 1 if x >= sym_cum[1],
4776+ N_CHAR if sym_cum[N_CHAR] > x,
4777+ i such that sym_cum[i - 1] > x >= sym_cum[i] otherwise */
4778+{
4779+ unsigned long i, j, k;
4780+
4781+ i = 1; j = N_CHAR;
4782+ while (i < j) {
4783+ k = (i + j) / 2;
4784+ if (sym_cum[k] > x) i = k + 1; else j = k;
4785+ }
4786+ return i;
4787+}
4788+
4789+unsigned long BinarySearchPos(unsigned long x)
4790+ /* 0 if x >= position_cum[1],
4791+ N - 1 if position_cum[N] > x,
4792+ i such that position_cum[i] > x >= position_cum[i + 1] otherwise */
4793+{
4794+ unsigned long i, j, k;
4795+
4796+ i = 1; j = N;
4797+ while (i < j) {
4798+ k = (i + j) / 2;
4799+ if (position_cum[k] > x) i = k + 1; else j = k;
4800+ }
4801+ return i - 1;
4802+}
4803+
4804+/* modified for block compression */
4805+/* on return, srclen will contain the number of successfully compressed bytes
4806+ and dstlen will contain completed compressed bytes */
4807+
4808+static int Encode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long *srclen,
4809+ unsigned long *dstlen)
4810+{
4811+ unsigned long c, i, len, r, s, last_match_length, sym, range;
4812+ unsigned long low = 0;
4813+ unsigned long high = Q4;
4814+ unsigned long shifts = 0; /* counts for magnifying low and high around Q2 */
4815+ unsigned char *ip, *op;
4816+ unsigned long written = 0;
4817+ unsigned long read = 0;
4818+ unsigned char buffer = 0;
4819+ unsigned char mask = 128;
4820+ unsigned char *srcend = srcbuf + *srclen;
4821+ unsigned char *dstend = dstbuf + *dstlen;
4822+ ip = srcbuf;
4823+ op = dstbuf;
4824+ StartModel();
4825+ InitTree(); /* initialize trees */
4826+ s = 0; r = N - F;
4827+ for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with
4828+ any character that will appear often. */
4829+ for (len = 0; (len < F) && (ip < srcend); len++)
4830+ text_buf[r + len] = *(ip++); /* Read F bytes into the last F bytes of
4831+ the buffer */
4832+ read = len;
4833+ for (i = 1; i <= F; i++) InsertNode(r - i); /* Insert the F strings,
4834+ each of which begins with one or more 'space' characters. Note
4835+ the order in which these strings are inserted. This way,
4836+ degenerate trees will be less likely to occur. */
4837+ InsertNode(r); /* Finally, insert the whole string just read. The
4838+ global variables match_length and match_position are set. */
4839+ do {
4840+ if (match_length > len) match_length = len; /* match_length
4841+ may be spuriously long near the end of text. */
4842+ if (match_length <= THRESHOLD) {
4843+ match_length = 1; /* Not long enough match. Send one byte. */
4844+ sym = char_to_sym[text_buf[r]];
4845+ range = high - low;
4846+ high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
4847+ low += (range * sym_cum[sym ]) / sym_cum[0];
4848+ for ( ; ; ) {
4849+ if (high <= Q2) {
4850+ if ((mask >>= 1) == 0) {
4851+ if (op >= dstend) {
4852+ *dstlen = written;
4853+ return -1;
4854+ }
4855+ *(op++) = buffer;
4856+ buffer = 0;
4857+ mask = 128;
4858+ written++;
4859+ *srclen = read;
4860+ }
4861+ for ( ; shifts > 0; shifts--) {
4862+ buffer |= mask;
4863+ if ((mask >>= 1) == 0) {
4864+ if (op >= dstend) {
4865+ *dstlen = written;
4866+ return -1;
4867+ }
4868+ *(op++) = buffer;
4869+ buffer = 0;
4870+ mask = 128;
4871+ written++;
4872+ *srclen = read;
4873+ }
4874+ }
4875+ } else if (low >= Q2) {
4876+ buffer |= mask;
4877+ if ((mask >>= 1) == 0) {
4878+ if (op >= dstend) {
4879+ *dstlen = written;
4880+ return -1;
4881+ }
4882+ *(op++) = buffer;
4883+ buffer = 0;
4884+ mask = 128;
4885+ written++;
4886+ *srclen = read;
4887+ }
4888+ for ( ; shifts > 0; shifts--) {
4889+ if ((mask >>= 1) == 0) {
4890+ if (op >= dstend) {
4891+ *dstlen = written;
4892+ return -1;
4893+ }
4894+ *(op++) = buffer;
4895+ buffer = 0;
4896+ mask = 128;
4897+ written++;
4898+ *srclen = read;
4899+ }
4900+ }
4901+ low -= Q2;
4902+ high -= Q2;
4903+ } else if (low >= Q1 && high <= Q3) {
4904+ shifts++;
4905+ low -= Q1;
4906+ high -= Q1;
4907+ } else break;
4908+ low += low; high += high;
4909+ }
4910+ UpdateModel(sym);
4911+ } else {
4912+ sym = char_to_sym[255 - THRESHOLD + match_length];
4913+ range = high - low;
4914+ high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
4915+ low += (range * sym_cum[sym ]) / sym_cum[0];
4916+ for ( ; ; ) {
4917+ if (high <= Q2) {
4918+ if ((mask >>= 1) == 0) {
4919+ if (op >= dstend) {
4920+ *dstlen = written;
4921+ return -1;
4922+ }
4923+ *(op++) = buffer;
4924+ buffer = 0;
4925+ mask = 128;
4926+ written++;
4927+ *srclen = read;
4928+ }
4929+ for ( ; shifts > 0; shifts--) {
4930+ buffer |= mask;
4931+ if ((mask >>= 1) == 0) {
4932+ if (op >= dstend) {
4933+ *dstlen = written;
4934+ return -1;
4935+ }
4936+ *(op++) = buffer;
4937+ buffer = 0;
4938+ mask = 128;
4939+ written++;
4940+ *srclen = read;
4941+ }
4942+ }
4943+ } else if (low >= Q2) {
4944+ buffer |= mask;
4945+ if ((mask >>= 1) == 0) {
4946+ if (op >= dstend) {
4947+ *dstlen = written;
4948+ return -1;
4949+ }
4950+ *(op++) = buffer;
4951+ buffer = 0;
4952+ mask = 128;
4953+ written++;
4954+ *srclen = read;
4955+ }
4956+ for ( ; shifts > 0; shifts--) {
4957+ if ((mask >>= 1) == 0) {
4958+ if (op >= dstend) {
4959+ *dstlen = written;
4960+ return -1;
4961+ }
4962+ *(op++) = buffer;
4963+ buffer = 0;
4964+ mask = 128;
4965+ written++;
4966+ *srclen = read;
4967+ }
4968+ }
4969+ low -= Q2;
4970+ high -= Q2;
4971+ } else if (low >= Q1 && high <= Q3) {
4972+ shifts++;
4973+ low -= Q1;
4974+ high -= Q1;
4975+ } else break;
4976+ low += low; high += high;
4977+ }
4978+ UpdateModel(sym);
4979+ range = high - low;
4980+ high = low + (range * position_cum[match_position - 1]) / position_cum[0];
4981+ low += (range * position_cum[match_position ]) / position_cum[0];
4982+ for ( ; ; ) {
4983+ if (high <= Q2) {
4984+ if ((mask >>= 1) == 0) {
4985+ if (op >= dstend) {
4986+ *dstlen = written;
4987+ return -1;
4988+ }
4989+ *(op++) = buffer;
4990+ buffer = 0;
4991+ mask = 128;
4992+ written++;
4993+ *srclen = read;
4994+ }
4995+ for ( ; shifts > 0; shifts--) {
4996+ buffer |= mask;
4997+ if ((mask >>= 1) == 0) {
4998+ if (op >= dstend) {
4999+ *dstlen = written;
5000+ return -1;
5001+ }
5002+ *(op++) = buffer;
5003+ buffer = 0;
5004+ mask = 128;
5005+ written++;
5006+ *srclen = read;
5007+ }
5008+ }
5009+ } else {
5010+ if (low >= Q2) {
5011+ buffer |= mask;
5012+ if ((mask >>= 1) == 0) {
5013+ if (op >= dstend) {
5014+ *dstlen = written;
5015+ return -1;
5016+ }
5017+ *(op++) = buffer;
5018+ buffer = 0;
5019+ mask = 128;
5020+ written++;
5021+ *srclen = read;
5022+ }
5023+ for ( ; shifts > 0; shifts--) {
5024+ if ((mask >>= 1) == 0) {
5025+ if (op >= dstend) {
5026+ *dstlen = written;
5027+ return -1;
5028+ }
5029+ *(op++) = buffer;
5030+ buffer = 0;
5031+ mask = 128;
5032+ written++;
5033+ *srclen = read;
5034+ }
5035+ }
5036+ low -= Q2;
5037+ high -= Q2;
5038+ } else {
5039+ if ((low >= Q1) && (high <= Q3)) {
5040+ shifts++;
5041+ low -= Q1;
5042+ high -= Q1;
5043+ } else {
5044+ break;
5045+ }
5046+ }
5047+ }
5048+ low += low;
5049+ high += high;
5050+ }
5051+ }
5052+ last_match_length = match_length;
5053+ for (i = 0; (i < last_match_length) && (ip < srcend); i++) {
5054+ c = *(ip++);
5055+ DeleteNode(s);
5056+ text_buf[s] = c;
5057+ if (s < F - 1)
5058+ text_buf[s + N] = c;
5059+ s = (s + 1) & (N - 1);
5060+ r = (r + 1) & (N - 1);
5061+ InsertNode(r);
5062+ }
5063+ read += i;
5064+ while (i++ < last_match_length) {
5065+ DeleteNode(s);
5066+ s = (s + 1) & (N - 1);
5067+ r = (r + 1) & (N - 1);
5068+ if (--len) InsertNode(r);
5069+ }
5070+ } while (len > 0);
5071+ shifts++;
5072+ if (low < Q1) {
5073+ if ((mask >>= 1) == 0) {
5074+ if (op >= dstend) {
5075+ *dstlen = written;
5076+ return -1;
5077+ }
5078+ *(op++) = buffer;
5079+ buffer = 0;
5080+ mask = 128;
5081+ written++;
5082+ *srclen = read;
5083+ }
5084+ for ( ; shifts > 0; shifts--) {
5085+ buffer |= mask;
5086+ if ((mask >>= 1) == 0) {
5087+ if (op >= dstend) {
5088+ *dstlen = written;
5089+ return -1;
5090+ }
5091+ *(op++) = buffer;
5092+ buffer = 0;
5093+ mask = 128;
5094+ written++;
5095+ *srclen = read;
5096+ }
5097+ }
5098+ } else {
5099+ buffer |= mask;
5100+ if ((mask >>= 1) == 0) {
5101+ if (op >= dstend) {
5102+ *dstlen = written;
5103+ return -1;
5104+ }
5105+ *(op++) = buffer;
5106+ buffer = 0;
5107+ mask = 128;
5108+ written++;
5109+ *srclen = read;
5110+ }
5111+ for ( ; shifts > 0; shifts--) {
5112+ if ((mask >>= 1) == 0) {
5113+ if (op >= dstend) {
5114+ *dstlen = written;
5115+ return -1;
5116+ }
5117+ *(op++) = buffer;
5118+ buffer = 0;
5119+ mask = 128;
5120+ written++;
5121+ *srclen = read;
5122+ }
5123+ }
5124+ }
5125+ for (i = 0; i < 7; i++) {
5126+ if ((mask >>= 1) == 0) {
5127+ if (op >= dstend) {
5128+ *dstlen = written;
5129+ return -1;
5130+ }
5131+ *(op++) = buffer;
5132+ buffer = 0;
5133+ mask = 128;
5134+ written++;
5135+ *srclen = read;
5136+ }
5137+ }
5138+ *dstlen = written;
5139+ return 0;
5140+}
5141+
5142+static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
5143+ unsigned long dstlen) /* Just the reverse of Encode(). */
5144+{
5145+ unsigned long i, r, j, k, c, range, sym;
5146+ unsigned char *ip, *op;
5147+ unsigned char *srcend = srcbuf + srclen;
5148+ unsigned char *dstend = dstbuf + dstlen;
5149+ unsigned char buffer = 0;
5150+ unsigned char mask = 0;
5151+ unsigned long low = 0;
5152+ unsigned long high = Q4;
5153+ unsigned long value = 0;
5154+ ip = srcbuf;
5155+ op = dstbuf;
5156+ for (i = 0; i < M + 2; i++) {
5157+ value *= 2;
5158+ if ((mask >>= 1) == 0) {
5159+ buffer = (ip >= srcend) ? 0 : *(ip++);
5160+ mask = 128;
5161+ }
5162+ value += ((buffer & mask) != 0);
5163+ }
5164+ StartModel();
5165+ for (i = 0; i < N - F; i++) text_buf[i] = ' ';
5166+ r = N - F;
5167+ while (op < dstend) {
5168+ range = high - low;
5169+ sym = BinarySearchSym((unsigned long)
5170+ (((value - low + 1) * sym_cum[0] - 1) / range));
5171+ high = low + (range * sym_cum[sym - 1]) / sym_cum[0];
5172+ low += (range * sym_cum[sym ]) / sym_cum[0];
5173+ for ( ; ; ) {
5174+ if (low >= Q2) {
5175+ value -= Q2; low -= Q2; high -= Q2;
5176+ } else if (low >= Q1 && high <= Q3) {
5177+ value -= Q1; low -= Q1; high -= Q1;
5178+ } else if (high > Q2) break;
5179+ low += low; high += high;
5180+ value *= 2;
5181+ if ((mask >>= 1) == 0) {
5182+ buffer = (ip >= srcend) ? 0 : *(ip++);
5183+ mask = 128;
5184+ }
5185+ value += ((buffer & mask) != 0);
5186+ }
5187+ c = sym_to_char[sym];
5188+ UpdateModel(sym);
5189+ if (c < 256) {
5190+ if (op >= dstend) return -1;
5191+ *(op++) = c;
5192+ text_buf[r++] = c;
5193+ r &= (N - 1);
5194+ } else {
5195+ j = c - 255 + THRESHOLD;
5196+ range = high - low;
5197+ i = BinarySearchPos((unsigned long)
5198+ (((value - low + 1) * position_cum[0] - 1) / range));
5199+ high = low + (range * position_cum[i ]) / position_cum[0];
5200+ low += (range * position_cum[i + 1]) / position_cum[0];
5201+ for ( ; ; ) {
5202+ if (low >= Q2) {
5203+ value -= Q2; low -= Q2; high -= Q2;
5204+ } else if (low >= Q1 && high <= Q3) {
5205+ value -= Q1; low -= Q1; high -= Q1;
5206+ } else if (high > Q2) break;
5207+ low += low; high += high;
5208+ value *= 2;
5209+ if ((mask >>= 1) == 0) {
5210+ buffer = (ip >= srcend) ? 0 : *(ip++);
5211+ mask = 128;
5212+ }
5213+ value += ((buffer & mask) != 0);
5214+ }
5215+ i = (r - i - 1) & (N - 1);
5216+ for (k = 0; k < j; k++) {
5217+ c = text_buf[(i + k) & (N - 1)];
5218+ if (op >= dstend) return -1;
5219+ *(op++) = c;
5220+ text_buf[r++] = c;
5221+ r &= (N - 1);
5222+ }
5223+ }
5224+ }
5225+ return 0;
5226+}
5227+
5228+/* interface to jffs2 bbc follows */
5229+
5230+#include "jffs2_bbc_framework.h"
5231+
5232+#define JFFS2_BBC_LZARI_BLOCK_SIGN {0x73, 0x9a, 0x1c, 0x4d}
5233+
5234+static int
5235+jffs2_bbc_lzari_compressor_init (void);
5236+
5237+static void
5238+jffs2_bbc_lzari_compressor_deinit (void);
5239+
5240+static int
5241+jffs2_bbc_lzari_compress (void *model, unsigned char *input,
5242+ unsigned char *output, unsigned long *sourcelen,
5243+ unsigned long *dstlen);
5244+
5245+static int
5246+jffs2_bbc_lzari_estimate (void *model, unsigned char *input,
5247+ unsigned long sourcelen, unsigned long *dstlen,
5248+ unsigned long *readtime, unsigned long *writetime);
5249+
5250+static int
5251+jffs2_bbc_lzari_decompress (void *model, unsigned char *input,
5252+ unsigned char *output, unsigned long sourcelen,
5253+ unsigned long dstlen);
5254+
5255+static char *
5256+jffs2_bbc_lzari_proc_info (void);
5257+
5258+static int
5259+jffs2_bbc_lzari_proc_command (char *command);
5260+
5261+struct jffs2_bbc_compressor_type jffs2_bbc_lzari = {
5262+ "lzari",
5263+ 0,
5264+ JFFS2_BBC_LZARI_BLOCK_SIGN,
5265+ jffs2_bbc_lzari_compressor_init,
5266+ NULL,
5267+ NULL,
5268+ jffs2_bbc_lzari_compressor_deinit,
5269+ jffs2_bbc_lzari_compress,
5270+ jffs2_bbc_lzari_estimate,
5271+ jffs2_bbc_lzari_decompress,
5272+ jffs2_bbc_lzari_proc_info,
5273+ jffs2_bbc_lzari_proc_command
5274+};
5275+
5276+static int
5277+jffs2_bbc_lzari_compressor_init (void)
5278+{
5279+ return 0;
5280+}
5281+
5282+static void
5283+jffs2_bbc_lzari_compressor_deinit (void)
5284+{
5285+}
5286+
5287+static int
5288+jffs2_bbc_lzari_compress (void *model, unsigned char *input,
5289+ unsigned char *output, unsigned long *sourcelen,
5290+ unsigned long *dstlen)
5291+{
5292+ int retval;
5293+ unsigned long dst = *dstlen;
5294+ *(output++) = jffs2_bbc_lzari.block_sign[0];
5295+ *(output++) = jffs2_bbc_lzari.block_sign[1];
5296+ dst -= 2;
5297+ retval = Encode(input, output, sourcelen, &dst);
5298+ dst += 2;
5299+ *dstlen = dst;
5300+ return retval;
5301+}
5302+
5303+static int
5304+jffs2_bbc_lzari_estimate (void *model, unsigned char *input,
5305+ unsigned long sourcelen, unsigned long *dstlen,
5306+ unsigned long *readtime, unsigned long *writetime)
5307+{
5308+ *dstlen = sourcelen / 2;
5309+ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 15;
5310+ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 7;
5311+ return 0;
5312+}
5313+
5314+static int
5315+jffs2_bbc_lzari_decompress (void *model, unsigned char *input,
5316+ unsigned char *output, unsigned long sourcelen,
5317+ unsigned long dstlen)
5318+{
5319+ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzari.block_sign[0] ) ||
5320+ ( *(input++) != (unsigned char)jffs2_bbc_lzari.block_sign[1] )
5321+ ) {
5322+ return -1;
5323+ } else {
5324+ return Decode(input, output, sourcelen - 2, dstlen);
5325+ }
5326+}
5327+
5328+static char *
5329+jffs2_bbc_lzari_proc_info (void)
5330+{
5331+ return "Lempel-Ziv-Arithmetic coding compression module";
5332+}
5333+
5334+static int
5335+jffs2_bbc_lzari_proc_command (char *command)
5336+{
5337+ return 0;
5338+}
5339+
5340+struct jffs2_bbc_compressor_type *
5341+jffs2_bbc_lzari_init (int mode)
5342+{
5343+ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzari) == 0)
5344+ {
5345+ return &jffs2_bbc_lzari;
5346+ }
5347+ else
5348+ {
5349+ return NULL;
5350+ }
5351+}
5352+
5353+void
5354+jffs2_bbc_lzari_deinit (void)
5355+{
5356+ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzari);
5357+}
5358--- /dev/null
5359+++ b/fs/jffs2/jffs2_bbc_lzhd_comp.c
5360@@ -0,0 +1,747 @@
5361+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
5362+
5363+/*
5364+ jffs2_bbc_lzhd_comp.c -- Lempel-Ziv-(dynamic) Huffman compression module for jffs2
5365+ Copyright (C) 2004 Patrik Kluba
5366+ Based on the LZHUF source included in LDS (lossless datacompression sources)
5367+ Block-compression and bitstream modifications by Patrik Kluba
5368+ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
5369+*/
5370+
5371+/*
5372+Original copyright follows:
5373+
5374+**************************************************************
5375+ lzhuf.c
5376+ written by Haruyasu Yoshizaki 11/20/1988
5377+ some minor changes 4/6/1989
5378+ comments translated by Haruhiko Okumura 4/7/1989
5379+**************************************************************
5380+
5381+LZHUF.C (c)1989 by Haruyasu Yoshizaki, Haruhiko Okumura, and Kenji Rikitake.
5382+All rights reserved. Permission granted for non-commercial use.
5383+
5384+*/
5385+
5386+/*
5387+
5388+ 2004-02-18 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
5389+ Replaced name lzh-d with lzhd
5390+ Fixed no return value
5391+
5392+ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
5393+ Initial release
5394+
5395+*/
5396+
5397+/* required because of memmove */
5398+#ifndef __KERNEL__
5399+ #include <string.h>
5400+#else
5401+ #include <linux/string.h>
5402+#endif
5403+
5404+/* lzhuf.c */
5405+
5406+#define N 4096 /* size of ring buffer */
5407+#define F 60 /* upper limit for match_length */
5408+#define THRESHOLD 2 /* encode string into position and length
5409+ if match_length is greater than this */
5410+#define NIL N /* index for root of binary search trees */
5411+
5412+static unsigned char
5413+ text_buf[N + F - 1]; /* ring buffer of size N,
5414+ with extra F-1 bytes to facilitate string comparison */
5415+static unsigned long match_position, match_length, /* of longest match. These are
5416+ set by the InsertNode() procedure. */
5417+ lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children &
5418+ parents -- These constitute binary search trees. */
5419+
5420+static void InitTree(void) /* initialize trees */
5421+{
5422+ unsigned long i;
5423+
5424+ /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
5425+ left children of node i. These nodes need not be initialized.
5426+ Also, dad[i] is the parent of node i. These are initialized to
5427+ NIL (= N), which stands for 'not used.'
5428+ For i = 0 to 255, rson[N + i + 1] is the root of the tree
5429+ for strings that begin with character i. These are initialized
5430+ to NIL. Note there are 256 trees. */
5431+
5432+ for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;
5433+ for (i = 0; i < N; i++) dad[i] = NIL;
5434+}
5435+
5436+static void InsertNode(unsigned long r)
5437+ /* Inserts string of length F, text_buf[r..r+F-1], into one of the
5438+ trees (text_buf[r]'th tree) and returns the longest-match position
5439+ and length via the global variables match_position and match_length.
5440+ If match_length = F, then removes the old node in favor of the new
5441+ one, because the old one will be deleted sooner.
5442+ Note r plays double role, as tree node and position in buffer. */
5443+{
5444+ unsigned long i, p, c;
5445+ signed long cmp;
5446+ unsigned char *key;
5447+
5448+ cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
5449+ rson[r] = lson[r] = NIL; match_length = 0;
5450+ for ( ; ; ) {
5451+ if (cmp >= 0) {
5452+ if (rson[p] != NIL) p = rson[p];
5453+ else { rson[p] = r; dad[r] = p; return; }
5454+ } else {
5455+ if (lson[p] != NIL) p = lson[p];
5456+ else { lson[p] = r; dad[r] = p; return; }
5457+ }
5458+ for (i = 1; i < F; i++)
5459+ if ((cmp = key[i] - text_buf[p + i]) != 0) break;
5460+ if (i > THRESHOLD) {
5461+ if (i > match_length) {
5462+ match_position = ((r - p) & (N - 1)) - 1;
5463+ if ((match_length = i) >= F) break;
5464+ }
5465+ if (i == match_length) {
5466+ if ((c = ((r - p) & (N - 1)) - 1) < match_position) {
5467+ match_position = c;
5468+ }
5469+ }
5470+ }
5471+ }
5472+ dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
5473+ dad[lson[p]] = r; dad[rson[p]] = r;
5474+ if (rson[dad[p]] == p) rson[dad[p]] = r;
5475+ else lson[dad[p]] = r;
5476+ dad[p] = NIL; /* remove p */
5477+}
5478+
5479+static void DeleteNode(unsigned long p) /* deletes node p from tree */
5480+{
5481+ unsigned long q;
5482+
5483+ if (dad[p] == NIL) return; /* not in tree */
5484+ if (rson[p] == NIL) q = lson[p];
5485+ else if (lson[p] == NIL) q = rson[p];
5486+ else {
5487+ q = lson[p];
5488+ if (rson[q] != NIL) {
5489+ do { q = rson[q]; } while (rson[q] != NIL);
5490+ rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
5491+ lson[q] = lson[p]; dad[lson[p]] = q;
5492+ }
5493+ rson[q] = rson[p]; dad[rson[p]] = q;
5494+ }
5495+ dad[q] = dad[p];
5496+ if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q;
5497+ dad[p] = NIL;
5498+}
5499+
5500+/* Huffman coding */
5501+
5502+#define N_CHAR (256 - THRESHOLD + F)
5503+ /* kinds of characters (character code = 0..N_CHAR-1) */
5504+#define T (N_CHAR * 2 - 1) /* size of table */
5505+#define R (T - 1) /* position of root */
5506+#define MAX_FREQ 0x8000 /* updates tree when the */
5507+ /* root frequency comes to this value. */
5508+
5509+typedef unsigned long uchar; // much-much faster
5510+
5511+/* table for encoding and decoding the upper 6 bits of position */
5512+
5513+/* for encoding */
5514+static uchar p_len[64] = {
5515+ 0x03, 0x04, 0x04, 0x04, 0x05, 0x05, 0x05, 0x05,
5516+ 0x05, 0x05, 0x05, 0x05, 0x06, 0x06, 0x06, 0x06,
5517+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5518+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5519+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5520+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5521+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
5522+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08
5523+};
5524+
5525+static uchar p_code[64] = {
5526+ 0x00, 0x20, 0x30, 0x40, 0x50, 0x58, 0x60, 0x68,
5527+ 0x70, 0x78, 0x80, 0x88, 0x90, 0x94, 0x98, 0x9C,
5528+ 0xA0, 0xA4, 0xA8, 0xAC, 0xB0, 0xB4, 0xB8, 0xBC,
5529+ 0xC0, 0xC2, 0xC4, 0xC6, 0xC8, 0xCA, 0xCC, 0xCE,
5530+ 0xD0, 0xD2, 0xD4, 0xD6, 0xD8, 0xDA, 0xDC, 0xDE,
5531+ 0xE0, 0xE2, 0xE4, 0xE6, 0xE8, 0xEA, 0xEC, 0xEE,
5532+ 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
5533+ 0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xFF
5534+};
5535+
5536+/* for decoding */
5537+static uchar d_code[256] = {
5538+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5539+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5540+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5541+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
5542+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
5543+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
5544+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
5545+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02,
5546+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
5547+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
5548+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
5549+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5550+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5551+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5552+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
5553+ 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
5554+ 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A, 0x0A,
5555+ 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B,
5556+ 0x0C, 0x0C, 0x0C, 0x0C, 0x0D, 0x0D, 0x0D, 0x0D,
5557+ 0x0E, 0x0E, 0x0E, 0x0E, 0x0F, 0x0F, 0x0F, 0x0F,
5558+ 0x10, 0x10, 0x10, 0x10, 0x11, 0x11, 0x11, 0x11,
5559+ 0x12, 0x12, 0x12, 0x12, 0x13, 0x13, 0x13, 0x13,
5560+ 0x14, 0x14, 0x14, 0x14, 0x15, 0x15, 0x15, 0x15,
5561+ 0x16, 0x16, 0x16, 0x16, 0x17, 0x17, 0x17, 0x17,
5562+ 0x18, 0x18, 0x19, 0x19, 0x1A, 0x1A, 0x1B, 0x1B,
5563+ 0x1C, 0x1C, 0x1D, 0x1D, 0x1E, 0x1E, 0x1F, 0x1F,
5564+ 0x20, 0x20, 0x21, 0x21, 0x22, 0x22, 0x23, 0x23,
5565+ 0x24, 0x24, 0x25, 0x25, 0x26, 0x26, 0x27, 0x27,
5566+ 0x28, 0x28, 0x29, 0x29, 0x2A, 0x2A, 0x2B, 0x2B,
5567+ 0x2C, 0x2C, 0x2D, 0x2D, 0x2E, 0x2E, 0x2F, 0x2F,
5568+ 0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
5569+ 0x38, 0x39, 0x3A, 0x3B, 0x3C, 0x3D, 0x3E, 0x3F,
5570+};
5571+
5572+static uchar d_len[256] = {
5573+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
5574+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
5575+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
5576+ 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03,
5577+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
5578+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
5579+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
5580+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
5581+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
5582+ 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04, 0x04,
5583+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5584+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5585+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5586+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5587+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5588+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5589+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5590+ 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05, 0x05,
5591+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5592+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5593+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5594+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5595+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5596+ 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06, 0x06,
5597+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5598+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5599+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5600+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5601+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5602+ 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
5603+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
5604+ 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08, 0x08,
5605+};
5606+
5607+static unsigned long freq[T + 1]; /* frequency table */
5608+
5609+static unsigned long prnt[T + N_CHAR]; /* pointers to parent nodes, except for the */
5610+ /* elements [T..T + N_CHAR - 1] which are used to get */
5611+ /* the positions of leaves corresponding to the codes. */
5612+
5613+static unsigned long son[T]; /* pointers to child nodes (son[], son[] + 1) */
5614+
5615+/* initialization of tree */
5616+
5617+static void StartHuff(void)
5618+{
5619+ unsigned long i, j;
5620+
5621+ for (i = 0; i < N_CHAR; i++) {
5622+ freq[i] = 1;
5623+ son[i] = i + T;
5624+ prnt[i + T] = i;
5625+ }
5626+ i = 0; j = N_CHAR;
5627+ while (j <= R) {
5628+ freq[j] = freq[i] + freq[i + 1];
5629+ son[j] = i;
5630+ prnt[i] = prnt[i + 1] = j;
5631+ i += 2; j++;
5632+ }
5633+ freq[T] = 0xffff;
5634+ prnt[R] = 0;
5635+}
5636+
5637+/* reconstruction of tree */
5638+
5639+static void reconst(void)
5640+{
5641+ unsigned long f, l, i, j, k;
5642+
5643+ /* collect leaf nodes in the first half of the table */
5644+ /* and replace the freq by (freq + 1) / 2. */
5645+ j = 0;
5646+ for (i = 0; i < T; i++) {
5647+ if (son[i] >= T) {
5648+ freq[j] = (freq[i] + 1) / 2;
5649+ son[j] = son[i];
5650+ j++;
5651+ }
5652+ }
5653+ /* begin constructing tree by connecting sons */
5654+ for (i = 0, j = N_CHAR; j < T; i += 2, j++) {
5655+ k = i + 1;
5656+ f = freq[j] = freq[i] + freq[k];
5657+ for (k = j - 1; f < freq[k]; k--);
5658+ k++;
5659+ l = (j - k) * 2;
5660+ memmove(&freq[k + 1], &freq[k], l*sizeof(unsigned long));
5661+ freq[k] = f;
5662+ memmove(&son[k + 1], &son[k], l*sizeof(unsigned long));
5663+ son[k] = i;
5664+ }
5665+ /* connect prnt */
5666+ for (i = 0; i < T; i++) {
5667+ if ((k = son[i]) >= T) {
5668+ prnt[k] = i;
5669+ } else {
5670+ prnt[k] = prnt[k + 1] = i;
5671+ }
5672+ }
5673+}
5674+
5675+/* increment frequency of given code by one, and update tree */
5676+
5677+static void update(unsigned long c)
5678+{
5679+ unsigned long i, j, k, l;
5680+
5681+ if (freq[R] == MAX_FREQ) {
5682+ reconst();
5683+ }
5684+ c = prnt[c + T];
5685+ do {
5686+ k = ++freq[c];
5687+
5688+ /* if the order is disturbed, exchange nodes */
5689+ if (k > freq[l = c + 1]) {
5690+ while (k > freq[++l]);
5691+ l--;
5692+ freq[c] = freq[l];
5693+ freq[l] = k;
5694+
5695+ i = son[c];
5696+ prnt[i] = l;
5697+ if (i < T) prnt[i + 1] = l;
5698+
5699+ j = son[l];
5700+ son[l] = i;
5701+
5702+ prnt[j] = c;
5703+ if (j < T) prnt[j + 1] = c;
5704+ son[c] = j;
5705+
5706+ c = l;
5707+ }
5708+ } while (c = prnt[c]); /* repeat up to root */
5709+}
5710+
5711+/* modified for block compression */
5712+/* on return, srclen will contain the number of successfully compressed bytes
5713+ and dstlen will contain completed compressed bytes */
5714+
5715+static int Encode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long *srclen,
5716+ unsigned long *dstlen)
5717+{
5718+ unsigned long c, i, j, k, len, r, s, last_match_length, code_buf_ptr;
5719+ unsigned char code_buf[17], mask;
5720+ unsigned char *ip, *op;
5721+ unsigned long written = 0;
5722+ unsigned long read = 0;
5723+ unsigned short putbuf = 0;
5724+ uchar putlen = 0;
5725+ unsigned char *srcend = srcbuf + *srclen;
5726+ unsigned char *dstend = dstbuf + *dstlen;
5727+ ip = srcbuf;
5728+ op = dstbuf;
5729+ StartHuff();
5730+ InitTree(); /* initialize trees */
5731+ code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and
5732+ code_buf[0] works as eight flags, "1" representing that the unit
5733+ is an unencoded letter (1 byte), "0" a position-and-length pair
5734+ (2 bytes). Thus, eight units require at most 16 bytes of code. */
5735+ code_buf_ptr = mask = 1;
5736+ s = 0; r = N - F;
5737+ for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with
5738+ any character that will appear often. */
5739+ for (len = 0; (len < F) && (ip < srcend); len++)
5740+ text_buf[r + len] = *(ip++); /* Read F bytes into the last F bytes of
5741+ the buffer */
5742+ read = len;
5743+ for (i = 1; i <= F; i++) InsertNode(r - i); /* Insert the F strings,
5744+ each of which begins with one or more 'space' characters. Note
5745+ the order in which these strings are inserted. This way,
5746+ degenerate trees will be less likely to occur. */
5747+ InsertNode(r); /* Finally, insert the whole string just read. The
5748+ global variables match_length and match_position are set. */
5749+ do {
5750+ if (match_length > len) match_length = len; /* match_length
5751+ may be spuriously long near the end of text. */
5752+ if (match_length <= THRESHOLD) {
5753+ match_length = 1; /* Not long enough match. Send one byte. */
5754+ c = text_buf[r];
5755+ i = 0; j = 0; k = prnt[c + T];
5756+ do {
5757+ i >>= 1;
5758+ /* if node's address is odd-numbered, choose bigger brother node */
5759+ if (k & 1) i |= 0x8000;
5760+ j++;
5761+ } while ((k = prnt[k]) != R);
5762+ putbuf |= i >> putlen;
5763+ if ((putlen += j) >= 8) {
5764+ if (op >= dstend) {
5765+ *dstlen = written;
5766+ return -1;
5767+ }
5768+ *(op++) = putbuf >> 8;
5769+ if ((putlen -= 8) >= 8) {
5770+ if (op >= dstend) {
5771+ *dstlen = written;
5772+ return -1;
5773+ }
5774+ *(op++) = putbuf;
5775+ written += 2;
5776+ putlen -= 8;
5777+ putbuf = i << (j - putlen); /**warm**/
5778+ } else {
5779+ putbuf <<= 8;
5780+ written++;
5781+ }
5782+ *srclen = read;
5783+ }
5784+ update(c);
5785+ } else {
5786+ c = 255 - THRESHOLD + match_length;
5787+ i = 0; j = 0; k = prnt[c + T];
5788+ do {
5789+ i >>= 1;
5790+ /* if node's address is odd-numbered, choose bigger brother node */
5791+ if (k & 1) i |= 0x8000;
5792+ j++;
5793+ } while ((k = prnt[k]) != R);
5794+ putbuf |= i >> putlen;
5795+ if ((putlen += j) >= 8) {
5796+ if (op >= dstend) {
5797+ *dstlen = written;
5798+ return -1;
5799+ }
5800+ *(op++) = putbuf >> 8;
5801+ if ((putlen -= 8) >= 8) {
5802+ if (op >= dstend) {
5803+ *dstlen = written;
5804+ return -1;
5805+ }
5806+ *(op++) = putbuf;
5807+ written += 2;
5808+ putlen -= 8;
5809+ putbuf = i << (j - putlen); /**warm**/
5810+ } else {
5811+ putbuf <<= 8;
5812+ written++;
5813+ }
5814+ *srclen = read;
5815+ }
5816+ update(c);
5817+ j = p_len[match_position >> 6];
5818+ i = p_code[match_position >> 6] << 8;
5819+ putbuf |= i >> putlen;
5820+ if ((putlen += j) >= 8) {
5821+ if (op >= dstend) {
5822+ *dstlen = written;
5823+ return -1;
5824+ }
5825+ *(op++) = putbuf >> 8;
5826+ if ((putlen -= 8) >= 8) {
5827+ if (op >= dstend) {
5828+ *dstlen = written;
5829+ return -1;
5830+ }
5831+ *(op++) = putbuf;
5832+ written += 2;
5833+ putlen -= 8;
5834+ putbuf = i << (j - putlen); /**hot**/
5835+ } else {
5836+ putbuf <<= 8;
5837+ written++;
5838+ }
5839+ *srclen = read;
5840+ }
5841+ j = 6;
5842+ i = (match_position & 0x3f) << 10;
5843+ putbuf |= i >> putlen;
5844+ if ((putlen += j) >= 8) {
5845+ if (op >= dstend) {
5846+ *dstlen = written;
5847+ return -1;
5848+ }
5849+ *(op++) = putbuf >> 8;
5850+ if ((putlen -= 8) >= 8) {
5851+ if (op >= dstend) {
5852+ *dstlen = written;
5853+ return -1;
5854+ }
5855+ *(op++) = putbuf;
5856+ written += 2;
5857+ putlen -= 8;
5858+ putbuf = i << (j - putlen); /**hot**/
5859+ } else {
5860+ putbuf <<= 8;
5861+ written++;
5862+ }
5863+ *srclen = read;
5864+ }
5865+ }
5866+ last_match_length = match_length;
5867+ for (i = 0; (i < last_match_length) && (ip < srcend); i++) {
5868+ c = *(ip++);
5869+ DeleteNode(s);
5870+ text_buf[s] = c;
5871+ if (s < F - 1)
5872+ text_buf[s + N] = c;
5873+ s = (s + 1) & (N - 1);
5874+ r = (r + 1) & (N - 1);
5875+ InsertNode(r);
5876+ }
5877+ read += i;
5878+ while (i++ < last_match_length) {
5879+ DeleteNode(s);
5880+ s = (s + 1) & (N - 1);
5881+ r = (r + 1) & (N - 1);
5882+ if (--len) InsertNode(r);
5883+ }
5884+ } while (len > 0);
5885+ if (putlen) {
5886+ if (op >= dstend) {
5887+ *dstlen = written;
5888+ return -1;
5889+ }
5890+ *(op++) = putbuf >> 8;
5891+ written++;
5892+ *srclen = read;
5893+ }
5894+ *dstlen = written;
5895+ return 0;
5896+}
5897+
5898+static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
5899+ unsigned long dstlen) /* Just the reverse of Encode(). */
5900+{
5901+ unsigned long i, r, j, k, c;
5902+ unsigned char *ip, *op;
5903+ unsigned char *srcend = srcbuf + srclen;
5904+ unsigned char *dstend = dstbuf + dstlen;
5905+ unsigned short getbuf = 0;
5906+ uchar getlen = 0;
5907+ ip = srcbuf;
5908+ op = dstbuf;
5909+ StartHuff();
5910+ for (i = 0; i < N - F; i++) text_buf[i] = ' ';
5911+ r = N - F;
5912+ while (op < dstend) {
5913+ c = son[R];
5914+ /* travel from root to leaf, */
5915+ /* choosing the smaller child node (son[]) if the read bit is 0, */
5916+ /* the bigger (son[]+1} if 1 */
5917+ while (c < T) {
5918+ while (getlen <= 8) {
5919+ unsigned short t;
5920+ t = (ip >= srcend) ? 0 : *(ip++);
5921+ getbuf |= t << (8 - getlen);
5922+ getlen += 8;
5923+ }
5924+ c += ((signed short)getbuf < 0);
5925+ getbuf <<= 1;
5926+ getlen--;
5927+ c = son[c];
5928+ }
5929+ c -= T;
5930+ update(c);
5931+ if (c < 256) {
5932+ if (op >= dstend) return -1;
5933+ *(op++) = c;
5934+ text_buf[r++] = c;
5935+ r &= (N - 1);
5936+ } else {
5937+ j = c - 255 + THRESHOLD;
5938+ while (getlen <= 8) {
5939+ unsigned short t;
5940+ t = (ip >= srcend) ? 0 : *(ip++);
5941+ getbuf |= t << (8 - getlen);
5942+ getlen += 8;
5943+ }
5944+ i = getbuf >> 8;
5945+ getbuf <<= 8;
5946+ getlen -= 8;
5947+ c = d_code[i] << 6;
5948+ k = d_len[i];
5949+ /* read lower 6 bits verbatim */
5950+ k -= 2;
5951+ while (k--) {
5952+ while (getlen <= 8) {
5953+ unsigned short t;
5954+ t = (ip >= srcend) ? 0 : *(ip++);
5955+ getbuf |= t << (8 - getlen);
5956+ getlen += 8;
5957+ }
5958+ i = (i << 1) + ((signed short)getbuf < 0);
5959+ getbuf <<= 1;
5960+ getlen--;
5961+ }
5962+ i = c | (i & 0x3F);
5963+ i = r - i - 1;
5964+ i &= (N - 1);
5965+ for (k = 0; k < j; k++) {
5966+ c = text_buf[(i + k) & (N - 1)];
5967+ if (op >= dstend) return -1;
5968+ *(op++) = c;
5969+ text_buf[r++] = c;
5970+ r &= (N - 1);
5971+ }
5972+ }
5973+ }
5974+ return 0;
5975+}
5976+
5977+/* interface to jffs2 bbc follows */
5978+
5979+#include "jffs2_bbc_framework.h"
5980+
5981+
5982+#define JFFS2_BBC_LZHD_BLOCK_SIGN {0x3a, 0x98, 0xf7, 0xda}
5983+
5984+static int
5985+jffs2_bbc_lzhd_compressor_init (void);
5986+
5987+static void
5988+jffs2_bbc_lzhd_compressor_deinit (void);
5989+
5990+static int
5991+jffs2_bbc_lzhd_compress (void *model, unsigned char *input,
5992+ unsigned char *output, unsigned long *sourcelen,
5993+ unsigned long *dstlen);
5994+
5995+static int
5996+jffs2_bbc_lzhd_estimate (void *model, unsigned char *input,
5997+ unsigned long sourcelen, unsigned long *dstlen,
5998+ unsigned long *readtime, unsigned long *writetime);
5999+
6000+static int
6001+jffs2_bbc_lzhd_decompress (void *model, unsigned char *input,
6002+ unsigned char *output, unsigned long sourcelen,
6003+ unsigned long dstlen);
6004+
6005+static char *
6006+jffs2_bbc_lzhd_proc_info (void);
6007+
6008+static int
6009+jffs2_bbc_lzhd_proc_command (char *command);
6010+
6011+struct jffs2_bbc_compressor_type jffs2_bbc_lzhd = {
6012+ "lzhd",
6013+ 0,
6014+ JFFS2_BBC_LZHD_BLOCK_SIGN,
6015+ jffs2_bbc_lzhd_compressor_init,
6016+ NULL,
6017+ NULL,
6018+ jffs2_bbc_lzhd_compressor_deinit,
6019+ jffs2_bbc_lzhd_compress,
6020+ jffs2_bbc_lzhd_estimate,
6021+ jffs2_bbc_lzhd_decompress,
6022+ jffs2_bbc_lzhd_proc_info,
6023+ jffs2_bbc_lzhd_proc_command
6024+};
6025+
6026+static int
6027+jffs2_bbc_lzhd_compressor_init (void)
6028+{
6029+ return 0;
6030+}
6031+
6032+static void
6033+jffs2_bbc_lzhd_compressor_deinit (void)
6034+{
6035+}
6036+
6037+static int
6038+jffs2_bbc_lzhd_compress (void *model, unsigned char *input,
6039+ unsigned char *output, unsigned long *sourcelen,
6040+ unsigned long *dstlen)
6041+{
6042+ int retval;
6043+ unsigned long dst = *dstlen;
6044+ *(output++) = jffs2_bbc_lzhd.block_sign[0];
6045+ *(output++) = jffs2_bbc_lzhd.block_sign[1];
6046+ dst -= 2;
6047+ retval = Encode(input, output, sourcelen, &dst);
6048+ dst += 2;
6049+ *dstlen = dst;
6050+ return retval;
6051+}
6052+
6053+static int
6054+jffs2_bbc_lzhd_estimate (void *model, unsigned char *input,
6055+ unsigned long sourcelen, unsigned long *dstlen,
6056+ unsigned long *readtime, unsigned long *writetime)
6057+{
6058+ *dstlen = sourcelen * 55 / 100;
6059+ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 8;
6060+ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 65 / 10;
6061+ return 0;
6062+}
6063+
6064+static int
6065+jffs2_bbc_lzhd_decompress (void *model, unsigned char *input,
6066+ unsigned char *output, unsigned long sourcelen,
6067+ unsigned long dstlen)
6068+{
6069+ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzhd.block_sign[0] ) ||
6070+ ( *(input++) != (unsigned char)jffs2_bbc_lzhd.block_sign[1] )
6071+ ) {
6072+ return -1;
6073+ } else {
6074+ return Decode(input, output, sourcelen - 2, dstlen);
6075+ }
6076+}
6077+
6078+static char *
6079+jffs2_bbc_lzhd_proc_info (void)
6080+{
6081+ return "Lempel-Ziv-(dynamic) Huffman compression module";
6082+}
6083+
6084+static int
6085+jffs2_bbc_lzhd_proc_command (char *command)
6086+{
6087+ return 0;
6088+}
6089+
6090+struct jffs2_bbc_compressor_type *
6091+jffs2_bbc_lzhd_init (int mode)
6092+{
6093+ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzhd) == 0)
6094+ {
6095+ return &jffs2_bbc_lzhd;
6096+ }
6097+ else
6098+ {
6099+ return NULL;
6100+ }
6101+}
6102+
6103+void
6104+jffs2_bbc_lzhd_deinit (void)
6105+{
6106+ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzhd);
6107+}
6108--- /dev/null
6109+++ b/fs/jffs2/jffs2_bbc_lzo_comp.c
6110@@ -0,0 +1,2435 @@
6111+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
6112+
6113+/*
6114+ jffs2_bbc_lzo_comp.c -- LZO1X-1 (and -999) compression module for jffs2
6115+ Copyright (C) 2004 Patrik Kluba
6116+ Based on the original LZO sources
6117+ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
6118+*/
6119+
6120+/*
6121+ Original copyright notice follows:
6122+
6123+ lzo1x_9x.c -- implementation of the LZO1X-999 compression algorithm
6124+ lzo_ptr.h -- low-level pointer constructs
6125+ lzo_swd.ch -- sliding window dictionary
6126+ lzoconf.h -- configuration for the LZO real-time data compression library
6127+ lzo_mchw.ch -- matching functions using a window
6128+ minilzo.c -- mini subset of the LZO real-time data compression library
6129+ config1x.h -- configuration for the LZO1X algorithm
6130+ lzo1x.h -- public interface of the LZO1X compression algorithm
6131+
6132+ These files are part of the LZO real-time data compression library.
6133+
6134+ Copyright (C) 1996-2002 Markus Franz Xaver Johannes Oberhumer
6135+ All Rights Reserved.
6136+
6137+ The LZO library is free software; you can redistribute it and/or
6138+ modify it under the terms of the GNU General Public License as
6139+ published by the Free Software Foundation; either version 2 of
6140+ the License, or (at your option) any later version.
6141+
6142+ The LZO library is distributed in the hope that it will be useful,
6143+ but WITHOUT ANY WARRANTY; without even the implied warranty of
6144+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
6145+ GNU General Public License for more details.
6146+
6147+ You should have received a copy of the GNU General Public License
6148+ along with the LZO library; see the file COPYING.
6149+ If not, write to the Free Software Foundation, Inc.,
6150+ 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
6151+
6152+ Markus F.X.J. Oberhumer
6153+ <markus@oberhumer.com>
6154+*/
6155+
6156+/*
6157+
6158+ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
6159+ Initial release
6160+ -removed all 16 bit code
6161+ -all sensitive data will be on 4 byte boundary
6162+ -removed check parts for library use
6163+ -removed all but LZO1X-* compression
6164+
6165+*/
6166+
6167+#ifndef __KERNEL__
6168+ #include <sys/types.h>
6169+ #include <stddef.h>
6170+ #include <string.h>
6171+ #include <limits.h>
6172+#else
6173+ #include <linux/kernel.h>
6174+ #include <linux/types.h>
6175+ #include <linux/stddef.h>
6176+ #include <linux/string.h>
6177+ #define USHRT_MAX 65535
6178+ /* #define UINT_MAX 4294967295U */
6179+#endif
6180+
6181+/* data type definitions */
6182+#define U32 unsigned long
6183+#define S32 signed long
6184+#define I32 long
6185+#define U16 unsigned short
6186+#define S16 signed short
6187+#define I16 short
6188+#define U8 unsigned char
6189+#define S8 signed char
6190+#define I8 char
6191+
6192+/*************************************/
6193+
6194+/* lzo_swd.ch */
6195+
6196+#define SWD_N N
6197+#define SWD_F F
6198+#define SWD_THRESHOLD THRESHOLD
6199+
6200+/* shortest unsigned int that 2 * SWD_F + SWD_N (currently 53248) fits in */
6201+typedef unsigned short swd_uint;
6202+/* upper limit of that data type */
6203+#define SWD_UINT_MAX USHRT_MAX
6204+
6205+/* minilzo.c */
6206+
6207+#define LZO_VERSION_DATE "Jul 12 2002"
6208+#define LZO_VERSION_STRING "1.08"
6209+#define LZO_VERSION 0x1080
6210+
6211+/* lzo_ptr.h */
6212+
6213+/* Integral types that have *exactly* the same number of bits as a lzo_voidp */
6214+typedef unsigned long lzo_ptr_t;
6215+typedef long lzo_sptr_t;
6216+
6217+
6218+/*************************************/
6219+
6220+/* config1x.h */
6221+
6222+#define M1_MAX_OFFSET 0x0400
6223+#define M2_MAX_OFFSET 0x0800
6224+#define M3_MAX_OFFSET 0x4000
6225+#define M4_MAX_OFFSET 0xbfff
6226+
6227+#define MX_MAX_OFFSET (M1_MAX_OFFSET + M2_MAX_OFFSET)
6228+
6229+#define M1_MIN_LEN 2
6230+#define M1_MAX_LEN 2
6231+#define M2_MIN_LEN 3
6232+#define M2_MAX_LEN 8
6233+#define M3_MIN_LEN 3
6234+#define M3_MAX_LEN 33
6235+#define M4_MIN_LEN 3
6236+#define M4_MAX_LEN 9
6237+
6238+#define M1_MARKER 0
6239+#define M2_MARKER 64
6240+#define M3_MARKER 32
6241+#define M4_MARKER 16
6242+
6243+#define MIN_LOOKAHEAD (M2_MAX_LEN + 1)
6244+
6245+/* minilzo.c */
6246+
6247+#define LZO_BYTE(x) ((unsigned char) ((x) & 0xff))
6248+
6249+#define LZO_MAX(a,b) ((a) >= (b) ? (a) : (b))
6250+#define LZO_MIN(a,b) ((a) <= (b) ? (a) : (b))
6251+#define LZO_MAX3(a,b,c) ((a) >= (b) ? LZO_MAX(a,c) : LZO_MAX(b,c))
6252+#define LZO_MIN3(a,b,c) ((a) <= (b) ? LZO_MIN(a,c) : LZO_MIN(b,c))
6253+
6254+#define lzo_sizeof(type) ((lzo_uint) (sizeof(type)))
6255+
6256+#define LZO_HIGH(array) ((lzo_uint) (sizeof(array)/sizeof(*(array))))
6257+
6258+#define LZO_SIZE(bits) (1u << (bits))
6259+#define LZO_MASK(bits) (LZO_SIZE(bits) - 1)
6260+
6261+#define LZO_LSIZE(bits) (1ul << (bits))
6262+#define LZO_LMASK(bits) (LZO_LSIZE(bits) - 1)
6263+
6264+#define LZO_USIZE(bits) ((lzo_uint) 1 << (bits))
6265+#define LZO_UMASK(bits) (LZO_USIZE(bits) - 1)
6266+
6267+#define LZO_STYPE_MAX(b) (((1l << (8*(b)-2)) - 1l) + (1l << (8*(b)-2)))
6268+#define LZO_UTYPE_MAX(b) (((1ul << (8*(b)-1)) - 1ul) + (1ul << (8*(b)-1)))
6269+
6270+#define _LZO_STRINGIZE(x) #x
6271+#define _LZO_MEXPAND(x) _LZO_STRINGIZE(x)
6272+
6273+#define _LZO_CONCAT2(a,b) a ## b
6274+#define _LZO_CONCAT3(a,b,c) a ## b ## c
6275+#define _LZO_CONCAT4(a,b,c,d) a ## b ## c ## d
6276+#define _LZO_CONCAT5(a,b,c,d,e) a ## b ## c ## d ## e
6277+
6278+#define _LZO_ECONCAT2(a,b) _LZO_CONCAT2(a,b)
6279+#define _LZO_ECONCAT3(a,b,c) _LZO_CONCAT3(a,b,c)
6280+#define _LZO_ECONCAT4(a,b,c,d) _LZO_CONCAT4(a,b,c,d)
6281+#define _LZO_ECONCAT5(a,b,c,d,e) _LZO_CONCAT5(a,b,c,d,e)
6282+
6283+#define lzo_dict_t const lzo_bytep
6284+#define lzo_dict_p lzo_dict_t *
6285+#define lzo_moff_t lzo_uint
6286+
6287+#define MEMCPY8_DS(dest,src,len) \
6288+ memcpy(dest,src,len); \
6289+ dest += len; \
6290+ src += len
6291+
6292+#define MEMCPY_DS(dest,src,len) \
6293+ do *dest++ = *src++; \
6294+ while (--len > 0)
6295+
6296+#define MEMMOVE_DS(dest,src,len) \
6297+ do *dest++ = *src++; \
6298+ while (--len > 0)
6299+
6300+#define BZERO8_PTR(s,l,n) memset((s),0,(lzo_uint)(l)*(n))
6301+
6302+#define LZO_BASE 65521u
6303+#define LZO_NMAX 5552
6304+
6305+#define LZO_DO1(buf,i) {s1 += buf[i]; s2 += s1;}
6306+#define LZO_DO2(buf,i) LZO_DO1(buf,i); LZO_DO1(buf,i+1);
6307+#define LZO_DO4(buf,i) LZO_DO2(buf,i); LZO_DO2(buf,i+2);
6308+#define LZO_DO8(buf,i) LZO_DO4(buf,i); LZO_DO4(buf,i+4);
6309+#define LZO_DO16(buf,i) LZO_DO8(buf,i); LZO_DO8(buf,i+8);
6310+
6311+#define IS_SIGNED(type) (((type) (-1)) < ((type) 0))
6312+#define IS_UNSIGNED(type) (((type) (-1)) > ((type) 0))
6313+
6314+#define IS_POWER_OF_2(x) (((x) & ((x) - 1)) == 0)
6315+
6316+#define D_BITS 14
6317+#define D_INDEX1(d,p) d = DM((0x21*DX3(p,5,5,6)) >> 5)
6318+#define D_INDEX2(d,p) d = (d & (D_MASK & 0x7ff)) ^ (D_HIGH | 0x1f)
6319+
6320+#define LZO_HASH LZO_HASH_LZO_INCREMENTAL_B
6321+
6322+#define DL_MIN_LEN M2_MIN_LEN
6323+
6324+#define D_SIZE LZO_SIZE(D_BITS)
6325+#define D_MASK LZO_MASK(D_BITS)
6326+
6327+#define D_HIGH ((D_MASK >> 1) + 1)
6328+
6329+#define DINDEX1 D_INDEX1
6330+#define DINDEX2 D_INDEX2
6331+
6332+#define DX2(p,s1,s2) \
6333+ (((((lzo_uint32)((p)[2]) << (s2)) ^ (p)[1]) << (s1)) ^ (p)[0])
6334+
6335+#define DX3(p,s1,s2,s3) ((DX2((p)+1,s2,s3) << (s1)) ^ (p)[0])
6336+#define DMS(v,s) ((lzo_uint) (((v) & (D_MASK >> (s))) << (s)))
6337+#define DM(v) DMS(v,0)
6338+
6339+#define DENTRY(p,in) (p)
6340+#define GINDEX(m_pos,m_off,dict,dindex,in) m_pos = dict[dindex]
6341+
6342+#define LZO_CHECK_MPOS_DET(m_pos,m_off,in,ip,max_offset) \
6343+ (m_pos == NULL || (m_off = (lzo_moff_t) (ip - m_pos)) > max_offset)
6344+
6345+#define LZO_CHECK_MPOS_NON_DET(m_pos,m_off,in,ip,max_offset) \
6346+ (BOUNDS_CHECKING_OFF_IN_EXPR( \
6347+ (PTR_LT(m_pos,in) || \
6348+ (m_off = (lzo_moff_t) PTR_DIFF(ip,m_pos)) <= 0 || \
6349+ m_off > max_offset) ))
6350+
6351+#define BOUNDS_CHECKING_OFF_IN_EXPR(expr) (expr)
6352+
6353+#define DD_BITS 0
6354+#define DD_SIZE LZO_SIZE(DD_BITS)
6355+#define DD_MASK LZO_MASK(DD_BITS)
6356+
6357+#define DL_BITS (D_BITS - DD_BITS)
6358+#define DL_SIZE LZO_SIZE(DL_BITS)
6359+#define DL_MASK LZO_MASK(DL_BITS)
6360+
6361+#define UPDATE_D(dict,drun,dv,p,in) dict[ DINDEX(dv,p) ] = DENTRY(p,in)
6362+#define UPDATE_I(dict,drun,index,p,in) dict[index] = DENTRY(p,in)
6363+#define UPDATE_P(ptr,drun,p,in) (ptr)[0] = DENTRY(p,in)
6364+
6365+#define __COPY4(dst,src) * (lzo_uint32p)(dst) = * (const lzo_uint32p)(src)
6366+#define COPY4(dst,src) __COPY4((lzo_ptr_t)(dst),(lzo_ptr_t)(src))
6367+
6368+#define TEST_IP (ip < ip_end)
6369+#define TEST_OP (op <= op_end)
6370+
6371+#define NEED_IP(x) \
6372+ if ((lzo_uint)(ip_end - ip) < (lzo_uint)(x)) goto input_overrun
6373+#define NEED_OP(x) \
6374+ if ((lzo_uint)(op_end - op) < (lzo_uint)(x)) goto output_overrun
6375+#define TEST_LOOKBEHIND(m_pos,out) if (m_pos < out) goto lookbehind_overrun
6376+
6377+/* lzo1x_9x.c */
6378+
6379+#define LZO_UINT_MAX UINT_MAX
6380+#define N M4_MAX_OFFSET
6381+#define THRESHOLD 1
6382+#define F 2048
6383+
6384+#define SWD_BEST_OFF (LZO_MAX3( M2_MAX_LEN, M3_MAX_LEN, M4_MAX_LEN ) + 1)
6385+
6386+/* ../include/lzoconf.h */
6387+
6388+typedef U32 lzo_uint32;
6389+typedef I32 lzo_int32;
6390+typedef U32 lzo_uint;
6391+typedef I32 lzo_int;
6392+typedef int lzo_bool;
6393+
6394+#define lzo_byte U8
6395+#define lzo_bytep U8 *
6396+#define lzo_charp char *
6397+#define lzo_voidp void *
6398+#define lzo_shortp short *
6399+#define lzo_ushortp unsigned short *
6400+#define lzo_uint32p lzo_uint32 *
6401+#define lzo_int32p lzo_int32 *
6402+#define lzo_uintp lzo_uint *
6403+#define lzo_intp lzo_int *
6404+#define lzo_voidpp lzo_voidp *
6405+#define lzo_bytepp lzo_bytep *
6406+#define lzo_sizeof_dict_t sizeof(lzo_bytep)
6407+
6408+#define LZO_E_OK 0
6409+#define LZO_E_ERROR (-1)
6410+#define LZO_E_OUT_OF_MEMORY (-2) /* not used right now */
6411+#define LZO_E_NOT_COMPRESSIBLE (-3) /* not used right now */
6412+#define LZO_E_INPUT_OVERRUN (-4)
6413+#define LZO_E_OUTPUT_OVERRUN (-5)
6414+#define LZO_E_LOOKBEHIND_OVERRUN (-6)
6415+#define LZO_E_EOF_NOT_FOUND (-7)
6416+#define LZO_E_INPUT_NOT_CONSUMED (-8)
6417+
6418+#define LZO_PTR_ALIGN_UP(_ptr,_size) \
6419+ ((_ptr) + (lzo_uint) __lzo_align_gap((const lzo_voidp)(_ptr),(lzo_uint)(_size)))
6420+#define LZO_ALIGN(_ptr,_size) LZO_PTR_ALIGN_UP(_ptr,_size)
6421+
6422+typedef int
6423+ (*lzo_compress_t) (const lzo_byte * src, lzo_uint src_len,
6424+ lzo_byte * dst, lzo_uintp dst_len,
6425+ lzo_voidp wrkmem);
6426+
6427+typedef int
6428+ (*lzo_decompress_t) (const lzo_byte * src, lzo_uint src_len,
6429+ lzo_byte * dst, lzo_uintp dst_len,
6430+ lzo_voidp wrkmem);
6431+
6432+typedef int
6433+ (*lzo_optimize_t) (lzo_byte * src, lzo_uint src_len,
6434+ lzo_byte * dst, lzo_uintp dst_len,
6435+ lzo_voidp wrkmem);
6436+
6437+typedef int
6438+ (*lzo_compress_dict_t) (const lzo_byte * src, lzo_uint src_len,
6439+ lzo_byte * dst, lzo_uintp dst_len,
6440+ lzo_voidp wrkmem,
6441+ const lzo_byte * dict, lzo_uint dict_len);
6442+
6443+typedef int
6444+ (*lzo_decompress_dict_t) (const lzo_byte * src, lzo_uint src_len,
6445+ lzo_byte * dst, lzo_uintp dst_len,
6446+ lzo_voidp wrkmem,
6447+ const lzo_byte * dict, lzo_uint dict_len);
6448+
6449+typedef int
6450+ (*lzo_compress_asm_t) (const lzo_byte * src, lzo_uint src_len,
6451+ lzo_byte * dst, lzo_uintp dst_len,
6452+ lzo_voidp wrkmem);
6453+
6454+typedef int
6455+ (*lzo_decompress_asm_t) (const lzo_byte * src, lzo_uint src_len,
6456+ lzo_byte * dst, lzo_uintp dst_len,
6457+ lzo_voidp wrkmem);
6458+
6459+typedef void (*lzo_progress_callback_t) (lzo_uint, lzo_uint);
6460+
6461+typedef union
6462+{
6463+ lzo_bytep p;
6464+ lzo_uint u;
6465+} __lzo_pu_u;
6466+typedef union
6467+{
6468+ lzo_bytep p;
6469+ lzo_uint32 u32;
6470+} __lzo_pu32_u;
6471+typedef union
6472+{
6473+ void *vp;
6474+ lzo_bytep bp;
6475+ lzo_uint32 u32;
6476+ long l;
6477+} lzo_align_t;
6478+
6479+/* lzo1x.h */
6480+
6481+#define LZO1X_1_MEM_COMPRESS ((lzo_uint32) (16384L * lzo_sizeof_dict_t))
6482+#define LZO1X_999_MEM_COMPRESS ((lzo_uint32) (14 * 16384L * sizeof(short)))
6483+
6484+/* lzo_ptr.h */
6485+
6486+#define PTR(a) ((lzo_ptr_t) (a))
6487+#define PTR_LINEAR(a) PTR(a)
6488+#define PTR_ALIGNED_4(a) ((PTR_LINEAR(a) & 3) == 0)
6489+#define PTR_ALIGNED_8(a) ((PTR_LINEAR(a) & 7) == 0)
6490+#define PTR_ALIGNED2_4(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 3) == 0)
6491+#define PTR_ALIGNED2_8(a,b) (((PTR_LINEAR(a) | PTR_LINEAR(b)) & 7) == 0)
6492+#define PTR_LT(a,b) (PTR(a) < PTR(b))
6493+#define PTR_GE(a,b) (PTR(a) >= PTR(b))
6494+#define PTR_DIFF(a,b) ((lzo_ptrdiff_t) (PTR(a) - PTR(b)))
6495+#define pd(a,b) ((lzo_uint) ((a)-(b)))
6496+
6497+typedef ptrdiff_t lzo_ptrdiff_t;
6498+
6499+typedef union
6500+{
6501+ char a_char;
6502+ unsigned char a_uchar;
6503+ short a_short;
6504+ unsigned short a_ushort;
6505+ int a_int;
6506+ unsigned int a_uint;
6507+ long a_long;
6508+ unsigned long a_ulong;
6509+ lzo_int a_lzo_int;
6510+ lzo_uint a_lzo_uint;
6511+ lzo_int32 a_lzo_int32;
6512+ lzo_uint32 a_lzo_uint32;
6513+ ptrdiff_t a_ptrdiff_t;
6514+ lzo_ptrdiff_t a_lzo_ptrdiff_t;
6515+ lzo_ptr_t a_lzo_ptr_t;
6516+ lzo_voidp a_lzo_voidp;
6517+ void *a_void_p;
6518+ lzo_bytep a_lzo_bytep;
6519+ lzo_bytepp a_lzo_bytepp;
6520+ lzo_uintp a_lzo_uintp;
6521+ lzo_uint *a_lzo_uint_p;
6522+ lzo_uint32p a_lzo_uint32p;
6523+ lzo_uint32 *a_lzo_uint32_p;
6524+ unsigned char *a_uchar_p;
6525+ char *a_char_p;
6526+}
6527+lzo_full_align_t;
6528+
6529+/* lzo_mchw.ch */
6530+
6531+typedef struct
6532+{
6533+ int init;
6534+
6535+ lzo_uint look;
6536+
6537+ lzo_uint m_len;
6538+ lzo_uint m_off;
6539+
6540+ lzo_uint last_m_len;
6541+ lzo_uint last_m_off;
6542+
6543+ const lzo_byte *bp;
6544+ const lzo_byte *ip;
6545+ const lzo_byte *in;
6546+ const lzo_byte *in_end;
6547+ lzo_byte *out;
6548+
6549+ lzo_progress_callback_t cb;
6550+
6551+ lzo_uint textsize;
6552+ lzo_uint codesize;
6553+ lzo_uint printcount;
6554+
6555+ unsigned long lit_bytes;
6556+ unsigned long match_bytes;
6557+ unsigned long rep_bytes;
6558+ unsigned long lazy;
6559+
6560+ lzo_uint r1_lit;
6561+ lzo_uint r1_m_len;
6562+
6563+ unsigned long m1a_m, m1b_m, m2_m, m3_m, m4_m;
6564+ unsigned long lit1_r, lit2_r, lit3_r;
6565+}
6566+lzo1x_999_t;
6567+
6568+#define getbyte(c) ((c).ip < (c).in_end ? *((c).ip)++ : (-1))
6569+
6570+/* lzo_swd.ch */
6571+
6572+#define SWD_UINT(x) ((swd_uint)(x))
6573+#define SWD_HSIZE 16384
6574+#define SWD_MAX_CHAIN 2048
6575+#define HEAD3(b,p) \
6576+ (((0x9f5f*(((((lzo_uint32)b[p]<<5)^b[p+1])<<5)^b[p+2]))>>5) & (SWD_HSIZE-1))
6577+#define HEAD2(b,p) (b[p] ^ ((unsigned)b[p+1]<<8))
6578+#define NIL2 SWD_UINT_MAX
6579+
6580+typedef struct
6581+{
6582+ lzo_uint n;
6583+ lzo_uint f;
6584+ lzo_uint threshold;
6585+
6586+ lzo_uint max_chain;
6587+ lzo_uint nice_length;
6588+ lzo_bool use_best_off;
6589+ lzo_uint lazy_insert;
6590+
6591+ lzo_uint m_len;
6592+ lzo_uint m_off;
6593+ lzo_uint look;
6594+ int b_char;
6595+
6596+ lzo_uint best_off[SWD_BEST_OFF];
6597+
6598+ lzo1x_999_t *c;
6599+ lzo_uint m_pos;
6600+
6601+ lzo_uint best_pos[SWD_BEST_OFF];
6602+
6603+ const lzo_byte *dict;
6604+ const lzo_byte *dict_end;
6605+ lzo_uint dict_len;
6606+
6607+ lzo_uint ip;
6608+ lzo_uint bp;
6609+ lzo_uint rp;
6610+ lzo_uint b_size;
6611+
6612+ unsigned char *b_wrap;
6613+
6614+ lzo_uint node_count;
6615+ lzo_uint first_rp;
6616+
6617+ unsigned char b[SWD_N + SWD_F + SWD_F];
6618+ swd_uint head3[SWD_HSIZE];
6619+ swd_uint succ3[SWD_N + SWD_F];
6620+ swd_uint best3[SWD_N + SWD_F];
6621+ swd_uint llen3[SWD_HSIZE];
6622+
6623+ swd_uint head2[65536L];
6624+}
6625+lzo1x_999_swd_t;
6626+
6627+#define s_head3(s,key) s->head3[key]
6628+#define swd_pos2off(s,pos) \
6629+ (s->bp > (pos) ? s->bp - (pos) : s->b_size - ((pos) - s->bp))
6630+
6631+static __inline__ void
6632+swd_getbyte (lzo1x_999_swd_t * s)
6633+{
6634+ int c;
6635+
6636+ if ((c = getbyte (*(s->c))) < 0)
6637+ {
6638+ if (s->look > 0)
6639+ --s->look;
6640+ }
6641+ else
6642+ {
6643+ s->b[s->ip] = LZO_BYTE (c);
6644+ if (s->ip < s->f)
6645+ s->b_wrap[s->ip] = LZO_BYTE (c);
6646+ }
6647+ if (++s->ip == s->b_size)
6648+ s->ip = 0;
6649+ if (++s->bp == s->b_size)
6650+ s->bp = 0;
6651+ if (++s->rp == s->b_size)
6652+ s->rp = 0;
6653+}
6654+
6655+static void
6656+swd_initdict (lzo1x_999_swd_t * s, const lzo_byte * dict, lzo_uint dict_len)
6657+{
6658+ s->dict = s->dict_end = NULL;
6659+ s->dict_len = 0;
6660+
6661+ if (!dict || dict_len <= 0)
6662+ return;
6663+ if (dict_len > s->n)
6664+ {
6665+ dict += dict_len - s->n;
6666+ dict_len = s->n;
6667+ }
6668+
6669+ s->dict = dict;
6670+ s->dict_len = dict_len;
6671+ s->dict_end = dict + dict_len;
6672+ memcpy (s->b, dict, dict_len);
6673+ s->ip = dict_len;
6674+}
6675+
6676+static void
6677+swd_insertdict (lzo1x_999_swd_t * s, lzo_uint node, lzo_uint len)
6678+{
6679+ lzo_uint key;
6680+
6681+ s->node_count = s->n - len;
6682+ s->first_rp = node;
6683+
6684+ while (len-- > 0)
6685+ {
6686+ key = HEAD3 (s->b, node);
6687+ s->succ3[node] = s_head3 (s, key);
6688+ s->head3[key] = SWD_UINT (node);
6689+ s->best3[node] = SWD_UINT (s->f + 1);
6690+ s->llen3[key]++;
6691+
6692+ key = HEAD2 (s->b, node);
6693+ s->head2[key] = SWD_UINT (node);
6694+
6695+ node++;
6696+ }
6697+}
6698+
6699+static int
6700+swd_init (lzo1x_999_swd_t * s, const lzo_byte * dict, lzo_uint dict_len)
6701+{
6702+
6703+ s->n = SWD_N;
6704+ s->f = SWD_F;
6705+ s->threshold = SWD_THRESHOLD;
6706+
6707+
6708+
6709+ s->max_chain = SWD_MAX_CHAIN;
6710+ s->nice_length = SWD_F;
6711+ s->use_best_off = 0;
6712+ s->lazy_insert = 0;
6713+
6714+ s->b_size = s->n + s->f;
6715+ if (2 * s->f >= s->n || s->b_size + s->f >= NIL2)
6716+ return LZO_E_ERROR;
6717+ s->b_wrap = s->b + s->b_size;
6718+ s->node_count = s->n;
6719+
6720+ memset (s->llen3, 0, sizeof (s->llen3[0]) * SWD_HSIZE);
6721+ memset (s->head2, 0xff, sizeof (s->head2[0]) * 65536L);
6722+
6723+ s->ip = 0;
6724+ swd_initdict (s, dict, dict_len);
6725+ s->bp = s->ip;
6726+ s->first_rp = s->ip;
6727+
6728+ s->look = (lzo_uint) (s->c->in_end - s->c->ip);
6729+ if (s->look > 0)
6730+ {
6731+ if (s->look > s->f)
6732+ s->look = s->f;
6733+ memcpy (&s->b[s->ip], s->c->ip, s->look);
6734+ s->c->ip += s->look;
6735+ s->ip += s->look;
6736+ }
6737+
6738+ if (s->ip == s->b_size)
6739+ s->ip = 0;
6740+
6741+ if (s->look >= 2 && s->dict_len > 0)
6742+ swd_insertdict (s, 0, s->dict_len);
6743+
6744+ s->rp = s->first_rp;
6745+ if (s->rp >= s->node_count)
6746+ s->rp -= s->node_count;
6747+ else
6748+ s->rp += s->b_size - s->node_count;
6749+
6750+ return LZO_E_OK;
6751+}
6752+
6753+static __inline__ void
6754+swd_remove_node (lzo1x_999_swd_t * s, lzo_uint node)
6755+{
6756+ if (s->node_count == 0)
6757+ {
6758+ lzo_uint key;
6759+
6760+ key = HEAD3 (s->b, node);
6761+
6762+ --s->llen3[key];
6763+
6764+ key = HEAD2 (s->b, node);
6765+
6766+ if ((lzo_uint) s->head2[key] == node)
6767+ s->head2[key] = NIL2;
6768+ }
6769+ else
6770+ --s->node_count;
6771+}
6772+
6773+static void
6774+swd_accept (lzo1x_999_swd_t * s, lzo_uint n)
6775+{
6776+
6777+ while (n--)
6778+ {
6779+ lzo_uint key;
6780+
6781+ swd_remove_node (s, s->rp);
6782+
6783+ key = HEAD3 (s->b, s->bp);
6784+ s->succ3[s->bp] = s_head3 (s, key);
6785+ s->head3[key] = SWD_UINT (s->bp);
6786+ s->best3[s->bp] = SWD_UINT (s->f + 1);
6787+ s->llen3[key]++;
6788+
6789+ key = HEAD2 (s->b, s->bp);
6790+ s->head2[key] = SWD_UINT (s->bp);;
6791+
6792+ swd_getbyte (s);
6793+ }
6794+}
6795+
6796+static void
6797+swd_search (lzo1x_999_swd_t * s, lzo_uint node, lzo_uint cnt)
6798+{
6799+ const unsigned char *p1;
6800+ const unsigned char *p2;
6801+ const unsigned char *px;
6802+
6803+ lzo_uint m_len = s->m_len;
6804+ const unsigned char *b = s->b;
6805+ const unsigned char *bp = s->b + s->bp;
6806+ const unsigned char *bx = s->b + s->bp + s->look;
6807+ unsigned char scan_end1;
6808+
6809+ scan_end1 = bp[m_len - 1];
6810+ for (; cnt-- > 0; node = s->succ3[node])
6811+ {
6812+ p1 = bp;
6813+ p2 = b + node;
6814+ px = bx;
6815+
6816+ if (p2[m_len - 1] == scan_end1 &&
6817+ p2[m_len] == p1[m_len] &&
6818+ p2[0] == p1[0] && p2[1] == p1[1])
6819+ {
6820+ lzo_uint i;
6821+
6822+ p1 += 2;
6823+ p2 += 2;
6824+ do
6825+ {
6826+ }
6827+ while (++p1 < px && *p1 == *++p2);
6828+
6829+ i = p1 - bp;
6830+
6831+ if (i < SWD_BEST_OFF)
6832+ {
6833+ if (s->best_pos[i] == 0)
6834+ s->best_pos[i] = node + 1;
6835+ }
6836+
6837+ if (i > m_len)
6838+ {
6839+ s->m_len = m_len = i;
6840+ s->m_pos = node;
6841+ if (m_len == s->look)
6842+ return;
6843+ if (m_len >= s->nice_length)
6844+ return;
6845+ if (m_len > (lzo_uint) s->best3[node])
6846+ return;
6847+ scan_end1 = bp[m_len - 1];
6848+ }
6849+ }
6850+ }
6851+}
6852+
6853+static lzo_bool
6854+swd_search2 (lzo1x_999_swd_t * s)
6855+{
6856+ lzo_uint key;
6857+
6858+ key = s->head2[HEAD2 (s->b, s->bp)];
6859+ if (key == NIL2)
6860+ return 0;
6861+
6862+ if (s->best_pos[2] == 0)
6863+ s->best_pos[2] = key + 1;
6864+
6865+ if (s->m_len < 2)
6866+ {
6867+ s->m_len = 2;
6868+ s->m_pos = key;
6869+ }
6870+ return 1;
6871+}
6872+
6873+static void
6874+swd_findbest (lzo1x_999_swd_t * s)
6875+{
6876+ lzo_uint key;
6877+ lzo_uint cnt, node;
6878+ lzo_uint len;
6879+
6880+ key = HEAD3 (s->b, s->bp);
6881+ node = s->succ3[s->bp] = s_head3 (s, key);
6882+ cnt = s->llen3[key]++;
6883+
6884+ if (cnt > s->max_chain && s->max_chain > 0)
6885+ cnt = s->max_chain;
6886+ s->head3[key] = SWD_UINT (s->bp);
6887+
6888+ s->b_char = s->b[s->bp];
6889+ len = s->m_len;
6890+ if (s->m_len >= s->look)
6891+ {
6892+ if (s->look == 0)
6893+ s->b_char = -1;
6894+ s->m_off = 0;
6895+ s->best3[s->bp] = SWD_UINT (s->f + 1);
6896+ }
6897+ else
6898+ {
6899+
6900+ if (swd_search2 (s))
6901+
6902+ if (s->look >= 3)
6903+ swd_search (s, node, cnt);
6904+ if (s->m_len > len)
6905+ s->m_off = swd_pos2off (s, s->m_pos);
6906+ s->best3[s->bp] = SWD_UINT (s->m_len);
6907+
6908+ if (s->use_best_off)
6909+ {
6910+ int i;
6911+ for (i = 2; i < SWD_BEST_OFF; i++)
6912+ if (s->best_pos[i] > 0)
6913+ s->best_off[i] =
6914+ swd_pos2off (s,
6915+ s->best_pos[i] -
6916+ 1);
6917+ else
6918+ s->best_off[i] = 0;
6919+ }
6920+
6921+ }
6922+
6923+ swd_remove_node (s, s->rp);
6924+
6925+ key = HEAD2 (s->b, s->bp);
6926+ s->head2[key] = SWD_UINT (s->bp);
6927+
6928+}
6929+
6930+/* lzo_mchw.ch */
6931+
6932+static int
6933+init_match (lzo1x_999_t * c, lzo1x_999_swd_t * s,
6934+ const lzo_byte * dict, lzo_uint dict_len, lzo_uint32 flags)
6935+{
6936+ int r;
6937+
6938+ c->init = 1;
6939+
6940+ s->c = c;
6941+
6942+ c->last_m_len = c->last_m_off = 0;
6943+
6944+ c->textsize = c->codesize = c->printcount = 0;
6945+ c->lit_bytes = c->match_bytes = c->rep_bytes = 0;
6946+ c->lazy = 0;
6947+
6948+ r = swd_init (s, dict, dict_len);
6949+ if (r != 0)
6950+ return r;
6951+
6952+ s->use_best_off = (flags & 1) ? 1 : 0;
6953+ return r;
6954+}
6955+
6956+static int
6957+find_match (lzo1x_999_t * c, lzo1x_999_swd_t * s,
6958+ lzo_uint this_len, lzo_uint skip)
6959+{
6960+ if (skip > 0)
6961+ {
6962+ swd_accept (s, this_len - skip);
6963+ c->textsize += this_len - skip + 1;
6964+ }
6965+ else
6966+ {
6967+ c->textsize += this_len - skip;
6968+ }
6969+
6970+ s->m_len = 1;
6971+ s->m_len = 1;
6972+
6973+ if (s->use_best_off)
6974+ memset (s->best_pos, 0, sizeof (s->best_pos));
6975+
6976+ swd_findbest (s);
6977+ c->m_len = s->m_len;
6978+ c->m_off = s->m_off;
6979+
6980+ swd_getbyte (s);
6981+
6982+ if (s->b_char < 0)
6983+ {
6984+ c->look = 0;
6985+ c->m_len = 0;
6986+ }
6987+ else
6988+ {
6989+ c->look = s->look + 1;
6990+ }
6991+ c->bp = c->ip - c->look;
6992+
6993+ if (c->cb && c->textsize > c->printcount)
6994+ {
6995+ (*c->cb) (c->textsize, c->codesize);
6996+ c->printcount += 1024;
6997+ }
6998+
6999+ return LZO_E_OK;
7000+}
7001+
7002+/* lzo1x_9x.c */
7003+
7004+static lzo_byte *
7005+code_match (lzo1x_999_t * c, lzo_byte * op, lzo_uint m_len, lzo_uint m_off)
7006+{
7007+ lzo_uint x_len = m_len;
7008+ lzo_uint x_off = m_off;
7009+
7010+ c->match_bytes += m_len;
7011+
7012+ if (m_len == 2)
7013+ {
7014+ m_off -= 1;
7015+
7016+ *op++ = LZO_BYTE (M1_MARKER | ((m_off & 3) << 2));
7017+ *op++ = LZO_BYTE (m_off >> 2);
7018+
7019+ c->m1a_m++;
7020+ }
7021+
7022+ else if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
7023+
7024+ {
7025+
7026+ m_off -= 1;
7027+ *op++ = LZO_BYTE (((m_len - 1) << 5) | ((m_off & 7) << 2));
7028+ *op++ = LZO_BYTE (m_off >> 3);
7029+ c->m2_m++;
7030+ }
7031+ else if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET
7032+ && c->r1_lit >= 4)
7033+ {
7034+ m_off -= 1 + M2_MAX_OFFSET;
7035+
7036+ *op++ = LZO_BYTE (M1_MARKER | ((m_off & 3) << 2));
7037+ *op++ = LZO_BYTE (m_off >> 2);
7038+
7039+ c->m1b_m++;
7040+ }
7041+ else if (m_off <= M3_MAX_OFFSET)
7042+ {
7043+ m_off -= 1;
7044+ if (m_len <= M3_MAX_LEN)
7045+ *op++ = LZO_BYTE (M3_MARKER | (m_len - 2));
7046+ else
7047+ {
7048+ m_len -= M3_MAX_LEN;
7049+ *op++ = M3_MARKER | 0;
7050+ while (m_len > 255)
7051+ {
7052+ m_len -= 255;
7053+ *op++ = 0;
7054+ }
7055+ *op++ = LZO_BYTE (m_len);
7056+ }
7057+
7058+ *op++ = LZO_BYTE (m_off << 2);
7059+ *op++ = LZO_BYTE (m_off >> 6);
7060+
7061+ c->m3_m++;
7062+ }
7063+ else
7064+ {
7065+ lzo_uint k;
7066+
7067+ m_off -= 0x4000;
7068+ k = (m_off & 0x4000) >> 11;
7069+ if (m_len <= M4_MAX_LEN)
7070+ *op++ = LZO_BYTE (M4_MARKER | k | (m_len - 2));
7071+ else
7072+ {
7073+ m_len -= M4_MAX_LEN;
7074+ *op++ = LZO_BYTE (M4_MARKER | k | 0);
7075+ while (m_len > 255)
7076+ {
7077+ m_len -= 255;
7078+ *op++ = 0;
7079+ }
7080+ *op++ = LZO_BYTE (m_len);
7081+ }
7082+
7083+ *op++ = LZO_BYTE (m_off << 2);
7084+ *op++ = LZO_BYTE (m_off >> 6);
7085+
7086+ c->m4_m++;
7087+ }
7088+
7089+ c->last_m_len = x_len;
7090+ c->last_m_off = x_off;
7091+ return op;
7092+}
7093+
7094+static lzo_byte *
7095+STORE_RUN (lzo1x_999_t * c, lzo_byte * op, const lzo_byte * ii, lzo_uint t)
7096+{
7097+ c->lit_bytes += t;
7098+
7099+ if (op == c->out && t <= 238)
7100+ {
7101+ *op++ = LZO_BYTE (17 + t);
7102+ }
7103+ else if (t <= 3)
7104+ {
7105+ op[-2] |= LZO_BYTE (t);
7106+
7107+ c->lit1_r++;
7108+ }
7109+ else if (t <= 18)
7110+ {
7111+ *op++ = LZO_BYTE (t - 3);
7112+ c->lit2_r++;
7113+ }
7114+ else
7115+ {
7116+ lzo_uint tt = t - 18;
7117+
7118+ *op++ = 0;
7119+ while (tt > 255)
7120+ {
7121+ tt -= 255;
7122+ *op++ = 0;
7123+ }
7124+ *op++ = LZO_BYTE (tt);
7125+ c->lit3_r++;
7126+ }
7127+ do
7128+ *op++ = *ii++;
7129+ while (--t > 0);
7130+
7131+ return op;
7132+}
7133+
7134+static lzo_byte *
7135+code_run (lzo1x_999_t * c, lzo_byte * op, const lzo_byte * ii,
7136+ lzo_uint lit, lzo_uint m_len)
7137+{
7138+ if (lit > 0)
7139+ {
7140+ op = STORE_RUN (c, op, ii, lit);
7141+ c->r1_m_len = m_len;
7142+ c->r1_lit = lit;
7143+ }
7144+ else
7145+ {
7146+ c->r1_m_len = 0;
7147+ c->r1_lit = 0;
7148+ }
7149+
7150+ return op;
7151+}
7152+
7153+static int
7154+len_of_coded_match (lzo_uint m_len, lzo_uint m_off, lzo_uint lit)
7155+{
7156+ int n = 4;
7157+
7158+ if (m_len < 2)
7159+ return -1;
7160+ if (m_len == 2)
7161+ return (m_off <= M1_MAX_OFFSET && lit > 0
7162+ && lit < 4) ? 2 : -1;
7163+ if (m_len <= M2_MAX_LEN && m_off <= M2_MAX_OFFSET)
7164+ return 2;
7165+ if (m_len == M2_MIN_LEN && m_off <= MX_MAX_OFFSET && lit >= 4)
7166+ return 2;
7167+ if (m_off <= M3_MAX_OFFSET)
7168+ {
7169+ if (m_len <= M3_MAX_LEN)
7170+ return 3;
7171+ m_len -= M3_MAX_LEN;
7172+ while (m_len > 255)
7173+ {
7174+ m_len -= 255;
7175+ n++;
7176+ }
7177+ return n;
7178+ }
7179+ if (m_off <= M4_MAX_OFFSET)
7180+ {
7181+ if (m_len <= M4_MAX_LEN)
7182+ return 3;
7183+ m_len -= M4_MAX_LEN;
7184+ while (m_len > 255)
7185+ {
7186+ m_len -= 255;
7187+ n++;
7188+ }
7189+ return n;
7190+ }
7191+ return -1;
7192+}
7193+
7194+static lzo_int
7195+min_gain (lzo_uint ahead, lzo_uint lit1, lzo_uint lit2, int l1, int l2,
7196+ int l3)
7197+{
7198+ lzo_int lazy_match_min_gain = 0;
7199+
7200+ lazy_match_min_gain += ahead;
7201+
7202+ if (lit1 <= 3)
7203+ lazy_match_min_gain += (lit2 <= 3) ? 0 : 2;
7204+ else if (lit1 <= 18)
7205+ lazy_match_min_gain += (lit2 <= 18) ? 0 : 1;
7206+
7207+ lazy_match_min_gain += (l2 - l1) * 2;
7208+ if (l3 > 0)
7209+ lazy_match_min_gain -= (ahead - l3) * 2;
7210+
7211+ if (lazy_match_min_gain < 0)
7212+ lazy_match_min_gain = 0;
7213+
7214+ return lazy_match_min_gain;
7215+}
7216+
7217+static void
7218+better_match (const lzo1x_999_swd_t * swd, lzo_uint * m_len, lzo_uint * m_off)
7219+{
7220+ if (*m_len <= M2_MIN_LEN)
7221+ return;
7222+
7223+ if (*m_off <= M2_MAX_OFFSET)
7224+ return;
7225+
7226+ if (*m_off > M2_MAX_OFFSET &&
7227+ *m_len >= M2_MIN_LEN + 1 && *m_len <= M2_MAX_LEN + 1 &&
7228+ swd->best_off[*m_len - 1]
7229+ && swd->best_off[*m_len - 1] <= M2_MAX_OFFSET)
7230+ {
7231+ *m_len = *m_len - 1;
7232+ *m_off = swd->best_off[*m_len];
7233+ return;
7234+ }
7235+
7236+ if (*m_off > M3_MAX_OFFSET &&
7237+ *m_len >= M4_MAX_LEN + 1 && *m_len <= M2_MAX_LEN + 2 &&
7238+ swd->best_off[*m_len - 2]
7239+ && swd->best_off[*m_len - 2] <= M2_MAX_OFFSET)
7240+ {
7241+ *m_len = *m_len - 2;
7242+ *m_off = swd->best_off[*m_len];
7243+ return;
7244+ }
7245+
7246+ if (*m_off > M3_MAX_OFFSET &&
7247+ *m_len >= M4_MAX_LEN + 1 && *m_len <= M3_MAX_LEN + 1 &&
7248+ swd->best_off[*m_len - 1]
7249+ && swd->best_off[*m_len - 1] <= M3_MAX_OFFSET)
7250+ {
7251+ *m_len = *m_len - 1;
7252+ *m_off = swd->best_off[*m_len];
7253+ }
7254+
7255+}
7256+
7257+/* minilzo.c */
7258+
7259+static lzo_bool
7260+lzo_assert (int expr)
7261+{
7262+ return (expr) ? 1 : 0;
7263+}
7264+
7265+/* lzo1x_9x.c */
7266+
7267+static int
7268+lzo1x_999_compress_internal (const lzo_byte * in, lzo_uint in_len,
7269+ lzo_byte * out, lzo_uintp out_len,
7270+ lzo_voidp wrkmem,
7271+ const lzo_byte * dict, lzo_uint dict_len,
7272+ lzo_progress_callback_t cb,
7273+ int try_lazy,
7274+ lzo_uint good_length,
7275+ lzo_uint max_lazy,
7276+ lzo_uint nice_length,
7277+ lzo_uint max_chain, lzo_uint32 flags)
7278+{
7279+ lzo_byte *op;
7280+ const lzo_byte *ii;
7281+ lzo_uint lit;
7282+ lzo_uint m_len, m_off;
7283+ lzo1x_999_t cc;
7284+ lzo1x_999_t *const c = &cc;
7285+ lzo1x_999_swd_t *const swd = (lzo1x_999_swd_t *) wrkmem;
7286+ int r;
7287+
7288+ if (!lzo_assert
7289+ (LZO1X_999_MEM_COMPRESS >= lzo_sizeof (lzo1x_999_swd_t)))
7290+ return LZO_E_ERROR;
7291+
7292+ if (try_lazy < 0)
7293+ try_lazy = 1;
7294+
7295+ if (good_length <= 0)
7296+ good_length = 32;
7297+
7298+ if (max_lazy <= 0)
7299+ max_lazy = 32;
7300+
7301+ if (nice_length <= 0)
7302+ nice_length = 0;
7303+
7304+ if (max_chain <= 0)
7305+ max_chain = SWD_MAX_CHAIN;
7306+
7307+ c->init = 0;
7308+ c->ip = c->in = in;
7309+ c->in_end = in + in_len;
7310+ c->out = out;
7311+ c->cb = cb;
7312+ c->m1a_m = c->m1b_m = c->m2_m = c->m3_m = c->m4_m = 0;
7313+ c->lit1_r = c->lit2_r = c->lit3_r = 0;
7314+
7315+ op = out;
7316+ ii = c->ip;
7317+ lit = 0;
7318+ c->r1_lit = c->r1_m_len = 0;
7319+
7320+ r = init_match (c, swd, dict, dict_len, flags);
7321+ if (r != 0)
7322+ return r;
7323+ if (max_chain > 0)
7324+ swd->max_chain = max_chain;
7325+ if (nice_length > 0)
7326+ swd->nice_length = nice_length;
7327+
7328+ r = find_match (c, swd, 0, 0);
7329+ if (r != 0)
7330+ return r;
7331+ while (c->look > 0)
7332+ {
7333+ lzo_uint ahead;
7334+ lzo_uint max_ahead;
7335+ int l1, l2, l3;
7336+
7337+ c->codesize = op - out;
7338+
7339+ m_len = c->m_len;
7340+ m_off = c->m_off;
7341+
7342+ if (lit == 0)
7343+ ii = c->bp;
7344+
7345+ if (m_len < 2 ||
7346+ (m_len == 2
7347+ && (m_off > M1_MAX_OFFSET || lit == 0 || lit >= 4))
7348+ || (m_len == 2 && op == out) || (op == out && lit == 0))
7349+ {
7350+
7351+ m_len = 0;
7352+ }
7353+ else if (m_len == M2_MIN_LEN)
7354+ {
7355+
7356+ if (m_off > MX_MAX_OFFSET && lit >= 4)
7357+ m_len = 0;
7358+ }
7359+
7360+ if (m_len == 0)
7361+ {
7362+
7363+ lit++;
7364+ swd->max_chain = max_chain;
7365+ r = find_match (c, swd, 1, 0);
7366+ continue;
7367+ }
7368+
7369+ if (swd->use_best_off)
7370+ better_match (swd, &m_len, &m_off);
7371+
7372+ ahead = 0;
7373+ if (try_lazy <= 0 || m_len >= max_lazy)
7374+ {
7375+
7376+ l1 = 0;
7377+ max_ahead = 0;
7378+ }
7379+ else
7380+ {
7381+
7382+ l1 = len_of_coded_match (m_len, m_off, lit);
7383+
7384+ max_ahead = LZO_MIN (try_lazy, l1 - 1);
7385+
7386+ }
7387+
7388+ while (ahead < max_ahead && c->look > m_len)
7389+ {
7390+ lzo_int lazy_match_min_gain;
7391+
7392+ if (m_len >= good_length)
7393+ swd->max_chain = max_chain >> 2;
7394+ else
7395+ swd->max_chain = max_chain;
7396+ r = find_match (c, swd, 1, 0);
7397+ ahead++;
7398+
7399+ if (c->m_len < m_len)
7400+ continue;
7401+
7402+ if (c->m_len == m_len && c->m_off >= m_off)
7403+ continue;
7404+
7405+ if (swd->use_best_off)
7406+ better_match (swd, &c->m_len, &c->m_off);
7407+
7408+ l2 = len_of_coded_match (c->m_len, c->m_off,
7409+ lit + ahead);
7410+ if (l2 < 0)
7411+ continue;
7412+
7413+ l3 = (op == out) ? -1 : len_of_coded_match (ahead,
7414+ m_off,
7415+ lit);
7416+
7417+ lazy_match_min_gain =
7418+ min_gain (ahead, lit, lit + ahead, l1, l2,
7419+ l3);
7420+ if (c->m_len >= m_len + lazy_match_min_gain)
7421+ {
7422+ c->lazy++;
7423+
7424+ if (l3 > 0)
7425+ {
7426+
7427+ op = code_run (c, op, ii, lit, ahead);
7428+ lit = 0;
7429+
7430+ op = code_match (c, op, ahead, m_off);
7431+ }
7432+ else
7433+ {
7434+ lit += ahead;
7435+ }
7436+ goto lazy_match_done;
7437+ }
7438+ }
7439+
7440+ op = code_run (c, op, ii, lit, m_len);
7441+ lit = 0;
7442+
7443+ op = code_match (c, op, m_len, m_off);
7444+ swd->max_chain = max_chain;
7445+ r = find_match (c, swd, m_len, 1 + ahead);
7446+
7447+ lazy_match_done:;
7448+ }
7449+
7450+ if (lit > 0)
7451+ op = STORE_RUN (c, op, ii, lit);
7452+
7453+ *op++ = M4_MARKER | 1;
7454+ *op++ = 0;
7455+ *op++ = 0;
7456+
7457+ c->codesize = op - out;
7458+
7459+ *out_len = op - out;
7460+
7461+ if (c->cb)
7462+ (*c->cb) (c->textsize, c->codesize);
7463+
7464+ return LZO_E_OK;
7465+}
7466+
7467+static int
7468+lzo1x_999_compress_level (const lzo_byte * in, lzo_uint in_len,
7469+ lzo_byte * out, lzo_uintp out_len,
7470+ lzo_voidp wrkmem,
7471+ const lzo_byte * dict, lzo_uint dict_len,
7472+ lzo_progress_callback_t cb, int compression_level)
7473+{
7474+ static const struct
7475+ {
7476+ int try_lazy;
7477+ lzo_uint good_length;
7478+ lzo_uint max_lazy;
7479+ lzo_uint nice_length;
7480+ lzo_uint max_chain;
7481+ lzo_uint32 flags;
7482+ } c[9] =
7483+ {
7484+ {
7485+ 0, 0, 0, 8, 4, 0},
7486+ {
7487+ 0, 0, 0, 16, 8, 0},
7488+ {
7489+ 0, 0, 0, 32, 16, 0},
7490+ {
7491+ 1, 4, 4, 16, 16, 0},
7492+ {
7493+ 1, 8, 16, 32, 32, 0},
7494+ {
7495+ 1, 8, 16, 128, 128, 0},
7496+ {
7497+ 2, 8, 32, 128, 256, 0},
7498+ {
7499+ 2, 32, 128, F, 2048, 1},
7500+ {
7501+ 2, F, F, F, 4096, 1}
7502+ };
7503+
7504+ if (compression_level < 1 || compression_level > 9)
7505+ return LZO_E_ERROR;
7506+
7507+ compression_level -= 1;
7508+ return lzo1x_999_compress_internal (in, in_len, out, out_len, wrkmem,
7509+ dict, dict_len, cb,
7510+ c[compression_level].try_lazy,
7511+ c[compression_level].good_length,
7512+ c[compression_level].max_lazy,
7513+ 0,
7514+ c[compression_level].max_chain,
7515+ c[compression_level].flags);
7516+}
7517+
7518+static int
7519+lzo1x_999_compress (const lzo_byte * in, lzo_uint in_len,
7520+ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
7521+{
7522+ return lzo1x_999_compress_level (in, in_len, out, out_len, wrkmem,
7523+ NULL, 0, 0, 8);
7524+}
7525+
7526+/* minilzo.c */
7527+
7528+static const lzo_byte __lzo_copyright[] = LZO_VERSION_STRING;
7529+
7530+static lzo_uint
7531+_lzo1x_1_do_compress (const lzo_byte * in, lzo_uint in_len,
7532+ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
7533+{
7534+
7535+ register const lzo_byte *ip;
7536+
7537+ lzo_byte *op;
7538+ const lzo_byte *const in_end = in + in_len;
7539+ const lzo_byte *const ip_end = in + in_len - 8 - 5;
7540+ const lzo_byte *ii;
7541+ lzo_dict_p const dict = (lzo_dict_p) wrkmem;
7542+
7543+ op = out;
7544+ ip = in;
7545+ ii = ip;
7546+
7547+ ip += 4;
7548+ for (;;)
7549+ {
7550+ register const lzo_byte *m_pos;
7551+
7552+ lzo_uint m_off;
7553+ lzo_uint m_len;
7554+ lzo_uint dindex;
7555+
7556+ DINDEX1 (dindex, ip);
7557+ GINDEX (m_pos, m_off, dict, dindex, in);
7558+ if (LZO_CHECK_MPOS_NON_DET
7559+ (m_pos, m_off, in, ip, M4_MAX_OFFSET))
7560+ goto literal;
7561+
7562+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
7563+ goto try_match;
7564+ DINDEX2 (dindex, ip);
7565+ GINDEX (m_pos, m_off, dict, dindex, in);
7566+
7567+ if (LZO_CHECK_MPOS_NON_DET
7568+ (m_pos, m_off, in, ip, M4_MAX_OFFSET))
7569+ goto literal;
7570+ if (m_off <= M2_MAX_OFFSET || m_pos[3] == ip[3])
7571+ goto try_match;
7572+ goto literal;
7573+
7574+ try_match:
7575+ if (m_pos[0] != ip[0] || m_pos[1] != ip[1])
7576+ {
7577+ }
7578+ else
7579+ {
7580+ if (m_pos[2] == ip[2])
7581+ {
7582+ goto match;
7583+ }
7584+ else
7585+ {
7586+ }
7587+ }
7588+
7589+ literal:
7590+ UPDATE_I (dict, 0, dindex, ip, in);
7591+ ++ip;
7592+ if (ip >= ip_end)
7593+ break;
7594+ continue;
7595+
7596+ match:
7597+ UPDATE_I (dict, 0, dindex, ip, in);
7598+
7599+ if (pd (ip, ii) > 0)
7600+ {
7601+ register lzo_uint t = pd (ip, ii);
7602+
7603+ if (t <= 3)
7604+ {
7605+ op[-2] |= LZO_BYTE (t);
7606+ }
7607+ else if (t <= 18)
7608+ *op++ = LZO_BYTE (t - 3);
7609+ else
7610+ {
7611+ register lzo_uint tt = t - 18;
7612+
7613+ *op++ = 0;
7614+ while (tt > 255)
7615+ {
7616+ tt -= 255;
7617+ *op++ = 0;
7618+ }
7619+ *op++ = LZO_BYTE (tt);;
7620+ }
7621+ do
7622+ *op++ = *ii++;
7623+ while (--t > 0);
7624+ }
7625+
7626+ ip += 3;
7627+ if (m_pos[3] != *ip++ || m_pos[4] != *ip++
7628+ || m_pos[5] != *ip++ || m_pos[6] != *ip++
7629+ || m_pos[7] != *ip++ || m_pos[8] != *ip++)
7630+ {
7631+ --ip;
7632+ m_len = ip - ii;
7633+
7634+ if (m_off <= M2_MAX_OFFSET)
7635+ {
7636+ m_off -= 1;
7637+
7638+ *op++ = LZO_BYTE (((m_len -
7639+ 1) << 5) | ((m_off & 7) <<
7640+ 2));
7641+ *op++ = LZO_BYTE (m_off >> 3);
7642+ }
7643+ else if (m_off <= M3_MAX_OFFSET)
7644+ {
7645+ m_off -= 1;
7646+ *op++ = LZO_BYTE (M3_MARKER | (m_len - 2));
7647+ goto m3_m4_offset;
7648+ }
7649+ else
7650+
7651+ {
7652+ m_off -= 0x4000;
7653+
7654+ *op++ = LZO_BYTE (M4_MARKER |
7655+ ((m_off & 0x4000) >> 11) |
7656+ (m_len - 2));
7657+ goto m3_m4_offset;
7658+ }
7659+ }
7660+ else
7661+ {
7662+ {
7663+ const lzo_byte *end = in_end;
7664+ const lzo_byte *m = m_pos + M2_MAX_LEN + 1;
7665+ while (ip < end && *m == *ip)
7666+ m++, ip++;
7667+ m_len = (ip - ii);
7668+ }
7669+
7670+
7671+ if (m_off <= M3_MAX_OFFSET)
7672+ {
7673+ m_off -= 1;
7674+ if (m_len <= 33)
7675+ *op++ = LZO_BYTE (M3_MARKER |
7676+ (m_len - 2));
7677+ else
7678+ {
7679+ m_len -= 33;
7680+ *op++ = M3_MARKER | 0;
7681+ goto m3_m4_len;
7682+ }
7683+ }
7684+ else
7685+ {
7686+ m_off -= 0x4000;
7687+
7688+ if (m_len <= M4_MAX_LEN)
7689+ *op++ = LZO_BYTE (M4_MARKER |
7690+ ((m_off & 0x4000) >>
7691+ 11) | (m_len - 2));
7692+
7693+ else
7694+ {
7695+ m_len -= M4_MAX_LEN;
7696+ *op++ = LZO_BYTE (M4_MARKER |
7697+ ((m_off & 0x4000) >>
7698+ 11));
7699+ m3_m4_len:
7700+ while (m_len > 255)
7701+ {
7702+ m_len -= 255;
7703+ *op++ = 0;
7704+ }
7705+
7706+ *op++ = LZO_BYTE (m_len);
7707+ }
7708+ }
7709+
7710+ m3_m4_offset:
7711+ *op++ = LZO_BYTE ((m_off & 63) << 2);
7712+ *op++ = LZO_BYTE (m_off >> 6);
7713+ }
7714+ ii = ip;
7715+ if (ip >= ip_end)
7716+ break;
7717+ }
7718+
7719+ *out_len = op - out;
7720+ return pd (in_end, ii);
7721+}
7722+
7723+static int
7724+lzo1x_1_compress (const lzo_byte * in, lzo_uint in_len,
7725+ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
7726+{
7727+ lzo_byte *op = out;
7728+ lzo_uint t;
7729+
7730+ if (in_len <= M2_MAX_LEN + 5)
7731+ t = in_len;
7732+ else
7733+ {
7734+ t = _lzo1x_1_do_compress (in, in_len, op, out_len, wrkmem);
7735+ op += *out_len;
7736+ }
7737+
7738+ if (t > 0)
7739+ {
7740+ const lzo_byte *ii = in + in_len - t;
7741+
7742+ if (op == out && t <= 238)
7743+ *op++ = LZO_BYTE (17 + t);
7744+ else if (t <= 3)
7745+ op[-2] |= LZO_BYTE (t);
7746+ else if (t <= 18)
7747+ *op++ = LZO_BYTE (t - 3);
7748+ else
7749+ {
7750+ lzo_uint tt = t - 18;
7751+
7752+ *op++ = 0;
7753+ while (tt > 255)
7754+ {
7755+ tt -= 255;
7756+ *op++ = 0;
7757+ }
7758+
7759+ *op++ = LZO_BYTE (tt);
7760+ }
7761+ do
7762+ *op++ = *ii++;
7763+ while (--t > 0);
7764+ }
7765+
7766+ *op++ = M4_MARKER | 1;
7767+ *op++ = 0;
7768+ *op++ = 0;
7769+
7770+ *out_len = op - out;
7771+ return 0;
7772+}
7773+
7774+static int
7775+lzo1x_decompress (const lzo_byte * in, lzo_uint in_len,
7776+ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
7777+{
7778+ register lzo_byte *op;
7779+ register const lzo_byte *ip;
7780+ register lzo_uint t;
7781+
7782+ register const lzo_byte *m_pos;
7783+
7784+ const lzo_byte *const ip_end = in + in_len;
7785+ lzo_byte *const op_end = out + *out_len;
7786+
7787+ *out_len = 0;
7788+
7789+ op = out;
7790+ ip = in;
7791+
7792+ if (*ip > 17)
7793+ {
7794+ t = *ip++ - 17;
7795+ if (t < 4)
7796+ goto match_next;
7797+ NEED_OP (t);
7798+ NEED_IP (t + 1);
7799+ do
7800+ *op++ = *ip++;
7801+ while (--t > 0);
7802+ goto first_literal_run;
7803+ }
7804+
7805+ while (TEST_IP && TEST_OP)
7806+ {
7807+ t = *ip++;
7808+ if (t >= 16)
7809+ goto match;
7810+ if (t == 0)
7811+ {
7812+ NEED_IP (1);
7813+ while (*ip == 0)
7814+ {
7815+ t += 255;
7816+ ip++;
7817+ NEED_IP (1);
7818+ }
7819+ t += 15 + *ip++;
7820+ }
7821+ NEED_OP (t + 3);
7822+ NEED_IP (t + 4);
7823+ if (PTR_ALIGNED2_4 (op, ip))
7824+ {
7825+ COPY4 (op, ip);
7826+
7827+ op += 4;
7828+ ip += 4;
7829+ if (--t > 0)
7830+ {
7831+ if (t >= 4)
7832+ {
7833+ do
7834+ {
7835+ COPY4 (op, ip);
7836+ op += 4;
7837+ ip += 4;
7838+ t -= 4;
7839+ }
7840+ while (t >= 4);
7841+ if (t > 0)
7842+ do
7843+ *op++ = *ip++;
7844+ while (--t > 0);
7845+ }
7846+ else
7847+ do
7848+ *op++ = *ip++;
7849+ while (--t > 0);
7850+ }
7851+ }
7852+ else
7853+ {
7854+ *op++ = *ip++;
7855+ *op++ = *ip++;
7856+ *op++ = *ip++;
7857+ do
7858+ *op++ = *ip++;
7859+ while (--t > 0);
7860+ }
7861+ first_literal_run:
7862+
7863+ t = *ip++;
7864+ if (t >= 16)
7865+ goto match;
7866+
7867+ m_pos = op - (1 + M2_MAX_OFFSET);
7868+ m_pos -= t >> 2;
7869+ m_pos -= *ip++ << 2;
7870+ TEST_LOOKBEHIND (m_pos, out);
7871+ NEED_OP (3);
7872+ *op++ = *m_pos++;
7873+ *op++ = *m_pos++;
7874+ *op++ = *m_pos;
7875+
7876+ goto match_done;
7877+
7878+ while (TEST_IP && TEST_OP)
7879+ {
7880+ match:
7881+ if (t >= 64)
7882+ {
7883+ m_pos = op - 1;
7884+ m_pos -= (t >> 2) & 7;
7885+ m_pos -= *ip++ << 3;
7886+ t = (t >> 5) - 1;
7887+ TEST_LOOKBEHIND (m_pos, out);
7888+ NEED_OP (t + 3 - 1);
7889+ goto copy_match;
7890+
7891+ }
7892+ else if (t >= 32)
7893+ {
7894+ t &= 31;
7895+ if (t == 0)
7896+ {
7897+ NEED_IP (1);
7898+ while (*ip == 0)
7899+ {
7900+ t += 255;
7901+ ip++;
7902+ NEED_IP (1);
7903+ }
7904+ t += 31 + *ip++;
7905+ }
7906+
7907+ m_pos = op - 1;
7908+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
7909+
7910+ ip += 2;
7911+ }
7912+ else if (t >= 16)
7913+ {
7914+ m_pos = op;
7915+ m_pos -= (t & 8) << 11;
7916+
7917+ t &= 7;
7918+ if (t == 0)
7919+ {
7920+ NEED_IP (1);
7921+ while (*ip == 0)
7922+ {
7923+ t += 255;
7924+ ip++;
7925+ NEED_IP (1);
7926+ }
7927+ t += 7 + *ip++;
7928+ }
7929+
7930+ m_pos -= (ip[0] >> 2) + (ip[1] << 6);
7931+
7932+ ip += 2;
7933+ if (m_pos == op)
7934+ goto eof_found;
7935+ m_pos -= 0x4000;
7936+ }
7937+ else
7938+ {
7939+
7940+ m_pos = op - 1;
7941+ m_pos -= t >> 2;
7942+ m_pos -= *ip++ << 2;
7943+ TEST_LOOKBEHIND (m_pos, out);
7944+ NEED_OP (2);
7945+ *op++ = *m_pos++;
7946+ *op++ = *m_pos;
7947+
7948+ goto match_done;
7949+ }
7950+
7951+ TEST_LOOKBEHIND (m_pos, out);
7952+ NEED_OP (t + 3 - 1);
7953+ if (t >= 2 * 4 - (3 - 1)
7954+ && PTR_ALIGNED2_4 (op, m_pos))
7955+ {
7956+ COPY4 (op, m_pos);
7957+ op += 4;
7958+ m_pos += 4;
7959+ t -= 4 - (3 - 1);
7960+ do
7961+ {
7962+ COPY4 (op, m_pos);
7963+ op += 4;
7964+ m_pos += 4;
7965+ t -= 4;
7966+ }
7967+ while (t >= 4);
7968+ if (t > 0)
7969+ do
7970+ *op++ = *m_pos++;
7971+ while (--t > 0);
7972+ }
7973+ else
7974+
7975+ {
7976+ copy_match:
7977+ *op++ = *m_pos++;
7978+ *op++ = *m_pos++;
7979+ do
7980+ *op++ = *m_pos++;
7981+ while (--t > 0);
7982+ }
7983+
7984+ match_done:
7985+ t = ip[-2] & 3;
7986+
7987+ if (t == 0)
7988+ break;
7989+
7990+ match_next:
7991+ NEED_OP (t);
7992+ NEED_IP (t + 1);
7993+ do
7994+ *op++ = *ip++;
7995+ while (--t > 0);
7996+ t = *ip++;
7997+ }
7998+ }
7999+ *out_len = op - out;
8000+ return LZO_E_EOF_NOT_FOUND;
8001+
8002+ eof_found:
8003+ *out_len = op - out;
8004+ return (ip == ip_end ? LZO_E_OK :
8005+ (ip <
8006+ ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
8007+
8008+ input_overrun:
8009+ *out_len = op - out;
8010+ return LZO_E_INPUT_OVERRUN;
8011+
8012+ output_overrun:
8013+ *out_len = op - out;
8014+ return LZO_E_OUTPUT_OVERRUN;
8015+
8016+ lookbehind_overrun:
8017+ *out_len = op - out;
8018+ return LZO_E_LOOKBEHIND_OVERRUN;
8019+}
8020+
8021+/* lzo1x_oo.ch */
8022+
8023+#define NO_LIT LZO_UINT_MAX
8024+
8025+static void
8026+copy2 (lzo_byte * ip, const lzo_byte * m_pos, lzo_ptrdiff_t off)
8027+{
8028+ ip[0] = m_pos[0];
8029+ if (off == 1)
8030+ ip[1] = m_pos[0];
8031+ else
8032+ ip[1] = m_pos[1];
8033+}
8034+
8035+static void
8036+copy3 (lzo_byte * ip, const lzo_byte * m_pos, lzo_ptrdiff_t off)
8037+{
8038+ ip[0] = m_pos[0];
8039+ if (off == 1)
8040+ {
8041+ ip[2] = ip[1] = m_pos[0];
8042+ }
8043+ else if (off == 2)
8044+ {
8045+ ip[1] = m_pos[1];
8046+ ip[2] = m_pos[0];
8047+ }
8048+ else
8049+ {
8050+ ip[1] = m_pos[1];
8051+ ip[2] = m_pos[2];
8052+ }
8053+}
8054+
8055+static int
8056+lzo1x_optimize (lzo_byte * in, lzo_uint in_len,
8057+ lzo_byte * out, lzo_uintp out_len, lzo_voidp wrkmem)
8058+{
8059+ register lzo_byte *op;
8060+ register lzo_byte *ip;
8061+ register lzo_uint t;
8062+ register lzo_byte *m_pos;
8063+ lzo_uint nl;
8064+ const lzo_byte *const ip_end = in + in_len;
8065+ const lzo_byte *const op_end = out + *out_len;
8066+ lzo_byte *litp = NULL;
8067+ lzo_uint lit = 0;
8068+ lzo_uint next_lit = NO_LIT;
8069+ long o_m1_a = 0, o_m1_b = 0, o_m2 = 0, o_m3_a = 0, o_m3_b = 0;
8070+
8071+ *out_len = 0;
8072+
8073+ op = out;
8074+ ip = in;
8075+
8076+ if (*ip > 17)
8077+ {
8078+ t = *ip++ - 17;
8079+ if (t < 4)
8080+ goto match_next;
8081+ goto first_literal_run;
8082+ }
8083+
8084+ while (TEST_IP && TEST_OP)
8085+ {
8086+ t = *ip++;
8087+ if (t >= 16)
8088+ goto match;
8089+ litp = ip - 1;
8090+ if (t == 0)
8091+ {
8092+ t = 15;
8093+ while (*ip == 0)
8094+ t += 255, ip++;
8095+ t += *ip++;
8096+ }
8097+ lit = t + 3;
8098+ copy_literal_run:
8099+ *op++ = *ip++;
8100+ *op++ = *ip++;
8101+ *op++ = *ip++;
8102+ first_literal_run:
8103+ do
8104+ *op++ = *ip++;
8105+ while (--t > 0);
8106+
8107+ t = *ip++;
8108+
8109+ if (t >= 16)
8110+ goto match;
8111+ m_pos = op - 1 - 0x800;
8112+ m_pos -= t >> 2;
8113+ m_pos -= *ip++ << 2;
8114+ *op++ = *m_pos++;
8115+ *op++ = *m_pos++;
8116+ *op++ = *m_pos++;
8117+ lit = 0;
8118+ goto match_done;
8119+
8120+ while (TEST_IP && TEST_OP)
8121+ {
8122+ if (t < 16)
8123+ {
8124+ m_pos = op - 1;
8125+ m_pos -= t >> 2;
8126+ m_pos -= *ip++ << 2;
8127+
8128+ if (litp == NULL)
8129+ goto copy_m1;
8130+
8131+ nl = ip[-2] & 3;
8132+ if (nl == 0 && lit == 1 && ip[0] >= 16)
8133+ {
8134+ next_lit = nl;
8135+ lit += 2;
8136+ *litp = LZO_BYTE ((*litp & ~3) | lit);
8137+ copy2 (ip - 2, m_pos, op - m_pos);
8138+ o_m1_a++;
8139+ }
8140+ else if (nl == 0 && ip[0] < 16 && ip[0] != 0
8141+ && (lit + 2 + ip[0] < 16))
8142+ {
8143+ t = *ip++;
8144+ *litp &= ~3;
8145+ copy2 (ip - 3 + 1, m_pos, op - m_pos);
8146+ litp += 2;
8147+ if (lit > 0)
8148+ memmove (litp + 1, litp, lit);
8149+ lit += 2 + t + 3;
8150+ *litp = LZO_BYTE (lit - 3);
8151+
8152+ o_m1_b++;
8153+ *op++ = *m_pos++;
8154+ *op++ = *m_pos++;
8155+ goto copy_literal_run;
8156+ }
8157+ copy_m1:
8158+ *op++ = *m_pos++;
8159+ *op++ = *m_pos++;
8160+ }
8161+ else
8162+ {
8163+ match:
8164+ if (t >= 64)
8165+ {
8166+ m_pos = op - 1;
8167+ m_pos -= (t >> 2) & 7;
8168+ m_pos -= *ip++ << 3;
8169+ t = (t >> 5) - 1;
8170+ if (litp == NULL)
8171+ goto copy_m;
8172+
8173+ nl = ip[-2] & 3;
8174+ if (t == 1 && lit > 3 && nl == 0 &&
8175+ ip[0] < 16 && ip[0] != 0
8176+ && (lit + 3 + ip[0] < 16))
8177+ {
8178+ t = *ip++;
8179+ copy3 (ip - 1 - 2, m_pos,
8180+ op - m_pos);
8181+ lit += 3 + t + 3;
8182+ *litp = LZO_BYTE (lit - 3);
8183+ o_m2++;
8184+ *op++ = *m_pos++;
8185+ *op++ = *m_pos++;
8186+ *op++ = *m_pos++;
8187+ goto copy_literal_run;
8188+ }
8189+ }
8190+ else
8191+ {
8192+ if (t >= 32)
8193+ {
8194+ t &= 31;
8195+ if (t == 0)
8196+ {
8197+ t = 31;
8198+ while (*ip == 0)
8199+ t += 255,
8200+ ip++;
8201+ t += *ip++;
8202+ }
8203+ m_pos = op - 1;
8204+ m_pos -= *ip++ >> 2;
8205+ m_pos -= *ip++ << 6;
8206+ }
8207+ else
8208+ {
8209+ m_pos = op;
8210+ m_pos -= (t & 8) << 11;
8211+ t &= 7;
8212+ if (t == 0)
8213+ {
8214+ t = 7;
8215+ while (*ip == 0)
8216+ t += 255,
8217+ ip++;
8218+ t += *ip++;
8219+ }
8220+ m_pos -= *ip++ >> 2;
8221+ m_pos -= *ip++ << 6;
8222+ if (m_pos == op)
8223+ goto eof_found;
8224+ m_pos -= 0x4000;
8225+ }
8226+ if (litp == NULL)
8227+ goto copy_m;
8228+
8229+ nl = ip[-2] & 3;
8230+ if (t == 1 && lit == 0 && nl == 0
8231+ && ip[0] >= 16)
8232+ {
8233+ next_lit = nl;
8234+ lit += 3;
8235+ *litp = LZO_BYTE ((*litp & ~3)
8236+ | lit);
8237+ copy3 (ip - 3, m_pos,
8238+ op - m_pos);
8239+ o_m3_a++;
8240+ }
8241+ else if (t == 1 && lit <= 3 && nl == 0
8242+ && ip[0] < 16 && ip[0] != 0
8243+ && (lit + 3 + ip[0] < 16))
8244+ {
8245+ t = *ip++;
8246+ *litp &= ~3;
8247+ copy3 (ip - 4 + 1, m_pos,
8248+ op - m_pos);
8249+ litp += 2;
8250+ if (lit > 0)
8251+ memmove (litp + 1,
8252+ litp, lit);
8253+ lit += 3 + t + 3;
8254+ *litp = LZO_BYTE (lit - 3);
8255+
8256+ o_m3_b++;
8257+ *op++ = *m_pos++;
8258+ *op++ = *m_pos++;
8259+ *op++ = *m_pos++;
8260+ goto copy_literal_run;
8261+ }
8262+ }
8263+ copy_m:
8264+ *op++ = *m_pos++;
8265+ *op++ = *m_pos++;
8266+ do
8267+ *op++ = *m_pos++;
8268+ while (--t > 0);
8269+ }
8270+
8271+ match_done:
8272+ if (next_lit == NO_LIT)
8273+ {
8274+ t = ip[-2] & 3;
8275+ lit = t;
8276+ litp = ip - 2;
8277+ }
8278+ else
8279+ t = next_lit;
8280+ next_lit = NO_LIT;
8281+ if (t == 0)
8282+ break;
8283+ match_next:
8284+ do
8285+ *op++ = *ip++;
8286+ while (--t > 0);
8287+ t = *ip++;
8288+ }
8289+ }
8290+
8291+ *out_len = op - out;
8292+ return LZO_E_EOF_NOT_FOUND;
8293+
8294+ eof_found:
8295+ *out_len = op - out;
8296+ return (ip == ip_end ? LZO_E_OK :
8297+ (ip <
8298+ ip_end ? LZO_E_INPUT_NOT_CONSUMED : LZO_E_INPUT_OVERRUN));
8299+}
8300+
8301+/* interface to jffs2 bbc follows */
8302+
8303+#include "jffs2_bbc_framework.h"
8304+
8305+#define BLOCKSIZE 4096
8306+#define OUTBLOCKSIZE (BLOCKSIZE + BLOCKSIZE / 64 + 16 + 3)
8307+
8308+#define JFFS2_BBC_LZO_BLOCK_SIGN {0x3f, 0x47, 0x5a, 0x18}
8309+
8310+static int
8311+jffs2_bbc_lzo_compressor_init (void);
8312+
8313+static void
8314+jffs2_bbc_lzo_compressor_deinit (void);
8315+
8316+static int
8317+jffs2_bbc_lzo_compress (void *model, unsigned char *input,
8318+ unsigned char *output, unsigned long *sourcelen,
8319+ unsigned long *dstlen);
8320+
8321+static int
8322+jffs2_bbc_lzo_estimate (void *model, unsigned char *input,
8323+ unsigned long sourcelen, unsigned long *dstlen,
8324+ unsigned long *readtime, unsigned long *writetime);
8325+
8326+static int
8327+jffs2_bbc_lzo_decompress (void *model, unsigned char *input,
8328+ unsigned char *output, unsigned long sourcelen,
8329+ unsigned long dstlen);
8330+
8331+static char *
8332+jffs2_bbc_lzo_proc_info (void);
8333+
8334+static int
8335+jffs2_bbc_lzo_proc_command (char *command);
8336+
8337+struct jffs2_bbc_compressor_type jffs2_bbc_lzo = {
8338+ "lzo",
8339+ 0,
8340+ JFFS2_BBC_LZO_BLOCK_SIGN,
8341+ jffs2_bbc_lzo_compressor_init,
8342+ NULL,
8343+ NULL,
8344+ jffs2_bbc_lzo_compressor_deinit,
8345+ jffs2_bbc_lzo_compress,
8346+ jffs2_bbc_lzo_estimate,
8347+ jffs2_bbc_lzo_decompress,
8348+ jffs2_bbc_lzo_proc_info,
8349+ jffs2_bbc_lzo_proc_command
8350+};
8351+
8352+static int
8353+no_lzo1x_optimize (lzo_byte * src, lzo_uint src_len,
8354+ lzo_byte * dst, lzo_uintp dst_len, lzo_voidp wrkmem)
8355+{
8356+ return 0;
8357+}
8358+
8359+#ifdef __KERNEL__
8360+static lzo_compress_t lzo1x_compressor = lzo1x_1_compress;
8361+static lzo_optimize_t lzo1x_optimizer = no_lzo1x_optimize;
8362+static int lzo1x_compressor_type = 1;
8363+static int lzo1x_optimize_type = 0;
8364+static unsigned long lzo1x_compressor_memsize = LZO1X_1_MEM_COMPRESS;
8365+#else
8366+static lzo_compress_t lzo1x_compressor = lzo1x_999_compress;
8367+static lzo_optimize_t lzo1x_optimizer = lzo1x_optimize;
8368+static int lzo1x_compressor_type = 999;
8369+static int lzo1x_optimize_type = 1;
8370+static unsigned long lzo1x_compressor_memsize = LZO1X_999_MEM_COMPRESS;
8371+#endif
8372+
8373+static lzo_bytep wrkmem = NULL; /* temporary buffer for compression, used by lzo */
8374+static lzo_bytep cmprssmem = NULL; /* temporary buffer for compression, used by interface */
8375+
8376+static int
8377+jffs2_bbc_lzo_compressor_init (void)
8378+{
8379+ wrkmem = (lzo_bytep) jffs2_bbc_malloc (lzo1x_compressor_memsize);
8380+ cmprssmem = (lzo_bytep) jffs2_bbc_malloc (OUTBLOCKSIZE);
8381+ return !(wrkmem && cmprssmem);
8382+}
8383+
8384+static void
8385+jffs2_bbc_lzo_compressor_deinit (void)
8386+{
8387+ jffs2_bbc_free (wrkmem);
8388+ jffs2_bbc_free (cmprssmem);
8389+}
8390+
8391+static int
8392+jffs2_bbc_lzo_compress (void *model, unsigned char *input,
8393+ unsigned char *output, unsigned long *sourcelen,
8394+ unsigned long *dstlen)
8395+{
8396+ lzo_uint csize = OUTBLOCKSIZE;
8397+ lzo_uint isize = *sourcelen;
8398+ int retval;
8399+ if ((retval =
8400+ lzo1x_compressor (input, *sourcelen, cmprssmem, &csize,
8401+ wrkmem)) != LZO_E_OK)
8402+ {
8403+ *sourcelen = *dstlen = 0;
8404+ return retval;
8405+ }
8406+ else
8407+ {
8408+ retval = lzo1x_optimizer (cmprssmem, csize, input, &isize,
8409+ NULL);
8410+ csize += 2;
8411+ if (csize <= *dstlen) {
8412+ *dstlen = csize;
8413+ *(output++) = jffs2_bbc_lzo.block_sign[0];
8414+ *(output++) = jffs2_bbc_lzo.block_sign[1];
8415+ memcpy (output, cmprssmem, csize - 2);
8416+ return retval;
8417+ } else {
8418+ *sourcelen = *dstlen = 0;
8419+ return -1;
8420+ }
8421+ }
8422+}
8423+
8424+static int
8425+jffs2_bbc_lzo_estimate (void *model, unsigned char *input,
8426+ unsigned long sourcelen, unsigned long *dstlen,
8427+ unsigned long *readtime, unsigned long *writetime)
8428+{
8429+ *dstlen = sourcelen * 55 / 100;
8430+ *readtime = JFFS2_BBC_ZLIB_READ_TIME / 2;
8431+ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 8 / 10; /* LZO1X-1 is much-much faster,
8432+ but LZO1X-999 is slow. The default mode for inside kernel compression is LZO1X-1
8433+ This should be *0.4 really */
8434+ return 0;
8435+}
8436+
8437+static int
8438+jffs2_bbc_lzo_decompress (void *model, unsigned char *input,
8439+ unsigned char *output, unsigned long sourcelen,
8440+ unsigned long dstlen)
8441+{
8442+ lzo_uint outlen = dstlen;
8443+ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzo.block_sign[0] ) ||
8444+ ( *(input++) != (unsigned char)jffs2_bbc_lzo.block_sign[1] )
8445+ ) {
8446+ return -1;
8447+ } else {
8448+ return lzo1x_decompress (input, sourcelen - 2, output, &outlen, NULL);
8449+ }
8450+}
8451+
8452+static char *
8453+jffs2_bbc_lzo_proc_info (void)
8454+{
8455+ if (lzo1x_compressor_type == 1)
8456+ {
8457+ if (lzo1x_optimize_type == 1)
8458+ {
8459+ return "LZO1X-1 compression with optimization";
8460+ }
8461+ else
8462+ {
8463+ return "LZO1X-1 compression without optimization";
8464+ }
8465+ }
8466+ else if (lzo1x_compressor_type == 999)
8467+ {
8468+ if (lzo1x_optimize_type == 1)
8469+ {
8470+ return "LZO1X-999 compression with optimization";
8471+ }
8472+ else
8473+ {
8474+ return "LZO1X-999 compression without optimization";
8475+ }
8476+ }
8477+ else
8478+ {
8479+ return "Unknown configuration!";
8480+ }
8481+}
8482+
8483+static int
8484+jffs2_bbc_lzo_proc_command (char *command)
8485+{
8486+ switch (*command)
8487+ {
8488+ case 'o':
8489+ /* switch optimization off */
8490+ lzo1x_optimizer = no_lzo1x_optimize;
8491+ lzo1x_optimize_type = 0;
8492+ jffs2_bbc_print1 ("Compression optimization switched off.\n");
8493+ return 0;
8494+ case 'O':
8495+ /* switch optimization on */
8496+ lzo1x_optimizer = lzo1x_optimize;
8497+ lzo1x_optimize_type = 1;
8498+ jffs2_bbc_print1 ("Compression optimization switched on.\n");
8499+ return 0;
8500+ case '1':
8501+ /* switch compression to LZO1X-1 */
8502+ jffs2_bbc_free (wrkmem);
8503+ lzo1x_compressor_type = 1;
8504+ lzo1x_compressor = lzo1x_1_compress;
8505+ lzo1x_compressor_memsize = LZO1X_1_MEM_COMPRESS;
8506+ wrkmem = (lzo_bytep)
8507+ jffs2_bbc_malloc (lzo1x_compressor_memsize);
8508+ jffs2_bbc_print1 ("Compression type switched to LZO1X-1.\n");
8509+ return 0;
8510+ case '9':
8511+ /* switch compression to LZO1X-999 */
8512+ jffs2_bbc_free (wrkmem);
8513+ lzo1x_compressor_type = 999;
8514+ lzo1x_compressor = lzo1x_999_compress;
8515+ lzo1x_compressor_memsize = LZO1X_999_MEM_COMPRESS;
8516+ wrkmem = (lzo_bytep)
8517+ jffs2_bbc_malloc (lzo1x_compressor_memsize);
8518+ jffs2_bbc_print1
8519+ ("Compression type switched to LZO1X-999.\n");
8520+ return 0;
8521+ default:
8522+ jffs2_bbc_print1 ("Unknown command!\n");
8523+ return 0;
8524+ }
8525+}
8526+
8527+
8528+struct jffs2_bbc_compressor_type *
8529+jffs2_bbc_lzo_init (int mode)
8530+{
8531+ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzo) == 0)
8532+ {
8533+ return &jffs2_bbc_lzo;
8534+ }
8535+ else
8536+ {
8537+ return NULL;
8538+ }
8539+}
8540+
8541+void
8542+jffs2_bbc_lzo_deinit (void)
8543+{
8544+ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzo);
8545+}
8546--- /dev/null
8547+++ b/fs/jffs2/jffs2_bbc_lzss_comp.c
8548@@ -0,0 +1,385 @@
8549+/* -*- Mode: C; indent-tabs-mode: t; c-basic-offset: 4; tab-width: 4 -*- */
8550+
8551+/*
8552+ jffs2_bbc_lzss_comp.c -- Lempel-Ziv-Storer-Szymanski compression module for jffs2
8553+ Copyright (C) 2004 Patrik Kluba
8554+ Based on the LZSS source included in LDS (lossless datacompression sources)
8555+ Block-compression modifications by Patrik Kluba
8556+ $Header: /openwrt/openwrt/package/linux/kernel-patches/301-jffs-compression,v 1.1 2005/03/26 10:33:31 wbx Exp $
8557+*/
8558+
8559+/*
8560+Original copyright follows:
8561+
8562+**************************************************************
8563+ LZSS.C -- A Data Compression Program
8564+**************************************************************
8565+ 4/6/1989 Haruhiko Okumura
8566+ Use, distribute, and modify this program freely.
8567+ Please send me your improved versions.
8568+ PC-VAN SCIENCE
8569+ NIFTY-Serve PAF01022
8570+ CompuServe 74050,1022
8571+**************************************************************
8572+
8573+*/
8574+
8575+/*
8576+
8577+ 2004-02-16 pajko <pajko(AT)halom(DOT)u-szeged(DOT)hu>
8578+ Initial release
8579+
8580+*/
8581+
8582+/* lzss.c */
8583+
8584+#define N 4096 /* size of ring buffer */
8585+#define F 18 /* upper limit for match_length */
8586+#define THRESHOLD 2 /* encode string into position and length
8587+ if match_length is greater than this */
8588+#define NIL N /* index for root of binary search trees */
8589+
8590+static unsigned char
8591+ text_buf[N + F - 1]; /* ring buffer of size N,
8592+ with extra F-1 bytes to facilitate string comparison */
8593+static unsigned long match_position, match_length; /* of longest match. These are
8594+ set by the InsertNode() procedure. */
8595+static unsigned long lson[N + 1], rson[N + 257], dad[N + 1]; /* left & right children &
8596+ parents -- These constitute binary search trees. */
8597+
8598+static void InitTree(void) /* initialize trees */
8599+{
8600+ unsigned long i;
8601+
8602+ /* For i = 0 to N - 1, rson[i] and lson[i] will be the right and
8603+ left children of node i. These nodes need not be initialized.
8604+ Also, dad[i] is the parent of node i. These are initialized to
8605+ NIL (= N), which stands for 'not used.'
8606+ For i = 0 to 255, rson[N + i + 1] is the root of the tree
8607+ for strings that begin with character i. These are initialized
8608+ to NIL. Note there are 256 trees. */
8609+
8610+ for (i = N + 1; i <= N + 256; i++) rson[i] = NIL;
8611+ for (i = 0; i < N; i++) dad[i] = NIL;
8612+}
8613+
8614+static void InsertNode(unsigned long r)
8615+ /* Inserts string of length F, text_buf[r..r+F-1], into one of the
8616+ trees (text_buf[r]'th tree) and returns the longest-match position
8617+ and length via the global variables match_position and match_length.
8618+ If match_length = F, then removes the old node in favor of the new
8619+ one, because the old one will be deleted sooner.
8620+ Note r plays double role, as tree node and position in buffer. */
8621+{
8622+ unsigned long i, p;
8623+ unsigned char *key;
8624+ signed long cmp;
8625+
8626+ cmp = 1; key = &text_buf[r]; p = N + 1 + key[0];
8627+ rson[r] = lson[r] = NIL; match_length = 0;
8628+ for ( ; ; ) {
8629+ if (cmp >= 0) {
8630+ if (rson[p] != NIL) p = rson[p];
8631+ else { rson[p] = r; dad[r] = p; return; }
8632+ } else {
8633+ if (lson[p] != NIL) p = lson[p];
8634+ else { lson[p] = r; dad[r] = p; return; }
8635+ }
8636+ for (i = 1; i < F; i++)
8637+ if ((cmp = key[i] - text_buf[p + i]) != 0) break;
8638+ if (i > match_length) {
8639+ match_position = p;
8640+ if ((match_length = i) >= F) break;
8641+ }
8642+ }
8643+ dad[r] = dad[p]; lson[r] = lson[p]; rson[r] = rson[p];
8644+ dad[lson[p]] = r; dad[rson[p]] = r;
8645+ if (rson[dad[p]] == p) rson[dad[p]] = r;
8646+ else lson[dad[p]] = r;
8647+ dad[p] = NIL; /* remove p */
8648+}
8649+
8650+static void DeleteNode(unsigned long p) /* deletes node p from tree */
8651+{
8652+ unsigned long q;
8653+
8654+ if (dad[p] == NIL) return; /* not in tree */
8655+ if (rson[p] == NIL) q = lson[p];
8656+ else if (lson[p] == NIL) q = rson[p];
8657+ else {
8658+ q = lson[p];
8659+ if (rson[q] != NIL) {
8660+ do { q = rson[q]; } while (rson[q] != NIL);
8661+ rson[dad[q]] = lson[q]; dad[lson[q]] = dad[q];
8662+ lson[q] = lson[p]; dad[lson[p]] = q;
8663+ }
8664+ rson[q] = rson[p]; dad[rson[p]] = q;
8665+ }
8666+ dad[q] = dad[p];
8667+ if (rson[dad[p]] == p) rson[dad[p]] = q; else lson[dad[p]] = q;
8668+ dad[p] = NIL;
8669+}
8670+
8671+/* modified for block compression */
8672+/* on return, srclen will contain the number of successfully compressed bytes
8673+ and dstlen will contain completed compressed bytes */
8674+
8675+static int Encode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long *srclen,
8676+ unsigned long *dstlen)
8677+{
8678+ unsigned long i, len, r, c, s, last_match_length, code_buf_ptr;
8679+ unsigned char code_buf[17], mask;
8680+ unsigned char *ip, *op;
8681+ unsigned long written = 0;
8682+ unsigned long read = 0;
8683+ unsigned char *srcend = srcbuf + *srclen;
8684+ unsigned char *dstend = dstbuf + *dstlen;
8685+ ip = srcbuf;
8686+ op = dstbuf;
8687+ InitTree(); /* initialize trees */
8688+ code_buf[0] = 0; /* code_buf[1..16] saves eight units of code, and
8689+ code_buf[0] works as eight flags, "1" representing that the unit
8690+ is an unencoded letter (1 byte), "0" a position-and-length pair
8691+ (2 bytes). Thus, eight units require at most 16 bytes of code. */
8692+ code_buf_ptr = mask = 1;
8693+ s = 0; r = N - F;
8694+ for (i = s; i < r; i++) text_buf[i] = ' '; /* Clear the buffer with
8695+ any character that will appear often. */
8696+ for (len = 0; (len < F) && (ip < srcend); len++)
8697+ text_buf[r + len] = *(ip++); /* Read F bytes into the last F bytes of
8698+ the buffer */
8699+ read = len;
8700+ for (i = 1; i <= F; i++) InsertNode(r - i); /* Insert the F strings,
8701+ each of which begins with one or more 'space' characters. Note
8702+ the order in which these strings are inserted. This way,
8703+ degenerate trees will be less likely to occur. */
8704+ InsertNode(r); /* Finally, insert the whole string just read. The
8705+ global variables match_length and match_position are set. */
8706+ do {
8707+ if (match_length > len) match_length = len; /* match_length
8708+ may be spuriously long near the end of text. */
8709+ if (match_length <= THRESHOLD) {
8710+ match_length = 1; /* Not long enough match. Send one byte. */
8711+ code_buf[0] |= mask; /* 'send one byte' flag */
8712+ code_buf[code_buf_ptr++] = text_buf[r]; /* Send uncoded. */
8713+ } else {
8714+ code_buf[code_buf_ptr++] = match_position;
8715+ code_buf[code_buf_ptr++] = (((match_position >> 4) & 0xf0)
8716+ | (match_length - (THRESHOLD + 1))); /* Send position and
8717+ length pair. Note match_length > THRESHOLD. */
8718+ }
8719+ if ((mask <<= 1) == 0) { /* Shift mask left one bit. */
8720+ if ((op + code_buf_ptr) > dstend) {
8721+ *dstlen = written; /* written contains bytes of complete compressed
8722+ code */
8723+ return -1;
8724+ };
8725+ for (i = 0; i < code_buf_ptr; *(op++) = code_buf[i++]); /* Send at most 8 units of */
8726+ /* code together */
8727+ written += code_buf_ptr;
8728+ *srclen = read; /* this many bytes have been successfully compressed */
8729+ code_buf[0] = 0; code_buf_ptr = mask = 1;
8730+ }
8731+ last_match_length = match_length;
8732+ for (i = 0; (i < last_match_length) && (ip < srcend); i++) {
8733+ c = *(ip++);
8734+ DeleteNode(s); /* Delete old strings and */
8735+ text_buf[s] = c; /* read new bytes */
8736+ if (s < F - 1) text_buf[s + N] = c; /* If the position is
8737+ near the end of buffer, extend the buffer to make
8738+ string comparison easier. */
8739+ s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
8740+ /* Since this is a ring buffer, increment the position
8741+ modulo N. */
8742+ InsertNode(r); /* Register the string in text_buf[r..r+F-1] */
8743+ }
8744+ read += i;
8745+ while (i++ < last_match_length) { /* After the end of text, */
8746+ DeleteNode(s); /* no need to read, but */
8747+ s = (s + 1) & (N - 1); r = (r + 1) & (N - 1);
8748+ if (--len) InsertNode(r); /* buffer may not be empty. */
8749+ }
8750+ } while (len > 0); /* until length of string to be processed is zero */
8751+ if (code_buf_ptr > 1) { /* Send remaining code. */
8752+ if ((op + code_buf_ptr) > dstend) {
8753+ *dstlen = written;
8754+ return -1;
8755+ }
8756+ for (i = 0; i < code_buf_ptr; *(op++) = code_buf[i++]);
8757+ written += code_buf_ptr;
8758+ *srclen = read;
8759+ }
8760+ *dstlen = written;
8761+ return 0;
8762+}
8763+
8764+static int Decode(unsigned char *srcbuf, unsigned char *dstbuf, unsigned long srclen,
8765+ unsigned long dstlen) /* Just the reverse of Encode(). */
8766+{
8767+ unsigned long i, r, c, j, k, flags;
8768+ unsigned char *ip, *op;
8769+ unsigned long written;
8770+ unsigned long read;
8771+ unsigned char *srcend = srcbuf + srclen;
8772+ unsigned char *dstend = dstbuf + dstlen;
8773+ read = written = 0;
8774+ ip = srcbuf;
8775+ op = dstbuf;
8776+ for (i = 0; i < N - F; i++) text_buf[i] = ' ';
8777+ r = N - F; flags = 0;
8778+ for ( ; ; ) {
8779+ if (((flags >>= 1) & 256) == 0) {
8780+ if (ip >= srcend) return 0;
8781+ c = *(ip++);
8782+ flags = c | 0xff00; /* uses higher byte cleverly */
8783+ } /* to count eight */
8784+ if (flags & 1) {
8785+ if (ip >= srcend) return 0;
8786+ c = *(ip++);
8787+ if (op >= dstend) return -1;
8788+ *(op++) = text_buf[r++] = c; r &= (N - 1);
8789+ } else {
8790+ if ((ip + 2) > srcend) return 0;
8791+ i = *(ip++);
8792+ j = *(ip++);
8793+ i |= ((j & 0xf0) << 4); j = (j & 0x0f) + THRESHOLD;
8794+ if ((op + j + 1) > dstend) return -1;
8795+ for (k = 0; k <= j; k++) {
8796+ c = text_buf[(i + k) & (N - 1)];
8797+ *(op++) = text_buf[r++] = c; r &= (N - 1);
8798+ }
8799+ }
8800+ }
8801+}
8802+
8803+/* interface to jffs2 bbc follows */
8804+
8805+#include "jffs2_bbc_framework.h"
8806+
8807+
8808+#define JFFS2_BBC_LZSS_BLOCK_SIGN {0x27, 0x6f, 0x12, 0xc4}
8809+
8810+static int
8811+jffs2_bbc_lzss_compressor_init (void);
8812+
8813+static void
8814+jffs2_bbc_lzss_compressor_deinit (void);
8815+
8816+static int
8817+jffs2_bbc_lzss_compress (void *model, unsigned char *input,
8818+ unsigned char *output, unsigned long *sourcelen,
8819+ unsigned long *dstlen);
8820+
8821+static int
8822+jffs2_bbc_lzss_estimate (void *model, unsigned char *input,
8823+ unsigned long sourcelen, unsigned long *dstlen,
8824+ unsigned long *readtime, unsigned long *writetime);
8825+
8826+static int
8827+jffs2_bbc_lzss_decompress (void *model, unsigned char *input,
8828+ unsigned char *output, unsigned long sourcelen,
8829+ unsigned long dstlen);
8830+
8831+static char *
8832+jffs2_bbc_lzss_proc_info (void);
8833+
8834+static int
8835+jffs2_bbc_lzss_proc_command (char *command);
8836+
8837+struct jffs2_bbc_compressor_type jffs2_bbc_lzss = {
8838+ "lzss",
8839+ 0,
8840+ JFFS2_BBC_LZSS_BLOCK_SIGN,
8841+ jffs2_bbc_lzss_compressor_init,
8842+ NULL,
8843+ NULL,
8844+ jffs2_bbc_lzss_compressor_deinit,
8845+ jffs2_bbc_lzss_compress,
8846+ jffs2_bbc_lzss_estimate,
8847+ jffs2_bbc_lzss_decompress,
8848+ jffs2_bbc_lzss_proc_info,
8849+ jffs2_bbc_lzss_proc_command
8850+};
8851+
8852+static int
8853+jffs2_bbc_lzss_compressor_init (void)
8854+{
8855+ return 0;
8856+}
8857+
8858+static void
8859+jffs2_bbc_lzss_compressor_deinit (void)
8860+{
8861+}
8862+
8863+static int
8864+jffs2_bbc_lzss_compress (void *model, unsigned char *input,
8865+ unsigned char *output, unsigned long *sourcelen,
8866+ unsigned long *dstlen)
8867+{
8868+ int retval;
8869+ unsigned long dst = *dstlen;
8870+ *(output++) = jffs2_bbc_lzss.block_sign[0];
8871+ *(output++) = jffs2_bbc_lzss.block_sign[1];
8872+ dst -= 2;
8873+ retval = Encode(input, output, sourcelen, &dst);
8874+ dst += 2;
8875+ *dstlen = dst;
8876+ return retval;
8877+}
8878+
8879+static int
8880+jffs2_bbc_lzss_estimate (void *model, unsigned char *input,
8881+ unsigned long sourcelen, unsigned long *dstlen,
8882+ unsigned long *readtime, unsigned long *writetime)
8883+{
8884+ *dstlen = sourcelen * 60 / 100;
8885+ *readtime = JFFS2_BBC_ZLIB_READ_TIME * 12 / 10;
8886+ *writetime = JFFS2_BBC_ZLIB_WRITE_TIME * 3;
8887+ return 0;
8888+}
8889+
8890+static int
8891+jffs2_bbc_lzss_decompress (void *model, unsigned char *input,
8892+ unsigned char *output, unsigned long sourcelen,
8893+ unsigned long dstlen)
8894+{
8895+ if ( ( *(input++) != (unsigned char)jffs2_bbc_lzss.block_sign[0] ) ||
8896+ ( *(input++) != (unsigned char)jffs2_bbc_lzss.block_sign[1] )
8897+ ) {
8898+ return -1;
8899+ } else {
8900+ return Decode(input, output, sourcelen - 2, dstlen);
8901+ }
8902+}
8903+
8904+static char *
8905+jffs2_bbc_lzss_proc_info (void)
8906+{
8907+ return "Lempel-Ziv-Storer-Szymanski compression module";
8908+}
8909+
8910+static int
8911+jffs2_bbc_lzss_proc_command (char *command)
8912+{
8913+ return 0;
8914+}
8915+
8916+struct jffs2_bbc_compressor_type *
8917+jffs2_bbc_lzss_init (int mode)
8918+{
8919+ if (jffs2_bbc_register_compressor (&jffs2_bbc_lzss) == 0)
8920+ {
8921+ return &jffs2_bbc_lzss;
8922+ }
8923+ else
8924+ {
8925+ return NULL;
8926+ }
8927+}
8928+
8929+void
8930+jffs2_bbc_lzss_deinit (void)
8931+{
8932+ jffs2_bbc_unregister_compressor (&jffs2_bbc_lzss);
8933+}
8934--- /dev/null
8935+++ b/fs/jffs2/linux-2.4.25.hpatch
8936@@ -0,0 +1,97 @@
8937+FMakefile
8938+=BBC insertion
8939+-COMPR_OBJS
8940+iMakefile.bbc.inc
8941++
8942+I
8943+?JFFS2_OBJS
8944++ $(JFFS2_BBC_KERNEL_OBJS) \
8945+
8946+F../Config.in
8947+=BBC insertion
8948+-tristate 'Compressed ROM file system support' CONFIG_CRAMFS
8949+iConfig.in.bbc.inc
8950++
8951+I
8952+F../../Documentation/Configure.help
8953+=BBC insertion
8954+-JFFS stats available
8955+iConfigure.help.bbc.inc
8956++
8957+I
8958+Fcompr_zlib.c
8959+=(de)compress->(de)compress2
8960+-int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
8961++int jffs2_zlib_compress2(unsigned char *data_in, unsigned char *cpage_out,
8962+-void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
8963++void jffs2_zlib_decompress2(unsigned char *data_in, unsigned char *cpage_out,
8964+?inflateEnd(&strm);
8965+?}
8966++
8967++extern int jffs2_zlib_compress(unsigned char *data_in, unsigned char *cpage_out, __u32 * sourcelen, __u32 * dstlen);
8968++extern void jffs2_zlib_decompress(unsigned char *data_in, unsigned char *cpage_out, __u32 srclen, __u32 destlen);
8969++
8970++int zlib_compress(unsigned char *data_in, unsigned char *cpage_out,
8971++ __u32 *sourcelen, __u32 *dstlen)
8972++{
8973++ return jffs2_zlib_compress(data_in,cpage_out,sourcelen,dstlen);
8974++}
8975++
8976++void zlib_decompress(unsigned char *data_in, unsigned char *cpage_out,
8977++ __u32 srclen, __u32 destlen)
8978++{
8979++ jffs2_zlib_decompress(data_in,cpage_out,srclen,destlen);
8980++}
8981++
8982+
8983+Ffile.c
8984+=set_act_sb before write
8985+-#include
8986++#include "jffs2_bbc_framework.h" /**BBC**/
8987+I
8988+?int jffs2_commit_write
8989+-jffs2_compress(
8990++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
8991+I
8992+
8993+Fgc.c
8994+=set_act_sb before write
8995+-#include
8996++#include "jffs2_bbc_framework.h" /**BBC**/
8997+I
8998+?int jffs2_garbage_collect_dnode(
8999+-jffs2_compress(
9000++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
9001+I
9002+
9003+Fread.c
9004+=set_act_sb before read
9005+-#include
9006++#include "jffs2_bbc_framework.h" /**BBC**/
9007+I
9008+?int jffs2_read_dnode(
9009+-jffs2_decompress(
9010++ jffs2_bbc_model_set_act_sb(c); /**BBC**/
9011+I
9012+
9013+Fsuper.c
9014+=init, load_model
9015+-#include
9016++#include "jffs2_bbc_fs.h" /**BBC**/
9017+I
9018+?struct super_block *jffs2_read_super(
9019+-return sb;
9020++ jffs2_bbc_load_model(sb); /**BBC**/
9021+I
9022+?void jffs2_put_super
9023+?c = JFFS2_SB_INFO
9024++ jffs2_bbc_unload_model(sb); /**BBC**/
9025+?init_jffs2_fs(void)
9026+?int ret;
9027++
9028++ jffs2_bbc_proc_init(); /**BBC**/
9029++
9030+?exit_jffs2_fs(void)
9031+?{
9032++ jffs2_bbc_proc_deinit(); /**BBC**/
9033++
9034--- a/fs/jffs2/read.c
9035+++ b/fs/jffs2/read.c
9036@@ -35,6 +35,7 @@
9037  *
9038  */
9039 
9040+#include "jffs2_bbc_framework.h" /**BBC**/
9041 #include <linux/kernel.h>
9042 #include <linux/slab.h>
9043 #include <linux/jffs2.h>
9044@@ -140,6 +141,7 @@ int jffs2_read_dnode(struct jffs2_sb_inf
9045     D2(printk(KERN_DEBUG "Data CRC matches calculated CRC %08x\n", crc));
9046     if (ri->compr != JFFS2_COMPR_NONE) {
9047         D2(printk(KERN_DEBUG "Decompress %d bytes from %p to %d bytes at %p\n", ri->csize, readbuf, ri->dsize, decomprbuf));
9048+ jffs2_bbc_model_set_act_sb(c); /**BBC**/
9049         ret = jffs2_decompress(ri->compr, readbuf, decomprbuf, ri->csize, ri->dsize);
9050         if (ret) {
9051             printk(KERN_WARNING "Error: jffs2_decompress returned %d\n", ret);
9052--- a/fs/jffs2/super.c
9053+++ b/fs/jffs2/super.c
9054@@ -35,6 +35,7 @@
9055  *
9056  */
9057 
9058+#include "jffs2_bbc_fs.h" /**BBC**/
9059 #include <linux/config.h>
9060 #include <linux/kernel.h>
9061 #include <linux/module.h>
9062@@ -272,6 +273,7 @@ static struct super_block *jffs2_read_su
9063     sb->s_magic = JFFS2_SUPER_MAGIC;
9064     if (!(sb->s_flags & MS_RDONLY))
9065         jffs2_start_garbage_collect_thread(c);
9066+ jffs2_bbc_load_model(sb); /**BBC**/
9067     return sb;
9068 
9069  out_root_i:
9070@@ -288,6 +290,7 @@ static struct super_block *jffs2_read_su
9071 void jffs2_put_super (struct super_block *sb)
9072 {
9073     struct jffs2_sb_info *c = JFFS2_SB_INFO(sb);
9074+ jffs2_bbc_unload_model(sb); /**BBC**/
9075 
9076     D2(printk(KERN_DEBUG "jffs2: jffs2_put_super()\n"));
9077 
9078@@ -344,6 +347,9 @@ static int __init init_jffs2_fs(void)
9079 {
9080     int ret;
9081 
9082+ jffs2_bbc_proc_init(); /**BBC**/
9083+
9084+
9085     printk(KERN_NOTICE "JFFS2 version 2.1. (C) 2001 Red Hat, Inc., designed by Axis Communications AB.\n");
9086 
9087 #ifdef JFFS2_OUT_OF_KERNEL
9088@@ -388,6 +394,8 @@ static int __init init_jffs2_fs(void)
9089 
9090 static void __exit exit_jffs2_fs(void)
9091 {
9092+ jffs2_bbc_proc_deinit(); /**BBC**/
9093+
9094     jffs2_destroy_slab_caches();
9095     jffs2_zlib_exit();
9096     unregister_filesystem(&jffs2_fs_type);
9097

Archive Download this file



interactive