1 /*------------------------------------------------------------------------- 2 * Filename: mini_inflate.c 3 * Version: $Id: mini_inflate.c,v 1.3 2002/01/24 22:58:42 rfeany Exp $ 4 * Copyright: Copyright (C) 2001, Russ Dill 5 * Author: Russ Dill <Russ.Dill@asu.edu> 6 * Description: Mini inflate implementation (RFC 1951) 7 *-----------------------------------------------------------------------*/ 8 /* 9 * 10 * This program is free software; you can redistribute it and/or modify 11 * it under the terms of the GNU General Public License as published by 12 * the Free Software Foundation; either version 2 of the License, or 13 * (at your option) any later version. 14 * 15 * This program is distributed in the hope that it will be useful, 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of 17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 * GNU General Public License for more details. 19 * 20 * You should have received a copy of the GNU General Public License 21 * along with this program; if not, write to the Free Software 22 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 23 * 24 */ 25 26 #include <config.h> 27 28 #if (CONFIG_COMMANDS & CFG_CMD_JFFS2) || defined(CONFIG_CMD_JFFS2) 29 30 #include <jffs2/mini_inflate.h> 31 32 /* The order that the code lengths in section 3.2.7 are in */ 33 static unsigned char huffman_order[] = {16, 17, 18, 0, 8, 7, 9, 6, 10, 5, 34 11, 4, 12, 3, 13, 2, 14, 1, 15}; 35 36 inline void cramfs_memset(int *s, const int c, size n) 37 { 38 n--; 39 for (;n > 0; n--) s[n] = c; 40 s[0] = c; 41 } 42 43 /* associate a stream with a block of data and reset the stream */ 44 static void init_stream(struct bitstream *stream, unsigned char *data, 45 void *(*inflate_memcpy)(void *, const void *, size)) 46 { 47 stream->error = NO_ERROR; 48 stream->memcpy = inflate_memcpy; 49 stream->decoded = 0; 50 stream->data = data; 51 stream->bit = 0; /* The first bit of the stream is the lsb of the 52 * first byte */ 53 54 /* really sorry about all this initialization, think of a better way, 55 * let me know and it will get cleaned up */ 56 stream->codes.bits = 8; 57 stream->codes.num_symbols = 19; 58 stream->codes.lengths = stream->code_lengths; 59 stream->codes.symbols = stream->code_symbols; 60 stream->codes.count = stream->code_count; 61 stream->codes.first = stream->code_first; 62 stream->codes.pos = stream->code_pos; 63 64 stream->lengths.bits = 16; 65 stream->lengths.num_symbols = 288; 66 stream->lengths.lengths = stream->length_lengths; 67 stream->lengths.symbols = stream->length_symbols; 68 stream->lengths.count = stream->length_count; 69 stream->lengths.first = stream->length_first; 70 stream->lengths.pos = stream->length_pos; 71 72 stream->distance.bits = 16; 73 stream->distance.num_symbols = 32; 74 stream->distance.lengths = stream->distance_lengths; 75 stream->distance.symbols = stream->distance_symbols; 76 stream->distance.count = stream->distance_count; 77 stream->distance.first = stream->distance_first; 78 stream->distance.pos = stream->distance_pos; 79 80 } 81 82 /* pull 'bits' bits out of the stream. The last bit pulled it returned as the 83 * msb. (section 3.1.1) 84 */ 85 inline unsigned long pull_bits(struct bitstream *stream, 86 const unsigned int bits) 87 { 88 unsigned long ret; 89 int i; 90 91 ret = 0; 92 for (i = 0; i < bits; i++) { 93 ret += ((*(stream->data) >> stream->bit) & 1) << i; 94 95 /* if, before incrementing, we are on bit 7, 96 * go to the lsb of the next byte */ 97 if (stream->bit++ == 7) { 98 stream->bit = 0; 99 stream->data++; 100 } 101 } 102 return ret; 103 } 104 105 inline int pull_bit(struct bitstream *stream) 106 { 107 int ret = ((*(stream->data) >> stream->bit) & 1); 108 if (stream->bit++ == 7) { 109 stream->bit = 0; 110 stream->data++; 111 } 112 return ret; 113 } 114 115 /* discard bits up to the next whole byte */ 116 static void discard_bits(struct bitstream *stream) 117 { 118 if (stream->bit != 0) { 119 stream->bit = 0; 120 stream->data++; 121 } 122 } 123 124 /* No decompression, the data is all literals (section 3.2.4) */ 125 static void decompress_none(struct bitstream *stream, unsigned char *dest) 126 { 127 unsigned int length; 128 129 discard_bits(stream); 130 length = *(stream->data++); 131 length += *(stream->data++) << 8; 132 pull_bits(stream, 16); /* throw away the inverse of the size */ 133 134 stream->decoded += length; 135 stream->memcpy(dest, stream->data, length); 136 stream->data += length; 137 } 138 139 /* Read in a symbol from the stream (section 3.2.2) */ 140 static int read_symbol(struct bitstream *stream, struct huffman_set *set) 141 { 142 int bits = 0; 143 int code = 0; 144 while (!(set->count[bits] && code < set->first[bits] + 145 set->count[bits])) { 146 code = (code << 1) + pull_bit(stream); 147 if (++bits > set->bits) { 148 /* error decoding (corrupted data?) */ 149 stream->error = CODE_NOT_FOUND; 150 return -1; 151 } 152 } 153 return set->symbols[set->pos[bits] + code - set->first[bits]]; 154 } 155 156 /* decompress a stream of data encoded with the passed length and distance 157 * huffman codes */ 158 static void decompress_huffman(struct bitstream *stream, unsigned char *dest) 159 { 160 struct huffman_set *lengths = &(stream->lengths); 161 struct huffman_set *distance = &(stream->distance); 162 163 int symbol, length, dist, i; 164 165 do { 166 if ((symbol = read_symbol(stream, lengths)) < 0) return; 167 if (symbol < 256) { 168 *(dest++) = symbol; /* symbol is a literal */ 169 stream->decoded++; 170 } else if (symbol > 256) { 171 /* Determine the length of the repitition 172 * (section 3.2.5) */ 173 if (symbol < 265) length = symbol - 254; 174 else if (symbol == 285) length = 258; 175 else { 176 length = pull_bits(stream, (symbol - 261) >> 2); 177 length += (4 << ((symbol - 261) >> 2)) + 3; 178 length += ((symbol - 1) % 4) << 179 ((symbol - 261) >> 2); 180 } 181 182 /* Determine how far back to go */ 183 if ((symbol = read_symbol(stream, distance)) < 0) 184 return; 185 if (symbol < 4) dist = symbol + 1; 186 else { 187 dist = pull_bits(stream, (symbol - 2) >> 1); 188 dist += (2 << ((symbol - 2) >> 1)) + 1; 189 dist += (symbol % 2) << ((symbol - 2) >> 1); 190 } 191 stream->decoded += length; 192 for (i = 0; i < length; i++) { 193 *dest = dest[-dist]; 194 dest++; 195 } 196 } 197 } while (symbol != 256); /* 256 is the end of the data block */ 198 } 199 200 /* Fill the lookup tables (section 3.2.2) */ 201 static void fill_code_tables(struct huffman_set *set) 202 { 203 int code = 0, i, length; 204 205 /* fill in the first code of each bit length, and the pos pointer */ 206 set->pos[0] = 0; 207 for (i = 1; i < set->bits; i++) { 208 code = (code + set->count[i - 1]) << 1; 209 set->first[i] = code; 210 set->pos[i] = set->pos[i - 1] + set->count[i - 1]; 211 } 212 213 /* Fill in the table of symbols in order of their huffman code */ 214 for (i = 0; i < set->num_symbols; i++) { 215 if ((length = set->lengths[i])) 216 set->symbols[set->pos[length]++] = i; 217 } 218 219 /* reset the pos pointer */ 220 for (i = 1; i < set->bits; i++) set->pos[i] -= set->count[i]; 221 } 222 223 static void init_code_tables(struct huffman_set *set) 224 { 225 cramfs_memset(set->lengths, 0, set->num_symbols); 226 cramfs_memset(set->count, 0, set->bits); 227 cramfs_memset(set->first, 0, set->bits); 228 } 229 230 /* read in the huffman codes for dynamic decoding (section 3.2.7) */ 231 static void decompress_dynamic(struct bitstream *stream, unsigned char *dest) 232 { 233 /* I tried my best to minimize the memory footprint here, while still 234 * keeping up performance. I really dislike the _lengths[] tables, but 235 * I see no way of eliminating them without a sizable performance 236 * impact. The first struct table keeps track of stats on each bit 237 * length. The _length table keeps a record of the bit length of each 238 * symbol. The _symbols table is for looking up symbols by the huffman 239 * code (the pos element points to the first place in the symbol table 240 * where that bit length occurs). I also hate the initization of these 241 * structs, if someone knows how to compact these, lemme know. */ 242 243 struct huffman_set *codes = &(stream->codes); 244 struct huffman_set *lengths = &(stream->lengths); 245 struct huffman_set *distance = &(stream->distance); 246 247 int hlit = pull_bits(stream, 5) + 257; 248 int hdist = pull_bits(stream, 5) + 1; 249 int hclen = pull_bits(stream, 4) + 4; 250 int length, curr_code, symbol, i, last_code; 251 252 last_code = 0; 253 254 init_code_tables(codes); 255 init_code_tables(lengths); 256 init_code_tables(distance); 257 258 /* fill in the count of each bit length' as well as the lengths 259 * table */ 260 for (i = 0; i < hclen; i++) { 261 length = pull_bits(stream, 3); 262 codes->lengths[huffman_order[i]] = length; 263 if (length) codes->count[length]++; 264 265 } 266 fill_code_tables(codes); 267 268 /* Do the same for the length codes, being carefull of wrap through 269 * to the distance table */ 270 curr_code = 0; 271 while (curr_code < hlit) { 272 if ((symbol = read_symbol(stream, codes)) < 0) return; 273 if (symbol == 0) { 274 curr_code++; 275 last_code = 0; 276 } else if (symbol < 16) { /* Literal length */ 277 lengths->lengths[curr_code] = last_code = symbol; 278 lengths->count[symbol]++; 279 curr_code++; 280 } else if (symbol == 16) { /* repeat the last symbol 3 - 6 281 * times */ 282 length = 3 + pull_bits(stream, 2); 283 for (;length; length--, curr_code++) 284 if (curr_code < hlit) { 285 lengths->lengths[curr_code] = 286 last_code; 287 lengths->count[last_code]++; 288 } else { /* wrap to the distance table */ 289 distance->lengths[curr_code - hlit] = 290 last_code; 291 distance->count[last_code]++; 292 } 293 } else if (symbol == 17) { /* repeat a bit length 0 */ 294 curr_code += 3 + pull_bits(stream, 3); 295 last_code = 0; 296 } else { /* same, but more times */ 297 curr_code += 11 + pull_bits(stream, 7); 298 last_code = 0; 299 } 300 } 301 fill_code_tables(lengths); 302 303 /* Fill the distance table, don't need to worry about wrapthrough 304 * here */ 305 curr_code -= hlit; 306 while (curr_code < hdist) { 307 if ((symbol = read_symbol(stream, codes)) < 0) return; 308 if (symbol == 0) { 309 curr_code++; 310 last_code = 0; 311 } else if (symbol < 16) { 312 distance->lengths[curr_code] = last_code = symbol; 313 distance->count[symbol]++; 314 curr_code++; 315 } else if (symbol == 16) { 316 length = 3 + pull_bits(stream, 2); 317 for (;length; length--, curr_code++) { 318 distance->lengths[curr_code] = 319 last_code; 320 distance->count[last_code]++; 321 } 322 } else if (symbol == 17) { 323 curr_code += 3 + pull_bits(stream, 3); 324 last_code = 0; 325 } else { 326 curr_code += 11 + pull_bits(stream, 7); 327 last_code = 0; 328 } 329 } 330 fill_code_tables(distance); 331 332 decompress_huffman(stream, dest); 333 } 334 335 /* fill in the length and distance huffman codes for fixed encoding 336 * (section 3.2.6) */ 337 static void decompress_fixed(struct bitstream *stream, unsigned char *dest) 338 { 339 /* let gcc fill in the initial values */ 340 struct huffman_set *lengths = &(stream->lengths); 341 struct huffman_set *distance = &(stream->distance); 342 343 cramfs_memset(lengths->count, 0, 16); 344 cramfs_memset(lengths->first, 0, 16); 345 cramfs_memset(lengths->lengths, 8, 144); 346 cramfs_memset(lengths->lengths + 144, 9, 112); 347 cramfs_memset(lengths->lengths + 256, 7, 24); 348 cramfs_memset(lengths->lengths + 280, 8, 8); 349 lengths->count[7] = 24; 350 lengths->count[8] = 152; 351 lengths->count[9] = 112; 352 353 cramfs_memset(distance->count, 0, 16); 354 cramfs_memset(distance->first, 0, 16); 355 cramfs_memset(distance->lengths, 5, 32); 356 distance->count[5] = 32; 357 358 359 fill_code_tables(lengths); 360 fill_code_tables(distance); 361 362 363 decompress_huffman(stream, dest); 364 } 365 366 /* returns the number of bytes decoded, < 0 if there was an error. Note that 367 * this function assumes that the block starts on a byte boundry 368 * (non-compliant, but I don't see where this would happen). section 3.2.3 */ 369 long decompress_block(unsigned char *dest, unsigned char *source, 370 void *(*inflate_memcpy)(void *, const void *, size)) 371 { 372 int bfinal, btype; 373 struct bitstream stream; 374 375 init_stream(&stream, source, inflate_memcpy); 376 do { 377 bfinal = pull_bit(&stream); 378 btype = pull_bits(&stream, 2); 379 if (btype == NO_COMP) decompress_none(&stream, dest + stream.decoded); 380 else if (btype == DYNAMIC_COMP) 381 decompress_dynamic(&stream, dest + stream.decoded); 382 else if (btype == FIXED_COMP) decompress_fixed(&stream, dest + stream.decoded); 383 else stream.error = COMP_UNKNOWN; 384 } while (!bfinal && !stream.error); 385 386 #if 0 387 putstr("decompress_block start\r\n"); 388 putLabeledWord("stream.error = ",stream.error); 389 putLabeledWord("stream.decoded = ",stream.decoded); 390 putLabeledWord("dest = ",dest); 391 putstr("decompress_block end\r\n"); 392 #endif 393 return stream.error ? -stream.error : stream.decoded; 394 } 395 396 #endif /* CFG_CMD_JFFS2 */ 397