| 1 | --- a/arch/arm/boot/compressed/Makefile |
| 2 | +++ b/arch/arm/boot/compressed/Makefile |
| 3 | @@ -63,7 +63,7 @@ endif |
| 4 | |
| 5 | SEDFLAGS = s/TEXT_START/$(ZTEXTADDR)/;s/BSS_START/$(ZBSSADDR)/ |
| 6 | |
| 7 | -targets := vmlinux vmlinux.lds piggy.gz piggy.o font.o font.c \ |
| 8 | +targets := vmlinux vmlinux.lds piggy.lzma piggy.o font.o font.c \ |
| 9 | head.o misc.o $(OBJS) |
| 10 | |
| 11 | ifeq ($(CONFIG_FUNCTION_TRACER),y) |
| 12 | @@ -96,10 +96,10 @@ $(obj)/vmlinux: $(obj)/vmlinux.lds $(obj |
| 13 | $(call if_changed,ld) |
| 14 | @: |
| 15 | |
| 16 | -$(obj)/piggy.gz: $(obj)/../Image FORCE |
| 17 | - $(call if_changed,gzip) |
| 18 | +$(obj)/piggy.lzma: $(obj)/../Image FORCE |
| 19 | + $(call if_changed,lzma) |
| 20 | |
| 21 | -$(obj)/piggy.o: $(obj)/piggy.gz FORCE |
| 22 | +$(obj)/piggy.o: $(obj)/piggy.lzma FORCE |
| 23 | |
| 24 | CFLAGS_font.o := -Dstatic= |
| 25 | |
| 26 | --- a/arch/arm/boot/compressed/misc.c |
| 27 | +++ b/arch/arm/boot/compressed/misc.c |
| 28 | @@ -186,36 +186,10 @@ static inline __ptr_t memcpy(__ptr_t __d |
| 29 | return __dest; |
| 30 | } |
| 31 | |
| 32 | -/* |
| 33 | - * gzip delarations |
| 34 | - */ |
| 35 | -#define OF(args) args |
| 36 | -#define STATIC static |
| 37 | - |
| 38 | -typedef unsigned char uch; |
| 39 | -typedef unsigned short ush; |
| 40 | -typedef unsigned long ulg; |
| 41 | - |
| 42 | -#define WSIZE 0x8000 /* Window size must be at least 32k, */ |
| 43 | +#define WSIZE 0x20000 /* Window size must be at least 128k, */ |
| 44 | /* and a power of two */ |
| 45 | |
| 46 | -static uch *inbuf; /* input buffer */ |
| 47 | -static uch window[WSIZE]; /* Sliding window buffer */ |
| 48 | - |
| 49 | -static unsigned insize; /* valid bytes in inbuf */ |
| 50 | -static unsigned inptr; /* index of next byte to be processed in inbuf */ |
| 51 | -static unsigned outcnt; /* bytes in output buffer */ |
| 52 | - |
| 53 | -/* gzip flag byte */ |
| 54 | -#define ASCII_FLAG 0x01 /* bit 0 set: file probably ascii text */ |
| 55 | -#define CONTINUATION 0x02 /* bit 1 set: continuation of multi-part gzip file */ |
| 56 | -#define EXTRA_FIELD 0x04 /* bit 2 set: extra field present */ |
| 57 | -#define ORIG_NAME 0x08 /* bit 3 set: original file name present */ |
| 58 | -#define COMMENT 0x10 /* bit 4 set: file comment present */ |
| 59 | -#define ENCRYPTED 0x20 /* bit 5 set: file is encrypted */ |
| 60 | -#define RESERVED 0xC0 /* bit 6,7: reserved */ |
| 61 | - |
| 62 | -#define get_byte() (inptr < insize ? inbuf[inptr++] : fill_inbuf()) |
| 63 | +static u8 window[WSIZE]; /* Sliding window buffer */ |
| 64 | |
| 65 | /* Diagnostic functions */ |
| 66 | #ifdef DEBUG |
| 67 | @@ -234,24 +208,21 @@ static unsigned outcnt; /* bytes in out |
| 68 | # define Tracecv(c,x) |
| 69 | #endif |
| 70 | |
| 71 | -static int fill_inbuf(void); |
| 72 | -static void flush_window(void); |
| 73 | static void error(char *m); |
| 74 | |
| 75 | extern char input_data[]; |
| 76 | extern char input_data_end[]; |
| 77 | |
| 78 | -static uch *output_data; |
| 79 | -static ulg output_ptr; |
| 80 | -static ulg bytes_out; |
| 81 | +static unsigned long output_ptr; |
| 82 | +static unsigned long bytes_out; |
| 83 | |
| 84 | static void error(char *m); |
| 85 | |
| 86 | static void putstr(const char *); |
| 87 | |
| 88 | extern int end; |
| 89 | -static ulg free_mem_ptr; |
| 90 | -static ulg free_mem_end_ptr; |
| 91 | +static unsigned long free_mem_ptr; |
| 92 | +static unsigned long free_mem_end_ptr; |
| 93 | |
| 94 | #ifdef STANDALONE_DEBUG |
| 95 | #define NO_INFLATE_MALLOC |
| 96 | @@ -259,50 +230,10 @@ static ulg free_mem_end_ptr; |
| 97 | |
| 98 | #define ARCH_HAS_DECOMP_WDOG |
| 99 | |
| 100 | -#include "../../../../lib/inflate.c" |
| 101 | - |
| 102 | -/* =========================================================================== |
| 103 | - * Fill the input buffer. This is called only when the buffer is empty |
| 104 | - * and at least one byte is really needed. |
| 105 | - */ |
| 106 | -int fill_inbuf(void) |
| 107 | -{ |
| 108 | - if (insize != 0) |
| 109 | - error("ran out of input data"); |
| 110 | - |
| 111 | - inbuf = input_data; |
| 112 | - insize = &input_data_end[0] - &input_data[0]; |
| 113 | - |
| 114 | - inptr = 1; |
| 115 | - return inbuf[0]; |
| 116 | -} |
| 117 | - |
| 118 | -/* =========================================================================== |
| 119 | - * Write the output window window[0..outcnt-1] and update crc and bytes_out. |
| 120 | - * (Used for the decompressed data only.) |
| 121 | - */ |
| 122 | -void flush_window(void) |
| 123 | -{ |
| 124 | - ulg c = crc; |
| 125 | - unsigned n; |
| 126 | - uch *in, *out, ch; |
| 127 | - |
| 128 | - in = window; |
| 129 | - out = &output_data[output_ptr]; |
| 130 | - for (n = 0; n < outcnt; n++) { |
| 131 | - ch = *out++ = *in++; |
| 132 | - c = crc_32_tab[((int)c ^ ch) & 0xff] ^ (c >> 8); |
| 133 | - } |
| 134 | - crc = c; |
| 135 | - bytes_out += (ulg)outcnt; |
| 136 | - output_ptr += (ulg)outcnt; |
| 137 | - outcnt = 0; |
| 138 | - putstr("."); |
| 139 | -} |
| 140 | - |
| 141 | #ifndef arch_error |
| 142 | #define arch_error(x) |
| 143 | #endif |
| 144 | +#include "unlzma.c" |
| 145 | |
| 146 | static void error(char *x) |
| 147 | { |
| 148 | @@ -317,20 +248,16 @@ static void error(char *x) |
| 149 | |
| 150 | #ifndef STANDALONE_DEBUG |
| 151 | |
| 152 | -ulg |
| 153 | -decompress_kernel(ulg output_start, ulg free_mem_ptr_p, ulg free_mem_ptr_end_p, |
| 154 | +unsigned long |
| 155 | +decompress_kernel(unsigned long output_start, unsigned long free_mem_ptr_p, unsigned long free_mem_ptr_end_p, |
| 156 | int arch_id) |
| 157 | { |
| 158 | - output_data = (uch *)output_start; /* Points to kernel start */ |
| 159 | - free_mem_ptr = free_mem_ptr_p; |
| 160 | - free_mem_end_ptr = free_mem_ptr_end_p; |
| 161 | __machine_arch_type = arch_id; |
| 162 | |
| 163 | arch_decomp_setup(); |
| 164 | |
| 165 | - makecrc(); |
| 166 | putstr("Uncompressing Linux..."); |
| 167 | - gunzip(); |
| 168 | + output_ptr += unlzma((u8 *) output_start, input_data, window); |
| 169 | putstr(" done, booting the kernel.\n"); |
| 170 | return output_ptr; |
| 171 | } |
| 172 | @@ -340,11 +267,8 @@ char output_buffer[1500*1024]; |
| 173 | |
| 174 | int main() |
| 175 | { |
| 176 | - output_data = output_buffer; |
| 177 | - |
| 178 | - makecrc(); |
| 179 | putstr("Uncompressing Linux..."); |
| 180 | - gunzip(); |
| 181 | + unlzma((u8 *) output_buffer, input_data, window); |
| 182 | putstr("done.\n"); |
| 183 | return 0; |
| 184 | } |
| 185 | --- a/arch/arm/boot/compressed/piggy.S |
| 186 | +++ b/arch/arm/boot/compressed/piggy.S |
| 187 | @@ -1,6 +1,6 @@ |
| 188 | .section .piggydata,#alloc |
| 189 | .globl input_data |
| 190 | input_data: |
| 191 | - .incbin "arch/arm/boot/compressed/piggy.gz" |
| 192 | + .incbin "arch/arm/boot/compressed/piggy.lzma" |
| 193 | .globl input_data_end |
| 194 | input_data_end: |
| 195 | --- /dev/null |
| 196 | +++ b/arch/arm/boot/compressed/unlzma.c |
| 197 | @@ -0,0 +1,429 @@ |
| 198 | +/* |
| 199 | + * Copyright (c) 2009 Felix Fietkau <nbd@openwrt.org> |
| 200 | + * |
| 201 | + * This program is free software; you can redistribute it and/or |
| 202 | + * modify it under the terms of the GNU General Public License |
| 203 | + * as published by the Free Software Foundation; either version 2, |
| 204 | + * or (at your option) any later version. |
| 205 | + * |
| 206 | + * This program is distributed in the hope that it will be useful, |
| 207 | + * but WITHOUT ANY WARRANTY; without even the implied warranty of |
| 208 | + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
| 209 | + * GNU General Public License for more details. |
| 210 | + * |
| 211 | + * You should have received a copy of the GNU General Public License |
| 212 | + * along with this program; if not, write to the Free Software |
| 213 | + * Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. |
| 214 | + * |
| 215 | + * uncompress.c |
| 216 | + */ |
| 217 | + |
| 218 | +#include <linux/types.h> |
| 219 | +#include <asm/byteorder.h> |
| 220 | +#include "unlzma.h" |
| 221 | + |
| 222 | +struct unlzma_ctx { |
| 223 | + const u8 *next_in; |
| 224 | + u8 *next_out; |
| 225 | + u8 *outbuf; |
| 226 | + |
| 227 | + /* reader state */ |
| 228 | + u32 code; |
| 229 | + u32 range; |
| 230 | + u32 bound; |
| 231 | + |
| 232 | + /* writer state */ |
| 233 | + u8 previous_byte; |
| 234 | + ssize_t pos; |
| 235 | + |
| 236 | + /* cstate */ |
| 237 | + int state; |
| 238 | + u32 rep0, rep1, rep2, rep3; |
| 239 | + |
| 240 | + void *workspace; |
| 241 | +} ctx; |
| 242 | + |
| 243 | +static int inbs = 0; |
| 244 | +static inline u8 |
| 245 | +rc_read(void) |
| 246 | +{ |
| 247 | +#if 0 |
| 248 | + if (unlikely(++inbs > 16 * 1024)) { |
| 249 | + putstr("."); |
| 250 | + inbs = 0; |
| 251 | + } |
| 252 | +#endif |
| 253 | + return *(ctx.next_in++); |
| 254 | +} |
| 255 | + |
| 256 | + |
| 257 | +static inline void |
| 258 | +rc_get_code(void) |
| 259 | +{ |
| 260 | + ctx.code = (ctx.code << 8) | rc_read(); |
| 261 | +} |
| 262 | + |
| 263 | +static inline void |
| 264 | +rc_normalize(void) |
| 265 | +{ |
| 266 | + if (ctx.range < (1 << RC_TOP_BITS)) { |
| 267 | + ctx.range <<= 8; |
| 268 | + rc_get_code(); |
| 269 | + } |
| 270 | +} |
| 271 | + |
| 272 | +static inline int |
| 273 | +rc_is_bit_0(u16 *p) |
| 274 | +{ |
| 275 | + rc_normalize(); |
| 276 | + ctx.bound = *p * (ctx.range >> RC_MODEL_TOTAL_BITS); |
| 277 | + return ctx.code < ctx.bound; |
| 278 | +} |
| 279 | + |
| 280 | +static inline void |
| 281 | +rc_update_bit_0(u16 *p) |
| 282 | +{ |
| 283 | + ctx.range = ctx.bound; |
| 284 | + *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS; |
| 285 | +} |
| 286 | + |
| 287 | +static inline void |
| 288 | +rc_update_bit_1(u16 *p) |
| 289 | +{ |
| 290 | + ctx.range -= ctx.bound; |
| 291 | + ctx.code -= ctx.bound; |
| 292 | + *p -= *p >> RC_MOVE_BITS; |
| 293 | +} |
| 294 | + |
| 295 | +static inline bool |
| 296 | +rc_get_bit(u16 *p, int *symbol) |
| 297 | +{ |
| 298 | + if (rc_is_bit_0(p)) { |
| 299 | + rc_update_bit_0(p); |
| 300 | + *symbol *= 2; |
| 301 | + return 0; |
| 302 | + } else { |
| 303 | + rc_update_bit_1(p); |
| 304 | + *symbol = *symbol * 2 + 1; |
| 305 | + return 1; |
| 306 | + } |
| 307 | +} |
| 308 | + |
| 309 | +static inline int |
| 310 | +rc_direct_bit(void) |
| 311 | +{ |
| 312 | + rc_normalize(); |
| 313 | + ctx.range >>= 1; |
| 314 | + if (ctx.code >= ctx.range) { |
| 315 | + ctx.code -= ctx.range; |
| 316 | + return 1; |
| 317 | + } |
| 318 | + return 0; |
| 319 | +} |
| 320 | + |
| 321 | +static inline void |
| 322 | +rc_bit_tree_decode(u16 *p, int num_levels, int *symbol) |
| 323 | +{ |
| 324 | + int i = num_levels; |
| 325 | + |
| 326 | + *symbol = 1; |
| 327 | + while (i--) |
| 328 | + rc_get_bit(p + *symbol, symbol); |
| 329 | + *symbol -= 1 << num_levels; |
| 330 | +} |
| 331 | + |
| 332 | +static inline u8 |
| 333 | +peek_old_byte(u32 offs) |
| 334 | +{ |
| 335 | + u32 pos = ctx.pos - offs; |
| 336 | + return ctx.outbuf[pos]; |
| 337 | +} |
| 338 | + |
| 339 | +static inline void |
| 340 | +write_byte(u8 byte) |
| 341 | +{ |
| 342 | + ctx.previous_byte = byte; |
| 343 | + *(ctx.next_out++) = byte; |
| 344 | + ctx.pos++; |
| 345 | +} |
| 346 | + |
| 347 | + |
| 348 | +static inline void |
| 349 | +copy_byte(u32 offs) |
| 350 | +{ |
| 351 | + write_byte(peek_old_byte(offs)); |
| 352 | +} |
| 353 | + |
| 354 | +static inline void |
| 355 | +copy_bytes(u32 rep0, int len) |
| 356 | +{ |
| 357 | + do { |
| 358 | + copy_byte(rep0); |
| 359 | + len--; |
| 360 | + } while (len != 0); |
| 361 | +} |
| 362 | + |
| 363 | +static inline void |
| 364 | +process_bit0(u16 *p, int pos_state, u16 *prob, |
| 365 | + int lc, u32 literal_pos_mask) |
| 366 | +{ |
| 367 | + int mi = 1; |
| 368 | + rc_update_bit_0(prob); |
| 369 | + prob = (p + LZMA_LITERAL + |
| 370 | + (LZMA_LIT_SIZE |
| 371 | + * (((ctx.pos & literal_pos_mask) << lc) |
| 372 | + + (ctx.previous_byte >> (8 - lc)))) |
| 373 | + ); |
| 374 | + |
| 375 | + if (ctx.state >= LZMA_NUM_LIT_STATES) { |
| 376 | + int match_byte = peek_old_byte(ctx.rep0); |
| 377 | + do { |
| 378 | + u16 bit; |
| 379 | + u16 *prob_lit; |
| 380 | + |
| 381 | + match_byte <<= 1; |
| 382 | + bit = match_byte & 0x100; |
| 383 | + prob_lit = prob + 0x100 + bit + mi; |
| 384 | + if (rc_get_bit(prob_lit, &mi) != !!bit) |
| 385 | + break; |
| 386 | + } while (mi < 0x100); |
| 387 | + } |
| 388 | + while (mi < 0x100) { |
| 389 | + u16 *prob_lit = prob + mi; |
| 390 | + rc_get_bit(prob_lit, &mi); |
| 391 | + } |
| 392 | + write_byte(mi); |
| 393 | + if (ctx.state < 4) |
| 394 | + ctx.state = 0; |
| 395 | + else if (ctx.state < 10) |
| 396 | + ctx.state -= 3; |
| 397 | + else |
| 398 | + ctx.state -= 6; |
| 399 | +} |
| 400 | + |
| 401 | +static inline void |
| 402 | +process_bit1(u16 *p, int pos_state, u16 *prob) |
| 403 | +{ |
| 404 | + int offset; |
| 405 | + u16 *prob_len; |
| 406 | + int num_bits; |
| 407 | + int len; |
| 408 | + |
| 409 | + rc_update_bit_1(prob); |
| 410 | + prob = p + LZMA_IS_REP + ctx.state; |
| 411 | + if (rc_is_bit_0(prob)) { |
| 412 | + rc_update_bit_0(prob); |
| 413 | + ctx.rep3 = ctx.rep2; |
| 414 | + ctx.rep2 = ctx.rep1; |
| 415 | + ctx.rep1 = ctx.rep0; |
| 416 | + ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? 0 : 3; |
| 417 | + prob = p + LZMA_LEN_CODER; |
| 418 | + } else { |
| 419 | + rc_update_bit_1(prob); |
| 420 | + prob = p + LZMA_IS_REP_G0 + ctx.state; |
| 421 | + if (rc_is_bit_0(prob)) { |
| 422 | + rc_update_bit_0(prob); |
| 423 | + prob = (p + LZMA_IS_REP_0_LONG |
| 424 | + + (ctx.state << |
| 425 | + LZMA_NUM_POS_BITS_MAX) + |
| 426 | + pos_state); |
| 427 | + if (rc_is_bit_0(prob)) { |
| 428 | + rc_update_bit_0(prob); |
| 429 | + |
| 430 | + ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? |
| 431 | + 9 : 11; |
| 432 | + copy_byte(ctx.rep0); |
| 433 | + return; |
| 434 | + } else { |
| 435 | + rc_update_bit_1(prob); |
| 436 | + } |
| 437 | + } else { |
| 438 | + u32 distance; |
| 439 | + |
| 440 | + rc_update_bit_1(prob); |
| 441 | + prob = p + LZMA_IS_REP_G1 + ctx.state; |
| 442 | + if (rc_is_bit_0(prob)) { |
| 443 | + rc_update_bit_0(prob); |
| 444 | + distance = ctx.rep1; |
| 445 | + } else { |
| 446 | + rc_update_bit_1(prob); |
| 447 | + prob = p + LZMA_IS_REP_G2 + ctx.state; |
| 448 | + if (rc_is_bit_0(prob)) { |
| 449 | + rc_update_bit_0(prob); |
| 450 | + distance = ctx.rep2; |
| 451 | + } else { |
| 452 | + rc_update_bit_1(prob); |
| 453 | + distance = ctx.rep3; |
| 454 | + ctx.rep3 = ctx.rep2; |
| 455 | + } |
| 456 | + ctx.rep2 = ctx.rep1; |
| 457 | + } |
| 458 | + ctx.rep1 = ctx.rep0; |
| 459 | + ctx.rep0 = distance; |
| 460 | + } |
| 461 | + ctx.state = ctx.state < LZMA_NUM_LIT_STATES ? 8 : 11; |
| 462 | + prob = p + LZMA_REP_LEN_CODER; |
| 463 | + } |
| 464 | + |
| 465 | + prob_len = prob + LZMA_LEN_CHOICE; |
| 466 | + if (rc_is_bit_0(prob_len)) { |
| 467 | + rc_update_bit_0(prob_len); |
| 468 | + prob_len = (prob + LZMA_LEN_LOW |
| 469 | + + (pos_state << |
| 470 | + LZMA_LEN_NUM_LOW_BITS)); |
| 471 | + offset = 0; |
| 472 | + num_bits = LZMA_LEN_NUM_LOW_BITS; |
| 473 | + } else { |
| 474 | + rc_update_bit_1(prob_len); |
| 475 | + prob_len = prob + LZMA_LEN_CHOICE_2; |
| 476 | + if (rc_is_bit_0(prob_len)) { |
| 477 | + rc_update_bit_0(prob_len); |
| 478 | + prob_len = (prob + LZMA_LEN_MID |
| 479 | + + (pos_state << |
| 480 | + LZMA_LEN_NUM_MID_BITS)); |
| 481 | + offset = 1 << LZMA_LEN_NUM_LOW_BITS; |
| 482 | + num_bits = LZMA_LEN_NUM_MID_BITS; |
| 483 | + } else { |
| 484 | + rc_update_bit_1(prob_len); |
| 485 | + prob_len = prob + LZMA_LEN_HIGH; |
| 486 | + offset = ((1 << LZMA_LEN_NUM_LOW_BITS) |
| 487 | + + (1 << LZMA_LEN_NUM_MID_BITS)); |
| 488 | + num_bits = LZMA_LEN_NUM_HIGH_BITS; |
| 489 | + } |
| 490 | + } |
| 491 | + |
| 492 | + rc_bit_tree_decode(prob_len, num_bits, &len); |
| 493 | + len += offset; |
| 494 | + |
| 495 | + if (ctx.state < 4) { |
| 496 | + int pos_slot; |
| 497 | + |
| 498 | + ctx.state += LZMA_NUM_LIT_STATES; |
| 499 | + prob = |
| 500 | + p + LZMA_POS_SLOT + |
| 501 | + ((len < |
| 502 | + LZMA_NUM_LEN_TO_POS_STATES ? len : |
| 503 | + LZMA_NUM_LEN_TO_POS_STATES - 1) |
| 504 | + << LZMA_NUM_POS_SLOT_BITS); |
| 505 | + rc_bit_tree_decode(prob, |
| 506 | + LZMA_NUM_POS_SLOT_BITS, |
| 507 | + &pos_slot); |
| 508 | + if (pos_slot >= LZMA_START_POS_MODEL_INDEX) { |
| 509 | + int i, mi; |
| 510 | + num_bits = (pos_slot >> 1) - 1; |
| 511 | + ctx.rep0 = 2 | (pos_slot & 1); |
| 512 | + if (pos_slot < LZMA_END_POS_MODEL_INDEX) { |
| 513 | + ctx.rep0 <<= num_bits; |
| 514 | + prob = p + LZMA_SPEC_POS + |
| 515 | + ctx.rep0 - pos_slot - 1; |
| 516 | + } else { |
| 517 | + num_bits -= LZMA_NUM_ALIGN_BITS; |
| 518 | + while (num_bits--) |
| 519 | + ctx.rep0 = (ctx.rep0 << 1) | |
| 520 | + rc_direct_bit(); |
| 521 | + prob = p + LZMA_ALIGN; |
| 522 | + ctx.rep0 <<= LZMA_NUM_ALIGN_BITS; |
| 523 | + num_bits = LZMA_NUM_ALIGN_BITS; |
| 524 | + } |
| 525 | + i = 1; |
| 526 | + mi = 1; |
| 527 | + while (num_bits--) { |
| 528 | + if (rc_get_bit(prob + mi, &mi)) |
| 529 | + ctx.rep0 |= i; |
| 530 | + i <<= 1; |
| 531 | + } |
| 532 | + } else |
| 533 | + ctx.rep0 = pos_slot; |
| 534 | + if (++(ctx.rep0) == 0) |
| 535 | + return; |
| 536 | + } |
| 537 | + |
| 538 | + len += LZMA_MATCH_MIN_LEN; |
| 539 | + |
| 540 | + copy_bytes(ctx.rep0, len); |
| 541 | +} |
| 542 | + |
| 543 | + |
| 544 | +static int |
| 545 | +do_unlzma(void) |
| 546 | +{ |
| 547 | + u8 hdr_buf[sizeof(struct lzma_header)]; |
| 548 | + struct lzma_header *header = (struct lzma_header *)hdr_buf; |
| 549 | + u32 pos_state_mask; |
| 550 | + u32 literal_pos_mask; |
| 551 | + int lc, pb, lp; |
| 552 | + int num_probs; |
| 553 | + int i, mi; |
| 554 | + u16 *p; |
| 555 | + |
| 556 | + for (i = 0; i < sizeof(struct lzma_header); i++) { |
| 557 | + hdr_buf[i] = rc_read(); |
| 558 | + } |
| 559 | + |
| 560 | + ctx.pos = 0; |
| 561 | + ctx.state = 0; |
| 562 | + ctx.rep0 = ctx.rep1 = ctx.rep2 = ctx.rep3 = 1; |
| 563 | + |
| 564 | + ctx.previous_byte = 0; |
| 565 | + ctx.code = 0; |
| 566 | + ctx.range = 0xFFFFFFFF; |
| 567 | + |
| 568 | + if (header->pos >= (9 * 5 * 5)) |
| 569 | + return -1; |
| 570 | + |
| 571 | + mi = 0; |
| 572 | + lc = header->pos; |
| 573 | + while (lc >= 9) { |
| 574 | + mi++; |
| 575 | + lc -= 9; |
| 576 | + } |
| 577 | + pb = 0; |
| 578 | + lp = mi; |
| 579 | + while (lp >= 5) { |
| 580 | + pb++; |
| 581 | + lp -= 5; |
| 582 | + } |
| 583 | + pos_state_mask = (1 << pb) - 1; |
| 584 | + literal_pos_mask = (1 << lp) - 1; |
| 585 | + |
| 586 | + p = (u16 *) ctx.workspace; |
| 587 | + if (!p) |
| 588 | + return -1; |
| 589 | + |
| 590 | + num_probs = LZMA_LITERAL + (LZMA_LIT_SIZE << (lc + lp)); |
| 591 | + for (i = 0; i < num_probs; i++) |
| 592 | + p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1; |
| 593 | + |
| 594 | + for (i = 0; i < 5; i++) |
| 595 | + rc_get_code(); |
| 596 | + |
| 597 | + while (1) { |
| 598 | + int pos_state = ctx.pos & pos_state_mask; |
| 599 | + u16 *prob = p + LZMA_IS_MATCH + |
| 600 | + (ctx.state << LZMA_NUM_POS_BITS_MAX) + pos_state; |
| 601 | + if (rc_is_bit_0(prob)) |
| 602 | + process_bit0(p, pos_state, prob, |
| 603 | + lc, literal_pos_mask); |
| 604 | + else { |
| 605 | + process_bit1(p, pos_state, prob); |
| 606 | + if (ctx.rep0 == 0) |
| 607 | + break; |
| 608 | + } |
| 609 | + } |
| 610 | + |
| 611 | + return ctx.pos; |
| 612 | +} |
| 613 | + |
| 614 | + |
| 615 | +static int unlzma(unsigned char *dest, const unsigned char *src, unsigned char *workspace) |
| 616 | +{ |
| 617 | + memset(&ctx, 0, sizeof(ctx)); |
| 618 | + ctx.outbuf = dest; |
| 619 | + ctx.next_in = src; |
| 620 | + ctx.next_out = dest; |
| 621 | + ctx.workspace = workspace; |
| 622 | + |
| 623 | + return do_unlzma(); |
| 624 | +} |
| 625 | + |
| 626 | + |
| 627 | --- /dev/null |
| 628 | +++ b/arch/arm/boot/compressed/unlzma.h |
| 629 | @@ -0,0 +1,81 @@ |
| 630 | +/* LZMA uncompresion module for pcomp |
| 631 | + * Copyright (C) 2009 Felix Fietkau <nbd@openwrt.org> |
| 632 | + * |
| 633 | + * Based on: |
| 634 | + * Initial Linux kernel adaptation |
| 635 | + * Copyright (C) 2006 Alain < alain@knaff.lu > |
| 636 | + * |
| 637 | + * Based on small lzma deflate implementation/Small range coder |
| 638 | + * implementation for lzma. |
| 639 | + * Copyright (C) 2006 Aurelien Jacobs < aurel@gnuage.org > |
| 640 | + * |
| 641 | + * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/) |
| 642 | + * Copyright (C) 1999-2005 Igor Pavlov |
| 643 | + * |
| 644 | + * This program is free software; you can redistribute it and/or modify it |
| 645 | + * under the terms of the GNU General Public License version 2 as published |
| 646 | + * by the Free Software Foundation. |
| 647 | + */ |
| 648 | +#ifndef __UNLZMA_H |
| 649 | +#define __UNLZMA_H |
| 650 | + |
| 651 | +struct lzma_header { |
| 652 | + __u8 pos; |
| 653 | + __le32 dict_size; |
| 654 | + __le64 uncompr_size; |
| 655 | +} __attribute__ ((packed)); |
| 656 | + |
| 657 | + |
| 658 | +#define RC_TOP_BITS 24 |
| 659 | +#define RC_MOVE_BITS 5 |
| 660 | +#define RC_MODEL_TOTAL_BITS 11 |
| 661 | + |
| 662 | +#define LZMA_BASE_SIZE 1846 |
| 663 | +#define LZMA_LIT_SIZE 768 |
| 664 | + |
| 665 | +#define LZMA_NUM_POS_BITS_MAX 4 |
| 666 | + |
| 667 | +#define LZMA_LEN_NUM_LOW_BITS 3 |
| 668 | +#define LZMA_LEN_NUM_MID_BITS 3 |
| 669 | +#define LZMA_LEN_NUM_HIGH_BITS 8 |
| 670 | + |
| 671 | +#define LZMA_LEN_CHOICE 0 |
| 672 | +#define LZMA_LEN_CHOICE_2 (LZMA_LEN_CHOICE + 1) |
| 673 | +#define LZMA_LEN_LOW (LZMA_LEN_CHOICE_2 + 1) |
| 674 | +#define LZMA_LEN_MID (LZMA_LEN_LOW \ |
| 675 | + + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))) |
| 676 | +#define LZMA_LEN_HIGH (LZMA_LEN_MID \ |
| 677 | + +(1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))) |
| 678 | +#define LZMA_NUM_LEN_PROBS (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)) |
| 679 | + |
| 680 | +#define LZMA_NUM_STATES 12 |
| 681 | +#define LZMA_NUM_LIT_STATES 7 |
| 682 | + |
| 683 | +#define LZMA_START_POS_MODEL_INDEX 4 |
| 684 | +#define LZMA_END_POS_MODEL_INDEX 14 |
| 685 | +#define LZMA_NUM_FULL_DISTANCES (1 << (LZMA_END_POS_MODEL_INDEX >> 1)) |
| 686 | + |
| 687 | +#define LZMA_NUM_POS_SLOT_BITS 6 |
| 688 | +#define LZMA_NUM_LEN_TO_POS_STATES 4 |
| 689 | + |
| 690 | +#define LZMA_NUM_ALIGN_BITS 4 |
| 691 | + |
| 692 | +#define LZMA_MATCH_MIN_LEN 2 |
| 693 | + |
| 694 | +#define LZMA_IS_MATCH 0 |
| 695 | +#define LZMA_IS_REP (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) |
| 696 | +#define LZMA_IS_REP_G0 (LZMA_IS_REP + LZMA_NUM_STATES) |
| 697 | +#define LZMA_IS_REP_G1 (LZMA_IS_REP_G0 + LZMA_NUM_STATES) |
| 698 | +#define LZMA_IS_REP_G2 (LZMA_IS_REP_G1 + LZMA_NUM_STATES) |
| 699 | +#define LZMA_IS_REP_0_LONG (LZMA_IS_REP_G2 + LZMA_NUM_STATES) |
| 700 | +#define LZMA_POS_SLOT (LZMA_IS_REP_0_LONG \ |
| 701 | + + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)) |
| 702 | +#define LZMA_SPEC_POS (LZMA_POS_SLOT \ |
| 703 | + +(LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)) |
| 704 | +#define LZMA_ALIGN (LZMA_SPEC_POS \ |
| 705 | + + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX) |
| 706 | +#define LZMA_LEN_CODER (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)) |
| 707 | +#define LZMA_REP_LEN_CODER (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS) |
| 708 | +#define LZMA_LITERAL (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS) |
| 709 | + |
| 710 | +#endif |
| 711 | |