162306a36Sopenharmony_ci/* 262306a36Sopenharmony_ci * JFFS2 -- Journalling Flash File System, Version 2. 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Copyright © 2001-2007 Red Hat, Inc. 562306a36Sopenharmony_ci * Copyright © 2004-2010 David Woodhouse <dwmw2@infradead.org> 662306a36Sopenharmony_ci * 762306a36Sopenharmony_ci * Created by Arjan van de Ven <arjanv@redhat.com> 862306a36Sopenharmony_ci * 962306a36Sopenharmony_ci * For licensing information, see the file 'LICENCE' in this directory. 1062306a36Sopenharmony_ci * 1162306a36Sopenharmony_ci * 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * Very simple lz77-ish encoder. 1462306a36Sopenharmony_ci * 1562306a36Sopenharmony_ci * Theory of operation: Both encoder and decoder have a list of "last 1662306a36Sopenharmony_ci * occurrences" for every possible source-value; after sending the 1762306a36Sopenharmony_ci * first source-byte, the second byte indicated the "run" length of 1862306a36Sopenharmony_ci * matches 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * The algorithm is intended to only send "whole bytes", no bit-messing. 2162306a36Sopenharmony_ci * 2262306a36Sopenharmony_ci */ 2362306a36Sopenharmony_ci 2462306a36Sopenharmony_ci#include <linux/kernel.h> 2562306a36Sopenharmony_ci#include <linux/types.h> 2662306a36Sopenharmony_ci#include <linux/errno.h> 2762306a36Sopenharmony_ci#include <linux/string.h> 2862306a36Sopenharmony_ci#include <linux/jffs2.h> 2962306a36Sopenharmony_ci#include "compr.h" 3062306a36Sopenharmony_ci 3162306a36Sopenharmony_ci/* _compress returns the compressed size, -1 if bigger */ 3262306a36Sopenharmony_cistatic int jffs2_rtime_compress(unsigned char *data_in, 3362306a36Sopenharmony_ci unsigned char *cpage_out, 3462306a36Sopenharmony_ci uint32_t *sourcelen, uint32_t *dstlen) 3562306a36Sopenharmony_ci{ 3662306a36Sopenharmony_ci unsigned short positions[256]; 3762306a36Sopenharmony_ci int outpos = 0; 3862306a36Sopenharmony_ci int pos=0; 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci if (*dstlen <= 3) 4162306a36Sopenharmony_ci return -1; 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci memset(positions,0,sizeof(positions)); 4462306a36Sopenharmony_ci 4562306a36Sopenharmony_ci while (pos < (*sourcelen) && outpos <= (*dstlen)-2) { 4662306a36Sopenharmony_ci int backpos, runlen=0; 4762306a36Sopenharmony_ci unsigned char value; 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci value = data_in[pos]; 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci cpage_out[outpos++] = data_in[pos++]; 5262306a36Sopenharmony_ci 5362306a36Sopenharmony_ci backpos = positions[value]; 5462306a36Sopenharmony_ci positions[value]=pos; 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci while ((backpos < pos) && (pos < (*sourcelen)) && 5762306a36Sopenharmony_ci (data_in[pos]==data_in[backpos++]) && (runlen<255)) { 5862306a36Sopenharmony_ci pos++; 5962306a36Sopenharmony_ci runlen++; 6062306a36Sopenharmony_ci } 6162306a36Sopenharmony_ci cpage_out[outpos++] = runlen; 6262306a36Sopenharmony_ci } 6362306a36Sopenharmony_ci 6462306a36Sopenharmony_ci if (outpos >= pos) { 6562306a36Sopenharmony_ci /* We failed */ 6662306a36Sopenharmony_ci return -1; 6762306a36Sopenharmony_ci } 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci /* Tell the caller how much we managed to compress, and how much space it took */ 7062306a36Sopenharmony_ci *sourcelen = pos; 7162306a36Sopenharmony_ci *dstlen = outpos; 7262306a36Sopenharmony_ci return 0; 7362306a36Sopenharmony_ci} 7462306a36Sopenharmony_ci 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_cistatic int jffs2_rtime_decompress(unsigned char *data_in, 7762306a36Sopenharmony_ci unsigned char *cpage_out, 7862306a36Sopenharmony_ci uint32_t srclen, uint32_t destlen) 7962306a36Sopenharmony_ci{ 8062306a36Sopenharmony_ci unsigned short positions[256]; 8162306a36Sopenharmony_ci int outpos = 0; 8262306a36Sopenharmony_ci int pos=0; 8362306a36Sopenharmony_ci 8462306a36Sopenharmony_ci memset(positions,0,sizeof(positions)); 8562306a36Sopenharmony_ci 8662306a36Sopenharmony_ci while (outpos<destlen) { 8762306a36Sopenharmony_ci unsigned char value; 8862306a36Sopenharmony_ci int backoffs; 8962306a36Sopenharmony_ci int repeat; 9062306a36Sopenharmony_ci 9162306a36Sopenharmony_ci value = data_in[pos++]; 9262306a36Sopenharmony_ci cpage_out[outpos++] = value; /* first the verbatim copied byte */ 9362306a36Sopenharmony_ci repeat = data_in[pos++]; 9462306a36Sopenharmony_ci backoffs = positions[value]; 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci positions[value]=outpos; 9762306a36Sopenharmony_ci if (repeat) { 9862306a36Sopenharmony_ci if (backoffs + repeat >= outpos) { 9962306a36Sopenharmony_ci while(repeat) { 10062306a36Sopenharmony_ci cpage_out[outpos++] = cpage_out[backoffs++]; 10162306a36Sopenharmony_ci repeat--; 10262306a36Sopenharmony_ci } 10362306a36Sopenharmony_ci } else { 10462306a36Sopenharmony_ci memcpy(&cpage_out[outpos],&cpage_out[backoffs],repeat); 10562306a36Sopenharmony_ci outpos+=repeat; 10662306a36Sopenharmony_ci } 10762306a36Sopenharmony_ci } 10862306a36Sopenharmony_ci } 10962306a36Sopenharmony_ci return 0; 11062306a36Sopenharmony_ci} 11162306a36Sopenharmony_ci 11262306a36Sopenharmony_cistatic struct jffs2_compressor jffs2_rtime_comp = { 11362306a36Sopenharmony_ci .priority = JFFS2_RTIME_PRIORITY, 11462306a36Sopenharmony_ci .name = "rtime", 11562306a36Sopenharmony_ci .compr = JFFS2_COMPR_RTIME, 11662306a36Sopenharmony_ci .compress = &jffs2_rtime_compress, 11762306a36Sopenharmony_ci .decompress = &jffs2_rtime_decompress, 11862306a36Sopenharmony_ci#ifdef JFFS2_RTIME_DISABLED 11962306a36Sopenharmony_ci .disabled = 1, 12062306a36Sopenharmony_ci#else 12162306a36Sopenharmony_ci .disabled = 0, 12262306a36Sopenharmony_ci#endif 12362306a36Sopenharmony_ci}; 12462306a36Sopenharmony_ci 12562306a36Sopenharmony_ciint jffs2_rtime_init(void) 12662306a36Sopenharmony_ci{ 12762306a36Sopenharmony_ci return jffs2_register_compressor(&jffs2_rtime_comp); 12862306a36Sopenharmony_ci} 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_civoid jffs2_rtime_exit(void) 13162306a36Sopenharmony_ci{ 13262306a36Sopenharmony_ci jffs2_unregister_compressor(&jffs2_rtime_comp); 13362306a36Sopenharmony_ci} 134