wok view syslinux/stuff/extra/loadhigh.u @ rev 18757

syslinux: compress c32 modules
author Pascal Bellard <pascal.bellard@slitaz.org>
date Tue Dec 29 08:59:31 2015 +0100 (2015-12-29)
parents
children 924e6ea5da10
line source
1 --- core/fs/loadhigh.c
2 +++ core/fs/loadhigh.c
3 @@ -36,6 +36,11 @@
4 #include <minmax.h>
5 #include "core.h"
6 #include "fs.h"
7 +#define LZLOAD ".c32 modules can be compressed with lz4 or lzma"
8 +#ifdef LZLOAD
9 +#include "../unlz4.c"
10 +#include "../unlzma.c"
11 +#endif
13 #define MAX_CHUNK (1 << 20) /* 1 MB */
15 @@ -51,6 +56,10 @@
16 uint32_t sector_mask;
17 size_t pad;
18 uint32_t retflags = 0;
19 +#ifdef LZLOAD
20 + char *unpacked = (char *) regs->edi.l;
21 + size_t unpackedsz;
22 +#endif
24 bytes = regs->eax.l;
25 zero_mask = regs->edx.w[0];
26 @@ -101,6 +110,27 @@
27 break;
28 }
29 }
30 +
31 +#ifdef LZLOAD
32 + unpackedsz = buf - unpacked;
33 + switch (* (short *) unpacked) {
34 + char *packed;
35 + case 0x005D:
36 + packed = unpacked + * (unsigned long *) (unpacked + 5)
37 + - unpackedsz + 1024;
38 +
39 + if (packed < unpacked + 1024)
40 + packed = unpacked + 1024;
41 + memmove(packed, unpacked, unpackedsz);
42 + unlzma(packed, unpacked, packed + unpackedsz /* head */);
43 + buf = packed;
44 + break;
45 + case 0x2204:
46 + case 0x2102:
47 + buf = unlz4(unpacked, buf);
48 + break;
49 + }
50 +#endif
52 pad = (size_t)buf & zero_mask;
53 if (pad)
54 --- /dev/null
55 +++ core/unlzma.c
56 @@ -0,0 +1,383 @@
57 +typedef unsigned char uint8_t;
58 +typedef unsigned short uint16_t;
59 +typedef unsigned uint32_t;
60 +typedef unsigned long long uint64_t;
61 +typedef unsigned size_t;
62 +#define SWAP_LE32(x) (x)
63 +#define SWAP_LE64(x) (x)
64 +/* vi: set sw=4 ts=4: */
65 +/*
66 + * Small lzma deflate implementation.
67 + * Copyright (C) 2006 Aurelien Jacobs <aurel@gnuage.org>
68 + *
69 + * Based on LzmaDecode.c from the LZMA SDK 4.22 (http://www.7-zip.org/)
70 + * Copyright (C) 1999-2005 Igor Pavlov
71 + *
72 + * Licensed under GPLv2 or later, see file LICENSE in this source tree.
73 + */
74 +
75 +#define PACKED __attribute__ ((packed))
76 +#define ALWAYS_INLINE inline
77 +#define speed_inline
78 +#define size_inline ALWAYS_INLINE
79 +
80 +
81 +typedef struct {
82 + uint8_t *ptr;
83 +
84 + uint32_t code;
85 + uint32_t range;
86 + uint32_t bound;
87 +} rc_t;
88 +
89 +#define RC_TOP_BITS 24
90 +#define RC_MOVE_BITS 5
91 +#define RC_MODEL_TOTAL_BITS 11
92 +
93 +/* Called twice, but one callsite is in speed_inline'd rc_is_bit_1() */
94 +static void rc_do_normalize(rc_t *rc)
95 +{
96 + rc->range <<= 8;
97 + rc->code = (rc->code << 8) | *rc->ptr++;
98 +}
99 +
100 +static ALWAYS_INLINE void rc_normalize(rc_t *rc)
101 +{
102 + if (rc->range < (1 << RC_TOP_BITS)) {
103 + rc_do_normalize(rc);
104 + }
105 +}
106 +
107 +/* Called once */
108 +static void rc_init(rc_t *rc) /*, int buffer_size) */
109 +{
110 + int i;
111 +
112 + rc->range = 0;
113 + for (i = 0; i < 5; i++) {
114 + rc_do_normalize(rc);
115 + }
116 + rc->range = 0xffffffff;
117 +}
118 +
119 +/* rc_is_bit_1 is called 9 times */
120 +static speed_inline int rc_is_bit_1(rc_t *rc, uint16_t *p)
121 +{
122 + rc_normalize(rc);
123 + rc->bound = *p * (rc->range >> RC_MODEL_TOTAL_BITS);
124 + if (rc->code < rc->bound) {
125 + rc->range = rc->bound;
126 + *p += ((1 << RC_MODEL_TOTAL_BITS) - *p) >> RC_MOVE_BITS;
127 + return 0;
128 + }
129 + rc->range -= rc->bound;
130 + rc->code -= rc->bound;
131 + *p -= *p >> RC_MOVE_BITS;
132 + return 1;
133 +}
134 +
135 +/* Called 4 times in unlzma loop */
136 +static ALWAYS_INLINE int rc_get_bit(rc_t *rc, uint16_t *p, int *symbol)
137 +{
138 + int ret = rc_is_bit_1(rc, p);
139 + *symbol = *symbol * 2 + ret;
140 + return ret;
141 +}
142 +
143 +/* Called once */
144 +static ALWAYS_INLINE int rc_direct_bit(rc_t *rc)
145 +{
146 + rc_normalize(rc);
147 + rc->range >>= 1;
148 + if (rc->code >= rc->range) {
149 + rc->code -= rc->range;
150 + return 1;
151 + }
152 + return 0;
153 +}
154 +
155 +/* Called twice */
156 +static speed_inline void
157 +rc_bit_tree_decode(rc_t *rc, uint16_t *p, int num_levels, int *symbol)
158 +{
159 + int i = num_levels;
160 +
161 + *symbol = 1;
162 + while (i--)
163 + rc_get_bit(rc, p + *symbol, symbol);
164 + *symbol -= 1 << num_levels;
165 +}
166 +
167 +
168 +typedef struct {
169 + uint8_t pos;
170 + uint32_t dict_size;
171 + uint64_t dst_size;
172 +} PACKED lzma_header_t;
173 +
174 +
175 +/* #defines will force compiler to compute/optimize each one with each usage.
176 + * Have heart and use enum instead. */
177 +enum {
178 + LZMA_BASE_SIZE = 1846,
179 + LZMA_LIT_SIZE = 768,
180 +
181 + LZMA_NUM_POS_BITS_MAX = 4,
182 +
183 + LZMA_LEN_NUM_LOW_BITS = 3,
184 + LZMA_LEN_NUM_MID_BITS = 3,
185 + LZMA_LEN_NUM_HIGH_BITS = 8,
186 +
187 + LZMA_LEN_CHOICE = 0,
188 + LZMA_LEN_CHOICE_2 = (LZMA_LEN_CHOICE + 1),
189 + LZMA_LEN_LOW = (LZMA_LEN_CHOICE_2 + 1),
190 + LZMA_LEN_MID = (LZMA_LEN_LOW \
191 + + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_LOW_BITS))),
192 + LZMA_LEN_HIGH = (LZMA_LEN_MID \
193 + + (1 << (LZMA_NUM_POS_BITS_MAX + LZMA_LEN_NUM_MID_BITS))),
194 + LZMA_NUM_LEN_PROBS = (LZMA_LEN_HIGH + (1 << LZMA_LEN_NUM_HIGH_BITS)),
195 +
196 + LZMA_NUM_STATES = 12,
197 + LZMA_NUM_LIT_STATES = 7,
198 +
199 + LZMA_START_POS_MODEL_INDEX = 4,
200 + LZMA_END_POS_MODEL_INDEX = 14,
201 + LZMA_NUM_FULL_DISTANCES = (1 << (LZMA_END_POS_MODEL_INDEX >> 1)),
202 +
203 + LZMA_NUM_POS_SLOT_BITS = 6,
204 + LZMA_NUM_LEN_TO_POS_STATES = 4,
205 +
206 + LZMA_NUM_ALIGN_BITS = 4,
207 +
208 + LZMA_MATCH_MIN_LEN = 2,
209 +
210 + LZMA_IS_MATCH = 0,
211 + LZMA_IS_REP = (LZMA_IS_MATCH + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
212 + LZMA_IS_REP_G0 = (LZMA_IS_REP + LZMA_NUM_STATES),
213 + LZMA_IS_REP_G1 = (LZMA_IS_REP_G0 + LZMA_NUM_STATES),
214 + LZMA_IS_REP_G2 = (LZMA_IS_REP_G1 + LZMA_NUM_STATES),
215 + LZMA_IS_REP_0_LONG = (LZMA_IS_REP_G2 + LZMA_NUM_STATES),
216 + LZMA_POS_SLOT = (LZMA_IS_REP_0_LONG \
217 + + (LZMA_NUM_STATES << LZMA_NUM_POS_BITS_MAX)),
218 + LZMA_SPEC_POS = (LZMA_POS_SLOT \
219 + + (LZMA_NUM_LEN_TO_POS_STATES << LZMA_NUM_POS_SLOT_BITS)),
220 + LZMA_ALIGN = (LZMA_SPEC_POS \
221 + + LZMA_NUM_FULL_DISTANCES - LZMA_END_POS_MODEL_INDEX),
222 + LZMA_LEN_CODER = (LZMA_ALIGN + (1 << LZMA_NUM_ALIGN_BITS)),
223 + LZMA_REP_LEN_CODER = (LZMA_LEN_CODER + LZMA_NUM_LEN_PROBS),
224 + LZMA_LITERAL = (LZMA_REP_LEN_CODER + LZMA_NUM_LEN_PROBS),
225 +};
226 +
227 +
228 +void unlzma(char *from, char *to, char *heap)
229 +{
230 + lzma_header_t header;
231 + int lc, pb, lp;
232 + uint32_t pos_state_mask;
233 + uint32_t literal_pos_mask;
234 + uint16_t *p;
235 + rc_t *rc = (rc_t *) heap;
236 + int i;
237 + uint8_t *buffer = (void *) to;
238 + uint8_t previous_byte = 0;
239 + size_t buffer_pos = 0;
240 + int len = 0;
241 + int state = 0;
242 + uint32_t rep0 = 1, rep1 = 1, rep2 = 1, rep3 = 1;
243 +
244 + memcpy(&header, from, sizeof(header));
245 + from += sizeof(header);
246 + heap += sizeof(*rc);
247 + rc->ptr = (void *) from;
248 +
249 + i = header.pos / 9;
250 + lc = header.pos % 9;
251 + pb = i / 5;
252 + lp = i % 5;
253 + pos_state_mask = (1 << pb) - 1;
254 + literal_pos_mask = (1 << lp) - 1;
255 +
256 + /* Example values from linux-3.3.4.tar.lzma:
257 + * dict_size: 64M, dst_size: 2^64-1
258 + */
259 + header.dict_size = SWAP_LE32(header.dict_size);
260 + header.dst_size = SWAP_LE64(header.dst_size);
261 +
262 + //if (header.dict_size == 0)
263 + // header.dict_size++;
264 +
265 + rc_init(rc);
266 +
267 + {
268 + int num_probs;
269 +
270 + num_probs = LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp));
271 + //p = xmalloc(num_probs * sizeof(*p));
272 + p = (void *) heap;
273 + num_probs += LZMA_LITERAL - LZMA_BASE_SIZE;
274 + for (i = 0; i < num_probs; i++)
275 + p[i] = (1 << RC_MODEL_TOTAL_BITS) >> 1;
276 + }
277 +
278 +
279 + while (buffer_pos < header.dst_size) {
280 + int pos_state = buffer_pos & pos_state_mask;
281 + uint16_t *prob = p + LZMA_IS_MATCH + (state << LZMA_NUM_POS_BITS_MAX) + pos_state;
282 +
283 + if (!rc_is_bit_1(rc, prob)) {
284 + static const char next_state[LZMA_NUM_STATES] =
285 + { 0, 0, 0, 0, 1, 2, 3, 4, 5, 6, 4, 5 };
286 + int mi = 1;
287 +
288 + prob = (p + LZMA_LITERAL
289 + + (LZMA_LIT_SIZE * (((buffer_pos & literal_pos_mask) << lc)
290 + + (previous_byte >> (8 - lc))
291 + )
292 + )
293 + );
294 +
295 + if (state >= LZMA_NUM_LIT_STATES) {
296 + int match_byte;
297 + uint32_t pos = buffer_pos - rep0;
298 +
299 + while (pos >= header.dict_size)
300 + pos += header.dict_size;
301 + match_byte = buffer[pos];
302 + do {
303 + int bit;
304 +
305 + match_byte <<= 1;
306 + bit = match_byte & 0x100;
307 + bit ^= (rc_get_bit(rc, prob + 0x100 + bit + mi, &mi) << 8); /* 0x100 or 0 */
308 + if (bit)
309 + break;
310 + } while (mi < 0x100);
311 + }
312 + while (mi < 0x100) {
313 + rc_get_bit(rc, prob + mi, &mi);
314 + }
315 +
316 + state = next_state[state];
317 +
318 + previous_byte = (uint8_t) mi;
319 + len = 1;
320 + goto one_byte2;
321 + } else {
322 + int num_bits;
323 + int offset;
324 + uint16_t *prob2;
325 +#define prob_len prob2
326 +
327 + prob2 = p + LZMA_IS_REP + state;
328 + if (!rc_is_bit_1(rc, prob2)) {
329 + rep3 = rep2;
330 + rep2 = rep1;
331 + rep1 = rep0;
332 + state = state < LZMA_NUM_LIT_STATES ? 0 : 3;
333 + prob2 = p + LZMA_LEN_CODER;
334 + } else {
335 + prob2 += LZMA_IS_REP_G0 - LZMA_IS_REP;
336 + if (!rc_is_bit_1(rc, prob2)) {
337 + prob2 = (p + LZMA_IS_REP_0_LONG
338 + + (state << LZMA_NUM_POS_BITS_MAX)
339 + + pos_state
340 + );
341 + if (!rc_is_bit_1(rc, prob2)) {
342 + state = state < LZMA_NUM_LIT_STATES ? 9 : 11;
343 + len = 1;
344 + goto string;
345 + }
346 + } else {
347 + uint32_t distance;
348 +
349 + prob2 += LZMA_IS_REP_G1 - LZMA_IS_REP_G0;
350 + distance = rep1;
351 + if (rc_is_bit_1(rc, prob2)) {
352 + prob2 += LZMA_IS_REP_G2 - LZMA_IS_REP_G1;
353 + distance = rep2;
354 + if (rc_is_bit_1(rc, prob2)) {
355 + distance = rep3;
356 + rep3 = rep2;
357 + }
358 + rep2 = rep1;
359 + }
360 + rep1 = rep0;
361 + rep0 = distance;
362 + }
363 + state = state < LZMA_NUM_LIT_STATES ? 8 : 11;
364 + prob2 = p + LZMA_REP_LEN_CODER;
365 + }
366 +
367 + prob_len = prob2 + LZMA_LEN_CHOICE;
368 + num_bits = LZMA_LEN_NUM_LOW_BITS;
369 + if (!rc_is_bit_1(rc, prob_len)) {
370 + prob_len += LZMA_LEN_LOW - LZMA_LEN_CHOICE
371 + + (pos_state << LZMA_LEN_NUM_LOW_BITS);
372 + offset = 0;
373 + } else {
374 + prob_len += LZMA_LEN_CHOICE_2 - LZMA_LEN_CHOICE;
375 + if (!rc_is_bit_1(rc, prob_len)) {
376 + prob_len += LZMA_LEN_MID - LZMA_LEN_CHOICE_2
377 + + (pos_state << LZMA_LEN_NUM_MID_BITS);
378 + offset = 1 << LZMA_LEN_NUM_LOW_BITS;
379 + num_bits += LZMA_LEN_NUM_MID_BITS - LZMA_LEN_NUM_LOW_BITS;
380 + } else {
381 + prob_len += LZMA_LEN_HIGH - LZMA_LEN_CHOICE_2;
382 + offset = ((1 << LZMA_LEN_NUM_LOW_BITS)
383 + + (1 << LZMA_LEN_NUM_MID_BITS));
384 + num_bits += LZMA_LEN_NUM_HIGH_BITS - LZMA_LEN_NUM_LOW_BITS;
385 + }
386 + }
387 + rc_bit_tree_decode(rc, prob_len, num_bits, &len);
388 + len += offset;
389 +
390 + if (state < 4) {
391 + int pos_slot;
392 + uint16_t *prob3;
393 +
394 + state += LZMA_NUM_LIT_STATES;
395 + prob3 = p + LZMA_POS_SLOT +
396 + ((len < LZMA_NUM_LEN_TO_POS_STATES ? len :
397 + LZMA_NUM_LEN_TO_POS_STATES - 1)
398 + << LZMA_NUM_POS_SLOT_BITS);
399 + rc_bit_tree_decode(rc, prob3,
400 + LZMA_NUM_POS_SLOT_BITS, &pos_slot);
401 + rep0 = pos_slot;
402 + if (pos_slot >= LZMA_START_POS_MODEL_INDEX) {
403 + int i2, mi2, num_bits2 = (pos_slot >> 1) - 1;
404 + rep0 = 2 | (pos_slot & 1);
405 + if (pos_slot < LZMA_END_POS_MODEL_INDEX) {
406 + rep0 <<= num_bits2;
407 + prob3 = p + LZMA_SPEC_POS + rep0 - pos_slot - 1;
408 + } else {
409 + for (; num_bits2 != LZMA_NUM_ALIGN_BITS; num_bits2--)
410 + rep0 = (rep0 << 1) | rc_direct_bit(rc);
411 + rep0 <<= LZMA_NUM_ALIGN_BITS;
412 + prob3 = p + LZMA_ALIGN;
413 + }
414 + i2 = 1;
415 + mi2 = 1;
416 + while (num_bits2--) {
417 + if (rc_get_bit(rc, prob3 + mi2, &mi2))
418 + rep0 |= i2;
419 + i2 <<= 1;
420 + }
421 + }
422 + if (++rep0 == 0)
423 + break;
424 + }
425 +
426 + len += LZMA_MATCH_MIN_LEN;
427 + string:
428 + do {
429 + uint32_t pos = buffer_pos - rep0;
430 + while (pos >= header.dict_size)
431 + pos += header.dict_size;
432 + previous_byte = buffer[pos];
433 + one_byte2:
434 + buffer[buffer_pos++] = previous_byte;
435 + len--;
436 + } while (len != 0 && buffer_pos < header.dst_size);
437 + }
438 + }
439 +}
440 --- /dev/null
441 +++ core/unlz4.c
442 @@ -0,0 +1,112 @@
443 +/*
444 + * Copyright (C) 2015, pascal.bellard@slitaz.org
445 + *
446 + * This program is free software; you can redistribute it and/or modify
447 + * it under the terms of the GNU General Public License version 2 as
448 + * published by the Free Software Foundation.
449 + */
450 +
451 +#define LZ4_MAGIC 0x184D2204 /* Spec 1.5.0 */
452 +#define LZ4_LEGACY 0x184C2102
453 +#define LZ4_SKIP(n) ((((n) - 0x184D2A50) >> 4) == 0)
454 +
455 +static unsigned lz4cnt(unsigned char **p, unsigned n)
456 +{
457 + int i;
458 +
459 + if (n == 0xF) do {
460 + i = *(*p)++;
461 + n += i;
462 + } while (i == 0xFF);
463 + return n;
464 +}
465 +
466 +char *unlz4(unsigned char *from, unsigned char *end)
467 +{
468 + unsigned char *p, *end_chunk, *to, flags, mask;
469 + long magic;
470 + unsigned i, n, size;
471 +
472 + for (p = from, flags = size = 0; p < end;) {
473 + while (1) {
474 + magic = * (long *) p;
475 + p += sizeof(long);
476 + if (magic == LZ4_LEGACY) continue;
477 + if (magic != LZ4_MAGIC) break;
478 + flags = *p;
479 + if (flags & 8) {
480 + size = * (unsigned *) (p + 2);
481 + goto sizefound;
482 + }
483 + p += 3; /* skip FLG BD HC */
484 + }
485 + if (LZ4_SKIP(magic)) {
486 + p += 4 + * (long *) p;
487 + continue;
488 + }
489 + mask = 4; /* Content checksum */
490 + if (magic) {
491 + if (magic > 0)
492 + for (end_chunk = p + magic; p < end_chunk;) {
493 + unsigned char token = *p++;
494 +
495 + n = lz4cnt(&p, token >> 4);
496 + size += n;
497 + p += n;
498 + if (p >= end_chunk) break;
499 + p += sizeof(unsigned short);
500 + size += 4 + lz4cnt(&p, token & 0xF);
501 + }
502 + else {
503 + magic &= 0x7FffFFff;
504 + p += magic;
505 + size += magic;
506 + }
507 + mask = 0x10; /* Block checksum */
508 + }
509 + if (flags & mask) p += 4; /* skip block checksum */
510 + }
511 +sizefound:
512 + size += 16 - (p - from);
513 + memmove(from + size, from, p - from);
514 + for (to = from, p = from += size, end += size, flags = 0; p < end;) {
515 + while (1) {
516 + magic = * (long *) p;
517 + p += sizeof(long);
518 + if (magic == LZ4_LEGACY) continue;
519 + if (magic != LZ4_MAGIC) break;
520 + flags = *p;
521 + if (flags & 8) p += 8; /* skip size */
522 + p += 3; /* skip FLG BD HC */
523 + }
524 + if (LZ4_SKIP(magic)) {
525 + p += 4 + * (long *) p;
526 + continue;
527 + }
528 + mask = 4; /* Content checksum */
529 + if (magic) {
530 + if (magic > 0)
531 + for (end_chunk = p + magic; p < end_chunk;) {
532 + char *dico;
533 + unsigned char token = *p++;
534 +
535 + n = lz4cnt(&p, token >> 4);
536 + for (i = 0; i < n; i++)
537 + *to++ = *p++;
538 + if (p >= end_chunk) break;
539 + dico = to - (* (unsigned short *) p);
540 + p += sizeof(unsigned short);
541 + n = 4 + lz4cnt(&p, token & 0xF);
542 + for (i = 0; i < n; i++)
543 + *to++ = *dico++;
544 + }
545 + else for (end_chunk = p + (magic & 0x7FffFFff);
546 + p < end_chunk;) {
547 + *to++ = *p++;
548 + }
549 + mask = 0x10; /* Block checksum */
550 + }
551 + if (flags & mask) p += 4; /* Skip checksum */
552 + }
553 + return to;
554 +}