summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/lzma/dcapi.c
blob: b8f59b0c2d28aa2c84f0f08c88f26e5140bcb519 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
#include "LzmaDecode.h"
#include "bcm63xx_util.h"
#include "lib_malloc.h"

#define LZMA_ORIGSIZE_SIZE 8

int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize);

// Call ANSI C LZMA decoder to decompress a LZMA block
int decompressLZMA(unsigned char *in, unsigned insize, unsigned char *out, unsigned outsize)
{

    SizeT inProcessed, outProcessed;
    unsigned origsize;
    int ret;
    CLzmaDecoderState state;

    ret = LzmaDecodeProperties(&state.Properties, in, LZMA_PROPERTIES_SIZE);
    if (ret != LZMA_RESULT_OK) {
        return ret;
    }
    in += LZMA_PROPERTIES_SIZE;
    
    state.Probs = (CProb *)KMALLOC(LzmaGetNumProbs(&state.Properties) * sizeof(CProb), 0);
    if (!state.Probs) {
        return 1001;
    }

    if (in[4]==0 && in[5]==0 && in[6]==0 && in[7]==0) { // uncompressed size < 4GB (should be)
        origsize = in[0] | (in[1] << 8) | (in[2] << 16) | (in[3] << 24);
        in += LZMA_ORIGSIZE_SIZE;
        if (origsize <= outsize) {
              ret = LzmaDecode(&state, in, insize, &inProcessed, out, origsize, &outProcessed);
        }
        else {
            // output buffer too small
            ret = 1000;
        }
    }
    else { // uncompressed size > 4GB, old lzma format or corrupted image, assume old format here
        printf("LZMA: Prossible old LZMA format, trying to decompress..\n");
        LzmaDecode(&state, in, insize, &inProcessed, out, outsize, &outProcessed);
        ret = 0; // It would return an error code as the output buffer size doesn't match. We need to ignore the code.
    }

    KFREE(state.Probs);
    
    return ret;
}